Skip to content

Commit

Permalink
Merge branch 'molly-6.39'
Browse files Browse the repository at this point in the history
  • Loading branch information
valldrac committed Nov 10, 2023
2 parents 8af6ea5 + eea908d commit 1b8570d
Show file tree
Hide file tree
Showing 136 changed files with 3,190 additions and 2,017 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ ext {
MAPS_API_KEY = getEnv('CI_MAPS_API_KEY') ?: mapsApiKey
}

def canonicalVersionCode = 1353
def canonicalVersionName = "6.38.2"
def canonicalVersionCode = 1355
def canonicalVersionName = "6.39.1"
def mollyRevision = 0

def postFixSize = 100
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,10 @@
android:name=".service.GenericForegroundService"
android:exported="false"/>

<service
android:name=".service.AttachmentProgressService"
android:exported="false"/>

<service
android:name=".gcm.FcmFetchBackgroundService"
android:exported="false"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ object ApkUpdateNotifications {
.setSmallIcon(R.drawable.ic_notification)
.setColor(ContextCompat.getColor(context, R.color.core_ultramarine))
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build()

ServiceUtil.getNotificationManager(context).notify(NotificationIds.APK_UPDATE_FAILED_INSTALL, notification)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@

import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.database.MediaTable;
import org.thoughtcrime.securesms.mediapreview.MediaPreviewCache;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.util.MediaUtil;

import java.util.ArrayList;
import java.util.List;

public class ThreadPhotoRailView extends FrameLayout {

@NonNull private final RecyclerView recyclerView;
Expand Down Expand Up @@ -56,11 +58,11 @@ public void setListener(@Nullable OnItemClickedListener listener) {
}
}

public void setCursor(@NonNull GlideRequests glideRequests, @Nullable Cursor cursor) {
this.recyclerView.setAdapter(new ThreadPhotoRailAdapter(getContext(), glideRequests, cursor, this.listener));
public void setMediaRecords(@NonNull GlideRequests glideRequests, @NonNull List<MediaTable.MediaRecord> mediaRecords) {
this.recyclerView.setAdapter(new ThreadPhotoRailAdapter(getContext(), glideRequests, mediaRecords, this.listener));
}

private static class ThreadPhotoRailAdapter extends CursorRecyclerViewAdapter<ThreadPhotoRailAdapter.ThreadPhotoViewHolder> {
private static class ThreadPhotoRailAdapter extends RecyclerView.Adapter<ThreadPhotoRailAdapter.ThreadPhotoViewHolder> {

@SuppressWarnings("unused")
private static final String TAG = Log.tag(ThreadPhotoRailAdapter.class);
Expand All @@ -69,37 +71,42 @@ private static class ThreadPhotoRailAdapter extends CursorRecyclerViewAdapter<Th

@Nullable private OnItemClickedListener clickedListener;

private final List<MediaTable.MediaRecord> mediaRecords = new ArrayList<>();

private ThreadPhotoRailAdapter(@NonNull Context context,
@NonNull GlideRequests glideRequests,
@Nullable Cursor cursor,
@NonNull List<MediaTable.MediaRecord> mediaRecords,
@Nullable OnItemClickedListener listener)
{
super(context, cursor);
this.glideRequests = glideRequests;
this.clickedListener = listener;

this.mediaRecords.clear();
this.mediaRecords.addAll(mediaRecords);
}

@Override
public int getItemCount() {
return mediaRecords.size();
}

@Override
public ThreadPhotoViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
public @NonNull ThreadPhotoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recipient_preference_photo_rail_item, parent, false);

return new ThreadPhotoViewHolder(itemView);
}

@Override
public void onBindItemViewHolder(ThreadPhotoViewHolder viewHolder, @NonNull Cursor cursor) {
ThumbnailView imageView = viewHolder.imageView;
MediaTable.MediaRecord mediaRecord = MediaTable.MediaRecord.from(cursor);
public void onBindViewHolder(@NonNull ThreadPhotoViewHolder viewHolder, int position) {
MediaTable.MediaRecord mediaRecord = mediaRecords.get(position);
Slide slide = MediaUtil.getSlideForAttachment(mediaRecord.getAttachment());

if (slide != null) {
imageView.setImageResource(glideRequests, slide, false, false);
}

imageView.setOnClickListener(v -> {
MediaPreviewCache.INSTANCE.setDrawable(imageView.getImageDrawable());
if (clickedListener != null) clickedListener.onItemClicked(imageView, mediaRecord);
viewHolder.imageView.setImageResource(glideRequests, slide, false, false);
viewHolder.imageView.setOnClickListener(v -> {
MediaPreviewCache.INSTANCE.setDrawable(viewHolder.imageView.getImageDrawable());
if (clickedListener != null) clickedListener.onItemClicked(viewHolder.imageView, mediaRecord);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,11 @@ class SwitchPreferenceViewHolder(itemView: View) : PreferenceViewHolder<SwitchPr
switchWidget.isChecked = model.isChecked
switchWidget.isEnabled = model.isEnabled

switchWidget.setOnCheckedChangeListener { _, _ ->
switchWidget.setOnCheckedChangeListener { _, isChecked ->
if (!model.onToggle(isChecked)) {
// MOLLY: Set the toggle button back to the previous state
switchWidget.toggle()
}
model.onClick()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ class HelpSettingsFragment : DSLSettingsFragment(R.string.preferences__help) {
switchPref(
title = DSLSettingsText.from(R.string.preferences__enable_debug_log),
isChecked = state.logEnabled,
onClick = {
if (state.logEnabled) {
onToggle = { isChecked -> if (!isChecked) {
MaterialAlertDialogBuilder(requireContext())
.setMessage(R.string.HelpSettingsFragment_disable_and_delete_debug_log)
.setPositiveButton(android.R.string.ok) { dialog, _ ->
Expand All @@ -83,8 +82,10 @@ class HelpSettingsFragment : DSLSettingsFragment(R.string.preferences__help) {
}
.setNegativeButton(android.R.string.cancel, null)
.show()
false
} else {
viewModel.setLogEnabled(true)
true
}
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.components.settings.DSLConfiguration
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
import org.thoughtcrime.securesms.components.settings.configure
import org.thoughtcrime.securesms.database.JobDatabase
import org.thoughtcrime.securesms.database.LocalMetricsDatabase
import org.thoughtcrime.securesms.database.LogDatabase
import org.thoughtcrime.securesms.database.MegaphoneDatabase
Expand Down Expand Up @@ -159,20 +160,65 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
}
)

clickPref(
title = DSLSettingsText.from("Clear all logs"),
onClick = {
SimpleTask.run({
LogDatabase.getInstance(requireActivity().application).logs.clearAll()
}) {
Toast.makeText(requireContext(), "Cleared all logs", Toast.LENGTH_SHORT).show()
}
}
)

clickPref(
title = DSLSettingsText.from("Clear keep longer logs"),
onClick = {
clearKeepLongerLogs()
}
)

clickPref(
title = DSLSettingsText.from("Clear all crashes"),
onClick = {
SimpleTask.run({
LogDatabase.getInstance(requireActivity().application).crashes.clear()
}) {
Toast.makeText(requireContext(), "Cleared crashes", Toast.LENGTH_SHORT).show()
}
}
)

clickPref(
title = DSLSettingsText.from("Clear all ANRs"),
onClick = {
SimpleTask.run({
LogDatabase.getInstance(requireActivity().application).anrs.clear()
}) {
Toast.makeText(requireContext(), "Cleared ANRs", Toast.LENGTH_SHORT).show()
}
}
)

clickPref(
title = DSLSettingsText.from("Log dump PreKey ServiceId-KeyIds"),
onClick = {
logPreKeyIds()
}
)

clickPref(
title = DSLSettingsText.from("Retry all jobs now"),
summary = DSLSettingsText.from("Clear backoff intervals, app will restart"),
onClick = {
SimpleTask.run({
JobDatabase.getInstance(ApplicationDependencies.getApplication()).debugResetBackoffInterval()
}) {
AppUtil.restart(requireContext())
}
}
)

dividerPref()

sectionHeaderPref(DSLSettingsText.from("Payments"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,16 @@ class PrivacySettingsFragment : DSLSettingsFragment(R.string.preferences__privac
title = DSLSettingsText.from(R.string.preferences__passphrase_lock),
summary = DSLSettingsText.from(R.string.preferences__protect_molly_database_with_a_passphrase),
isChecked = state.passphraseLock,
onClick = {
val enabled = !state.passphraseLock
val mode = if (enabled) ChangePassphraseDialogFragment.MODE_ENABLE else ChangePassphraseDialogFragment.MODE_DISABLE

onToggle = { isChecked ->
val mode = if (isChecked) ChangePassphraseDialogFragment.MODE_ENABLE else ChangePassphraseDialogFragment.MODE_DISABLE
val dialog = ChangePassphraseDialogFragment.newInstance(mode)
dialog.setMasterSecretChangedListener { masterSecret ->
viewModel.setPassphraseLockEnabled(enabled)
viewModel.setPassphraseLockEnabled(isChecked)
(activity as PassphraseActivity).setMasterSecret(masterSecret)
ConversationUtil.refreshRecipientShortcuts()
}
dialog.show(parentFragmentManager, "ChangePassphraseDialogFragment")
false
}
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -567,15 +567,15 @@ class ConversationSettingsFragment : DSLSettingsFragment(
}
}

if (state.sharedMedia != null && state.sharedMedia.count > 0) {
if (state.sharedMedia.isNotEmpty()) {
dividerPref()

sectionHeaderPref(R.string.recipient_preference_activity__shared_media)

@Suppress("DEPRECATION")
customPref(
SharedMediaPreference.Model(
mediaCursor = state.sharedMedia,
mediaRecords = state.sharedMedia,
mediaIds = state.sharedMediaIds,
onMediaRecordClick = { view, mediaRecord, isLtr ->
view.transitionName = "thumb"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.recipients.RecipientUtil
import org.thoughtcrime.securesms.util.FeatureFlags
import java.io.IOException
import java.util.Optional

private val TAG = Log.tag(ConversationSettingsRepository::class.java)

Expand All @@ -56,11 +55,11 @@ class ConversationSettingsRepository(
}

@WorkerThread
fun getThreadMedia(threadId: Long): Optional<Cursor> {
return if (threadId <= 0) {
Optional.empty()
fun getThreadMedia(threadId: Long, limit: Int): Cursor? {
return if (threadId > 0) {
SignalDatabase.media.getGalleryMediaForThread(threadId, MediaTable.Sorting.Newest, limit)
} else {
Optional.of(SignalDatabase.media.getGalleryMediaForThread(threadId, MediaTable.Sorting.Newest))
null
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package org.thoughtcrime.securesms.components.settings.conversation

import android.database.Cursor
import org.thoughtcrime.securesms.components.settings.conversation.preferences.ButtonStripPreference
import org.thoughtcrime.securesms.components.settings.conversation.preferences.CallPreference
import org.thoughtcrime.securesms.components.settings.conversation.preferences.LegacyGroupPreference
import org.thoughtcrime.securesms.database.MediaTable
import org.thoughtcrime.securesms.database.model.IdentityRecord
import org.thoughtcrime.securesms.database.model.StoryViewState
import org.thoughtcrime.securesms.groups.GroupId
Expand All @@ -18,7 +18,7 @@ data class ConversationSettingsState(
val buttonStripState: ButtonStripPreference.State = ButtonStripPreference.State(),
val disappearingMessagesLifespan: Int = 0,
val canModifyBlockedState: Boolean = false,
val sharedMedia: Cursor? = null,
val sharedMedia: List<MediaTable.MediaRecord> = emptyList(),
val sharedMediaIds: List<Long> = listOf(),
val displayInternalRecipientDetails: Boolean = false,
val calls: List<CallPreference.Model> = emptyList(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.subjects.PublishSubject
import io.reactivex.rxjava3.subjects.Subject
import org.signal.core.util.CursorUtil
import org.signal.core.util.ThreadUtil
import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.readToList
import org.thoughtcrime.securesms.components.settings.conversation.preferences.ButtonStripPreference
import org.thoughtcrime.securesms.components.settings.conversation.preferences.CallPreference
import org.thoughtcrime.securesms.components.settings.conversation.preferences.LegacyGroupPreference
import org.thoughtcrime.securesms.database.AttachmentTable
import org.thoughtcrime.securesms.database.MediaTable
import org.thoughtcrime.securesms.database.RecipientTable
import org.thoughtcrime.securesms.database.model.StoryViewState
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
Expand All @@ -34,16 +34,13 @@ import org.thoughtcrime.securesms.util.FeatureFlags
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil
import org.thoughtcrime.securesms.util.livedata.Store
import java.util.Optional

sealed class ConversationSettingsViewModel(
private val callMessageIds: LongArray,
private val repository: ConversationSettingsRepository,
specificSettingsState: SpecificSettingsState
) : ViewModel() {

private val openedMediaCursors = HashSet<Cursor>()

@Volatile
private var cleared = false

Expand All @@ -66,37 +63,26 @@ sealed class ConversationSettingsViewModel(
val threadId: LiveData<Long> = state.map { it.threadId }.distinctUntilChanged()
val updater: LiveData<Long> = LiveDataUtil.combineLatest(threadId, sharedMediaUpdateTrigger) { tId, _ -> tId }

val sharedMedia: LiveData<Optional<Cursor>> = LiveDataUtil.mapAsync(SignalExecutors.BOUNDED, updater) { tId ->
repository.getThreadMedia(tId)
val sharedMedia: LiveData<List<MediaTable.MediaRecord>> = LiveDataUtil.mapAsync(SignalExecutors.BOUNDED, updater) { tId ->
repository.getThreadMedia(threadId = tId, limit = 100)?.readToList { cursor ->
MediaTable.MediaRecord.from(cursor)
} ?: emptyList()
}

store.update(repository.getCallEvents(callMessageIds).toObservable()) { callRecords, state ->
state.copy(calls = callRecords.map { (call, messageRecord) -> CallPreference.Model(call, messageRecord) })
}

store.update(sharedMedia) { cursor, state ->
store.update(sharedMedia) { mediaRecords, state ->
if (!cleared) {
if (cursor.isPresent) {
openedMediaCursors.add(cursor.get())
}

val ids: List<Long> = cursor.map<List<Long>> {
val result = mutableListOf<Long>()
while (it.moveToNext()) {
result.add(CursorUtil.requireLong(it, AttachmentTable.ROW_ID))
}
result
}.orElse(listOf())

state.copy(
sharedMedia = cursor.orElse(null),
sharedMediaIds = ids,
sharedMedia = mediaRecords,
sharedMediaIds = mediaRecords.mapNotNull { it.attachment?.attachmentId?.rowId },
sharedMediaLoaded = true,
displayInternalRecipientDetails = repository.isInternalRecipientDetailsEnabled()
)
} else {
cursor.orElse(null).ensureClosed()
state.copy(sharedMedia = null)
state.copy(sharedMedia = emptyList())
}
}
}
Expand Down Expand Up @@ -125,7 +111,6 @@ sealed class ConversationSettingsViewModel(

override fun onCleared() {
cleared = true
openedMediaCursors.forEach { it.ensureClosed() }
store.clear()
disposable.clear()
}
Expand Down
Loading

0 comments on commit 1b8570d

Please sign in to comment.