Match attachments by properties

This commit is contained in:
M66B 2019-05-08 10:32:37 +02:00
parent 61f7a2f692
commit 4cf330dfb6
11 changed files with 1807 additions and 57 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1390,7 +1390,7 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
a.sequence = ++sequence;
a.id = db.attachment().insertAttachment(a);
try {
parts.downloadAttachment(context, index, a.id);
parts.downloadAttachment(context, a);
} catch (Throwable ex) {
Log.e(ex);
}

View File

@ -248,7 +248,7 @@ public class AdapterAttachment extends RecyclerView.Adapter<AdapterAttachment.Vi
db.attachment().setProgress(id, 0);
EntityOperation.queue(context, db, message, EntityOperation.ATTACHMENT, sequence);
EntityOperation.queue(context, db, message, EntityOperation.ATTACHMENT, id);
db.setTransactionSuccessful();
} finally {

View File

@ -150,7 +150,7 @@ public class AdapterImage extends RecyclerView.Adapter<AdapterImage.ViewHolder>
db.attachment().setProgress(id, 0);
EntityMessage msg = db.message().getMessage(message);
EntityOperation.queue(context, db, msg, EntityOperation.ATTACHMENT, sequence);
EntityOperation.queue(context, db, msg, EntityOperation.ATTACHMENT, id);
db.setTransactionSuccessful();
} finally {

View File

@ -1343,7 +1343,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
for (EntityAttachment attachment : db.attachment().getAttachments(message.id))
if (attachment.progress == null && !attachment.available) {
db.attachment().setProgress(attachment.id, 0);
EntityOperation.queue(context, db, msg, EntityOperation.ATTACHMENT, attachment.sequence);
EntityOperation.queue(context, db, msg, EntityOperation.ATTACHMENT, attachment.id);
}
db.setTransactionSuccessful();
@ -1691,7 +1691,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
List<EntityAttachment> attachments = db.attachment().getAttachments(message.id);
for (EntityAttachment attachment : attachments)
if (!attachment.available && !TextUtils.isEmpty(attachment.cid))
EntityOperation.queue(context, db, message, EntityOperation.ATTACHMENT, attachment.sequence);
EntityOperation.queue(context, db, message, EntityOperation.ATTACHMENT, attachment.id);
db.setTransactionSuccessful();
} finally {

View File

@ -691,10 +691,14 @@ class Core {
// Download attachment
DB db = DB.getInstance(context);
int sequence = jargs.getInt(0);
long id = jargs.getLong(0);
// Get attachment
EntityAttachment attachment = db.attachment().getAttachment(op.message, sequence);
EntityAttachment attachment = db.attachment().getAttachment(id);
if (attachment == null)
attachment = db.attachment().getAttachment(message.id, (int) id); // legacy
if (attachment == null)
throw new IllegalArgumentException("Attachment not found");
if (attachment.available)
return;
@ -703,10 +707,28 @@ class Core {
if (imessage == null)
throw new MessageRemovedException();
// Download attachment
MessageHelper helper = new MessageHelper((MimeMessage) imessage);
MessageHelper.MessageParts parts = helper.getMessageParts();
parts.downloadAttachment(context, sequence - 1, attachment.id);
// Match attachment by attributes
// Some servers order attachments randomly
boolean found = false;
List<EntityAttachment> attachments = db.attachment().getAttachments(message.id);
for (EntityAttachment a : attachments) {
if (Objects.equals(a.name, attachment.name) &&
Objects.equals(a.type, attachment.type) &&
Objects.equals(a.disposition, attachment.disposition) &&
Objects.equals(a.cid, attachment.cid) &&
Objects.equals(a.encryption, attachment.encryption) &&
Objects.equals(a.size, attachment.size)) {
found = true;
// Download attachment
MessageHelper helper = new MessageHelper((MimeMessage) imessage);
MessageHelper.MessageParts parts = helper.getMessageParts();
parts.downloadAttachment(context, a);
}
}
if (!found && !EntityFolder.DRAFTS.equals(folder.type))
throw new IllegalArgumentException("Attachment not found");
updateMessageSize(context, message.id);
}
@ -1566,7 +1588,7 @@ class Core {
if (!attachment.available)
if (state.getNetworkState().isUnmetered() || (attachment.size != null && attachment.size < maxSize))
try {
parts.downloadAttachment(context, attachment.sequence - 1, attachment.id);
parts.downloadAttachment(context, attachment);
} catch (Throwable ex) {
Log.e(ex);
}

View File

@ -51,7 +51,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory;
// https://developer.android.com/topic/libraries/architecture/room.html
@Database(
version = 79,
version = 80,
entities = {
EntityIdentity.class,
EntityAccount.class,
@ -801,6 +801,14 @@ public abstract class DB extends RoomDatabase {
db.execSQL("ALTER TABLE `message` ADD COLUMN `plain_only` INTEGER");
}
})
.addMigrations(new Migration(79, 80) {
@Override
public void migrate(SupportSQLiteDatabase db) {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("DROP INDEX index_attachment_message_cid");
db.execSQL("CREATE INDEX `index_attachment_message_cid` ON `attachment` (`message`, `cid`)");
}
})
.build();
}

View File

@ -59,7 +59,8 @@ public interface DaoAttachment {
@Query("SELECT * FROM attachment" +
" WHERE message = :message" +
" AND cid = :cid")
" AND cid = :cid" +
" LIMIT 1")
EntityAttachment getAttachment(long message, String cid);
@Query("UPDATE attachment" +
@ -67,11 +68,6 @@ public interface DaoAttachment {
" WHERE id = :id")
void setMessage(long id, long message);
@Query("UPDATE attachment" +
" SET name = :name, type = :type, disposition = :disposition, cid = :cid, encryption = :encryption" +
" WHERE id = :id")
void setInfo(long id, String name, String type, String disposition, String cid, Integer encryption);
@Query("UPDATE attachment" +
" SET error = NULL, progress = :progress, available = 0" +
" WHERE id = :id")

View File

@ -45,7 +45,7 @@ import static androidx.room.ForeignKey.CASCADE;
indices = {
@Index(value = {"message"}),
@Index(value = {"message", "sequence"}, unique = true),
@Index(value = {"message", "cid"}, unique = true)
@Index(value = {"message", "cid"})
}
)
public class EntityAttachment {

View File

@ -2182,7 +2182,7 @@ public class FragmentCompose extends FragmentBase {
List<EntityAttachment> attachments = db.attachment().getAttachments(draft.id);
for (EntityAttachment attachment : attachments)
if (!attachment.available)
EntityOperation.queue(context, db, draft, EntityOperation.ATTACHMENT, attachment.sequence);
EntityOperation.queue(context, db, draft, EntityOperation.ATTACHMENT, attachment.id);
}
db.setTransactionSuccessful();

View File

@ -826,34 +826,17 @@ public class MessageHelper {
return result;
}
void downloadAttachment(Context context, int index, long id) throws MessagingException, IOException {
Log.i("downloading attchment id=" + id + " seq=" + index);
// Attachments of drafts might not have been uploaded yet
if (index >= attachments.size()) {
Log.w("Attachment unavailable sequence=" + index + " size=" + attachments.size());
return;
}
void downloadAttachment(Context context, EntityAttachment attachment) throws MessagingException, IOException {
Log.i("downloading attachment id=" + attachment.id);
DB db = DB.getInstance(context);
// Get data
AttachmentPart apart = attachments.get(index);
EntityAttachment attachment = db.attachment().getAttachment(id);
if (attachment == null)
return;
// Set info again in case ordering changed
db.attachment().setInfo(id,
apart.attachment.name,
apart.attachment.type,
apart.attachment.disposition,
apart.attachment.cid,
apart.attachment.encryption);
AttachmentPart apart = attachments.get(attachment.sequence - 1);
// Download attachment
File file = attachment.getFile(context);
db.attachment().setProgress(id, null);
db.attachment().setProgress(attachment.id, null);
try (InputStream is = apart.part.getInputStream()) {
long size = 0;
long total = apart.part.getSize();
@ -866,19 +849,19 @@ public class MessageHelper {
// Update progress
if (total > 0)
db.attachment().setProgress(id, (int) (size * 100 / total));
db.attachment().setProgress(attachment.id, (int) (size * 100 / total));
}
}
// Store attachment data
db.attachment().setDownloaded(id, size);
db.attachment().setDownloaded(attachment.id, size);
Log.i("Downloaded attachment size=" + size);
} catch (FolderClosedIOException ex) {
throw new FolderClosedException(ex.getFolder(), "downloadAttachment", ex);
} catch (Throwable ex) {
// Reset progress on failure
db.attachment().setError(id, Helper.formatThrowable(ex));
db.attachment().setError(attachment.id, Helper.formatThrowable(ex));
throw ex;
}
}
@ -922,18 +905,6 @@ public class MessageHelper {
getMessageParts(cmessage, parts, false);
// Fix duplicate CIDs
List<EntityAttachment> attachments = parts.getAttachments();
for (int i = 0; i < attachments.size(); i++) {
String cid = attachments.get(i).cid;
if (cid != null)
for (int j = i + 1; j < attachments.size(); j++) {
EntityAttachment a = attachments.get(j);
if (cid.equals(a.cid))
a.cid = null;
}
}
return parts;
}