Enable Media Preview to respond to media changes.

fork-5.53.8
Cody Henthorne 2020-07-09 12:19:58 -04:00 zatwierdzone przez Greyson Parrelli
rodzic 1fe38f5ed1
commit 3c069fb588
8 zmienionych plików z 139 dodań i 19 usunięć

Wyświetl plik

@ -20,10 +20,12 @@ import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@ -73,6 +75,7 @@ import org.thoughtcrime.securesms.util.SaveAttachmentTask.Attachment;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
/**
* Activity for displaying media attachments in-app
@ -117,17 +120,20 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
private boolean showThread;
private MediaDatabase.Sorting sorting;
private @Nullable Cursor cursor = null;
public static @NonNull Intent intentFromMediaRecord(@NonNull Context context,
@NonNull MediaRecord mediaRecord,
boolean leftIsRecent)
{
DatabaseAttachment attachment = Objects.requireNonNull(mediaRecord.getAttachment());
Intent intent = new Intent(context, MediaPreviewActivity.class);
intent.putExtra(MediaPreviewActivity.THREAD_ID_EXTRA, mediaRecord.getThreadId());
intent.putExtra(MediaPreviewActivity.DATE_EXTRA, mediaRecord.getDate());
intent.putExtra(MediaPreviewActivity.SIZE_EXTRA, mediaRecord.getAttachment().getSize());
intent.putExtra(MediaPreviewActivity.CAPTION_EXTRA, mediaRecord.getAttachment().getCaption());
intent.putExtra(MediaPreviewActivity.SIZE_EXTRA, attachment.getSize());
intent.putExtra(MediaPreviewActivity.CAPTION_EXTRA, attachment.getCaption());
intent.putExtra(MediaPreviewActivity.LEFT_IS_RECENT_EXTRA, leftIsRecent);
intent.setDataAndType(mediaRecord.getAttachment().getDataUri(), mediaRecord.getContentType());
intent.setDataAndType(attachment.getDataUri(), mediaRecord.getContentType());
return intent;
}
@ -228,6 +234,15 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
restartItem = cleanupMedia();
}
@Override
protected void onDestroy() {
if (cursor != null) {
cursor.close();
cursor = null;
}
super.onDestroy();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
@ -344,6 +359,7 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
mediaPager.removeAllViews();
mediaPager.setAdapter(null);
viewModel.setCursor(this, null, leftIsRecent);
return restartItem;
}
@ -475,19 +491,46 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
@Override
public void onLoadFinished(@NonNull Loader<Pair<Cursor, Integer>> loader, @Nullable Pair<Cursor, Integer> data) {
if (data != null) {
@SuppressWarnings("ConstantConditions")
CursorPagerAdapter adapter = new CursorPagerAdapter(getSupportFragmentManager(),this, data.first, data.second, leftIsRecent);
if (data.first == cursor) {
return;
}
if (cursor != null) {
cursor.close();
}
cursor = Objects.requireNonNull(data.first);
int mediaPosition = Objects.requireNonNull(data.second);
CursorPagerAdapter adapter = new CursorPagerAdapter(getSupportFragmentManager(),this, cursor, mediaPosition, leftIsRecent);
mediaPager.setAdapter(adapter);
adapter.setActive(true);
viewModel.setCursor(this, data.first, leftIsRecent);
viewModel.setCursor(this, cursor, leftIsRecent);
int item = restartItem >= 0 ? restartItem : data.second;
int item = restartItem >= 0 ? restartItem : mediaPosition;
mediaPager.setCurrentItem(item);
if (item == 0) {
viewPagerListener.onPageSelected(0);
}
cursor.registerContentObserver(new ContentObserver(new Handler(getMainLooper())) {
@Override
public void onChange(boolean selfChange) {
onMediaChange();
}
});
} else {
mediaNotAvailable();
}
}
private void onMediaChange() {
MediaItemAdapter adapter = (MediaItemAdapter) mediaPager.getAdapter();
if (adapter != null) {
adapter.checkMedia(mediaPager.getCurrentItem());
}
}
@ -502,6 +545,12 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
return true;
}
@Override
public void mediaNotAvailable() {
Toast.makeText(this, R.string.MediaPreviewActivity_media_no_longer_available, Toast.LENGTH_LONG).show();
finish();
}
private void toggleUiVisibility() {
int systemUiVisibility = getWindow().getDecorView().getSystemUiVisibility();
if ((systemUiVisibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0) {
@ -621,6 +670,11 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
public boolean hasFragmentFor(int position) {
return mediaPreviewFragment != null;
}
@Override
public void checkMedia(int currentItem) {
}
}
private static void anchorMarginsToBottomInsets(@NonNull View viewToAnchor) {
@ -712,7 +766,7 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
cursor.moveToPosition(cursorPosition);
MediaDatabase.MediaRecord mediaRecord = MediaDatabase.MediaRecord.from(context, cursor);
DatabaseAttachment attachment = mediaRecord.getAttachment();
DatabaseAttachment attachment = Objects.requireNonNull(mediaRecord.getAttachment());
MediaPreviewFragment fragment = MediaPreviewFragment.newInstance(attachment, autoPlay);
mediaFragments.put(position, fragment);
@ -734,16 +788,15 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
public MediaItem getMediaItemFor(int position) {
cursor.moveToPosition(getCursorPosition(position));
MediaRecord mediaRecord = MediaRecord.from(context, cursor);
RecipientId recipientId = mediaRecord.getRecipientId();
RecipientId threadRecipientId = mediaRecord.getThreadRecipientId();
if (mediaRecord.getAttachment().getDataUri() == null) throw new AssertionError();
MediaRecord mediaRecord = MediaRecord.from(context, cursor);
DatabaseAttachment attachment = Objects.requireNonNull(mediaRecord.getAttachment());
RecipientId recipientId = mediaRecord.getRecipientId();
RecipientId threadRecipientId = mediaRecord.getThreadRecipientId();
return new MediaItem(Recipient.live(recipientId).get(),
Recipient.live(threadRecipientId).get(),
mediaRecord.getAttachment(),
mediaRecord.getAttachment().getDataUri(),
attachment,
Objects.requireNonNull(attachment.getDataUri()),
mediaRecord.getContentType(),
mediaRecord.getDate(),
mediaRecord.isOutgoing());
@ -767,6 +820,14 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
return mediaFragments.containsKey(position);
}
@Override
public void checkMedia(int position) {
MediaPreviewFragment fragment = mediaFragments.get(position);
if (fragment != null) {
fragment.checkMediaStillAvailable();
}
}
private int getCursorPosition(int position) {
if (leftIsRecent) return position;
else return cursor.getCount() - 1 - position;
@ -805,5 +866,6 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
void pause(int position);
@Nullable View getPlaybackControls(int position);
boolean hasFragmentFor(int position);
void checkMedia(int currentItem);
}
}

Wyświetl plik

@ -309,6 +309,23 @@ public class AttachmentDatabase extends Database {
}
}
public boolean hasAttachment(@NonNull AttachmentId id) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
try (Cursor cursor = database.query(TABLE_NAME,
new String[]{ROW_ID, UNIQUE_ID},
PART_ID_WHERE,
id.toStrings(),
null,
null,
null)) {
if (cursor != null && cursor.getCount() > 0) {
return true;
}
}
return false;
}
public boolean hasAttachmentFilesForMessage(long mmsId) {
String selection = MMS_ID + " = ? AND (" + DATA + " NOT NULL OR " + TRANSFER_STATE + " != ?)";
String[] args = new String[] { String.valueOf(mmsId), String.valueOf(TRANSFER_PROGRESS_DONE) };

Wyświetl plik

@ -67,6 +67,10 @@ public abstract class Database {
cursor.setNotificationUri(context.getContentResolver(), DatabaseContentProviders.Conversation.getUriForThread(threadId));
}
protected void setNotifyConversationListeners(Cursor cursor) {
cursor.setNotificationUri(context.getContentResolver(), DatabaseContentProviders.Conversation.getUriForAllThreads());
}
protected void setNotifyVerboseConversationListeners(Cursor cursor, long threadId) {
cursor.setNotificationUri(context.getContentResolver(), DatabaseContentProviders.Conversation.getVerboseUriForThread(threadId));
}

Wyświetl plik

@ -27,6 +27,10 @@ public class DatabaseContentProviders {
public static Uri getVerboseUriForThread(long threadId) {
return Uri.parse(CONTENT_URI_STRING + "verbose/" + threadId);
}
public static Uri getUriForAllThreads() {
return Uri.parse(CONTENT_URI_STRING);
}
}
public static class Attachment extends NoopContentProvider {

Wyświetl plik

@ -89,11 +89,19 @@ public class MediaDatabase extends Database {
}
public @NonNull Cursor getGalleryMediaForThread(long threadId, @NonNull Sorting sorting) {
return getGalleryMediaForThread(threadId, sorting, false);
}
public @NonNull Cursor getGalleryMediaForThread(long threadId, @NonNull Sorting sorting, boolean listenToAllThreads) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
String query = sorting.applyToQuery(applyEqualityOperator(threadId, GALLERY_MEDIA_QUERY));
String[] args = {threadId + ""};
Cursor cursor = database.rawQuery(query, args);
setNotifyConversationListeners(cursor, threadId);
if (listenToAllThreads) {
setNotifyConversationListeners(cursor);
} else {
setNotifyConversationListeners(cursor, threadId);
}
return cursor;
}

Wyświetl plik

@ -11,6 +11,7 @@ import androidx.core.util.Pair;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MediaDatabase;
import org.thoughtcrime.securesms.database.MediaDatabase.Sorting;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.util.AsyncLoader;
@ -35,7 +36,7 @@ public final class PagingMediaLoader extends AsyncLoader<Pair<Cursor, Integer>>
@Override
public @Nullable Pair<Cursor, Integer> loadInBackground() {
Cursor cursor = DatabaseFactory.getMediaDatabase(getContext()).getGalleryMediaForThread(threadId, sorting);
Cursor cursor = DatabaseFactory.getMediaDatabase(getContext()).getGalleryMediaForThread(threadId, sorting, threadId == MediaDatabase.ALL_THREADS);
while (cursor.moveToNext()) {
AttachmentId attachmentId = new AttachmentId(cursor.getLong(cursor.getColumnIndexOrThrow(AttachmentDatabase.ROW_ID)), cursor.getLong(cursor.getColumnIndexOrThrow(AttachmentDatabase.UNIQUE_ID)));

Wyświetl plik

@ -10,7 +10,13 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.mms.PartUriParser;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
import java.util.Objects;
public abstract class MediaPreviewFragment extends Fragment {
@ -19,7 +25,8 @@ public abstract class MediaPreviewFragment extends Fragment {
static final String DATA_CONTENT_TYPE = "DATA_CONTENT_TYPE";
static final String AUTO_PLAY = "AUTO_PLAY";
protected Events events;
private AttachmentId attachmentId;
protected Events events;
public static MediaPreviewFragment newInstance(@NonNull Attachment attachment, boolean autoPlay) {
return newInstance(attachment.getDataUri(), attachment.getContentType(), attachment.getSize(), autoPlay);
@ -60,6 +67,12 @@ public abstract class MediaPreviewFragment extends Fragment {
events = (Events) context;
}
@Override
public void onResume() {
super.onResume();
checkMediaStillAvailable();
}
public void cleanUp() {
}
@ -70,8 +83,18 @@ public abstract class MediaPreviewFragment extends Fragment {
return null;
}
public interface Events {
public void checkMediaStillAvailable() {
if (attachmentId == null) {
attachmentId = new PartUriParser(Objects.requireNonNull(requireArguments().getParcelable(DATA_URI))).getPartId();
}
SimpleTask.run(getViewLifecycleOwner().getLifecycle(),
() -> DatabaseFactory.getAttachmentDatabase(requireContext()).hasAttachment(attachmentId),
hasAttachment -> { if (!hasAttachment) events.mediaNotAvailable(); });
}
public interface Events {
boolean singleTapOnMedia();
void mediaNotAvailable();
}
}

Wyświetl plik

@ -1271,6 +1271,7 @@
<string name="MediaPreviewActivity_media_delete_confirmation_title">Delete message?</string>
<string name="MediaPreviewActivity_media_delete_confirmation_message">This will permanently delete this message.</string>
<string name="MediaPreviewActivity_s_to_s">%1$s to %2$s</string>
<string name="MediaPreviewActivity_media_no_longer_available">Media no longer available.</string>
<!-- MessageNotifier -->
<string name="MessageNotifier_d_new_messages_in_d_conversations">%1$d new messages in %2$d conversations</string>