[android] Let AttachmentCreator return same LiveData after configuration changes

parent 73580916
...@@ -29,7 +29,6 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -29,7 +29,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Logger; import java.util.logging.Logger;
import static java.util.Objects.requireNonNull;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
...@@ -46,6 +45,7 @@ public class AttachmentCreator { ...@@ -46,6 +45,7 @@ public class AttachmentCreator {
private final MessagingManager messagingManager; private final MessagingManager messagingManager;
private final AttachmentRetriever retriever; private final AttachmentRetriever retriever;
// store unsent items separately, as LiveData might not return latest value
private final Map<Uri, AttachmentItem> unsentItems = private final Map<Uri, AttachmentItem> unsentItems =
new ConcurrentHashMap<>(); new ConcurrentHashMap<>();
private final Map<Uri, MutableLiveData<AttachmentItemResult>> private final Map<Uri, MutableLiveData<AttachmentItemResult>>
...@@ -66,32 +66,38 @@ public class AttachmentCreator { ...@@ -66,32 +66,38 @@ public class AttachmentCreator {
@UiThread @UiThread
public AttachmentResult storeAttachments(GroupId groupId, public AttachmentResult storeAttachments(GroupId groupId,
Collection<Uri> uris) { Collection<Uri> uris, boolean restart) {
if (task != null && !isStoring()) throw new AssertionError();
List<LiveData<AttachmentItemResult>> itemResults = new ArrayList<>(); List<LiveData<AttachmentItemResult>> itemResults = new ArrayList<>();
List<Uri> urisToStore = new ArrayList<>(); if (restart) {
for (Uri uri : uris) { // This can happen due to configuration changes.
MutableLiveData<AttachmentItemResult> liveData = // So don't create new attachments, if we have (or creating) them.
new MutableLiveData<>(); // Instead, re-subscribe to the existing LiveData.
itemResults.add(liveData); if (task == null || isNotStoring()) throw new AssertionError();
liveDataResult.put(uri, liveData); for (Uri uri : uris) {
if (unsentItems.containsKey(uri)) { // We don't want to expose mutable(!) LiveData
// This can happen due to configuration changes. LiveData<AttachmentItemResult> liveData =
// So don't create a new attachment, if we have one already. liveDataResult.get(uri);
AttachmentItem item = requireNonNull(unsentItems.get(uri)); if (liveData == null) throw new IllegalStateException();
AttachmentItemResult result = itemResults.add(liveData);
new AttachmentItemResult(uri, item); }
liveData.setValue(result); if (liveDataFinished == null) throw new IllegalStateException();
} else { } else {
if (task != null && isNotStoring()) throw new AssertionError();
List<Uri> urisToStore = new ArrayList<>();
for (Uri uri : uris) {
urisToStore.add(uri); urisToStore.add(uri);
MutableLiveData<AttachmentItemResult> liveData =
new MutableLiveData<>();
liveDataResult.put(uri, liveData);
itemResults.add(liveData);
} }
boolean needsSize = uris.size() == 1;
task = new AttachmentCreationTask(messagingManager,
app.getContentResolver(), this, groupId, urisToStore,
needsSize);
ioExecutor.execute(() -> task.storeAttachments());
liveDataFinished = new MutableLiveData<>();
} }
boolean needsSize = uris.size() == 1;
task = new AttachmentCreationTask(messagingManager,
app.getContentResolver(), this, groupId, urisToStore,
needsSize);
ioExecutor.execute(() -> task.storeAttachments());
liveDataFinished = new MutableLiveData<>();
return new AttachmentResult(itemResults, liveDataFinished); return new AttachmentResult(itemResults, liveDataFinished);
} }
...@@ -185,6 +191,7 @@ public class AttachmentCreator { ...@@ -185,6 +191,7 @@ public class AttachmentCreator {
@UiThread @UiThread
public void deleteUnsentAttachments() { public void deleteUnsentAttachments() {
// Make a copy for the IoExecutor as we clear the unsentItems soon
List<AttachmentItem> itemsToDelete = List<AttachmentItem> itemsToDelete =
new ArrayList<>(unsentItems.values()); new ArrayList<>(unsentItems.values());
ioExecutor.execute(() -> { ioExecutor.execute(() -> {
...@@ -198,8 +205,8 @@ public class AttachmentCreator { ...@@ -198,8 +205,8 @@ public class AttachmentCreator {
}); });
} }
private boolean isStoring() { private boolean isNotStoring() {
return liveDataFinished != null; return liveDataFinished == null;
} }
} }
...@@ -11,7 +11,7 @@ import java.util.List; ...@@ -11,7 +11,7 @@ import java.util.List;
@UiThread @UiThread
public interface AttachmentManager { public interface AttachmentManager {
AttachmentResult storeAttachments(Collection<Uri> uri); AttachmentResult storeAttachments(Collection<Uri> uri, boolean restart);
List<AttachmentHeader> getAttachmentHeadersForSending(); List<AttachmentHeader> getAttachmentHeadersForSending();
......
...@@ -150,8 +150,7 @@ public class ConversationViewModel extends AndroidViewModel ...@@ -150,8 +150,7 @@ public class ConversationViewModel extends AndroidViewModel
contact.postValue(c); contact.postValue(c);
logDuration(LOG, "Loading contact", start); logDuration(LOG, "Loading contact", start);
start = now(); start = now();
messagingGroupId = messagingGroupId = messagingManager.getContactGroup(c).getId();
messagingManager.getConversationId(contactId);
logDuration(LOG, "Load conversation GroupId", start); logDuration(LOG, "Load conversation GroupId", start);
start = now(); start = now();
checkFeaturesAndOnboarding(contactId); checkFeaturesAndOnboarding(contactId);
...@@ -197,10 +196,11 @@ public class ConversationViewModel extends AndroidViewModel ...@@ -197,10 +196,11 @@ public class ConversationViewModel extends AndroidViewModel
@Override @Override
@UiThread @UiThread
public AttachmentResult storeAttachments(Collection<Uri> uris) { public AttachmentResult storeAttachments(Collection<Uri> uris,
boolean restart) {
GroupId groupId = messagingGroupId; GroupId groupId = messagingGroupId;
if (groupId == null) throw new IllegalStateException(); if (groupId == null) throw new IllegalStateException();
return attachmentCreator.storeAttachments(groupId, uris); return attachmentCreator.storeAttachments(groupId, uris, restart);
} }
@Override @Override
......
...@@ -153,17 +153,17 @@ public class TextAttachmentController extends TextSendController ...@@ -153,17 +153,17 @@ public class TextAttachmentController extends TextSendController
if (loadingUris || !imageUris.isEmpty()) throw new AssertionError(); if (loadingUris || !imageUris.isEmpty()) throw new AssertionError();
if (resultData.getData() != null) { if (resultData.getData() != null) {
imageUris.add(resultData.getData()); imageUris.add(resultData.getData());
onNewUris(); onNewUris(false);
} else if (SDK_INT >= 18 && resultData.getClipData() != null) { } else if (SDK_INT >= 18 && resultData.getClipData() != null) {
ClipData clipData = resultData.getClipData(); ClipData clipData = resultData.getClipData();
for (int i = 0; i < clipData.getItemCount(); i++) { for (int i = 0; i < clipData.getItemCount(); i++) {
imageUris.add(clipData.getItemAt(i).getUri()); imageUris.add(clipData.getItemAt(i).getUri());
} }
onNewUris(); onNewUris(false);
} }
} }
private void onNewUris() { private void onNewUris(boolean restart) {
if (imageUris.isEmpty()) return; if (imageUris.isEmpty()) return;
if (loadingUris) throw new AssertionError(); if (loadingUris) throw new AssertionError();
loadingUris = true; loadingUris = true;
...@@ -172,7 +172,8 @@ public class TextAttachmentController extends TextSendController ...@@ -172,7 +172,8 @@ public class TextAttachmentController extends TextSendController
List<ImagePreviewItem> items = ImagePreviewItem.fromUris(imageUris); List<ImagePreviewItem> items = ImagePreviewItem.fromUris(imageUris);
imagePreview.showPreview(items); imagePreview.showPreview(items);
// store attachments and show preview when successful // store attachments and show preview when successful
AttachmentResult result = attachmentManager.storeAttachments(imageUris); AttachmentResult result =
attachmentManager.storeAttachments(imageUris, restart);
for (LiveData<AttachmentItemResult> liveData : result for (LiveData<AttachmentItemResult> liveData : result
.getItemResults()) { .getItemResults()) {
onLiveDataReturned(liveData); onLiveDataReturned(liveData);
...@@ -240,7 +241,7 @@ public class TextAttachmentController extends TextSendController ...@@ -240,7 +241,7 @@ public class TextAttachmentController extends TextSendController
SavedState state = (SavedState) inState; SavedState state = (SavedState) inState;
if (!imageUris.isEmpty()) throw new AssertionError(); if (!imageUris.isEmpty()) throw new AssertionError();
if (state.imageUris != null) imageUris.addAll(state.imageUris); if (state.imageUris != null) imageUris.addAll(state.imageUris);
onNewUris(); onNewUris(true);
return state.getSuperState(); return state.getSuperState();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment