Loading k9mail/src/main/java/com/fsck/k9/activity/compose/AttachmentPresenter.java +2 −5 Original line number Diff line number Diff line Loading @@ -131,11 +131,8 @@ public class AttachmentPresenter { } public void addAttachment(Uri uri, String contentType) { Attachment attachment = new Attachment(); attachment.uri = uri; attachment.state = Attachment.LoadingState.URI_ONLY; attachment.contentType = contentType; attachment.loaderId = getNextFreeLoaderId(); int loaderId = getNextFreeLoaderId(); Attachment attachment = Attachment.createAttachment(uri, loaderId, contentType); if (attachments.containsKey(uri)) { return; Loading k9mail/src/main/java/com/fsck/k9/activity/loader/AttachmentContentLoader.java +19 −15 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ import android.util.Log; import com.fsck.k9.K9; import com.fsck.k9.activity.misc.Attachment; import com.fsck.k9.activity.misc.Attachment.LoadingState; import de.cketti.safecontentresolver.SafeContentResolver; import de.cketti.safecontentresolver.SafeContentResolverCompat; import org.apache.commons.io.IOUtils; Loading @@ -24,20 +25,27 @@ import org.apache.commons.io.IOUtils; public class AttachmentContentLoader extends AsyncTaskLoader<Attachment> { private static final String FILENAME_PREFIX = "attachment"; private final Attachment mAttachment; private final Attachment sourceAttachment; private Attachment cachedResultAttachment; public AttachmentContentLoader(Context context, Attachment attachment) { super(context); mAttachment = attachment; if (attachment.state != LoadingState.METADATA) { throw new IllegalArgumentException("Attachment provided to content loader must be in METADATA state"); } sourceAttachment = attachment; } @Override protected void onStartLoading() { if (mAttachment.state == Attachment.LoadingState.COMPLETE) { deliverResult(mAttachment); if (cachedResultAttachment != null) { deliverResult(sourceAttachment); } if (takeContentChanged() || mAttachment.state == Attachment.LoadingState.METADATA) { if (takeContentChanged() || cachedResultAttachment == null) { forceLoad(); } } Loading @@ -55,7 +63,7 @@ public class AttachmentContentLoader extends AsyncTaskLoader<Attachment> { } SafeContentResolver safeContentResolver = SafeContentResolverCompat.newInstance(context); InputStream in = safeContentResolver.openInputStream(mAttachment.uri); InputStream in = safeContentResolver.openInputStream(sourceAttachment.uri); try { FileOutputStream out = new FileOutputStream(file); try { Loading @@ -67,17 +75,13 @@ public class AttachmentContentLoader extends AsyncTaskLoader<Attachment> { in.close(); } mAttachment.filename = file.getAbsolutePath(); mAttachment.state = Attachment.LoadingState.COMPLETE; return mAttachment; cachedResultAttachment = sourceAttachment.deriveWithLoadComplete(file.getAbsolutePath()); return cachedResultAttachment; } catch (IOException e) { e.printStackTrace(); Log.e(K9.LOG_TAG, "Error saving attachment!", e); } mAttachment.filename = null; mAttachment.state = Attachment.LoadingState.CANCELLED; return mAttachment; cachedResultAttachment = sourceAttachment.deriveWithLoadCancelled(); return cachedResultAttachment; } } k9mail/src/main/java/com/fsck/k9/activity/loader/AttachmentInfoLoader.java +16 −13 Original line number Diff line number Diff line Loading @@ -12,34 +12,41 @@ import android.util.Log; import com.fsck.k9.K9; import com.fsck.k9.activity.misc.Attachment; import com.fsck.k9.activity.misc.Attachment.LoadingState; import com.fsck.k9.mail.internet.MimeUtility; /** * Loader to fetch metadata of an attachment. */ public class AttachmentInfoLoader extends AsyncTaskLoader<Attachment> { private final Attachment mAttachment; private final Attachment sourceAttachment; private Attachment cachedResultAttachment; public AttachmentInfoLoader(Context context, Attachment attachment) { super(context); mAttachment = attachment; if (attachment.state != LoadingState.URI_ONLY) { throw new IllegalArgumentException("Attachment provided to metadata loader must be in URI_ONLY state"); } sourceAttachment = attachment; } @Override protected void onStartLoading() { if (mAttachment.state == Attachment.LoadingState.METADATA) { deliverResult(mAttachment); if (cachedResultAttachment != null) { deliverResult(cachedResultAttachment); } if (takeContentChanged() || mAttachment.state == Attachment.LoadingState.URI_ONLY) { if (takeContentChanged() || cachedResultAttachment == null) { forceLoad(); } } @Override public Attachment loadInBackground() { Uri uri = mAttachment.uri; String contentType = mAttachment.contentType; Uri uri = sourceAttachment.uri; String contentType = sourceAttachment.contentType; long size = -1; String name = null; Loading Loading @@ -91,11 +98,7 @@ public class AttachmentInfoLoader extends AsyncTaskLoader<Attachment> { } Log.v(K9.LOG_TAG, "new attachment.size: " + size); mAttachment.contentType = usableContentType; mAttachment.name = name; mAttachment.size = size; mAttachment.state = Attachment.LoadingState.METADATA; return mAttachment; cachedResultAttachment = sourceAttachment.deriveWithMetadataLoaded(usableContentType, name, size); return cachedResultAttachment; } } k9mail/src/main/java/com/fsck/k9/activity/misc/Attachment.java +67 −45 Original line number Diff line number Diff line Loading @@ -15,76 +15,103 @@ public class Attachment implements Parcelable { * * In most cases this will be a {@code content://}-URI. */ public Uri uri; public final Uri uri; /** * The current loading state. */ public LoadingState state; public final LoadingState state; /** * The ID of the loader that is used to load the metadata or contents. */ public int loaderId; public final int loaderId; /** * The content type of the attachment. * * Only valid when {@link #state} is {@link LoadingState#METADATA} or * {@link LoadingState#COMPLETE}. * Valid iff {@link #state} is {@link LoadingState#METADATA} or {@link LoadingState#COMPLETE}. */ public String contentType; public final String contentType; /** * The (file)name of the attachment. * * Only valid when {@link #state} is {@link LoadingState#METADATA} or * {@link LoadingState#COMPLETE}. * Valid iff {@link #state} is {@link LoadingState#METADATA} or {@link LoadingState#COMPLETE}. */ public String name; public final String name; /** * The size of the attachment. * * Only valid when {@link #state} is {@link LoadingState#METADATA} or * {@link LoadingState#COMPLETE}. * Valid iff {@link #state} is {@link LoadingState#METADATA} or {@link LoadingState#COMPLETE}. */ public long size; public final Long size; /** * The name of the temporary file containing the local copy of the attachment. * * Only valid when {@link #state} is {@link LoadingState#COMPLETE}. * Valid iff {@link #state} is {@link LoadingState#COMPLETE}. */ public String filename; public Attachment() {} public final String filename; public enum LoadingState { /** * The only thing we know about this attachment is {@link #uri}. */ URI_ONLY, /** * The metadata of this attachment have been loaded. * * {@link #contentType}, {@link #name}, and {@link #size} should contain usable values. */ METADATA, /** * The contents of the attachments have been copied to the temporary file {@link #filename}. */ COMPLETE, /** * Something went wrong while trying to fetch the attachment's contents. */ CANCELLED } private Attachment(Uri uri, LoadingState state, int loaderId, String contentType, String name, Long size, String filename) { this.uri = uri; this.state = state; this.loaderId = loaderId; this.contentType = contentType; this.name = name; this.size = size; this.filename = filename; } private Attachment(Parcel in) { uri = in.readParcelable(Uri.class.getClassLoader()); state = (LoadingState) in.readSerializable(); loaderId = in.readInt(); contentType = in.readString(); name = in.readString(); if (in.readInt() != 0) { size = in.readLong(); } else { size = null; } filename = in.readString(); } public static Attachment createAttachment(Uri uri, int loaderId, String contentType) { return new Attachment(uri, Attachment.LoadingState.URI_ONLY, loaderId, contentType, null, null, null); } public Attachment deriveWithMetadataLoaded(String usableContentType, String name, long size) { if (state != Attachment.LoadingState.URI_ONLY) { throw new IllegalStateException("deriveWithMetadataLoaded can only be called on a URI_ONLY attachment!"); } return new Attachment(uri, Attachment.LoadingState.METADATA, loaderId, usableContentType, name, size, null); } public Attachment deriveWithLoadCancelled() { if (state != Attachment.LoadingState.METADATA) { throw new IllegalStateException("deriveWitLoadCancelled can only be called on a METADATA attachment!"); } return new Attachment(uri, Attachment.LoadingState.CANCELLED, loaderId, contentType, name, size, null); } public Attachment deriveWithLoadComplete(String absolutePath) { if (state != Attachment.LoadingState.METADATA) { throw new IllegalStateException("deriveWithLoadComplete can only be called on a METADATA attachment!"); } return new Attachment(uri, Attachment.LoadingState.COMPLETE, loaderId, contentType, name, size, absolutePath); } // === Parcelable === @Override Loading @@ -99,7 +126,12 @@ public class Attachment implements Parcelable { dest.writeInt(loaderId); dest.writeString(contentType); dest.writeString(name); if (size != null) { dest.writeInt(1); dest.writeLong(size); } else { dest.writeInt(0); } dest.writeString(filename); } Loading @@ -115,14 +147,4 @@ public class Attachment implements Parcelable { return new Attachment[size]; } }; public Attachment(Parcel in) { uri = in.readParcelable(Uri.class.getClassLoader()); state = (LoadingState) in.readSerializable(); loaderId = in.readInt(); contentType = in.readString(); name = in.readString(); size = in.readLong(); filename = in.readString(); } } k9mail/src/test/java/com/fsck/k9/message/PgpMessageBuilderTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -376,7 +376,7 @@ public class PgpMessageBuilderTest { .setEnablePgpInline(true) .build(); pgpMessageBuilder.setCryptoStatus(cryptoStatus); pgpMessageBuilder.setAttachments(Collections.singletonList(new Attachment())); pgpMessageBuilder.setAttachments(Collections.singletonList(Attachment.createAttachment(null, 0, null))); Callback mockCallback = mock(Callback.class); pgpMessageBuilder.buildAsync(mockCallback); Loading @@ -393,7 +393,7 @@ public class PgpMessageBuilderTest { .setEnablePgpInline(true) .build(); pgpMessageBuilder.setCryptoStatus(cryptoStatus); pgpMessageBuilder.setAttachments(Collections.singletonList(new Attachment())); pgpMessageBuilder.setAttachments(Collections.singletonList(Attachment.createAttachment(null, 0, null))); Callback mockCallback = mock(Callback.class); pgpMessageBuilder.buildAsync(mockCallback); Loading Loading
k9mail/src/main/java/com/fsck/k9/activity/compose/AttachmentPresenter.java +2 −5 Original line number Diff line number Diff line Loading @@ -131,11 +131,8 @@ public class AttachmentPresenter { } public void addAttachment(Uri uri, String contentType) { Attachment attachment = new Attachment(); attachment.uri = uri; attachment.state = Attachment.LoadingState.URI_ONLY; attachment.contentType = contentType; attachment.loaderId = getNextFreeLoaderId(); int loaderId = getNextFreeLoaderId(); Attachment attachment = Attachment.createAttachment(uri, loaderId, contentType); if (attachments.containsKey(uri)) { return; Loading
k9mail/src/main/java/com/fsck/k9/activity/loader/AttachmentContentLoader.java +19 −15 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ import android.util.Log; import com.fsck.k9.K9; import com.fsck.k9.activity.misc.Attachment; import com.fsck.k9.activity.misc.Attachment.LoadingState; import de.cketti.safecontentresolver.SafeContentResolver; import de.cketti.safecontentresolver.SafeContentResolverCompat; import org.apache.commons.io.IOUtils; Loading @@ -24,20 +25,27 @@ import org.apache.commons.io.IOUtils; public class AttachmentContentLoader extends AsyncTaskLoader<Attachment> { private static final String FILENAME_PREFIX = "attachment"; private final Attachment mAttachment; private final Attachment sourceAttachment; private Attachment cachedResultAttachment; public AttachmentContentLoader(Context context, Attachment attachment) { super(context); mAttachment = attachment; if (attachment.state != LoadingState.METADATA) { throw new IllegalArgumentException("Attachment provided to content loader must be in METADATA state"); } sourceAttachment = attachment; } @Override protected void onStartLoading() { if (mAttachment.state == Attachment.LoadingState.COMPLETE) { deliverResult(mAttachment); if (cachedResultAttachment != null) { deliverResult(sourceAttachment); } if (takeContentChanged() || mAttachment.state == Attachment.LoadingState.METADATA) { if (takeContentChanged() || cachedResultAttachment == null) { forceLoad(); } } Loading @@ -55,7 +63,7 @@ public class AttachmentContentLoader extends AsyncTaskLoader<Attachment> { } SafeContentResolver safeContentResolver = SafeContentResolverCompat.newInstance(context); InputStream in = safeContentResolver.openInputStream(mAttachment.uri); InputStream in = safeContentResolver.openInputStream(sourceAttachment.uri); try { FileOutputStream out = new FileOutputStream(file); try { Loading @@ -67,17 +75,13 @@ public class AttachmentContentLoader extends AsyncTaskLoader<Attachment> { in.close(); } mAttachment.filename = file.getAbsolutePath(); mAttachment.state = Attachment.LoadingState.COMPLETE; return mAttachment; cachedResultAttachment = sourceAttachment.deriveWithLoadComplete(file.getAbsolutePath()); return cachedResultAttachment; } catch (IOException e) { e.printStackTrace(); Log.e(K9.LOG_TAG, "Error saving attachment!", e); } mAttachment.filename = null; mAttachment.state = Attachment.LoadingState.CANCELLED; return mAttachment; cachedResultAttachment = sourceAttachment.deriveWithLoadCancelled(); return cachedResultAttachment; } }
k9mail/src/main/java/com/fsck/k9/activity/loader/AttachmentInfoLoader.java +16 −13 Original line number Diff line number Diff line Loading @@ -12,34 +12,41 @@ import android.util.Log; import com.fsck.k9.K9; import com.fsck.k9.activity.misc.Attachment; import com.fsck.k9.activity.misc.Attachment.LoadingState; import com.fsck.k9.mail.internet.MimeUtility; /** * Loader to fetch metadata of an attachment. */ public class AttachmentInfoLoader extends AsyncTaskLoader<Attachment> { private final Attachment mAttachment; private final Attachment sourceAttachment; private Attachment cachedResultAttachment; public AttachmentInfoLoader(Context context, Attachment attachment) { super(context); mAttachment = attachment; if (attachment.state != LoadingState.URI_ONLY) { throw new IllegalArgumentException("Attachment provided to metadata loader must be in URI_ONLY state"); } sourceAttachment = attachment; } @Override protected void onStartLoading() { if (mAttachment.state == Attachment.LoadingState.METADATA) { deliverResult(mAttachment); if (cachedResultAttachment != null) { deliverResult(cachedResultAttachment); } if (takeContentChanged() || mAttachment.state == Attachment.LoadingState.URI_ONLY) { if (takeContentChanged() || cachedResultAttachment == null) { forceLoad(); } } @Override public Attachment loadInBackground() { Uri uri = mAttachment.uri; String contentType = mAttachment.contentType; Uri uri = sourceAttachment.uri; String contentType = sourceAttachment.contentType; long size = -1; String name = null; Loading Loading @@ -91,11 +98,7 @@ public class AttachmentInfoLoader extends AsyncTaskLoader<Attachment> { } Log.v(K9.LOG_TAG, "new attachment.size: " + size); mAttachment.contentType = usableContentType; mAttachment.name = name; mAttachment.size = size; mAttachment.state = Attachment.LoadingState.METADATA; return mAttachment; cachedResultAttachment = sourceAttachment.deriveWithMetadataLoaded(usableContentType, name, size); return cachedResultAttachment; } }
k9mail/src/main/java/com/fsck/k9/activity/misc/Attachment.java +67 −45 Original line number Diff line number Diff line Loading @@ -15,76 +15,103 @@ public class Attachment implements Parcelable { * * In most cases this will be a {@code content://}-URI. */ public Uri uri; public final Uri uri; /** * The current loading state. */ public LoadingState state; public final LoadingState state; /** * The ID of the loader that is used to load the metadata or contents. */ public int loaderId; public final int loaderId; /** * The content type of the attachment. * * Only valid when {@link #state} is {@link LoadingState#METADATA} or * {@link LoadingState#COMPLETE}. * Valid iff {@link #state} is {@link LoadingState#METADATA} or {@link LoadingState#COMPLETE}. */ public String contentType; public final String contentType; /** * The (file)name of the attachment. * * Only valid when {@link #state} is {@link LoadingState#METADATA} or * {@link LoadingState#COMPLETE}. * Valid iff {@link #state} is {@link LoadingState#METADATA} or {@link LoadingState#COMPLETE}. */ public String name; public final String name; /** * The size of the attachment. * * Only valid when {@link #state} is {@link LoadingState#METADATA} or * {@link LoadingState#COMPLETE}. * Valid iff {@link #state} is {@link LoadingState#METADATA} or {@link LoadingState#COMPLETE}. */ public long size; public final Long size; /** * The name of the temporary file containing the local copy of the attachment. * * Only valid when {@link #state} is {@link LoadingState#COMPLETE}. * Valid iff {@link #state} is {@link LoadingState#COMPLETE}. */ public String filename; public Attachment() {} public final String filename; public enum LoadingState { /** * The only thing we know about this attachment is {@link #uri}. */ URI_ONLY, /** * The metadata of this attachment have been loaded. * * {@link #contentType}, {@link #name}, and {@link #size} should contain usable values. */ METADATA, /** * The contents of the attachments have been copied to the temporary file {@link #filename}. */ COMPLETE, /** * Something went wrong while trying to fetch the attachment's contents. */ CANCELLED } private Attachment(Uri uri, LoadingState state, int loaderId, String contentType, String name, Long size, String filename) { this.uri = uri; this.state = state; this.loaderId = loaderId; this.contentType = contentType; this.name = name; this.size = size; this.filename = filename; } private Attachment(Parcel in) { uri = in.readParcelable(Uri.class.getClassLoader()); state = (LoadingState) in.readSerializable(); loaderId = in.readInt(); contentType = in.readString(); name = in.readString(); if (in.readInt() != 0) { size = in.readLong(); } else { size = null; } filename = in.readString(); } public static Attachment createAttachment(Uri uri, int loaderId, String contentType) { return new Attachment(uri, Attachment.LoadingState.URI_ONLY, loaderId, contentType, null, null, null); } public Attachment deriveWithMetadataLoaded(String usableContentType, String name, long size) { if (state != Attachment.LoadingState.URI_ONLY) { throw new IllegalStateException("deriveWithMetadataLoaded can only be called on a URI_ONLY attachment!"); } return new Attachment(uri, Attachment.LoadingState.METADATA, loaderId, usableContentType, name, size, null); } public Attachment deriveWithLoadCancelled() { if (state != Attachment.LoadingState.METADATA) { throw new IllegalStateException("deriveWitLoadCancelled can only be called on a METADATA attachment!"); } return new Attachment(uri, Attachment.LoadingState.CANCELLED, loaderId, contentType, name, size, null); } public Attachment deriveWithLoadComplete(String absolutePath) { if (state != Attachment.LoadingState.METADATA) { throw new IllegalStateException("deriveWithLoadComplete can only be called on a METADATA attachment!"); } return new Attachment(uri, Attachment.LoadingState.COMPLETE, loaderId, contentType, name, size, absolutePath); } // === Parcelable === @Override Loading @@ -99,7 +126,12 @@ public class Attachment implements Parcelable { dest.writeInt(loaderId); dest.writeString(contentType); dest.writeString(name); if (size != null) { dest.writeInt(1); dest.writeLong(size); } else { dest.writeInt(0); } dest.writeString(filename); } Loading @@ -115,14 +147,4 @@ public class Attachment implements Parcelable { return new Attachment[size]; } }; public Attachment(Parcel in) { uri = in.readParcelable(Uri.class.getClassLoader()); state = (LoadingState) in.readSerializable(); loaderId = in.readInt(); contentType = in.readString(); name = in.readString(); size = in.readLong(); filename = in.readString(); } }
k9mail/src/test/java/com/fsck/k9/message/PgpMessageBuilderTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -376,7 +376,7 @@ public class PgpMessageBuilderTest { .setEnablePgpInline(true) .build(); pgpMessageBuilder.setCryptoStatus(cryptoStatus); pgpMessageBuilder.setAttachments(Collections.singletonList(new Attachment())); pgpMessageBuilder.setAttachments(Collections.singletonList(Attachment.createAttachment(null, 0, null))); Callback mockCallback = mock(Callback.class); pgpMessageBuilder.buildAsync(mockCallback); Loading @@ -393,7 +393,7 @@ public class PgpMessageBuilderTest { .setEnablePgpInline(true) .build(); pgpMessageBuilder.setCryptoStatus(cryptoStatus); pgpMessageBuilder.setAttachments(Collections.singletonList(new Attachment())); pgpMessageBuilder.setAttachments(Collections.singletonList(Attachment.createAttachment(null, 0, null))); Callback mockCallback = mock(Callback.class); pgpMessageBuilder.buildAsync(mockCallback); Loading