mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-23 02:10:44 +01:00
Implement StoryDistributionListRecord and processing.
This commit is contained in:
committed by
Cody Henthorne
parent
2cd7462573
commit
c359b0134a
@@ -6,6 +6,7 @@ import android.database.Cursor
|
||||
import androidx.core.content.contentValuesOf
|
||||
import org.signal.core.util.CursorUtil
|
||||
import org.signal.core.util.SqlUtil
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.requireLong
|
||||
import org.signal.core.util.requireNonNullString
|
||||
import org.signal.core.util.requireString
|
||||
@@ -14,9 +15,12 @@ import org.thoughtcrime.securesms.database.model.DistributionListPartialRecord
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListRecord
|
||||
import org.thoughtcrime.securesms.database.model.StoryType
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.storage.StorageRecordUpdate
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.util.Base64
|
||||
import org.whispersystems.signalservice.api.push.DistributionId
|
||||
import org.whispersystems.signalservice.api.storage.SignalStoryDistributionListRecord
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
@@ -25,6 +29,8 @@ import java.util.UUID
|
||||
class DistributionListDatabase constructor(context: Context?, databaseHelper: SignalDatabase?) : Database(context, databaseHelper) {
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(DistributionListDatabase::class.java)
|
||||
|
||||
@JvmField
|
||||
val CREATE_TABLE: Array<String> = arrayOf(ListTable.CREATE_TABLE, MembershipTable.CREATE_TABLE)
|
||||
|
||||
@@ -34,18 +40,18 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
||||
val recipientId = db.insert(
|
||||
RecipientDatabase.TABLE_NAME, null,
|
||||
contentValuesOf(
|
||||
RecipientDatabase.GROUP_TYPE to RecipientDatabase.GroupType.DISTRIBUTION_LIST.id,
|
||||
RecipientDatabase.DISTRIBUTION_LIST_ID to DistributionListId.MY_STORY_ID,
|
||||
RecipientDatabase.STORAGE_SERVICE_ID to Base64.encodeBytes(StorageSyncHelper.generateKey()),
|
||||
RecipientDatabase.PROFILE_SHARING to 1
|
||||
)
|
||||
)
|
||||
val listUUID = UUID.randomUUID().toString()
|
||||
db.insert(
|
||||
ListTable.TABLE_NAME, null,
|
||||
contentValuesOf(
|
||||
ListTable.ID to DistributionListId.MY_STORY_ID,
|
||||
ListTable.NAME to listUUID,
|
||||
ListTable.DISTRIBUTION_ID to listUUID,
|
||||
ListTable.NAME to DistributionId.MY_STORY.toString(),
|
||||
ListTable.DISTRIBUTION_ID to DistributionId.MY_STORY.toString(),
|
||||
ListTable.RECIPIENT_ID to recipientId
|
||||
)
|
||||
)
|
||||
@@ -60,6 +66,7 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
||||
const val DISTRIBUTION_ID = "distribution_id"
|
||||
const val RECIPIENT_ID = "recipient_id"
|
||||
const val ALLOWS_REPLIES = "allows_replies"
|
||||
const val DELETION_TIMESTAMP = "deletion_timestamp"
|
||||
|
||||
const val CREATE_TABLE = """
|
||||
CREATE TABLE $TABLE_NAME (
|
||||
@@ -67,9 +74,12 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
||||
$NAME TEXT UNIQUE NOT NULL,
|
||||
$DISTRIBUTION_ID TEXT UNIQUE NOT NULL,
|
||||
$RECIPIENT_ID INTEGER UNIQUE REFERENCES ${RecipientDatabase.TABLE_NAME} (${RecipientDatabase.ID}),
|
||||
$ALLOWS_REPLIES INTEGER DEFAULT 1
|
||||
$ALLOWS_REPLIES INTEGER DEFAULT 1,
|
||||
$DELETION_TIMESTAMP INTEGER DEFAULT 0
|
||||
)
|
||||
"""
|
||||
|
||||
const val IS_NOT_DELETED = "$DELETION_TIMESTAMP == 0"
|
||||
}
|
||||
|
||||
private object MembershipTable {
|
||||
@@ -127,10 +137,10 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
||||
val projection = arrayOf(ListTable.ID, ListTable.NAME, ListTable.RECIPIENT_ID, ListTable.ALLOWS_REPLIES)
|
||||
|
||||
val where = when {
|
||||
query.isNullOrEmpty() && includeMyStory -> null
|
||||
query.isNullOrEmpty() -> "${ListTable.ID} != ?"
|
||||
includeMyStory -> "${ListTable.NAME} LIKE ? OR ${ListTable.ID} == ?"
|
||||
else -> "${ListTable.NAME} LIKE ? AND ${ListTable.ID} != ?"
|
||||
query.isNullOrEmpty() && includeMyStory -> ListTable.IS_NOT_DELETED
|
||||
query.isNullOrEmpty() -> "${ListTable.ID} != ? AND ${ListTable.IS_NOT_DELETED}"
|
||||
includeMyStory -> "(${ListTable.NAME} LIKE ? OR ${ListTable.ID} == ?) AND ${ListTable.IS_NOT_DELETED}"
|
||||
else -> "${ListTable.NAME} LIKE ? AND ${ListTable.ID} != ? AND ${ListTable.IS_NOT_DELETED}"
|
||||
}
|
||||
|
||||
val whereArgs = when {
|
||||
@@ -145,7 +155,7 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
||||
fun getCustomListsForUi(): List<DistributionListPartialRecord> {
|
||||
val db = readableDatabase
|
||||
val projection = SqlUtil.buildArgs(ListTable.ID, ListTable.NAME, ListTable.RECIPIENT_ID, ListTable.ALLOWS_REPLIES)
|
||||
val selection = "${ListTable.ID} != ${DistributionListId.MY_STORY_ID}"
|
||||
val selection = "${ListTable.ID} != ${DistributionListId.MY_STORY_ID} AND ${ListTable.IS_NOT_DELETED}"
|
||||
|
||||
return db.query(ListTable.TABLE_NAME, projection, selection, null, null, null, null)?.use {
|
||||
val results = mutableListOf<DistributionListPartialRecord>()
|
||||
@@ -167,15 +177,23 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
||||
/**
|
||||
* @return The id of the list if successful, otherwise null. If not successful, you can assume it was a name conflict.
|
||||
*/
|
||||
fun createList(name: String, members: List<RecipientId>): DistributionListId? {
|
||||
fun createList(
|
||||
name: String,
|
||||
members: List<RecipientId>,
|
||||
distributionId: DistributionId = DistributionId.from(UUID.randomUUID()),
|
||||
allowsReplies: Boolean = true,
|
||||
deletionTimestamp: Long = 0L
|
||||
): DistributionListId? {
|
||||
val db = writableDatabase
|
||||
|
||||
db.beginTransaction()
|
||||
try {
|
||||
val values = ContentValues().apply {
|
||||
put(ListTable.NAME, name)
|
||||
put(ListTable.DISTRIBUTION_ID, UUID.randomUUID().toString())
|
||||
put(ListTable.NAME, if (deletionTimestamp == 0L) name else createUniqueNameForDeletedStory())
|
||||
put(ListTable.DISTRIBUTION_ID, distributionId.toString())
|
||||
put(ListTable.ALLOWS_REPLIES, if (deletionTimestamp == 0L) allowsReplies else false)
|
||||
putNull(ListTable.RECIPIENT_ID)
|
||||
put(ListTable.DELETION_TIMESTAMP, deletionTimestamp)
|
||||
}
|
||||
|
||||
val id = writableDatabase.insert(ListTable.TABLE_NAME, null, values)
|
||||
@@ -203,7 +221,7 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
||||
}
|
||||
|
||||
fun getStoryType(listId: DistributionListId): StoryType {
|
||||
readableDatabase.query(ListTable.TABLE_NAME, arrayOf(ListTable.ALLOWS_REPLIES), "${ListTable.ID} = ?", SqlUtil.buildArgs(listId), null, null, null).use { cursor ->
|
||||
readableDatabase.query(ListTable.TABLE_NAME, arrayOf(ListTable.ALLOWS_REPLIES), "${ListTable.ID} = ? AND ${ListTable.IS_NOT_DELETED}", SqlUtil.buildArgs(listId), null, null, null).use { cursor ->
|
||||
return if (cursor.moveToFirst()) {
|
||||
if (CursorUtil.requireBoolean(cursor, ListTable.ALLOWS_REPLIES)) {
|
||||
StoryType.STORY_WITH_REPLIES
|
||||
@@ -217,10 +235,29 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
||||
}
|
||||
|
||||
fun setAllowsReplies(listId: DistributionListId, allowsReplies: Boolean) {
|
||||
writableDatabase.update(ListTable.TABLE_NAME, contentValuesOf(ListTable.ALLOWS_REPLIES to allowsReplies), "${ListTable.ID} = ?", SqlUtil.buildArgs(listId))
|
||||
writableDatabase.update(ListTable.TABLE_NAME, contentValuesOf(ListTable.ALLOWS_REPLIES to allowsReplies), "${ListTable.ID} = ? AND ${ListTable.IS_NOT_DELETED}", SqlUtil.buildArgs(listId))
|
||||
}
|
||||
|
||||
fun getList(listId: DistributionListId): DistributionListRecord? {
|
||||
readableDatabase.query(ListTable.TABLE_NAME, null, "${ListTable.ID} = ? AND ${ListTable.IS_NOT_DELETED}", SqlUtil.buildArgs(listId), null, null, null).use { cursor ->
|
||||
return if (cursor.moveToFirst()) {
|
||||
val id: DistributionListId = DistributionListId.from(cursor.requireLong(ListTable.ID))
|
||||
|
||||
DistributionListRecord(
|
||||
id = id,
|
||||
name = cursor.requireNonNullString(ListTable.NAME),
|
||||
distributionId = DistributionId.from(cursor.requireNonNullString(ListTable.DISTRIBUTION_ID)),
|
||||
allowsReplies = CursorUtil.requireBoolean(cursor, ListTable.ALLOWS_REPLIES),
|
||||
members = getMembers(id),
|
||||
deletedAtTimestamp = 0L
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getListForStorageSync(listId: DistributionListId): DistributionListRecord? {
|
||||
readableDatabase.query(ListTable.TABLE_NAME, null, "${ListTable.ID} = ?", SqlUtil.buildArgs(listId), null, null, null).use { cursor ->
|
||||
return if (cursor.moveToFirst()) {
|
||||
val id: DistributionListId = DistributionListId.from(cursor.requireLong(ListTable.ID))
|
||||
@@ -230,7 +267,8 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
||||
name = cursor.requireNonNullString(ListTable.NAME),
|
||||
distributionId = DistributionId.from(cursor.requireNonNullString(ListTable.DISTRIBUTION_ID)),
|
||||
allowsReplies = CursorUtil.requireBoolean(cursor, ListTable.ALLOWS_REPLIES),
|
||||
members = getMembers(id)
|
||||
members = getRawMembers(id),
|
||||
deletedAtTimestamp = cursor.requireLong(ListTable.DELETION_TIMESTAMP)
|
||||
)
|
||||
} else {
|
||||
null
|
||||
@@ -239,7 +277,7 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
||||
}
|
||||
|
||||
fun getDistributionId(listId: DistributionListId): DistributionId? {
|
||||
readableDatabase.query(ListTable.TABLE_NAME, arrayOf(ListTable.DISTRIBUTION_ID), "${ListTable.ID} = ?", SqlUtil.buildArgs(listId), null, null, null).use { cursor ->
|
||||
readableDatabase.query(ListTable.TABLE_NAME, arrayOf(ListTable.DISTRIBUTION_ID), "${ListTable.ID} = ? AND ${ListTable.IS_NOT_DELETED}", SqlUtil.buildArgs(listId), null, null, null).use { cursor ->
|
||||
return if (cursor.moveToFirst()) {
|
||||
DistributionId.from(cursor.requireString(ListTable.DISTRIBUTION_ID))
|
||||
} else {
|
||||
@@ -318,7 +356,130 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
||||
writableDatabase.update(MembershipTable.TABLE_NAME, values, "${MembershipTable.RECIPIENT_ID} = ?", SqlUtil.buildArgs(oldId))
|
||||
}
|
||||
|
||||
fun deleteList(distributionListId: DistributionListId) {
|
||||
writableDatabase.delete(ListTable.TABLE_NAME, ID_WHERE, SqlUtil.buildArgs(distributionListId))
|
||||
fun deleteList(distributionListId: DistributionListId, deletionTimestamp: Long = System.currentTimeMillis()) {
|
||||
writableDatabase.update(
|
||||
ListTable.TABLE_NAME,
|
||||
contentValuesOf(
|
||||
ListTable.NAME to createUniqueNameForDeletedStory(),
|
||||
ListTable.ALLOWS_REPLIES to false,
|
||||
ListTable.DELETION_TIMESTAMP to deletionTimestamp
|
||||
),
|
||||
ID_WHERE,
|
||||
SqlUtil.buildArgs(distributionListId)
|
||||
)
|
||||
|
||||
writableDatabase.delete(
|
||||
MembershipTable.TABLE_NAME,
|
||||
"${MembershipTable.LIST_ID} = ?",
|
||||
SqlUtil.buildArgs(distributionListId)
|
||||
)
|
||||
}
|
||||
|
||||
fun getRecipientIdForSyncRecord(record: SignalStoryDistributionListRecord): RecipientId? {
|
||||
val uuid: UUID = UuidUtil.parseOrNull(record.identifier) ?: return null
|
||||
val distributionId = DistributionId.from(uuid)
|
||||
|
||||
return readableDatabase.query(
|
||||
ListTable.TABLE_NAME,
|
||||
arrayOf(ListTable.RECIPIENT_ID),
|
||||
"${ListTable.DISTRIBUTION_ID} = ?",
|
||||
SqlUtil.buildArgs(distributionId.toString()),
|
||||
null, null, null
|
||||
)?.use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
RecipientId.from(CursorUtil.requireLong(cursor, ListTable.RECIPIENT_ID))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getRecipientId(distributionListId: DistributionListId): RecipientId? {
|
||||
return readableDatabase.query(
|
||||
ListTable.TABLE_NAME,
|
||||
arrayOf(ListTable.RECIPIENT_ID),
|
||||
"${ListTable.ID} = ?",
|
||||
SqlUtil.buildArgs(distributionListId),
|
||||
null, null, null
|
||||
)?.use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
RecipientId.from(CursorUtil.requireLong(cursor, ListTable.RECIPIENT_ID))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun applyStorageSyncStoryDistributionListInsert(insert: SignalStoryDistributionListRecord) {
|
||||
createList(
|
||||
name = insert.name,
|
||||
members = insert.recipients.map(RecipientId::from),
|
||||
distributionId = DistributionId.from(UuidUtil.parseOrThrow(insert.identifier)),
|
||||
allowsReplies = insert.allowsReplies(),
|
||||
deletionTimestamp = insert.deletedAtTimestamp
|
||||
)
|
||||
}
|
||||
|
||||
fun applyStorageSyncStoryDistributionListUpdate(update: StorageRecordUpdate<SignalStoryDistributionListRecord>) {
|
||||
val distributionId = DistributionId.from(UuidUtil.parseOrThrow(update.new.identifier))
|
||||
|
||||
val distributionListId: DistributionListId? = readableDatabase.query(ListTable.TABLE_NAME, arrayOf(ListTable.ID), "${ListTable.DISTRIBUTION_ID} = ?", SqlUtil.buildArgs(distributionId.toString()), null, null, null).use { cursor ->
|
||||
if (cursor == null || !cursor.moveToFirst()) {
|
||||
null
|
||||
} else {
|
||||
DistributionListId.from(CursorUtil.requireLong(cursor, ListTable.ID))
|
||||
}
|
||||
}
|
||||
|
||||
if (distributionListId == null) {
|
||||
Log.w(TAG, "Cannot find required distribution list.")
|
||||
return
|
||||
}
|
||||
|
||||
if (update.new.deletedAtTimestamp > 0L) {
|
||||
if (distributionId.asUuid().equals(DistributionId.MY_STORY.asUuid())) {
|
||||
Log.w(TAG, "Refusing to delete My Story.")
|
||||
return
|
||||
}
|
||||
|
||||
deleteList(distributionListId, update.new.deletedAtTimestamp)
|
||||
return
|
||||
}
|
||||
|
||||
writableDatabase.beginTransaction()
|
||||
try {
|
||||
val listTableValues = contentValuesOf(
|
||||
ListTable.ALLOWS_REPLIES to update.new.allowsReplies(),
|
||||
ListTable.NAME to update.new.name
|
||||
)
|
||||
|
||||
writableDatabase.update(
|
||||
ListTable.TABLE_NAME,
|
||||
listTableValues,
|
||||
"${ListTable.DISTRIBUTION_ID} = ?",
|
||||
SqlUtil.buildArgs(distributionId.toString())
|
||||
)
|
||||
|
||||
val currentlyInDistributionList = getRawMembers(distributionListId).toSet()
|
||||
val shouldBeInDistributionList = update.new.recipients.map(RecipientId::from).toSet()
|
||||
val toRemove = currentlyInDistributionList - shouldBeInDistributionList
|
||||
val toAdd = shouldBeInDistributionList - currentlyInDistributionList
|
||||
|
||||
toRemove.forEach {
|
||||
removeMemberFromList(distributionListId, it)
|
||||
}
|
||||
|
||||
toAdd.forEach {
|
||||
addMemberToList(distributionListId, it)
|
||||
}
|
||||
|
||||
writableDatabase.setTransactionSuccessful()
|
||||
} finally {
|
||||
writableDatabase.endTransaction()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createUniqueNameForDeletedStory(): String {
|
||||
return "DELETED-${UUID.randomUUID()}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,6 +593,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
DISTRIBUTION_LIST_ID,
|
||||
distributionListId.serialize(),
|
||||
ContentValues().apply {
|
||||
put(GROUP_TYPE, GroupType.DISTRIBUTION_LIST.id)
|
||||
put(DISTRIBUTION_LIST_ID, distributionListId.serialize())
|
||||
put(STORAGE_SERVICE_ID, Base64.encodeBytes(StorageSyncHelper.generateKey()))
|
||||
put(PROFILE_SHARING, 1)
|
||||
@@ -1071,10 +1072,10 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
$STORAGE_SERVICE_ID NOT NULL AND (
|
||||
($GROUP_TYPE = ? AND $SERVICE_ID NOT NULL AND $ID != ?)
|
||||
OR
|
||||
$GROUP_TYPE IN (?)
|
||||
$GROUP_TYPE IN (?, ?)
|
||||
)
|
||||
""".trimIndent()
|
||||
val args = SqlUtil.buildArgs(GroupType.NONE.id, Recipient.self().id, GroupType.SIGNAL_V1.id)
|
||||
val args = SqlUtil.buildArgs(GroupType.NONE.id, Recipient.self().id, GroupType.SIGNAL_V1.id, GroupType.DISTRIBUTION_LIST.id)
|
||||
val out: MutableMap<RecipientId, StorageId> = HashMap()
|
||||
|
||||
readableDatabase.query(TABLE_NAME, arrayOf(ID, STORAGE_SERVICE_ID, GROUP_TYPE), query, args, null, null, null).use { cursor ->
|
||||
@@ -1087,6 +1088,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
when (groupType) {
|
||||
GroupType.NONE -> out[id] = StorageId.forContact(key)
|
||||
GroupType.SIGNAL_V1 -> out[id] = StorageId.forGroupV1(key)
|
||||
GroupType.DISTRIBUTION_LIST -> out[id] = StorageId.forStoryDistributionList(key)
|
||||
else -> throw AssertionError()
|
||||
}
|
||||
}
|
||||
@@ -2504,7 +2506,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||
}
|
||||
|
||||
val query = "$ID = ? AND ($GROUP_TYPE IN (?, ?, ?) OR $REGISTERED = ?)"
|
||||
val args = SqlUtil.buildArgs(recipientId, GroupType.SIGNAL_V1.id, GroupType.SIGNAL_V2.id, GroupType.DISTRIBUTION_LIST, RegisteredState.REGISTERED.id)
|
||||
val args = SqlUtil.buildArgs(recipientId, GroupType.SIGNAL_V1.id, GroupType.SIGNAL_V2.id, GroupType.DISTRIBUTION_LIST.id, RegisteredState.REGISTERED.id)
|
||||
writableDatabase.update(TABLE_NAME, values, query, args)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColors
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper.entrySet
|
||||
import org.thoughtcrime.securesms.database.KeyValueDatabase
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListId
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ReactionList
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
@@ -196,8 +195,9 @@ object SignalDatabaseMigrations {
|
||||
private const val GROUP_STORIES = 134
|
||||
private const val MMS_COUNT_INDEX = 135
|
||||
private const val STORY_SENDS = 136
|
||||
private const val STORY_TYPE_AND_DISTRIBUTION = 137
|
||||
|
||||
const val DATABASE_VERSION = 136
|
||||
const val DATABASE_VERSION = 137
|
||||
|
||||
@JvmStatic
|
||||
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
@@ -2458,7 +2458,7 @@ object SignalDatabaseMigrations {
|
||||
val recipientId = db.insert(
|
||||
"recipient", null,
|
||||
contentValuesOf(
|
||||
"distribution_list_id" to DistributionListId.MY_STORY_ID,
|
||||
"distribution_list_id" to 1L,
|
||||
"storage_service_key" to Base64.encodeBytes(StorageSyncHelper.generateKey()),
|
||||
"profile_sharing" to 1
|
||||
)
|
||||
@@ -2468,7 +2468,7 @@ object SignalDatabaseMigrations {
|
||||
db.insert(
|
||||
"distribution_list", null,
|
||||
contentValuesOf(
|
||||
"_id" to DistributionListId.MY_STORY_ID,
|
||||
"_id" to 1L,
|
||||
"name" to listUUID,
|
||||
"distribution_id" to listUUID,
|
||||
"recipient_id" to recipientId
|
||||
@@ -2503,6 +2503,27 @@ object SignalDatabaseMigrations {
|
||||
|
||||
db.execSQL("CREATE INDEX story_sends_recipient_id_sent_timestamp_allows_replies_index ON story_sends (recipient_id, sent_timestamp, allows_replies)")
|
||||
}
|
||||
|
||||
if (oldVersion < STORY_TYPE_AND_DISTRIBUTION) {
|
||||
db.execSQL("ALTER TABLE distribution_list ADD COLUMN deletion_timestamp INTEGER DEFAULT 0")
|
||||
|
||||
db.execSQL(
|
||||
"""
|
||||
UPDATE recipient
|
||||
SET group_type = 4
|
||||
WHERE distribution_list_id IS NOT NULL
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
db.execSQL(
|
||||
"""
|
||||
UPDATE distribution_list
|
||||
SET name = '00000000-0000-0000-0000-000000000000',
|
||||
distribution_id = '00000000-0000-0000-0000-000000000000'
|
||||
WHERE _id = 1
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -11,5 +11,6 @@ data class DistributionListRecord(
|
||||
val name: String,
|
||||
val distributionId: DistributionId,
|
||||
val allowsReplies: Boolean,
|
||||
val members: List<RecipientId>
|
||||
val members: List<RecipientId>,
|
||||
val deletedAtTimestamp: Long
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user