kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add support for new group story display states.
rodzic
8ca94eb3d5
commit
c47a724654
|
@ -13,7 +13,11 @@ sealed class ContactSearchData(val contactSearchKey: ContactSearchKey) {
|
|||
*
|
||||
* Note that if the recipient is a group, it's participant list size is used instead of viewerCount.
|
||||
*/
|
||||
data class Story(val recipient: Recipient, val viewerCount: Int, val privacyMode: DistributionListPrivacyMode) : ContactSearchData(ContactSearchKey.RecipientSearchKey.Story(recipient.id))
|
||||
data class Story(
|
||||
val recipient: Recipient,
|
||||
val viewerCount: Int,
|
||||
val privacyMode: DistributionListPrivacyMode
|
||||
) : ContactSearchData(ContactSearchKey.RecipientSearchKey.Story(recipient.id))
|
||||
|
||||
/**
|
||||
* A row displaying a known recipient.
|
||||
|
|
|
@ -261,7 +261,6 @@ class ContactSearchPagedDataSource(
|
|||
rhs.recipient.isMyStory -> 1
|
||||
lhsActiveRank < rhsActiveRank -> -1
|
||||
lhsActiveRank > rhsActiveRank -> 1
|
||||
lhsActiveRank == rhsActiveRank -> -1
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
package org.thoughtcrime.securesms.contacts.paged
|
||||
|
||||
import androidx.annotation.CheckResult
|
||||
import io.reactivex.rxjava3.core.Completable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListId
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
|
||||
class ContactSearchRepository {
|
||||
@CheckResult
|
||||
fun filterOutUnselectableContactSearchKeys(contactSearchKeys: Set<ContactSearchKey>): Single<Set<ContactSearchSelectionResult>> {
|
||||
return Single.fromCallable {
|
||||
contactSearchKeys.map {
|
||||
|
@ -35,12 +39,25 @@ class ContactSearchRepository {
|
|||
}
|
||||
}
|
||||
|
||||
fun unmarkDisplayAsStory(groupId: GroupId): Completable {
|
||||
@CheckResult
|
||||
fun markDisplayAsStory(recipientIds: Collection<RecipientId>): Completable {
|
||||
return Completable.fromAction {
|
||||
SignalDatabase.groups.markDisplayAsStory(groupId, false)
|
||||
SignalDatabase.groups.setShowAsStoryState(recipientIds, GroupDatabase.ShowAsStoryState.ALWAYS)
|
||||
SignalDatabase.recipients.markNeedsSync(recipientIds)
|
||||
StorageSyncHelper.scheduleSyncForDataChange()
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
fun unmarkDisplayAsStory(groupId: GroupId): Completable {
|
||||
return Completable.fromAction {
|
||||
SignalDatabase.groups.setShowAsStoryState(groupId, GroupDatabase.ShowAsStoryState.NEVER)
|
||||
SignalDatabase.recipients.markNeedsSync(Recipient.externalGroupExact(groupId).id)
|
||||
StorageSyncHelper.scheduleSyncForDataChange()
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
fun deletePrivateStory(distributionListId: DistributionListId): Completable {
|
||||
return Completable.fromAction {
|
||||
SignalDatabase.distributionLists.deleteList(distributionListId)
|
||||
|
|
|
@ -99,6 +99,7 @@ class ContactSearchViewModel(
|
|||
}
|
||||
|
||||
fun addToVisibleGroupStories(groupStories: Set<ContactSearchKey.RecipientSearchKey.Story>) {
|
||||
disposables += contactSearchRepository.markDisplayAsStory(groupStories.map { it.recipientId }).subscribe {
|
||||
configurationStore.update { state ->
|
||||
state.copy(
|
||||
groupStories = state.groupStories + groupStories.map {
|
||||
|
@ -108,6 +109,7 @@ class ContactSearchViewModel(
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removeGroupStory(story: ContactSearchData.Story) {
|
||||
Preconditions.checkArgument(story.recipient.isGroup)
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.annimon.stream.Stream;
|
|||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.signal.core.util.CursorUtil;
|
||||
import org.signal.core.util.SQLiteDatabaseExtensionsKt;
|
||||
import org.signal.core.util.SetUtil;
|
||||
import org.signal.core.util.SqlUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
|
@ -37,6 +38,7 @@ import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob;
|
|||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct;
|
||||
|
@ -45,6 +47,7 @@ import org.whispersystems.signalservice.api.push.ACI;
|
|||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.push.exceptions.GroupNotFoundException;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.security.SecureRandom;
|
||||
|
@ -84,7 +87,7 @@ public class GroupDatabase extends Database {
|
|||
private static final String EXPECTED_V2_ID = "expected_v2_id";
|
||||
private static final String UNMIGRATED_V1_MEMBERS = "former_v1_members";
|
||||
private static final String DISTRIBUTION_ID = "distribution_id";
|
||||
private static final String DISPLAY_AS_STORY = "display_as_story";
|
||||
private static final String SHOW_AS_STORY_STATE = "display_as_story";
|
||||
|
||||
/** Was temporarily used for PNP accept by pni but is no longer needed/updated */
|
||||
@Deprecated
|
||||
|
@ -118,7 +121,7 @@ public class GroupDatabase extends Database {
|
|||
EXPECTED_V2_ID + " TEXT DEFAULT NULL, " +
|
||||
UNMIGRATED_V1_MEMBERS + " TEXT DEFAULT NULL, " +
|
||||
DISTRIBUTION_ID + " TEXT DEFAULT NULL, " +
|
||||
DISPLAY_AS_STORY + " INTEGER DEFAULT 0, " +
|
||||
SHOW_AS_STORY_STATE + " INTEGER DEFAULT 0, " +
|
||||
AUTH_SERVICE_ID + " TEXT DEFAULT NULL);";
|
||||
|
||||
public static final String[] CREATE_INDEXS = {
|
||||
|
@ -1462,11 +1465,20 @@ public class GroupDatabase extends Database {
|
|||
}
|
||||
|
||||
public @NonNull List<GroupId> getGroupsToDisplayAsStories() throws BadGroupIdException {
|
||||
String[] selection = SqlUtil.buildArgs(GROUP_ID);
|
||||
String where = DISPLAY_AS_STORY + " = ? AND " + ACTIVE + " = ?";
|
||||
String[] whereArgs = SqlUtil.buildArgs(1, 1);
|
||||
String query = "SELECT " + GROUP_ID + ", (" +
|
||||
"SELECT " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.DATE_RECEIVED + " FROM " + MmsDatabase.TABLE_NAME +
|
||||
" WHERE " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.RECIPIENT_ID + " = " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID +
|
||||
" AND " + MmsDatabase.STORY_TYPE + " > 1 ORDER BY " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.DATE_RECEIVED + " DESC LIMIT 1" +
|
||||
") as active_timestamp" +
|
||||
" FROM " + TABLE_NAME +
|
||||
" INNER JOIN " + ThreadDatabase.TABLE_NAME + " ON " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID + " = " + TABLE_NAME + "." + RECIPIENT_ID +
|
||||
" WHERE " + ACTIVE + " = 1 " +
|
||||
" AND (" +
|
||||
SHOW_AS_STORY_STATE + " = " + ShowAsStoryState.ALWAYS.code +
|
||||
" OR (" + SHOW_AS_STORY_STATE + " = " + ShowAsStoryState.IF_ACTIVE.code + " AND active_timestamp IS NOT NULL)" +
|
||||
") ORDER BY active_timestamp DESC";
|
||||
|
||||
try (Cursor cursor = getReadableDatabase().query(TABLE_NAME, selection, where, whereArgs, null, null, null, null)) {
|
||||
try (Cursor cursor = getReadableDatabase().query(query)) {
|
||||
if (cursor == null || cursor.getCount() == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
@ -1480,17 +1492,43 @@ public class GroupDatabase extends Database {
|
|||
}
|
||||
}
|
||||
|
||||
public void markDisplayAsStory(@NonNull GroupId groupId) {
|
||||
markDisplayAsStory(groupId, true);
|
||||
public @NonNull ShowAsStoryState getShowAsStoryState(@NonNull GroupId groupId) {
|
||||
String[] projection = SqlUtil.buildArgs(SHOW_AS_STORY_STATE);
|
||||
String where = GROUP_ID + " = ?";
|
||||
String[] whereArgs = SqlUtil.buildArgs(groupId.toString());
|
||||
|
||||
try (Cursor cursor = getReadableDatabase().query(TABLE_NAME, projection, where, whereArgs, null, null, null)) {
|
||||
if (!cursor.moveToFirst()) {
|
||||
throw new AssertionError("Group does not exist.");
|
||||
}
|
||||
|
||||
public void markDisplayAsStory(@NonNull GroupId groupId, boolean displayAsStory) {
|
||||
int serializedState = CursorUtil.requireInt(cursor, SHOW_AS_STORY_STATE);
|
||||
return ShowAsStoryState.deserialize(serializedState);
|
||||
}
|
||||
}
|
||||
|
||||
public void setShowAsStoryState(@NonNull GroupId groupId, @NonNull ShowAsStoryState showAsStoryState) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(DISPLAY_AS_STORY, displayAsStory);
|
||||
contentValues.put(SHOW_AS_STORY_STATE, showAsStoryState.code);
|
||||
|
||||
getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?", SqlUtil.buildArgs(groupId.toString()));
|
||||
}
|
||||
|
||||
public void setShowAsStoryState(@NonNull Collection<RecipientId> recipientIds, @NonNull ShowAsStoryState showAsStoryState) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
List<SqlUtil.Query> queries = SqlUtil.buildCollectionQuery(RECIPIENT_ID, recipientIds);
|
||||
|
||||
contentValues.put(SHOW_AS_STORY_STATE, showAsStoryState.code);
|
||||
|
||||
SQLiteDatabaseExtensionsKt.withinTransaction(getWritableDatabase(), db -> {
|
||||
for (SqlUtil.Query query : queries) {
|
||||
db.update(TABLE_NAME, contentValues, query.getWhere(), query.getWhereArgs());
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public enum MemberSet {
|
||||
FULL_MEMBERS_INCLUDING_SELF(true, false),
|
||||
FULL_MEMBERS_EXCLUDING_SELF(false, false),
|
||||
|
@ -1506,6 +1544,45 @@ public class GroupDatabase extends Database {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* State object describing whether or not to display a story in a list.
|
||||
*/
|
||||
public enum ShowAsStoryState {
|
||||
/**
|
||||
* The default value. Display the group as a story if the group has stories in it currently.
|
||||
*/
|
||||
IF_ACTIVE(0),
|
||||
/**
|
||||
* Always display the group as a story unless explicitly removed. This state is entered if the
|
||||
* user sends a story to a group or otherwise explicitly selects it to appear.
|
||||
*/
|
||||
ALWAYS(1),
|
||||
/**
|
||||
* Never display the story as a group. This state is entered if the user removes the group from
|
||||
* their list, and is only navigated away from if the user explicitly adds the group again.
|
||||
*/
|
||||
NEVER(2);
|
||||
|
||||
private final int code;
|
||||
|
||||
ShowAsStoryState(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
private static @NonNull ShowAsStoryState deserialize(int code) {
|
||||
switch (code) {
|
||||
case 0:
|
||||
return IF_ACTIVE;
|
||||
case 1:
|
||||
return ALWAYS;
|
||||
case 2:
|
||||
return NEVER;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown code: " + code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum MemberLevel {
|
||||
NOT_A_MEMBER(false),
|
||||
PENDING_MEMBER(false),
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper.getChatCo
|
|||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase.LegacyGroupInsertException
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase.MissedGroupMigrationInsertException
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase.ShowAsStoryState
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.distributionLists
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.groups
|
||||
|
@ -110,6 +111,7 @@ import org.whispersystems.signalservice.api.storage.SignalContactRecord
|
|||
import org.whispersystems.signalservice.api.storage.SignalGroupV1Record
|
||||
import org.whispersystems.signalservice.api.storage.SignalGroupV2Record
|
||||
import org.whispersystems.signalservice.api.storage.StorageId
|
||||
import org.whispersystems.signalservice.internal.storage.protos.GroupV2Record
|
||||
import java.io.Closeable
|
||||
import java.io.IOException
|
||||
import java.util.Arrays
|
||||
|
@ -1076,6 +1078,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
|||
.build()
|
||||
)
|
||||
|
||||
groups.setShowAsStoryState(groupId, insert.storySendMode.toShowAsStoryState())
|
||||
updateExtras(recipient.id) {
|
||||
it.setHideStory(insert.shouldHideStory())
|
||||
}
|
||||
|
@ -1095,12 +1098,14 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
|||
}
|
||||
|
||||
val masterKey = update.old.masterKeyOrThrow
|
||||
val recipient = Recipient.externalGroupExact(GroupId.v2(masterKey))
|
||||
val groupId = GroupId.v2(masterKey)
|
||||
val recipient = Recipient.externalGroupExact(groupId)
|
||||
|
||||
updateExtras(recipient.id) {
|
||||
it.setHideStory(update.new.shouldHideStory())
|
||||
}
|
||||
|
||||
groups.setShowAsStoryState(groupId, update.new.storySendMode.toShowAsStoryState())
|
||||
threads.applyStorageSyncUpdate(recipient.id, update.new)
|
||||
recipient.live().refresh()
|
||||
}
|
||||
|
@ -1209,6 +1214,15 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
|||
}
|
||||
}
|
||||
|
||||
private fun GroupV2Record.StorySendMode.toShowAsStoryState(): ShowAsStoryState {
|
||||
return when (this) {
|
||||
GroupV2Record.StorySendMode.DEFAULT -> ShowAsStoryState.IF_ACTIVE
|
||||
GroupV2Record.StorySendMode.DISABLED -> ShowAsStoryState.NEVER
|
||||
GroupV2Record.StorySendMode.ENABLED -> ShowAsStoryState.ALWAYS
|
||||
GroupV2Record.StorySendMode.UNRECOGNIZED -> ShowAsStoryState.IF_ACTIVE
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRecordForSync(query: String?, args: Array<String>?): List<RecipientRecord> {
|
||||
val table =
|
||||
"""
|
||||
|
|
|
@ -239,10 +239,6 @@ class MediaSelectionRepository(context: Context) {
|
|||
val recipient = Recipient.resolved(contact.recipientId)
|
||||
val isStory = contact.isStory || recipient.isDistributionList
|
||||
|
||||
if (isStory && recipient.isActiveGroup && recipient.isGroup) {
|
||||
SignalDatabase.groups.markDisplayAsStory(recipient.requireGroupId())
|
||||
}
|
||||
|
||||
if (isStory && !recipient.isMyStory) {
|
||||
SignalStore.storyValues().setLatestStorySend(StorySend.newSend(recipient))
|
||||
}
|
||||
|
|
|
@ -68,10 +68,6 @@ class TextStoryPostSendRepository {
|
|||
val recipient = Recipient.resolved(contact.requireShareContact().recipientId.get())
|
||||
val isStory = contact is ContactSearchKey.RecipientSearchKey.Story || recipient.isDistributionList
|
||||
|
||||
if (isStory && recipient.isActiveGroup && recipient.isGroup) {
|
||||
SignalDatabase.groups.markDisplayAsStory(recipient.requireGroupId())
|
||||
}
|
||||
|
||||
if (isStory && !recipient.isMyStory) {
|
||||
SignalStore.storyValues().setLatestStorySend(StorySend.newSend(recipient))
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey;
|
|||
import org.thoughtcrime.securesms.conversation.MessageSendType;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.Mention;
|
||||
|
@ -232,10 +233,6 @@ public final class MultiShareSender {
|
|||
storyType = StoryType.STORY_WITH_REPLIES;
|
||||
}
|
||||
|
||||
if (recipient.isActiveGroup() && recipient.isGroup()) {
|
||||
SignalDatabase.groups().markDisplayAsStory(recipient.requireGroupId());
|
||||
}
|
||||
|
||||
if (!recipient.isMyStory()) {
|
||||
SignalStore.storyValues().setLatestStorySend(StorySend.newSend(recipient));
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.groups.GroupId;
|
|||
import org.thoughtcrime.securesms.groups.GroupsV1MigrationUtil;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.signalservice.api.storage.SignalGroupV2Record;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.GroupV2Record;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
@ -74,9 +75,10 @@ public final class GroupV2RecordProcessor extends DefaultStorageRecordProcessor<
|
|||
long muteUntil = remote.getMuteUntil();
|
||||
boolean notifyForMentionsWhenMuted = remote.notifyForMentionsWhenMuted();
|
||||
boolean hideStory = remote.shouldHideStory();
|
||||
GroupV2Record.StorySendMode storySendMode = remote.getStorySendMode();
|
||||
|
||||
boolean matchesRemote = doParamsMatch(remote, unknownFields, blocked, profileSharing, archived, forcedUnread, muteUntil, notifyForMentionsWhenMuted, hideStory);
|
||||
boolean matchesLocal = doParamsMatch(local, unknownFields, blocked, profileSharing, archived, forcedUnread, muteUntil, notifyForMentionsWhenMuted, hideStory);
|
||||
boolean matchesRemote = doParamsMatch(remote, unknownFields, blocked, profileSharing, archived, forcedUnread, muteUntil, notifyForMentionsWhenMuted, hideStory, storySendMode);
|
||||
boolean matchesLocal = doParamsMatch(local, unknownFields, blocked, profileSharing, archived, forcedUnread, muteUntil, notifyForMentionsWhenMuted, hideStory, storySendMode);
|
||||
|
||||
if (matchesRemote) {
|
||||
return remote;
|
||||
|
@ -91,6 +93,7 @@ public final class GroupV2RecordProcessor extends DefaultStorageRecordProcessor<
|
|||
.setMuteUntil(muteUntil)
|
||||
.setNotifyForMentionsWhenMuted(notifyForMentionsWhenMuted)
|
||||
.setHideStory(hideStory)
|
||||
.setStorySendMode(storySendMode)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +142,8 @@ public final class GroupV2RecordProcessor extends DefaultStorageRecordProcessor<
|
|||
boolean forcedUnread,
|
||||
long muteUntil,
|
||||
boolean notifyForMentionsWhenMuted,
|
||||
boolean hideStory)
|
||||
boolean hideStory,
|
||||
@NonNull GroupV2Record.StorySendMode storySendMode)
|
||||
{
|
||||
return Arrays.equals(unknownFields, group.serializeUnknownFields()) &&
|
||||
blocked == group.isBlocked() &&
|
||||
|
@ -148,6 +152,7 @@ public final class GroupV2RecordProcessor extends DefaultStorageRecordProcessor<
|
|||
forcedUnread == group.isForcedUnread() &&
|
||||
muteUntil == group.getMuteUntil() &&
|
||||
notifyForMentionsWhenMuted == group.notifyForMentionsWhenMuted() &&
|
||||
hideStory == group.shouldHideStory();
|
||||
hideStory == group.shouldHideStory() &&
|
||||
storySendMode == group.getStorySendMode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import androidx.annotation.Nullable;
|
|||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
|
@ -31,6 +32,7 @@ import org.whispersystems.signalservice.api.subscriptions.SubscriberId;
|
|||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.AccountRecord;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.IdentityState;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.GroupV2Record;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -164,6 +166,19 @@ public final class StorageSyncModels {
|
|||
}
|
||||
|
||||
boolean hideStory = recipient.getExtras() != null && recipient.getExtras().hideStory();
|
||||
GroupDatabase.ShowAsStoryState showAsStoryState = SignalDatabase.groups().getShowAsStoryState(groupId);
|
||||
GroupV2Record.StorySendMode storySendMode;
|
||||
|
||||
switch (showAsStoryState) {
|
||||
case ALWAYS:
|
||||
storySendMode = GroupV2Record.StorySendMode.ENABLED;
|
||||
break;
|
||||
case NEVER:
|
||||
storySendMode = GroupV2Record.StorySendMode.DISABLED;
|
||||
break;
|
||||
default:
|
||||
storySendMode = GroupV2Record.StorySendMode.DEFAULT;
|
||||
}
|
||||
|
||||
return new SignalGroupV2Record.Builder(rawStorageId, groupMasterKey, recipient.getSyncExtras().getStorageProto())
|
||||
.setBlocked(recipient.isBlocked())
|
||||
|
@ -173,6 +188,7 @@ public final class StorageSyncModels {
|
|||
.setMuteUntil(recipient.getMuteUntil())
|
||||
.setNotifyForMentionsWhenMuted(recipient.getMentionSetting() == RecipientDatabase.MentionSetting.ALWAYS_NOTIFY)
|
||||
.setHideStory(hideStory)
|
||||
.setStorySendMode(storySendMode)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,18 @@ package org.thoughtcrime.securesms.stories.settings.group
|
|||
import io.reactivex.rxjava3.core.Completable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
|
||||
class GroupStorySettingsRepository {
|
||||
fun unmarkAsGroupStory(groupId: GroupId): Completable {
|
||||
return Completable.fromAction {
|
||||
SignalDatabase.groups.markDisplayAsStory(groupId, false)
|
||||
SignalDatabase.groups.setShowAsStoryState(groupId, GroupDatabase.ShowAsStoryState.NEVER)
|
||||
SignalDatabase.recipients.markNeedsSync(Recipient.externalGroupExact(groupId).id)
|
||||
StorageSyncHelper.scheduleSyncForDataChange()
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
|
||||
|
|
|
@ -2,18 +2,20 @@ package org.thoughtcrime.securesms.stories.settings.story
|
|||
|
||||
import io.reactivex.rxjava3.core.Completable
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
|
||||
class StoriesPrivacySettingsRepository {
|
||||
fun markGroupsAsStories(groups: List<RecipientId>): Completable {
|
||||
return Completable.fromCallable {
|
||||
groups
|
||||
.map { Recipient.resolved(it) }
|
||||
.forEach { SignalDatabase.groups.markDisplayAsStory(it.requireGroupId()) }
|
||||
SignalDatabase.groups.setShowAsStoryState(groups, GroupDatabase.ShowAsStoryState.ALWAYS)
|
||||
SignalDatabase.recipients.markNeedsSync(groups)
|
||||
StorageSyncHelper.scheduleSyncForDataChange()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
package org.signal.core.util
|
||||
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import android.content.ContentValues
|
||||
import android.text.TextUtils
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import java.lang.NullPointerException
|
||||
import java.lang.StringBuilder
|
||||
import java.util.ArrayList
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import java.util.LinkedList
|
||||
import java.util.Locale
|
||||
import java.util.stream.Collectors
|
||||
|
|
|
@ -82,6 +82,10 @@ public final class SignalGroupV2Record implements SignalRecord {
|
|||
diff.add("HideStory");
|
||||
}
|
||||
|
||||
if (!Objects.equals(this.getStorySendMode(), that.getStorySendMode())) {
|
||||
diff.add("StorySendMode");
|
||||
}
|
||||
|
||||
if (!Objects.equals(this.hasUnknownFields(), that.hasUnknownFields())) {
|
||||
diff.add("UnknownFields");
|
||||
}
|
||||
|
@ -140,6 +144,10 @@ public final class SignalGroupV2Record implements SignalRecord {
|
|||
return proto.getHideStory();
|
||||
}
|
||||
|
||||
public GroupV2Record.StorySendMode getStorySendMode() {
|
||||
return proto.getStorySendMode();
|
||||
}
|
||||
|
||||
public GroupV2Record toProto() {
|
||||
return proto;
|
||||
}
|
||||
|
@ -213,6 +221,11 @@ public final class SignalGroupV2Record implements SignalRecord {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setStorySendMode(GroupV2Record.StorySendMode storySendMode) {
|
||||
builder.setStorySendMode(storySendMode);
|
||||
return this;
|
||||
}
|
||||
|
||||
private static GroupV2Record.Builder parseUnknowns(byte[] serializedUnknowns) {
|
||||
try {
|
||||
return GroupV2Record.parseFrom(serializedUnknowns).toBuilder();
|
||||
|
|
|
@ -100,6 +100,12 @@ message GroupV1Record {
|
|||
}
|
||||
|
||||
message GroupV2Record {
|
||||
enum StorySendMode {
|
||||
DEFAULT = 0;
|
||||
DISABLED = 1;
|
||||
ENABLED = 2;
|
||||
}
|
||||
|
||||
bytes masterKey = 1;
|
||||
bool blocked = 2;
|
||||
bool whitelisted = 3;
|
||||
|
@ -108,6 +114,8 @@ message GroupV2Record {
|
|||
uint64 mutedUntilTimestamp = 6;
|
||||
bool dontNotifyForMentionsIfMuted = 7;
|
||||
bool hideStory = 8;
|
||||
reserved /* storySendEnabled */ 9;
|
||||
StorySendMode storySendMode = 10;
|
||||
}
|
||||
|
||||
message Payments {
|
||||
|
|
Ładowanie…
Reference in New Issue