Integrate contact hiding with message requests.
This commit is contained in:
parent
74877b839e
commit
48360d08d4
15 changed files with 107 additions and 16 deletions
|
@ -93,7 +93,7 @@ public class NewConversationActivity extends ContactSelectionActivity
|
|||
ContactsManagementViewModel.Factory factory = new ContactsManagementViewModel.Factory(repository);
|
||||
|
||||
contactLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
|
||||
if (activityResult.getResultCode() == RESULT_OK) {
|
||||
if (activityResult.getResultCode() != RESULT_CANCELED) {
|
||||
handleManualRefresh();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -24,12 +24,13 @@ data class ConversationData(
|
|||
|
||||
data class MessageRequestData @JvmOverloads constructor(
|
||||
val isMessageRequestAccepted: Boolean,
|
||||
val isHidden: Boolean,
|
||||
private val groupsInCommon: Boolean = false,
|
||||
val isGroup: Boolean = false
|
||||
) {
|
||||
|
||||
fun includeWarningUpdateMessage(): Boolean {
|
||||
return !isMessageRequestAccepted && !groupsInCommon
|
||||
return !isMessageRequestAccepted && !groupsInCommon && !isHidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
|||
long startTime = System.currentTimeMillis();
|
||||
int size = getSizeInternal() +
|
||||
(messageRequestData.includeWarningUpdateMessage() ? 1 : 0) +
|
||||
(messageRequestData.isHidden() ? 1 : 0) +
|
||||
(showUniversalExpireTimerUpdate ? 1 : 0);
|
||||
|
||||
Log.d(TAG, "[size(), thread " + threadId + "] " + (System.currentTimeMillis() - startTime) + " ms");
|
||||
|
@ -124,6 +125,10 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
|||
records.add(new InMemoryMessageRecord.NoGroupsInCommon(threadId, messageRequestData.isGroup()));
|
||||
}
|
||||
|
||||
if (messageRequestData.isHidden() && (start + length >= size())) {
|
||||
records.add(new InMemoryMessageRecord.RemovedContactHidden(threadId));
|
||||
}
|
||||
|
||||
if (showUniversalExpireTimerUpdate) {
|
||||
records.add(new InMemoryMessageRecord.UniversalExpireTimerUpdate(threadId));
|
||||
}
|
||||
|
|
|
@ -65,7 +65,8 @@ class ConversationRepository {
|
|||
long lastScrolled = metadata.getLastScrolled();
|
||||
int lastScrolledPosition = 0;
|
||||
boolean isMessageRequestAccepted = RecipientUtil.isMessageRequestAccepted(context, threadId);
|
||||
ConversationData.MessageRequestData messageRequestData = new ConversationData.MessageRequestData(isMessageRequestAccepted);
|
||||
boolean isConversationHidden = RecipientUtil.isRecipientHidden(threadId);
|
||||
ConversationData.MessageRequestData messageRequestData = new ConversationData.MessageRequestData(isMessageRequestAccepted, isConversationHidden);
|
||||
boolean showUniversalExpireTimerUpdate = false;
|
||||
|
||||
if (lastSeen > 0) {
|
||||
|
@ -98,7 +99,7 @@ class ConversationRepository {
|
|||
} else if (conversationRecipient.hasGroupsInCommon()) {
|
||||
recipientIsKnownOrHasGroupsInCommon = true;
|
||||
}
|
||||
messageRequestData = new ConversationData.MessageRequestData(isMessageRequestAccepted, recipientIsKnownOrHasGroupsInCommon, isGroup);
|
||||
messageRequestData = new ConversationData.MessageRequestData(isMessageRequestAccepted, isConversationHidden, recipientIsKnownOrHasGroupsInCommon, isGroup);
|
||||
}
|
||||
|
||||
if (SignalStore.settings().getUniversalExpireTimer() != 0 &&
|
||||
|
|
|
@ -569,7 +569,11 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
|
|||
int defaultTint = ContextCompat.getColor(context, R.color.signal_text_secondary);
|
||||
|
||||
if (!thread.isMessageRequestAccepted()) {
|
||||
return emphasisAdded(context, context.getString(R.string.ThreadRecord_message_request), defaultTint);
|
||||
if (thread.isRecipientHidden()) {
|
||||
return emphasisAdded(context, context.getString(R.string.ThreadRecord_hidden_recipient), defaultTint);
|
||||
} else {
|
||||
return emphasisAdded(context, context.getString(R.string.ThreadRecord_message_request), defaultTint);
|
||||
}
|
||||
} else if (MessageTypes.isGroupUpdate(thread.getType())) {
|
||||
if (thread.getRecipient().isPushV2Group()) {
|
||||
return emphasisAdded(context, MessageRecord.getGv2ChangeDescription(context, thread.getBody(), null), defaultTint);
|
||||
|
|
|
@ -1583,6 +1583,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
private fun getExtrasFor(record: MessageRecord, body: ThreadBody): Extra? {
|
||||
val threadRecipient = if (record.isOutgoing) record.recipient else getRecipientForThreadId(record.threadId)
|
||||
val messageRequestAccepted = RecipientUtil.isMessageRequestAccepted(record.threadId, threadRecipient)
|
||||
val isHidden = threadRecipient?.isHidden ?: false
|
||||
val individualRecipientId = record.individualRecipient.id
|
||||
|
||||
if (!messageRequestAccepted && threadRecipient != null) {
|
||||
|
@ -1609,7 +1610,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
}
|
||||
}
|
||||
} else {
|
||||
return Extra.forMessageRequest(individualRecipientId)
|
||||
return Extra.forMessageRequest(individualRecipientId, isHidden)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1772,7 +1773,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
groupAddedBy = jsonObject.getString("groupAddedBy"),
|
||||
individualRecipientId = jsonObject.getString("individualRecipientId")!!,
|
||||
bodyRanges = jsonObject.getString("bodyRanges"),
|
||||
isScheduled = jsonObject.getBoolean("isScheduled")
|
||||
isScheduled = jsonObject.getBoolean("isScheduled"),
|
||||
isRecipientHidden = jsonObject.getBoolean("isRecipientHidden")
|
||||
)
|
||||
} catch (exception: Exception) {
|
||||
null
|
||||
|
@ -1855,7 +1857,10 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
val bodyRanges: String? = null,
|
||||
@field:JsonProperty
|
||||
@param:JsonProperty("isScheduled")
|
||||
val isScheduled: Boolean = false
|
||||
val isScheduled: Boolean = false,
|
||||
@field:JsonProperty
|
||||
@param:JsonProperty("isRecipientHidden")
|
||||
val isRecipientHidden: Boolean = false
|
||||
) {
|
||||
|
||||
fun getIndividualRecipientId(): String {
|
||||
|
@ -1879,8 +1884,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
return Extra(isRemoteDelete = true, individualRecipientId = individualRecipient.serialize())
|
||||
}
|
||||
|
||||
fun forMessageRequest(individualRecipient: RecipientId): Extra {
|
||||
return Extra(isMessageRequestAccepted = false, individualRecipientId = individualRecipient.serialize())
|
||||
fun forMessageRequest(individualRecipient: RecipientId, isHidden: Boolean = false): Extra {
|
||||
return Extra(isMessageRequestAccepted = false, individualRecipientId = individualRecipient.serialize(), isRecipientHidden = isHidden)
|
||||
}
|
||||
|
||||
fun forGroupMessageRequest(recipientId: RecipientId, individualRecipient: RecipientId): Extra {
|
||||
|
|
|
@ -23,6 +23,7 @@ public class InMemoryMessageRecord extends MessageRecord {
|
|||
private static final int NO_GROUPS_IN_COMMON_ID = -1;
|
||||
private static final int UNIVERSAL_EXPIRE_TIMER_ID = -2;
|
||||
private static final int FORCE_BUBBLE_ID = -3;
|
||||
private static final int HIDDEN_CONTACT_WARNING_ID = -4;
|
||||
|
||||
private InMemoryMessageRecord(long id,
|
||||
String body,
|
||||
|
@ -118,6 +119,29 @@ public class InMemoryMessageRecord extends MessageRecord {
|
|||
}
|
||||
}
|
||||
|
||||
public static final class RemovedContactHidden extends InMemoryMessageRecord {
|
||||
|
||||
public RemovedContactHidden(long threadId) {
|
||||
super(HIDDEN_CONTACT_WARNING_ID, "", Recipient.UNKNOWN, threadId, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable UpdateDescription getUpdateDisplayBody(@NonNull Context context, @Nullable Consumer<RecipientId> recipientClickHandler) {
|
||||
return UpdateDescription.staticDescription(context.getString(R.string.ConversationUpdateItem_hidden_contact_message_to_add_back),
|
||||
R.drawable.symbol_info_compact_16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showActionButton() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show temporary update message about setting the disappearing messages timer upon first message
|
||||
* send.
|
||||
|
|
|
@ -222,6 +222,11 @@ public final class ThreadRecord {
|
|||
else return true;
|
||||
}
|
||||
|
||||
public boolean isRecipientHidden() {
|
||||
if (extra != null) return extra.isRecipientHidden();
|
||||
else return true;
|
||||
}
|
||||
|
||||
public boolean isPinned() {
|
||||
return isPinned;
|
||||
}
|
||||
|
|
|
@ -116,6 +116,8 @@ final class MessageRequestRepository {
|
|||
} else {
|
||||
if (RecipientUtil.isMessageRequestAccepted(context, threadId)) {
|
||||
return MessageRequestState.NONE;
|
||||
} else if (RecipientUtil.isRecipientHidden(threadId)) {
|
||||
return MessageRequestState.INDIVIDUAL_HIDDEN;
|
||||
} else {
|
||||
return MessageRequestState.INDIVIDUAL;
|
||||
}
|
||||
|
|
|
@ -35,5 +35,8 @@ public enum MessageRequestState {
|
|||
GROUP_V2_ADD,
|
||||
|
||||
/** A message request is needed for an individual */
|
||||
INDIVIDUAL
|
||||
INDIVIDUAL,
|
||||
|
||||
/** A message request is needed for an individual since they have been hidden */
|
||||
INDIVIDUAL_HIDDEN
|
||||
}
|
||||
|
|
|
@ -139,6 +139,12 @@ public class MessageRequestsBottomView extends ConstraintLayout {
|
|||
setActiveInactiveGroups(normalButtons, blockedButtons, gv1MigrationButtons);
|
||||
accept.setText(R.string.MessageRequestBottomView_accept);
|
||||
break;
|
||||
case INDIVIDUAL_HIDDEN:
|
||||
question.setText(HtmlCompat.fromHtml(getContext().getString(R.string.MessageRequestBottomView_do_you_want_to_let_s_message_you_you_removed_them_before,
|
||||
HtmlUtil.bold(recipient.getShortDisplayName(getContext()))), 0));
|
||||
setActiveInactiveGroups(normalButtons, blockedButtons, gv1MigrationButtons);
|
||||
accept.setText(R.string.MessageRequestBottomView_accept);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@ public class Recipient {
|
|||
private final String profileAvatar;
|
||||
private final ProfileAvatarFileDetails profileAvatarFileDetails;
|
||||
private final boolean profileSharing;
|
||||
private final boolean isHidden;
|
||||
private final long lastProfileFetch;
|
||||
private final String notificationChannel;
|
||||
private final UnidentifiedAccessMode unidentifiedAccessMode;
|
||||
|
@ -412,6 +413,7 @@ public class Recipient {
|
|||
this.profileAvatar = null;
|
||||
this.profileAvatarFileDetails = ProfileAvatarFileDetails.NO_DETAILS;
|
||||
this.profileSharing = false;
|
||||
this.isHidden = false;
|
||||
this.lastProfileFetch = 0;
|
||||
this.notificationChannel = null;
|
||||
this.unidentifiedAccessMode = UnidentifiedAccessMode.DISABLED;
|
||||
|
@ -466,6 +468,7 @@ public class Recipient {
|
|||
this.profileAvatar = details.profileAvatar;
|
||||
this.profileAvatarFileDetails = details.profileAvatarFileDetails;
|
||||
this.profileSharing = details.profileSharing;
|
||||
this.isHidden = details.isHidden;
|
||||
this.lastProfileFetch = details.lastProfileFetch;
|
||||
this.notificationChannel = details.notificationChannel;
|
||||
this.unidentifiedAccessMode = details.unidentifiedAccessMode;
|
||||
|
@ -833,6 +836,10 @@ public class Recipient {
|
|||
return profileSharing;
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return isHidden;
|
||||
}
|
||||
|
||||
public long getLastProfileFetchTime() {
|
||||
return lastProfileFetch;
|
||||
}
|
||||
|
@ -1290,6 +1297,7 @@ public class Recipient {
|
|||
expireMessages == other.expireMessages &&
|
||||
Objects.equals(profileAvatarFileDetails, other.profileAvatarFileDetails) &&
|
||||
profileSharing == other.profileSharing &&
|
||||
isHidden == other.isHidden &&
|
||||
forceSmsSelection == other.forceSmsSelection &&
|
||||
Objects.equals(serviceId, other.serviceId) &&
|
||||
Objects.equals(username, other.username) &&
|
||||
|
|
|
@ -63,6 +63,7 @@ public class RecipientDetails {
|
|||
final String profileAvatar;
|
||||
final ProfileAvatarFileDetails profileAvatarFileDetails;
|
||||
final boolean profileSharing;
|
||||
final boolean isHidden;
|
||||
final long lastProfileFetch;
|
||||
final boolean systemContact;
|
||||
final boolean isSelf;
|
||||
|
@ -122,6 +123,7 @@ public class RecipientDetails {
|
|||
this.profileAvatar = record.getProfileAvatar();
|
||||
this.profileAvatarFileDetails = record.getProfileAvatarFileDetails();
|
||||
this.profileSharing = record.isProfileSharing();
|
||||
this.isHidden = record.isHidden();
|
||||
this.lastProfileFetch = record.getLastProfileFetch();
|
||||
this.systemContact = systemContact;
|
||||
this.isSelf = isSelf;
|
||||
|
@ -176,6 +178,7 @@ public class RecipientDetails {
|
|||
this.profileAvatar = null;
|
||||
this.profileAvatarFileDetails = ProfileAvatarFileDetails.NO_DETAILS;
|
||||
this.profileSharing = false;
|
||||
this.isHidden = false;
|
||||
this.lastProfileFetch = 0;
|
||||
this.systemContact = true;
|
||||
this.isSelf = false;
|
||||
|
|
|
@ -198,6 +198,22 @@ public class RecipientUtil {
|
|||
StorageSyncHelper.scheduleSyncForDataChange();
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public static boolean isRecipientHidden(long threadId) {
|
||||
if (threadId < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ThreadTable threadTable = SignalDatabase.threads();
|
||||
Recipient threadRecipient = threadTable.getRecipientForThreadId(threadId);
|
||||
|
||||
if (threadRecipient == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return threadRecipient.isHidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* If true, the new message request UI does not need to be shown, and it's safe to send read
|
||||
* receipts.
|
||||
|
@ -281,7 +297,8 @@ public class RecipientUtil {
|
|||
threadRecipient.isProfileSharing() ||
|
||||
threadRecipient.isSystemContact() ||
|
||||
!threadRecipient.isRegistered() ||
|
||||
threadRecipient.isForceSmsSelection();
|
||||
threadRecipient.isForceSmsSelection() ||
|
||||
threadRecipient.isHidden();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -331,9 +348,11 @@ public class RecipientUtil {
|
|||
threadRecipient.isSystemContact() ||
|
||||
threadRecipient.isForceSmsSelection() ||
|
||||
!threadRecipient.isRegistered() ||
|
||||
hasSentMessageInThread(threadId) ||
|
||||
noSecureMessagesAndNoCallsInThread(threadId) ||
|
||||
isPreMessageRequestThread(threadId);
|
||||
(!threadRecipient.isHidden() && (
|
||||
hasSentMessageInThread(threadId) ||
|
||||
noSecureMessagesAndNoCallsInThread(threadId) ||
|
||||
isPreMessageRequestThread(threadId))
|
||||
);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
|
|
|
@ -1479,6 +1479,8 @@
|
|||
<string name="MessageRequestBottomView_delete">Delete</string>
|
||||
<string name="MessageRequestBottomView_block">Block</string>
|
||||
<string name="MessageRequestBottomView_unblock">Unblock</string>
|
||||
<!-- Text explaining a message request from someone you've removed before -->
|
||||
<string name="MessageRequestBottomView_do_you_want_to_let_s_message_you_you_removed_them_before">Let %1$s message you and share your name and photo with them? You have removed this person in the past.</string>
|
||||
<string name="MessageRequestBottomView_do_you_want_to_let_s_message_you_they_wont_know_youve_seen_their_messages_until_you_accept">Let %1$s message you and share your name and photo with them? They won\'t know you\'ve seen their message until you accept.</string>
|
||||
<!-- Shown in message request flow. Describes what will happen if you unblock a Signal user -->
|
||||
<string name="MessageRequestBottomView_do_you_want_to_let_s_message_you_wont_receive_any_messages_until_you_unblock_them">Let %1$s message you and share your name and photo with them? You won\'t receive any messages until you unblock them.</string>
|
||||
|
@ -1992,6 +1994,8 @@
|
|||
<string name="ThreadRecord_message_could_not_be_processed">Message could not be processed</string>
|
||||
<string name="ThreadRecord_delivery_issue">Delivery issue</string>
|
||||
<string name="ThreadRecord_message_request">Message Request</string>
|
||||
<!-- Thread preview for a recipient that has been hidden -->
|
||||
<string name="ThreadRecord_hidden_recipient">You have hidden this person, message them again to add them back to your list.</string>
|
||||
<string name="ThreadRecord_photo">Photo</string>
|
||||
<string name="ThreadRecord_gif">GIF</string>
|
||||
<string name="ThreadRecord_voice_message">Voice Message</string>
|
||||
|
@ -2387,7 +2391,8 @@
|
|||
<string name="ConversationUpdateItem_send_payment">Send payment</string>
|
||||
<!-- Update item button text to activate payments -->
|
||||
<string name="ConversationUpdateItem_activate_payments">Activate payments</string>
|
||||
|
||||
<!-- Update item alerting the user they hid this person and that they can message them to unhide them -->
|
||||
<string name="ConversationUpdateItem_hidden_contact_message_to_add_back">You have removed this person, messaging them again will add them back to your list.</string>
|
||||
|
||||
<!-- audio_view -->
|
||||
<string name="audio_view__play_pause_accessibility_description">Play … Pause</string>
|
||||
|
|
Loading…
Add table
Reference in a new issue