Add support for starring messages.

This commit is contained in:
Greyson Parrelli
2026-03-20 21:24:10 -04:00
committed by Cody Henthorne
parent 6496f236ea
commit 48374e6950
48 changed files with 1149 additions and 49 deletions

View File

@@ -11,6 +11,7 @@ import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.ImageView;
import android.widget.TextView;
@@ -24,6 +25,7 @@ import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieProperty;
import com.airbnb.lottie.model.KeyPath;
import org.signal.core.ui.view.Stub;
import org.signal.core.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
@@ -56,6 +58,8 @@ public class ConversationItemFooter extends ConstraintLayout {
private ImageView insecureIndicatorView;
private DeliveryStatusView deliveryStatusView;
private ImageView pinnedView;
private Stub<ImageView> starredStub;
private int iconColor;
private boolean onlyShowSendingStatus;
private TextView audioDuration;
private LottieAnimationView revealDot;
@@ -100,6 +104,7 @@ public class ConversationItemFooter extends ConstraintLayout {
insecureIndicatorView = findViewById(R.id.footer_insecure_indicator);
deliveryStatusView = findViewById(R.id.footer_delivery_status);
pinnedView = findViewById(R.id.footer_pinned);
starredStub = new Stub<>((ViewStub) findViewById(R.id.footer_starred));
audioDuration = findViewById(R.id.footer_audio_duration);
revealDot = findViewById(R.id.footer_revealed_dot);
playbackSpeedToggleTextView = findViewById(R.id.footer_audio_playback_speed_toggle);
@@ -146,6 +151,7 @@ public class ConversationItemFooter extends ConstraintLayout {
presentDeliveryStatus(messageRecord);
presentAudioDuration(messageRecord);
presentPinnedIcon(messageRecord);
presentStarredIcon(messageRecord);
}
public void setAudioDuration(long totalDurationMillis, long currentPostionMillis) {
@@ -174,10 +180,14 @@ public class ConversationItemFooter extends ConstraintLayout {
}
public void setIconColor(int color) {
iconColor = color;
timerView.setColorFilter(color, PorterDuff.Mode.SRC_IN);
insecureIndicatorView.setColorFilter(color);
deliveryStatusView.setTint(color);
pinnedView.setColorFilter(color, PorterDuff.Mode.SRC_IN);
if (starredStub.resolved()) {
starredStub.get().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
}
public void setRevealDotColor(int color) {
@@ -449,6 +459,16 @@ public class ConversationItemFooter extends ConstraintLayout {
}
}
private void presentStarredIcon(@NonNull MessageRecord messageRecord) {
if (messageRecord.isStarred()) {
ImageView starredView = starredStub.get();
starredView.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN);
starredView.setVisibility(View.VISIBLE);
} else {
starredStub.setVisibility(View.GONE);
}
}
private void showAudioDurationViews() {
audioDuration.setVisibility(View.VISIBLE);
revealDot.setVisibility(View.VISIBLE);

View File

@@ -13,4 +13,5 @@ sealed interface LabsSettingsEvents {
data class ToggleBetterSearch(val enabled: Boolean) : LabsSettingsEvents
data class ToggleAutoLowerHand(val enabled: Boolean) : LabsSettingsEvents
data class ToggleNewApngRenderer(val enabled: Boolean) : LabsSettingsEvents
data class ToggleStarredMessages(val enabled: Boolean) : LabsSettingsEvents
}

View File

@@ -151,6 +151,15 @@ private fun LabsSettingsContent(
onCheckChanged = { onEvent(LabsSettingsEvents.ToggleNewApngRenderer(it)) }
)
}
item {
Rows.ToggleRow(
checked = state.starredMessages,
text = "Starred Messages",
label = "Enables starring messages for later reference. Adds star/unstar to the long-press menu and a starred messages screen accessible from conversation settings and the main menu.",
onCheckChanged = { onEvent(LabsSettingsEvents.ToggleStarredMessages(it)) }
)
}
}
}
}

View File

@@ -15,5 +15,6 @@ data class LabsSettingsState(
val groupSuggestionsForMembers: Boolean = false,
val betterSearch: Boolean = false,
val autoLowerHand: Boolean = false,
val newApngRenderer: Boolean = false
val newApngRenderer: Boolean = false,
val starredMessages: Boolean = false
)

View File

@@ -45,6 +45,10 @@ class LabsSettingsViewModel : ViewModel() {
SignalStore.labs.newApngRenderer = event.enabled
_state.value = _state.value.copy(newApngRenderer = event.enabled)
}
is LabsSettingsEvents.ToggleStarredMessages -> {
SignalStore.labs.starredMessages = event.enabled
_state.value = _state.value.copy(starredMessages = event.enabled)
}
}
}
@@ -56,7 +60,8 @@ class LabsSettingsViewModel : ViewModel() {
groupSuggestionsForMembers = SignalStore.labs.groupSuggestionsForMembers,
betterSearch = SignalStore.labs.betterSearch,
autoLowerHand = SignalStore.labs.autoLowerHand,
newApngRenderer = SignalStore.labs.newApngRenderer
newApngRenderer = SignalStore.labs.newApngRenderer,
starredMessages = SignalStore.labs.starredMessages
)
}
}

View File

@@ -89,6 +89,7 @@ import org.thoughtcrime.securesms.groups.ui.invitesandrequests.ManagePendingAndR
import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupDescriptionDialog
import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupInviteSentDialog
import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupsLearnMoreBottomSheetDialogFragment
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.mediaoverview.MediaOverviewActivity
import org.thoughtcrime.securesms.mediapreview.MediaIntentFactory
import org.thoughtcrime.securesms.mediasend.camerax.CameraXUtil
@@ -100,6 +101,7 @@ import org.thoughtcrime.securesms.recipients.RecipientExporter
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.recipients.ui.about.AboutSheet
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment
import org.thoughtcrime.securesms.starred.StarredMessagesActivity
import org.thoughtcrime.securesms.stories.Stories
import org.thoughtcrime.securesms.stories.StoryViewerArgs
import org.thoughtcrime.securesms.stories.dialogs.StoryDialogs
@@ -634,6 +636,16 @@ class ConversationSettingsFragment :
)
}
if (!state.recipient.isReleaseNotes && SignalStore.labs.starredMessages) {
clickPref(
title = DSLSettingsText.from(R.string.ConversationSettingsFragment__starred_messages),
icon = DSLSettingsIcon.from(R.drawable.symbol_star_outline_24),
onClick = {
startActivity(StarredMessagesActivity.createIntent(requireContext(), state.threadId))
}
)
}
state.withRecipientSettingsState { recipientState ->
when (recipientState.contactLinkState) {
ContactLinkState.OPEN -> {