mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-27 06:29:54 +00:00
Close Cursor in Media Preview V2.
This commit is contained in:
@@ -579,7 +579,7 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mediaNotAvailable();
|
||||
onMediaNotAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,7 +595,7 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mediaNotAvailable() {
|
||||
public void onMediaNotAvailable() {
|
||||
Toast.makeText(this, R.string.MediaPreviewActivity_media_no_longer_available, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -93,10 +93,6 @@ 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.getSignalReadableDatabase();
|
||||
String query = sorting.applyToQuery(applyEqualityOperator(threadId, GALLERY_MEDIA_QUERY));
|
||||
String[] args = {threadId + ""};
|
||||
|
||||
@@ -46,7 +46,7 @@ public final class PagingMediaLoader extends AsyncLoader<Pair<Cursor, Integer>>
|
||||
public @Nullable Pair<Cursor, Integer> loadInBackground() {
|
||||
ApplicationDependencies.getDatabaseObserver().registerAttachmentObserver(observer);
|
||||
|
||||
Cursor cursor = SignalDatabase.media().getGalleryMediaForThread(threadId, sorting, threadId == MediaDatabase.ALL_THREADS);
|
||||
Cursor cursor = SignalDatabase.media().getGalleryMediaForThread(threadId, sorting);
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
AttachmentId attachmentId = new AttachmentId(cursor.getLong(cursor.getColumnIndexOrThrow(AttachmentDatabase.ROW_ID)), cursor.getLong(cursor.getColumnIndexOrThrow(AttachmentDatabase.UNIQUE_ID)));
|
||||
|
||||
@@ -96,12 +96,12 @@ public abstract class MediaPreviewFragment extends Fragment {
|
||||
|
||||
SimpleTask.run(getViewLifecycleOwner().getLifecycle(),
|
||||
() -> SignalDatabase.attachments().hasAttachment(attachmentId),
|
||||
hasAttachment -> { if (!hasAttachment) events.mediaNotAvailable(); });
|
||||
hasAttachment -> { if (!hasAttachment) events.onMediaNotAvailable(); });
|
||||
}
|
||||
|
||||
public interface Events {
|
||||
boolean singleTapOnMedia();
|
||||
void mediaNotAvailable();
|
||||
void onMediaNotAvailable();
|
||||
void onMediaReady();
|
||||
default @Nullable VideoControlsDelegate getVideoControlsDelegate() {
|
||||
return null;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.thoughtcrime.securesms.mediapreview
|
||||
|
||||
import android.net.Uri
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
@@ -11,7 +10,6 @@ import org.thoughtcrime.securesms.database.AttachmentDatabase
|
||||
import org.thoughtcrime.securesms.database.MediaDatabase
|
||||
import org.thoughtcrime.securesms.database.MediaDatabase.Sorting
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.media
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority
|
||||
|
||||
/**
|
||||
* Repository for accessing the attachments in the encrypted database.
|
||||
@@ -28,45 +26,43 @@ class MediaPreviewRepository {
|
||||
* @param sorting the ordering of the results
|
||||
* @param limit the maximum quantity of the results
|
||||
*/
|
||||
fun getAttachments(startingUri: Uri, threadId: Long, sorting: Sorting, limit: Int = 500): Flowable<Result> {
|
||||
fun getAttachments(startingAttachmentId: AttachmentId, threadId: Long, sorting: Sorting, limit: Int = 500): Flowable<Result> {
|
||||
return Single.fromCallable {
|
||||
val cursor = media.getGalleryMediaForThread(threadId, sorting)
|
||||
|
||||
val acc = mutableListOf<MediaDatabase.MediaRecord>()
|
||||
var initialPosition = 0
|
||||
var attachmentUri: Uri? = null
|
||||
while (cursor.moveToNext()) {
|
||||
val attachmentId = AttachmentId(cursor.requireLong(AttachmentDatabase.ROW_ID), cursor.requireLong(AttachmentDatabase.UNIQUE_ID))
|
||||
attachmentUri = PartAuthority.getAttachmentDataUri(attachmentId)
|
||||
if (attachmentUri == startingUri) {
|
||||
initialPosition = cursor.position
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (attachmentUri == startingUri) {
|
||||
val frontLimit: Int = limit / 2
|
||||
if (initialPosition < frontLimit) {
|
||||
cursor.moveToFirst()
|
||||
} else {
|
||||
cursor.move(-frontLimit)
|
||||
}
|
||||
for (i in 0..limit) {
|
||||
val element = MediaDatabase.MediaRecord.from(cursor)
|
||||
if (element != null) {
|
||||
acc.add(element)
|
||||
}
|
||||
if (!cursor.isLast) {
|
||||
cursor.moveToNext()
|
||||
} else {
|
||||
media.getGalleryMediaForThread(threadId, sorting).use { cursor ->
|
||||
val mediaRecords = mutableListOf<MediaDatabase.MediaRecord>()
|
||||
var startingRow = -1
|
||||
while (cursor.moveToNext()) {
|
||||
if (startingAttachmentId.rowId == cursor.requireLong(AttachmentDatabase.ROW_ID) &&
|
||||
startingAttachmentId.uniqueId == cursor.requireLong(AttachmentDatabase.UNIQUE_ID)
|
||||
) {
|
||||
startingRow = cursor.position
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Could not find $startingUri in thread $threadId")
|
||||
|
||||
var itemPosition = -1
|
||||
if (startingRow >= 0) {
|
||||
val frontLimit: Int = limit / 2
|
||||
val windowStart = if (startingRow >= frontLimit) startingRow - frontLimit else 0
|
||||
|
||||
itemPosition = startingRow - windowStart
|
||||
|
||||
cursor.moveToPosition(windowStart)
|
||||
|
||||
for (i in 0..limit) {
|
||||
val element = MediaDatabase.MediaRecord.from(cursor)
|
||||
if (element != null) {
|
||||
mediaRecords.add(element)
|
||||
}
|
||||
if (!cursor.moveToNext()) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
Result(itemPosition, mediaRecords.toList())
|
||||
}
|
||||
Result(initialPosition, acc.toList())
|
||||
}.subscribeOn(Schedulers.io()).toFlowable()
|
||||
}
|
||||
|
||||
data class Result(val initialPosition: Int, val records: List<MediaDatabase.MediaRecord>)
|
||||
}
|
||||
|
||||
@@ -142,10 +142,14 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
|
||||
}
|
||||
viewModel.setShowThread(args.showThread)
|
||||
val sorting = MediaDatabase.Sorting.values()[args.sorting]
|
||||
viewModel.fetchAttachments(args.initialMediaUri, args.threadId, sorting)
|
||||
viewModel.fetchAttachments(PartAuthority.requireAttachmentId(args.initialMediaUri), args.threadId, sorting)
|
||||
}
|
||||
|
||||
private fun bindCurrentState(currentState: MediaPreviewV2State) {
|
||||
if (currentState.position == -1 && currentState.mediaRecords.isEmpty()) {
|
||||
onMediaNotAvailable()
|
||||
return
|
||||
}
|
||||
when (currentState.loadState) {
|
||||
MediaPreviewV2State.LoadState.READY -> bindReadyState(currentState)
|
||||
MediaPreviewV2State.LoadState.LOADED -> {
|
||||
@@ -159,7 +163,7 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
|
||||
private fun bindReadyState(currentState: MediaPreviewV2State) {
|
||||
(binding.mediaPager.adapter as MediaPreviewV2Adapter).updateBackingItems(currentState.mediaRecords.mapNotNull { it.attachment })
|
||||
if (binding.mediaPager.currentItem != currentState.position) {
|
||||
binding.mediaPager.currentItem = currentState.position
|
||||
binding.mediaPager.setCurrentItem(currentState.position, false)
|
||||
}
|
||||
val currentItem: MediaDatabase.MediaRecord = currentState.mediaRecords[currentState.position]
|
||||
binding.toolbar.title = getTitleText(currentItem, currentState.showThread)
|
||||
@@ -295,11 +299,9 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
|
||||
return true
|
||||
}
|
||||
|
||||
override fun mediaNotAvailable() {
|
||||
Snackbar.make(binding.root, R.string.MediaPreviewActivity_media_no_longer_available, Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.MediaPreviewActivity_dismiss_due_to_error) {
|
||||
requireActivity().finish()
|
||||
}.show()
|
||||
override fun onMediaNotAvailable() {
|
||||
Toast.makeText(requireContext(), R.string.MediaPreviewActivity_media_no_longer_available, Toast.LENGTH_LONG).show()
|
||||
requireActivity().finish()
|
||||
}
|
||||
|
||||
override fun onMediaReady() {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.thoughtcrime.securesms.mediapreview
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.ViewModel
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
@@ -11,6 +10,7 @@ import io.reactivex.rxjava3.functions.Consumer
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentId
|
||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
|
||||
import org.thoughtcrime.securesms.database.MediaDatabase
|
||||
import org.thoughtcrime.securesms.util.AttachmentUtil
|
||||
@@ -24,8 +24,8 @@ class MediaPreviewV2ViewModel : ViewModel() {
|
||||
|
||||
val state: Flowable<MediaPreviewV2State> = store.stateFlowable.observeOn(AndroidSchedulers.mainThread())
|
||||
|
||||
fun fetchAttachments(startingUri: Uri, threadId: Long, sorting: MediaDatabase.Sorting) {
|
||||
disposables += store.update(repository.getAttachments(startingUri, threadId, sorting)) {
|
||||
fun fetchAttachments(startingAttachmentId: AttachmentId, threadId: Long, sorting: MediaDatabase.Sorting) {
|
||||
disposables += store.update(repository.getAttachments(startingAttachmentId, threadId, sorting)) {
|
||||
result: MediaPreviewRepository.Result, oldState: MediaPreviewV2State ->
|
||||
oldState.copy(
|
||||
position = result.initialPosition,
|
||||
|
||||
@@ -75,7 +75,7 @@ public final class VideoMediaPreviewFragment extends MediaPreviewFragment {
|
||||
|
||||
@Override
|
||||
public void onError() {
|
||||
events.mediaNotAvailable();
|
||||
events.onMediaNotAvailable();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user