mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 08:39:22 +01:00
Implement ability to view badges and modify whether they appear.
Note: this is available in staging only.
This commit is contained in:
@@ -23,6 +23,7 @@ import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.groups.GroupMasterKey;
|
||||
import org.signal.zkgroup.profiles.ProfileKey;
|
||||
import org.signal.zkgroup.profiles.ProfileKeyCredential;
|
||||
import org.thoughtcrime.securesms.badges.models.Badge;
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||
@@ -33,6 +34,7 @@ import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BadgeList;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ChatColor;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DeviceLastResetTime;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ProfileKeyCredentialColumnData;
|
||||
@@ -153,6 +155,7 @@ public class RecipientDatabase extends Database {
|
||||
private static final String GROUPS_IN_COMMON = "groups_in_common";
|
||||
private static final String CHAT_COLORS = "chat_colors";
|
||||
private static final String CUSTOM_CHAT_COLORS_ID = "custom_chat_colors_id";
|
||||
private static final String BADGES = "badges";
|
||||
|
||||
public static final String SEARCH_PROFILE_NAME = "search_signal_profile";
|
||||
private static final String SORT_NAME = "sort_name";
|
||||
@@ -188,7 +191,8 @@ public class RecipientDatabase extends Database {
|
||||
MENTION_SETTING,
|
||||
ABOUT, ABOUT_EMOJI,
|
||||
EXTRAS, GROUPS_IN_COMMON,
|
||||
CHAT_COLORS, CUSTOM_CHAT_COLORS_ID
|
||||
CHAT_COLORS, CUSTOM_CHAT_COLORS_ID,
|
||||
BADGES
|
||||
};
|
||||
|
||||
private static final String[] ID_PROJECTION = new String[]{ID};
|
||||
@@ -372,7 +376,8 @@ public class RecipientDatabase extends Database {
|
||||
EXTRAS + " BLOB DEFAULT NULL, " +
|
||||
GROUPS_IN_COMMON + " INTEGER DEFAULT 0, " +
|
||||
CHAT_COLORS + " BLOB DEFAULT NULL, " +
|
||||
CUSTOM_CHAT_COLORS_ID + " INTEGER DEFAULT 0);";
|
||||
CUSTOM_CHAT_COLORS_ID + " INTEGER DEFAULT 0, " +
|
||||
BADGES + " BLOB DEFAULT NULL);";
|
||||
|
||||
private static final String INSIGHTS_INVITEE_LIST = "SELECT " + TABLE_NAME + "." + ID +
|
||||
" FROM " + TABLE_NAME +
|
||||
@@ -1208,49 +1213,52 @@ public class RecipientDatabase extends Database {
|
||||
}
|
||||
|
||||
static @NonNull RecipientSettings getRecipientSettings(@NonNull Context context, @NonNull Cursor cursor, @NonNull String idColumnName) {
|
||||
long id = CursorUtil.requireLong(cursor, idColumnName);
|
||||
UUID uuid = UuidUtil.parseOrNull(CursorUtil.requireString(cursor, UUID));
|
||||
String username = CursorUtil.requireString(cursor, USERNAME);
|
||||
String e164 = CursorUtil.requireString(cursor, PHONE);
|
||||
String email = CursorUtil.requireString(cursor, EMAIL);
|
||||
GroupId groupId = GroupId.parseNullableOrThrow(CursorUtil.requireString(cursor, GROUP_ID));
|
||||
int groupType = CursorUtil.requireInt(cursor, GROUP_TYPE);
|
||||
boolean blocked = CursorUtil.requireBoolean(cursor, BLOCKED);
|
||||
String messageRingtone = CursorUtil.requireString(cursor, MESSAGE_RINGTONE);
|
||||
String callRingtone = CursorUtil.requireString(cursor, CALL_RINGTONE);
|
||||
int messageVibrateState = CursorUtil.requireInt(cursor, MESSAGE_VIBRATE);
|
||||
int callVibrateState = CursorUtil.requireInt(cursor, CALL_VIBRATE);
|
||||
long muteUntil = cursor.getLong(cursor.getColumnIndexOrThrow(MUTE_UNTIL));
|
||||
int insightsBannerTier = CursorUtil.requireInt(cursor, SEEN_INVITE_REMINDER);
|
||||
int defaultSubscriptionId = CursorUtil.requireInt(cursor, DEFAULT_SUBSCRIPTION_ID);
|
||||
int expireMessages = CursorUtil.requireInt(cursor, MESSAGE_EXPIRATION_TIME);
|
||||
int registeredState = CursorUtil.requireInt(cursor, REGISTERED);
|
||||
String profileKeyString = CursorUtil.requireString(cursor, PROFILE_KEY);
|
||||
String profileKeyCredentialString = CursorUtil.requireString(cursor, PROFILE_KEY_CREDENTIAL);
|
||||
String systemGivenName = CursorUtil.requireString(cursor, SYSTEM_GIVEN_NAME);
|
||||
String systemFamilyName = CursorUtil.requireString(cursor, SYSTEM_FAMILY_NAME);
|
||||
String systemDisplayName = CursorUtil.requireString(cursor, SYSTEM_JOINED_NAME);
|
||||
String systemContactPhoto = CursorUtil.requireString(cursor, SYSTEM_PHOTO_URI);
|
||||
String systemPhoneLabel = CursorUtil.requireString(cursor, SYSTEM_PHONE_LABEL);
|
||||
String systemContactUri = CursorUtil.requireString(cursor, SYSTEM_CONTACT_URI);
|
||||
String profileGivenName = CursorUtil.requireString(cursor, PROFILE_GIVEN_NAME);
|
||||
String profileFamilyName = CursorUtil.requireString(cursor, PROFILE_FAMILY_NAME);
|
||||
String signalProfileAvatar = CursorUtil.requireString(cursor, SIGNAL_PROFILE_AVATAR);
|
||||
boolean profileSharing = CursorUtil.requireBoolean(cursor, PROFILE_SHARING);
|
||||
long lastProfileFetch = cursor.getLong(cursor.getColumnIndexOrThrow(LAST_PROFILE_FETCH));
|
||||
String notificationChannel = CursorUtil.requireString(cursor, NOTIFICATION_CHANNEL);
|
||||
int unidentifiedAccessMode = CursorUtil.requireInt(cursor, UNIDENTIFIED_ACCESS_MODE);
|
||||
boolean forceSmsSelection = CursorUtil.requireBoolean(cursor, FORCE_SMS_SELECTION);
|
||||
long capabilities = CursorUtil.requireLong(cursor, CAPABILITIES);
|
||||
String storageKeyRaw = CursorUtil.requireString(cursor, STORAGE_SERVICE_ID);
|
||||
int mentionSettingId = CursorUtil.requireInt(cursor, MENTION_SETTING);
|
||||
byte[] wallpaper = CursorUtil.requireBlob(cursor, WALLPAPER);
|
||||
byte[] serializedChatColors = CursorUtil.requireBlob(cursor, CHAT_COLORS);
|
||||
long customChatColorsId = CursorUtil.requireLong(cursor, CUSTOM_CHAT_COLORS_ID);
|
||||
String serializedAvatarColor = CursorUtil.requireString(cursor, AVATAR_COLOR);
|
||||
String about = CursorUtil.requireString(cursor, ABOUT);
|
||||
String aboutEmoji = CursorUtil.requireString(cursor, ABOUT_EMOJI);
|
||||
boolean hasGroupsInCommon = CursorUtil.requireBoolean(cursor, GROUPS_IN_COMMON);
|
||||
long id = CursorUtil.requireLong(cursor, idColumnName);
|
||||
UUID uuid = UuidUtil.parseOrNull(CursorUtil.requireString(cursor, UUID));
|
||||
String username = CursorUtil.requireString(cursor, USERNAME);
|
||||
String e164 = CursorUtil.requireString(cursor, PHONE);
|
||||
String email = CursorUtil.requireString(cursor, EMAIL);
|
||||
GroupId groupId = GroupId.parseNullableOrThrow(CursorUtil.requireString(cursor, GROUP_ID));
|
||||
int groupType = CursorUtil.requireInt(cursor, GROUP_TYPE);
|
||||
boolean blocked = CursorUtil.requireBoolean(cursor, BLOCKED);
|
||||
String messageRingtone = CursorUtil.requireString(cursor, MESSAGE_RINGTONE);
|
||||
String callRingtone = CursorUtil.requireString(cursor, CALL_RINGTONE);
|
||||
int messageVibrateState = CursorUtil.requireInt(cursor, MESSAGE_VIBRATE);
|
||||
int callVibrateState = CursorUtil.requireInt(cursor, CALL_VIBRATE);
|
||||
long muteUntil = cursor.getLong(cursor.getColumnIndexOrThrow(MUTE_UNTIL));
|
||||
int insightsBannerTier = CursorUtil.requireInt(cursor, SEEN_INVITE_REMINDER);
|
||||
int defaultSubscriptionId = CursorUtil.requireInt(cursor, DEFAULT_SUBSCRIPTION_ID);
|
||||
int expireMessages = CursorUtil.requireInt(cursor, MESSAGE_EXPIRATION_TIME);
|
||||
int registeredState = CursorUtil.requireInt(cursor, REGISTERED);
|
||||
String profileKeyString = CursorUtil.requireString(cursor, PROFILE_KEY);
|
||||
String profileKeyCredentialString = CursorUtil.requireString(cursor, PROFILE_KEY_CREDENTIAL);
|
||||
String systemGivenName = CursorUtil.requireString(cursor, SYSTEM_GIVEN_NAME);
|
||||
String systemFamilyName = CursorUtil.requireString(cursor, SYSTEM_FAMILY_NAME);
|
||||
String systemDisplayName = CursorUtil.requireString(cursor, SYSTEM_JOINED_NAME);
|
||||
String systemContactPhoto = CursorUtil.requireString(cursor, SYSTEM_PHOTO_URI);
|
||||
String systemPhoneLabel = CursorUtil.requireString(cursor, SYSTEM_PHONE_LABEL);
|
||||
String systemContactUri = CursorUtil.requireString(cursor, SYSTEM_CONTACT_URI);
|
||||
String profileGivenName = CursorUtil.requireString(cursor, PROFILE_GIVEN_NAME);
|
||||
String profileFamilyName = CursorUtil.requireString(cursor, PROFILE_FAMILY_NAME);
|
||||
String signalProfileAvatar = CursorUtil.requireString(cursor, SIGNAL_PROFILE_AVATAR);
|
||||
boolean profileSharing = CursorUtil.requireBoolean(cursor, PROFILE_SHARING);
|
||||
long lastProfileFetch = cursor.getLong(cursor.getColumnIndexOrThrow(LAST_PROFILE_FETCH));
|
||||
String notificationChannel = CursorUtil.requireString(cursor, NOTIFICATION_CHANNEL);
|
||||
int unidentifiedAccessMode = CursorUtil.requireInt(cursor, UNIDENTIFIED_ACCESS_MODE);
|
||||
boolean forceSmsSelection = CursorUtil.requireBoolean(cursor, FORCE_SMS_SELECTION);
|
||||
long capabilities = CursorUtil.requireLong(cursor, CAPABILITIES);
|
||||
String storageKeyRaw = CursorUtil.requireString(cursor, STORAGE_SERVICE_ID);
|
||||
int mentionSettingId = CursorUtil.requireInt(cursor, MENTION_SETTING);
|
||||
byte[] wallpaper = CursorUtil.requireBlob(cursor, WALLPAPER);
|
||||
byte[] serializedChatColors = CursorUtil.requireBlob(cursor, CHAT_COLORS);
|
||||
long customChatColorsId = CursorUtil.requireLong(cursor, CUSTOM_CHAT_COLORS_ID);
|
||||
String serializedAvatarColor = CursorUtil.requireString(cursor, AVATAR_COLOR);
|
||||
String about = CursorUtil.requireString(cursor, ABOUT);
|
||||
String aboutEmoji = CursorUtil.requireString(cursor, ABOUT_EMOJI);
|
||||
boolean hasGroupsInCommon = CursorUtil.requireBoolean(cursor, GROUPS_IN_COMMON);
|
||||
byte[] serializedBadgeList = CursorUtil.requireBlob(cursor, BADGES);
|
||||
|
||||
List<Badge> badges = parseBadgeList(serializedBadgeList);
|
||||
|
||||
byte[] profileKey = null;
|
||||
ProfileKeyCredential profileKeyCredential = null;
|
||||
@@ -1343,7 +1351,40 @@ public class RecipientDatabase extends Database {
|
||||
aboutEmoji,
|
||||
getSyncExtras(cursor),
|
||||
getExtras(cursor),
|
||||
hasGroupsInCommon);
|
||||
hasGroupsInCommon,
|
||||
badges);
|
||||
}
|
||||
|
||||
private static @NonNull List<Badge> parseBadgeList(byte[] serializedBadgeList) {
|
||||
BadgeList badgeList = null;
|
||||
if (serializedBadgeList != null) {
|
||||
try {
|
||||
badgeList = BadgeList.parseFrom(serializedBadgeList);
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
|
||||
List<Badge> badges;
|
||||
if (badgeList != null) {
|
||||
List<BadgeList.Badge> protoBadges = badgeList.getBadgesList();
|
||||
badges = new ArrayList<>(protoBadges.size());
|
||||
for (BadgeList.Badge protoBadge : protoBadges) {
|
||||
badges.add(new Badge(
|
||||
protoBadge.getId(),
|
||||
Badge.Category.Companion.fromCode(protoBadge.getCategory()),
|
||||
Uri.parse(protoBadge.getImageUrl()),
|
||||
protoBadge.getName(),
|
||||
protoBadge.getDescription(),
|
||||
protoBadge.getExpiration(),
|
||||
protoBadge.getVisible()
|
||||
));
|
||||
}
|
||||
} else {
|
||||
badges = Collections.emptyList();
|
||||
}
|
||||
|
||||
return badges;
|
||||
}
|
||||
|
||||
private static @NonNull RecipientSettings.SyncExtras getSyncExtras(@NonNull Cursor cursor) {
|
||||
@@ -1639,6 +1680,28 @@ public class RecipientDatabase extends Database {
|
||||
return DeviceLastResetTime.newBuilder().build();
|
||||
}
|
||||
|
||||
public void setBadges(@NonNull RecipientId id, @NonNull List<Badge> badges) {
|
||||
BadgeList.Builder badgeListBuilder = BadgeList.newBuilder();
|
||||
|
||||
for (final Badge badge : badges) {
|
||||
badgeListBuilder.addBadges(BadgeList.Badge.newBuilder()
|
||||
.setId(badge.getId())
|
||||
.setCategory(badge.getCategory().getCode())
|
||||
.setDescription(badge.getDescription())
|
||||
.setExpiration(badge.getExpirationTimestamp())
|
||||
.setVisible(badge.getVisible())
|
||||
.setName(badge.getName())
|
||||
.setImageUrl(badge.getImageUrl().toString()));
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.put(BADGES, badgeListBuilder.build().toByteArray());
|
||||
|
||||
if (update(id, values)) {
|
||||
Recipient.live(id).refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setCapabilities(@NonNull RecipientId id, @NonNull SignalServiceProfile.Capabilities capabilities) {
|
||||
long value = 0;
|
||||
|
||||
@@ -3228,6 +3291,7 @@ public class RecipientDatabase extends Database {
|
||||
private final SyncExtras syncExtras;
|
||||
private final Recipient.Extras extras;
|
||||
private final boolean hasGroupsInCommon;
|
||||
private final List<Badge> badges;
|
||||
|
||||
RecipientSettings(@NonNull RecipientId id,
|
||||
@Nullable UUID uuid,
|
||||
@@ -3271,7 +3335,8 @@ public class RecipientDatabase extends Database {
|
||||
@Nullable String aboutEmoji,
|
||||
@NonNull SyncExtras syncExtras,
|
||||
@Nullable Recipient.Extras extras,
|
||||
boolean hasGroupsInCommon)
|
||||
boolean hasGroupsInCommon,
|
||||
@NonNull List<Badge> badges)
|
||||
{
|
||||
this.id = id;
|
||||
this.uuid = uuid;
|
||||
@@ -3318,9 +3383,10 @@ public class RecipientDatabase extends Database {
|
||||
this.avatarColor = avatarColor;
|
||||
this.about = about;
|
||||
this.aboutEmoji = aboutEmoji;
|
||||
this.syncExtras = syncExtras;
|
||||
this.extras = extras;
|
||||
this.hasGroupsInCommon = hasGroupsInCommon;
|
||||
this.syncExtras = syncExtras;
|
||||
this.extras = extras;
|
||||
this.hasGroupsInCommon = hasGroupsInCommon;
|
||||
this.badges = badges;
|
||||
}
|
||||
|
||||
public RecipientId getId() {
|
||||
@@ -3511,6 +3577,10 @@ public class RecipientDatabase extends Database {
|
||||
return hasGroupsInCommon;
|
||||
}
|
||||
|
||||
public @NonNull List<Badge> getBadges() {
|
||||
return badges;
|
||||
}
|
||||
|
||||
long getCapabilities() {
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
@@ -216,8 +216,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab
|
||||
private static final int GROUP_CALL_RING_TABLE = 115;
|
||||
private static final int CLEANUP_SESSION_MIGRATION = 116;
|
||||
private static final int RECEIPT_TIMESTAMP = 117;
|
||||
private static final int BADGES = 118;
|
||||
|
||||
private static final int DATABASE_VERSION = 117;
|
||||
private static final int DATABASE_VERSION = 118;
|
||||
private static final String DATABASE_NAME = "signal.db";
|
||||
|
||||
private final Context context;
|
||||
@@ -2043,6 +2044,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab
|
||||
db.execSQL("ALTER TABLE mms ADD COLUMN receipt_timestamp INTEGER DEFAULT -1");
|
||||
}
|
||||
|
||||
if (oldVersion < BADGES) {
|
||||
db.execSQL("ALTER TABLE recipient ADD COLUMN badges BLOB DEFAULT NULL");
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
||||
Reference in New Issue
Block a user