Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ configurations.configureEach {
exclude(module = "commons-logging")
}

val canonicalVersionCode = 421
val canonicalVersionName = "1.28.0"
val canonicalVersionCode = 426
val canonicalVersionName = "1.28.1"

val postFixSize = 10
val abiPostFix = mapOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ data class OpenGroup(
val room: String,
@SerialName("displayName") // This rename caters for existing data
val name: String,
val description: String?,
val description: String? = null,
val publicKey: String,
val imageId: String?,
val infoUpdates: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,11 @@ class AvatarUploadManager @Inject constructor(
val result = it.userProfile.getPic()
val userPic = remoteFile.toUserPic()
if (isReupload) {
it.userProfile.setReuploadedPic(userPic)
it.userProfile.setPic(userPic)

// TODO: We'll need to call this when the libsession re-enables the re-uploaded
// avatar logic.
// it.userProfile.setReuploadedPic(userPic)
} else {
it.userProfile.setPic(userPic)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static org.thoughtcrime.securesms.database.MmsSmsColumns.ID;
import static org.thoughtcrime.securesms.database.MmsSmsColumns.NOTIFIED;
import static org.thoughtcrime.securesms.database.MmsSmsColumns.READ;
import static org.thoughtcrime.securesms.database.MmsSmsColumns.THREAD_ID;

import android.content.ContentValues;
import android.content.Context;
Expand Down Expand Up @@ -525,6 +526,8 @@ public int getMessagePositionInConversation(long threadId, long sentTimestamp, @
return -1;
}

// Please note this migration contain a mistake (message_id used as thread_id), it's corrected in the subsequent release,
// so you shouldn't try to fix it here.
private static void migrateLegacyCommunityAddresses(final SQLiteDatabase db, final String tableName) {
final String query = "SELECT " + ID + ", " + MmsSmsColumns.ADDRESS + " FROM " + tableName;
try (final Cursor cursor = db.rawQuery(query)) {
Expand Down Expand Up @@ -578,11 +581,80 @@ private static void migrateLegacyCommunityAddresses(final SQLiteDatabase db, fin
}
}

// This is an attempt to fix the issue in migrateLegacyCommunityAddresses
private static void migrateLegacyCommunityAddresses2(final SQLiteDatabase db, final String tableName) {
final String query = "SELECT " + ID + ", " + THREAD_ID + ", " + MmsSmsColumns.ADDRESS + " FROM " + tableName;
try (final Cursor cursor = db.rawQuery(query)) {
while (cursor.moveToNext()) {
final long messageId = cursor.getLong(0);
final long threadId = cursor.getLong(1);
final String address = cursor.getString(2);
final String newAddress;

try {
if (address.startsWith(GroupUtil.COMMUNITY_PREFIX)) {
// First, if a message has a sender being a community address, it suggests the message
// is sent by us (this is an assumption from other part of the code).
// This also means that the address will be the thread's address, if the thread address
// is indeed a community address
final String threadSql = "SELECT " + ThreadDatabase.ADDRESS + " FROM " +
ThreadDatabase.TABLE_NAME + " WHERE " + ThreadDatabase.ID + " = ?";
try (final Cursor threadCursor = db.rawQuery(threadSql, threadId)) {
if (threadCursor.moveToNext()) {
final Address threadAddress = Address.fromSerialized(threadCursor.getString(0));
if (threadAddress instanceof Address.Community) {
newAddress = threadAddress.getAddress();
} else {
// If this message has a sender being a community address, but the thread address
// is not community(!), we'll have to fall back to unsafe group id migration
final String groupId = GroupUtil.getDecodedGroupID(address);
final int dotIndex = groupId.lastIndexOf('.');
if (dotIndex > 0 && dotIndex < groupId.length() - 1) {
newAddress = new Address.Community(
groupId.substring(0, dotIndex),
groupId.substring(dotIndex + 1)
).getAddress();
} else {
Log.w(TAG, "Unable to decode group id from address: " + address);
continue;
}
}
} else {
Log.w(TAG, "Thread not found for message id = " + messageId);
// Thread not found? - this is strange but if we don't have threads these messages
// aren't visible anyway.
continue;
}
}
} else {
continue;
}
} catch (Throwable e) {
Log.e(TAG, "Error while migrating address " + address, e);
continue;
}

if (!newAddress.equals(address)) {
Log.i(TAG, "Migrating message ID=" + messageId);
ContentValues contentValues = new ContentValues(1);
contentValues.put(MmsSmsColumns.ADDRESS, newAddress);
db.update(tableName, contentValues, ID + " = ?", new String[]{String.valueOf(messageId)});
}
}
}

}

public static void migrateLegacyCommunityAddresses(final SQLiteDatabase db) {
migrateLegacyCommunityAddresses(db, SmsDatabase.TABLE_NAME);
migrateLegacyCommunityAddresses(db, MmsDatabase.TABLE_NAME);
}

public static void migrateLegacyCommunityAddresses2(final SQLiteDatabase db) {
migrateLegacyCommunityAddresses2(db, SmsDatabase.TABLE_NAME);
migrateLegacyCommunityAddresses2(db, MmsDatabase.TABLE_NAME);
}

private Cursor queryTables(String[] projection, String selection, String order, String limit) {
String reactionsColumn = "json_group_array(json_object(" +
"'" + ReactionDatabase.ROW_ID + "', " + ReactionDatabase.TABLE_NAME + "." + ReactionDatabase.ROW_ID + ", " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.database.Cursor
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import net.zetetic.database.sqlcipher.SQLiteDatabase
import org.json.JSONArray
import org.json.JSONException
import org.session.libsignal.utilities.JsonUtil.SaneJSONObject
Expand Down Expand Up @@ -86,15 +87,15 @@ class ReactionDatabase(context: Context, helper: Provider<SQLCipherOpenHelper>)
@JvmField
val CREATE_MESSAGE_ID_MMS_INDEX = arrayOf("CREATE INDEX IF NOT EXISTS reaction_message_id_mms_idx ON $TABLE_NAME ($MESSAGE_ID, $IS_MMS)")

@JvmField
val MIGRATE_REACTION_TABLE_TO_USE_RECIPIENT_SETTINGS = arrayOf(
fun migrateToDropForeignConstraint(db: SQLiteDatabase) {
// Create the new table with updated schema
"""
db.rawExecSQL(
"""
CREATE TABLE ${TABLE_NAME}_new (
$ROW_ID INTEGER PRIMARY KEY,
$MESSAGE_ID INTEGER NOT NULL,
$IS_MMS INTEGER NOT NULL,
$AUTHOR_ID INTEGER NOT NULL REFERENCES ${RecipientSettingsDatabase.TABLE_NAME} (${RecipientSettingsDatabase.COL_ADDRESS}) ON DELETE CASCADE,
$AUTHOR_ID TEXT NOT NULL,
$EMOJI TEXT NOT NULL,
$SERVER_ID TEXT NOT NULL,
$COUNT INTEGER NOT NULL,
Expand All @@ -103,27 +104,34 @@ class ReactionDatabase(context: Context, helper: Provider<SQLCipherOpenHelper>)
$DATE_RECEIVED INTEGER NOT NULL,
UNIQUE($MESSAGE_ID, $IS_MMS, $EMOJI, $AUTHOR_ID) ON CONFLICT REPLACE
)
""",
"""
)

// Copy data from the old table to the new table
"""
INSERT INTO ${TABLE_NAME}_new ($ROW_ID, $MESSAGE_ID, $IS_MMS, $AUTHOR_ID, $EMOJI, $SERVER_ID, $COUNT, $SORT_ID, $DATE_SENT, $DATE_RECEIVED)
SELECT $ROW_ID, $MESSAGE_ID, $IS_MMS, ${AUTHOR_ID}, $EMOJI, $SERVER_ID, $COUNT, $SORT_ID, $DATE_SENT, $DATE_RECEIVED
db.rawExecSQL(
"""
INSERT OR REPLACE INTO ${TABLE_NAME}_new ($ROW_ID, $MESSAGE_ID, $IS_MMS, $AUTHOR_ID, $EMOJI, $SERVER_ID, $COUNT, $SORT_ID, $DATE_SENT, $DATE_RECEIVED)
SELECT $ROW_ID, $MESSAGE_ID, $IS_MMS, $AUTHOR_ID, $EMOJI, $SERVER_ID, $COUNT, $SORT_ID, $DATE_SENT, $DATE_RECEIVED
FROM $TABLE_NAME
""",
""")

// Drop the old table and their triggers
"DROP TABLE $TABLE_NAME",
"DROP TRIGGER reactions_sms_delete",
"DROP TRIGGER reactions_mms_delete",
db.rawExecSQL("DROP TRIGGER IF EXISTS reactions_sms_delete")
db.rawExecSQL("DROP TRIGGER IF EXISTS reactions_mms_delete")
db.rawExecSQL("DROP TABLE IF EXISTS $TABLE_NAME")

// Rename the new table to the original table name
"ALTER TABLE ${TABLE_NAME}_new RENAME TO $TABLE_NAME",
db.rawExecSQL("ALTER TABLE ${TABLE_NAME}_new RENAME TO $TABLE_NAME")

// Add the necessary indexes and triggers to the new table
*CREATE_INDEXS,
*CREATE_REACTION_TRIGGERS,
)
for (indexCmd in CREATE_INDEXS) {
db.rawExecSQL(indexCmd)
}

for (triggerCmd in CREATE_REACTION_TRIGGERS) {
db.rawExecSQL(triggerCmd)
}
}

private fun readReaction(cursor: Cursor): ReactionRecord {
return ReactionRecord(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
private static final int lokiV50 = 71;
private static final int lokiV51 = 72;
private static final int lokiV52 = 73;
private static final int lokiV53 = 74;

// Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
private static final int DATABASE_VERSION = lokiV52;
private static final int DATABASE_VERSION = lokiV53;
private static final int MIN_DATABASE_VERSION = lokiV7;
public static final String DATABASE_NAME = "session.db";

Expand Down Expand Up @@ -248,8 +249,8 @@ public void onCreate(SQLiteDatabase db) {
db.execSQL(ThreadDatabase.ADD_SNIPPET_CONTENT_COLUMN);

executeStatements(db, RecipientSettingsDatabase.Companion.getMIGRATION_CREATE_TABLE());
ReactionDatabase.Companion.migrateToDropForeignConstraint(db);
db.execSQL(RecipientSettingsDatabase.MIGRATE_DROP_OLD_TABLE);
executeStatements(db, ReactionDatabase.MIGRATE_REACTION_TABLE_TO_USE_RECIPIENT_SETTINGS);
db.execSQL(BlindedIdMappingDatabase.DROP_TABLE_COMMAND);
db.execSQL(ExpirationConfigurationDatabase.DROP_TABLE_COMMAND);
db.execSQL(SessionContactDatabase.getDropTableCommand());
Expand Down Expand Up @@ -570,8 +571,8 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

executeStatements(db, RecipientSettingsDatabase.Companion.getMIGRATION_CREATE_TABLE());
db.execSQL(RecipientSettingsDatabase.MIGRATE_MOVE_DATA_FROM_OLD_TABLE);
ReactionDatabase.Companion.migrateToDropForeignConstraint(db);
db.execSQL(RecipientSettingsDatabase.MIGRATE_DROP_OLD_TABLE);
executeStatements(db, ReactionDatabase.MIGRATE_REACTION_TABLE_TO_USE_RECIPIENT_SETTINGS);
db.execSQL(BlindedIdMappingDatabase.DROP_TABLE_COMMAND);
db.execSQL(ExpirationConfigurationDatabase.DROP_TABLE_COMMAND);
db.execSQL(SessionContactDatabase.getDropTableCommand());
Expand All @@ -582,6 +583,10 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
executeStatements(db, CommunityDatabase.Companion.getMIGRATE_DROP_OLD_TABLES());
}

if (oldVersion < lokiV53) {
MmsSmsDatabase.migrateLegacyCommunityAddresses2(db);
}

db.setTransactionSuccessful();
} finally {
db.endTransaction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
Expand Down Expand Up @@ -226,12 +225,13 @@ class DefaultConversationRepository @Inject constructor(
it == TextSecurePreferences.SET_FORCE_POST_PRO
}
).debounce(500)
.onStart { emit(Unit) }
.mapLatest {
withContext(Dispatchers.Default) {
threadDb.getThreads(allAddresses)
}
}
.onStart { emit(allAddresses) }
.map { allAddresses }
}
.map { addresses ->
withContext(Dispatchers.Default) {
threadDb.getThreads(addresses)
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ kotlinVersion = "2.2.20"
kryoVersion = "5.6.2"
kspVersion = "2.2.10-2.0.2"
legacySupportV13Version = "1.0.0"
libsessionUtilAndroidVersion = "1.0.8"
libsessionUtilAndroidVersion = "1.0.8-1-g27817b4"
media3ExoplayerVersion = "1.8.0"
mockitoCoreVersion = "5.20.0"
navVersion = "2.9.4"
Expand Down
Loading