kopia lustrzana https://github.com/ryukoposting/Signal-Android
Enable Media Preview to respond to media changes.
rodzic
1fe38f5ed1
commit
3c069fb588
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) };
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
Ładowanie…
Reference in New Issue