Add support for new group story display states.

fork-5.53.8
Alex Hart 2022-09-22 13:21:53 -03:00 zatwierdzone przez Cody Henthorne
rodzic 8ca94eb3d5
commit c47a724654
16 zmienionych plików z 211 dodań i 63 usunięć

Wyświetl plik

@ -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.

Wyświetl plik

@ -261,7 +261,6 @@ class ContactSearchPagedDataSource(
rhs.recipient.isMyStory -> 1
lhsActiveRank < rhsActiveRank -> -1
lhsActiveRank > rhsActiveRank -> 1
lhsActiveRank == rhsActiveRank -> -1
else -> 0
}
}

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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),

Wyświetl plik

@ -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 =
"""

Wyświetl plik

@ -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))
}

Wyświetl plik

@ -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))
}

Wyświetl plik

@ -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));
}

Wyświetl plik

@ -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();
}
}

Wyświetl plik

@ -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();
}

Wyświetl plik

@ -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())
}

Wyświetl plik

@ -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()
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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();

Wyświetl plik

@ -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 {