From db31301244c1d43d305e402d909c14c37e4b9303 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Tue, 26 Nov 2024 20:20:53 +0800 Subject: [PATCH 01/42] Migration database --- .../one/mixin/android/db/MixinDatabase.kt | 7 +- .../android/db/pending/PendingDatabaseImp.kt | 6 +- .../java/one/mixin/android/fts/FtsDatabase.kt | 6 +- .../android/ui/common/PinCodeFragment.kt | 15 +- .../one/mixin/android/ui/home/MainActivity.kt | 9 +- .../android/ui/landing/InitializeActivity.kt | 9 + .../android/ui/landing/MigrationFragment.kt | 52 ++++++ .../ui/landing/MnemonicPhraseFragment.kt | 13 +- .../android/util/database/DatabaseUtil.kt | 172 +++++++++--------- 9 files changed, 177 insertions(+), 112 deletions(-) create mode 100644 app/src/main/java/one/mixin/android/ui/landing/MigrationFragment.kt diff --git a/app/src/main/java/one/mixin/android/db/MixinDatabase.kt b/app/src/main/java/one/mixin/android/db/MixinDatabase.kt index 5ea623506d..1f05ef30c3 100644 --- a/app/src/main/java/one/mixin/android/db/MixinDatabase.kt +++ b/app/src/main/java/one/mixin/android/db/MixinDatabase.kt @@ -73,6 +73,7 @@ import one.mixin.android.db.converter.SafeDepositConverter import one.mixin.android.db.converter.SafeWithdrawalConverter import one.mixin.android.db.converter.TreasuryConverter import one.mixin.android.db.converter.WithdrawalMemoPossibilityConverter +import one.mixin.android.session.Session import one.mixin.android.ui.wallet.alert.vo.Alert import one.mixin.android.util.GsonHelper import one.mixin.android.util.SINGLE_DB_EXECUTOR @@ -126,6 +127,8 @@ import one.mixin.android.vo.safe.RawTransaction import one.mixin.android.vo.safe.SafeSnapshot import one.mixin.android.vo.safe.Token import one.mixin.android.vo.safe.TokensExtra +import timber.log.Timber +import java.io.File import java.util.concurrent.Executors import kotlin.math.max import kotlin.math.min @@ -291,8 +294,10 @@ abstract class MixinDatabase : RoomDatabase() { fun getDatabase(context: Context): MixinDatabase { synchronized(lock) { if (INSTANCE == null) { + val dir = File(context.filesDir, Session.getAccount()?.identityNumber ?: "temp") + if (!dir.exists()) dir.mkdirs() val builder = - Room.databaseBuilder(context, MixinDatabase::class.java, DB_NAME) + Room.databaseBuilder(context, MixinDatabase::class.java, File(dir, DB_NAME).absolutePath) .openHelperFactory( MixinOpenHelperFactory( FrameworkSQLiteOpenHelperFactory(), diff --git a/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt b/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt index d3b1088060..bc55d3403e 100644 --- a/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt +++ b/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt @@ -14,11 +14,13 @@ import one.mixin.android.Constants.DataBase.PENDING_DB_NAME import one.mixin.android.db.FloodMessageDao import one.mixin.android.db.JobDao import one.mixin.android.db.insertNoReplace +import one.mixin.android.session.Session import one.mixin.android.util.GsonHelper import one.mixin.android.util.debug.getContent import one.mixin.android.vo.FloodMessage import one.mixin.android.vo.Job import one.mixin.android.vo.MessageMedia +import java.io.File @Database( entities = [ @@ -47,11 +49,13 @@ abstract class PendingDatabaseImp : RoomDatabase(), PendingDatabase { ): PendingDatabaseImp { synchronized(lock) { if (INSTANCE == null) { + val dir = File(context.filesDir, Session.getAccount()?.identityNumber ?: "temp") + if (!dir.exists()) dir.mkdirs() val builder = Room.databaseBuilder( context, PendingDatabaseImp::class.java, - PENDING_DB_NAME, + File(dir, PENDING_DB_NAME).absolutePath ).enableMultiInstanceInvalidation().addCallback( object : Callback() { override fun onOpen(db: SupportSQLiteDatabase) { diff --git a/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt b/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt index edaa0898a8..98026339c0 100644 --- a/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt +++ b/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt @@ -6,6 +6,8 @@ import androidx.room.Room import androidx.room.RoomDatabase import androidx.sqlite.db.SupportSQLiteDatabase import one.mixin.android.Constants.DataBase.FTS_DB_NAME +import one.mixin.android.session.Session +import java.io.File @Database( entities = [ @@ -25,11 +27,13 @@ abstract class FtsDatabase : RoomDatabase() { fun getDatabase(context: Context): FtsDatabase { synchronized(lock) { if (INSTANCE == null) { + val dir = File(context.filesDir, Session.getAccount()?.identityNumber ?: "temp") + if (!dir.exists()) dir.mkdirs() val builder = Room.databaseBuilder( context, FtsDatabase::class.java, - FTS_DB_NAME, + File(dir, FTS_DB_NAME).absolutePath, ).addCallback( object : Callback() { override fun onOpen(db: SupportSQLiteDatabase) { diff --git a/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt b/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt index b7cdbbe86e..42587c6473 100644 --- a/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt @@ -27,9 +27,7 @@ import one.mixin.android.session.decryptPinToken import one.mixin.android.ui.landing.InitializeActivity import one.mixin.android.ui.landing.RestoreActivity import one.mixin.android.util.ErrorHandler -import one.mixin.android.util.database.clearDatabase import one.mixin.android.util.database.clearJobsAndRawTransaction -import one.mixin.android.util.database.getLastUserId import one.mixin.android.vo.Account import one.mixin.android.vo.User import one.mixin.android.vo.toUser @@ -96,16 +94,9 @@ abstract class PinCodeFragment( val account = response.data as Account - val lastUserId = getLastUserId(requireContext()) - val sameUser = lastUserId != null && lastUserId == account.userId - if (sameUser) { - showLoading() - clearJobsAndRawTransaction(requireContext()) - } else { - showLoading() - clearDatabase(requireContext()) - defaultSharedPreferences.clear() - } + showLoading() + clearJobsAndRawTransaction(requireContext(), account.identityNumber) + val privateKey = sessionKey.privateKey val pinToken = decryptPinToken(account.pinToken.decodeBase64(), privateKey) Session.storeEd25519Seed(privateKey.base64Encode()) diff --git a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt index dfc299dc1e..deba576b8e 100644 --- a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt +++ b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt @@ -83,6 +83,7 @@ import one.mixin.android.extension.areBubblesAllowedCompat import one.mixin.android.extension.checkStorageNotLow import one.mixin.android.extension.colorFromAttribute import one.mixin.android.extension.defaultSharedPreferences +import one.mixin.android.extension.getLegacyBackupPath import one.mixin.android.extension.getStringDeviceId import one.mixin.android.extension.inTransaction import one.mixin.android.extension.indeterminateProgressDialog @@ -160,7 +161,6 @@ import one.mixin.android.ui.tip.wc.WalletConnectActivity import one.mixin.android.ui.tip.wc.WalletUnlockBottomSheetDialogFragment import one.mixin.android.ui.tip.wc.WalletUnlockBottomSheetDialogFragment.Companion.TYPE_ETH import one.mixin.android.ui.tip.wc.WalletUnlockBottomSheetDialogFragment.Companion.TYPE_SOLANA -import one.mixin.android.ui.wallet.BackupMnemonicPhraseWarningBottomSheetDialogFragment import one.mixin.android.ui.wallet.WalletActivity import one.mixin.android.ui.wallet.WalletActivity.Companion.BUY import one.mixin.android.ui.wallet.WalletFragment @@ -169,6 +169,7 @@ import one.mixin.android.util.ErrorHandler import one.mixin.android.util.NewVersionBulletin.Companion.PREF_NEW_VERSION import one.mixin.android.util.RomUtil import one.mixin.android.util.RootUtil +import one.mixin.android.util.database.legacyDatabaseExists import one.mixin.android.util.reportException import one.mixin.android.util.rxpermission.RxPermissions import one.mixin.android.vo.Conversation @@ -255,6 +256,12 @@ class MainActivity : BlazeBaseActivity() { } } + if (legacyDatabaseExists(this)) { + InitializeActivity.showMigration(this) + finish() + return + } + if (Session.getAccount()?.fullName.isNullOrBlank()) { InitializeActivity.showSetupName(this) finish() diff --git a/app/src/main/java/one/mixin/android/ui/landing/InitializeActivity.kt b/app/src/main/java/one/mixin/android/ui/landing/InitializeActivity.kt index e39e008ed7..f99f17f524 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/InitializeActivity.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/InitializeActivity.kt @@ -19,12 +19,14 @@ class InitializeActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) + val dbMigration = intent.getBooleanExtra(DB_MIGRATION, false) val setName = intent.getBooleanExtra(SET_NAME, false) val setPin = intent.getBooleanExtra(SET_PIN, false) val wrongTime = intent.getBooleanExtra(WRONG_TIME, false) val oldVersion = intent.getBooleanExtra(OLD_VERSION, false) val dbUpgrade = intent.getBooleanExtra(DB_UPGRADE, false) when { + dbMigration -> replaceFragment(MigrationFragment.newInstance(), R.id.container) setName -> replaceFragment(SetupNameFragment.newInstance(), R.id.container) setPin -> replaceFragment(SetupPinFragment.newInstance(), R.id.container) wrongTime -> replaceFragment(TimeFragment.newInstance(), R.id.container) @@ -48,6 +50,7 @@ class InitializeActivity : BaseActivity() { const val WRONG_TIME = "wrong_time" const val OLD_VERSION = "old_version" const val DB_UPGRADE = "db_upgrade" + const val DB_MIGRATION = "db_migration" private fun getIntent( context: Context, @@ -56,6 +59,7 @@ class InitializeActivity : BaseActivity() { wrongTime: Boolean = false, oldVersion: Boolean = false, dbUpgrade: Boolean = false, + dbMigration: Boolean = false, ): Intent { return Intent(context, InitializeActivity::class.java).apply { this.putExtra(SET_NAME, setName) @@ -63,6 +67,7 @@ class InitializeActivity : BaseActivity() { this.putExtra(WRONG_TIME, wrongTime) this.putExtra(OLD_VERSION, oldVersion) this.putExtra(DB_UPGRADE, dbUpgrade) + this.putExtra(DB_MIGRATION, dbMigration) } } @@ -117,5 +122,9 @@ class InitializeActivity : BaseActivity() { fun showDBUpgrade(context: Context) { context.startActivity(getIntent(context, dbUpgrade = true)) } + + fun showMigration(context: Context) { + context.startActivity(getIntent(context, dbMigration = true)) + } } } diff --git a/app/src/main/java/one/mixin/android/ui/landing/MigrationFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/MigrationFragment.kt new file mode 100644 index 0000000000..8de4141b38 --- /dev/null +++ b/app/src/main/java/one/mixin/android/ui/landing/MigrationFragment.kt @@ -0,0 +1,52 @@ +package one.mixin.android.ui.landing + +import android.annotation.SuppressLint +import android.os.Bundle +import android.view.View +import android.view.WindowManager +import androidx.lifecycle.lifecycleScope +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import one.mixin.android.R +import one.mixin.android.databinding.FragmentUpgradeBinding +import one.mixin.android.ui.common.BaseFragment +import one.mixin.android.ui.home.MainActivity +import one.mixin.android.util.database.migrationDbFile +import one.mixin.android.util.viewBinding + +@AndroidEntryPoint +class MigrationFragment : BaseFragment(R.layout.fragment_upgrade) { + companion object { + const val TAG: String = "MigrationFragment" + + + fun newInstance() = MigrationFragment() + } + + private val binding by viewBinding(FragmentUpgradeBinding::bind) + + + @SuppressLint("SetTextI18n") + override fun onViewCreated( + view: View, + savedInstanceState: Bundle?, + ) { + super.onViewCreated(view, savedInstanceState) + requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + lifecycleScope.launch { + binding.pb.isIndeterminate = true + withContext(Dispatchers.IO) { + migrationDbFile(requireContext()) + } + MainActivity.show(requireContext()) + activity?.finish() + } + } + + override fun onDestroyView() { + super.onDestroyView() + activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } +} diff --git a/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt index bb8125b153..6489ad42b7 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt @@ -52,9 +52,7 @@ import one.mixin.android.ui.landing.components.MnemonicPhrasePage import one.mixin.android.ui.landing.vo.MnemonicPhraseState import one.mixin.android.util.ErrorHandler.Companion.NEED_CAPTCHA import one.mixin.android.util.GsonHelper -import one.mixin.android.util.database.clearDatabase import one.mixin.android.util.database.clearJobsAndRawTransaction -import one.mixin.android.util.database.getLastUserId import one.mixin.android.util.getMixinErrorStringByCode import one.mixin.android.util.viewBinding import one.mixin.android.vo.toUser @@ -288,14 +286,9 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { ) if (r?.isSuccess == true) { val account = r.data!! - val lastUserId = getLastUserId(requireContext()) - val sameUser = lastUserId != null && lastUserId == account.userId - if (sameUser) { - clearJobsAndRawTransaction(requireContext()) - } else { - clearDatabase(requireContext()) - defaultSharedPreferences.clear() - } + + clearJobsAndRawTransaction(requireContext(),account.identityNumber) + val privateKey = sessionKey.privateKey val pinToken = decryptPinToken(account.pinToken.decodeBase64(), privateKey) Session.storeEd25519Seed(privateKey.base64Encode()) diff --git a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt index b8514be09b..0b5ad5a590 100644 --- a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt +++ b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt @@ -2,103 +2,22 @@ package one.mixin.android.util.database import android.annotation.SuppressLint import android.content.Context -import android.database.Cursor import android.database.sqlite.SQLiteDatabase import android.os.Build import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import one.mixin.android.Constants +import one.mixin.android.extension.moveTo +import one.mixin.android.session.Session import one.mixin.android.util.reportException -import timber.log.Timber import java.io.File -suspend fun getLastUserId(context: Context): String? = - withContext(Dispatchers.IO) { - val dbFile = context.getDatabasePath(Constants.DataBase.DB_NAME) - if (!dbFile.exists()) { - return@withContext null - } - var c: Cursor? = null - var db: SQLiteDatabase? = null - - try { - db = - SQLiteDatabase.openDatabase( - dbFile.absolutePath, - null, - SQLiteDatabase.OPEN_READONLY, - ) - c = db.rawQuery("SELECT user_id FROM users WHERE relationship = 'ME'", null) - var userId: String? = null - if (c.moveToFirst()) { - userId = c.getString(0) - } - return@withContext userId - } catch (e: Exception) { - return@withContext null - } finally { - c?.close() - db?.close() - } - } - -@SuppressLint("ObsoleteSdkInt") -suspend fun clearDatabase(context: Context) = - withContext(Dispatchers.IO) { - try { - clearFts(context) - clearPending(context) - val dbFile = context.getDatabasePath(Constants.DataBase.DB_NAME) - if (!dbFile.exists()) { - return@withContext - } - dbFile.parent?.let { - File("$it${File.separator}${Constants.DataBase.DB_NAME}-shm").delete() - File("$it${File.separator}${Constants.DataBase.DB_NAME}-wal").delete() - File("$it${File.separator}${Constants.DataBase.DB_NAME}-journal").delete() - } - do { - dbFile.delete() - } while (dbFile.exists()) - } catch (e: Exception) { - Timber.e(e) - } - } - @SuppressLint("ObsoleteSdkInt") -suspend fun clearPending(context: Context) = - withContext(Dispatchers.IO) { - val dbFile = context.getDatabasePath(Constants.DataBase.PENDING_DB_NAME) - if (!dbFile.exists()) { - return@withContext - } - dbFile.parent?.let { - File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}-shm").delete() - File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}-wal").delete() - File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}-journal").delete() - } - dbFile.delete() - } - -suspend fun clearFts(context: Context) = - withContext(Dispatchers.IO) { - val dbFile = context.getDatabasePath(Constants.DataBase.FTS_DB_NAME) - if (!dbFile.exists()) { - return@withContext - } - dbFile.parent?.let { - File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}-shm").delete() - File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}-wal").delete() - File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}-journal").delete() - } - dbFile.delete() - } - -@SuppressLint("ObsoleteSdkInt") -suspend fun clearJobsAndRawTransaction(context: Context) = +suspend fun clearJobsAndRawTransaction(context: Context, identityNumber: String) = withContext(Dispatchers.IO) { + val dir = File(context.filesDir, identityNumber) val supportsDeferForeignKeys = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP - val dbFile = context.getDatabasePath(Constants.DataBase.DB_NAME) + val dbFile = File(dir, Constants.DataBase.DB_NAME) if (!dbFile.exists()) { return@withContext } @@ -131,3 +50,84 @@ suspend fun clearJobsAndRawTransaction(context: Context) = db?.rawQuery("PRAGMA wal_checkpoint(FULL)", null)?.close() } } + +fun legacyDatabaseExists(context: Context): Boolean { + val dbFile = context.getDatabasePath(Constants.DataBase.DB_NAME) + return dbFile.exists() && dbFile.length() > 0 +} + +fun migrationDbFile(context: Context) { + if (Session.getAccount() == null) { + return + } + + val dbFile = context.getDatabasePath(Constants.DataBase.DB_NAME) + if (!dbFile.exists() || dbFile.length() <= 0) { + return + } + val dir = File(dbFile.parent, Session.getAccount()!!.identityNumber) + if (!dir.exists()) dir.mkdirs() + checkpoint(dbFile) + moveDbFile(dbFile, dir) + dbFile.parent?.let { + checkpoint(File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}")) + checkpoint(File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}")) + + moveDbFile( + File("$it${File.separator}${Constants.DataBase.DB_NAME}-shm"), dir + ) + moveDbFile( + File("$it${File.separator}${Constants.DataBase.DB_NAME}-wal"), dir + ) + moveDbFile( + File("$it${File.separator}${Constants.DataBase.DB_NAME}-journal"), dir + ) + moveDbFile( + File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}"), dir + ) + moveDbFile( + File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}-shm"), dir + ) + moveDbFile( + File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}-wal"), dir + ) + moveDbFile( + File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}-journal"), dir + ) + moveDbFile( + File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}"), dir + ) + moveDbFile( + File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}-shm"), dir + ) + moveDbFile( + File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}-wal"), dir + ) + moveDbFile( + File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}-journal"), dir + ) + } +} + +private fun checkpoint(dbFile: File){ + if (!dbFile.exists()) return + var db: SQLiteDatabase? = null + try { + db = + SQLiteDatabase.openDatabase( + dbFile.absolutePath, + null, + SQLiteDatabase.OPEN_READWRITE, + ) + db?.rawQuery("PRAGMA wal_checkpoint(FULL)", null)?.close() + } catch (e: Exception) { + reportException(e) + } +} + +private fun moveDbFile(file: File, dir: File) { + if (!file.exists() || file.length() <= 0) { + return + } + file.moveTo(File(dir, file.name)) +} \ No newline at end of file From da2db3029bfb76578f35c98b7b0ea48b75256b93 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Tue, 26 Nov 2024 20:28:02 +0800 Subject: [PATCH 02/42] Support db backup --- .../one/mixin/android/ui/landing/RestoreFragment.kt | 7 ++++++- .../java/one/mixin/android/util/backup/Backup.kt | 12 ++++++++---- .../one/mixin/android/util/database/DatabaseUtil.kt | 7 +++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/one/mixin/android/ui/landing/RestoreFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/RestoreFragment.kt index 95d2f7dfc5..58cb996add 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/RestoreFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/RestoreFragment.kt @@ -26,6 +26,7 @@ import one.mixin.android.extension.putBoolean import one.mixin.android.extension.showConfirmDialog import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.transfer.TransferActivity +import one.mixin.android.util.database.localDbFile import one.mixin.android.util.rxpermission.RxPermissions import one.mixin.android.util.viewBinding @@ -99,7 +100,11 @@ class RestoreFragment : BaseFragment(R.layout.fragment_restore) { private suspend fun getLocalDataInfo(): Pair? = withContext(Dispatchers.IO) { - val dbFile = requireContext().getDatabasePath(Constants.DataBase.DB_NAME) + var dbFile = requireContext().getDatabasePath(Constants.DataBase.DB_NAME) + if (!dbFile.exists()) { + return@withContext null + } + dbFile = localDbFile(requireContext()) if (!dbFile.exists()) { return@withContext null } diff --git a/app/src/main/java/one/mixin/android/util/backup/Backup.kt b/app/src/main/java/one/mixin/android/util/backup/Backup.kt index e2df892922..a0decebea9 100644 --- a/app/src/main/java/one/mixin/android/util/backup/Backup.kt +++ b/app/src/main/java/one/mixin/android/util/backup/Backup.kt @@ -24,6 +24,7 @@ import one.mixin.android.extension.getDisplayPath import one.mixin.android.extension.getLegacyBackupPath import one.mixin.android.extension.getMediaPath import one.mixin.android.extension.getOldBackupPath +import one.mixin.android.util.database.localDbFile import timber.log.Timber import java.io.File import java.io.FileInputStream @@ -37,7 +38,7 @@ suspend fun backup( context: Context, callback: (Result) -> Unit, ) = coroutineScope { - val dbFile = context.getDatabasePath(DB_NAME) + val dbFile = context.getDatabasePath(DB_NAME) ?: localDbFile(context) if (dbFile == null) { withContext(Dispatchers.Main) { Timber.e("No database files found") @@ -196,7 +197,7 @@ suspend fun backupApi29( } return@withContext } - val dbFile = context.getDatabasePath(DB_NAME) + val dbFile = context.getDatabasePath(DB_NAME) ?: localDbFile(context) if (dbFile == null) { Timber.e("No database files found") withContext(Dispatchers.Main) { @@ -264,7 +265,10 @@ suspend fun restore( val target = internalFindBackup(context, coroutineContext) ?: return@withContext callback(Result.NOT_FOUND) - val file = context.getDatabasePath(DB_NAME) + var file = context.getDatabasePath(DB_NAME) + if (!file.exists()){ + file = localDbFile(context) + } try { if (file.exists()) { file.delete() @@ -314,7 +318,7 @@ suspend fun restoreApi29( } return@withContext } - val file = context.getDatabasePath(DB_NAME) + val file = localDbFile(context) ?: return@withContext try { val inputStream = context.contentResolver.openInputStream(backupDb.uri) if (inputStream == null) { diff --git a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt index 0b5ad5a590..7e162c1604 100644 --- a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt +++ b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt @@ -130,4 +130,11 @@ private fun moveDbFile(file: File, dir: File) { return } file.moveTo(File(dir, file.name)) +} + +fun localDbFile(context: Context): File? { + if (Session.getAccount() == null) { + return null + } + return File(context.filesDir, Session.getAccount()!!.identityNumber) } \ No newline at end of file From 7614283e4f01c714e1d564044983b715135f300f Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Wed, 27 Nov 2024 14:30:45 +0800 Subject: [PATCH 03/42] Update --- .../android/db/InscriptionCollectionDao.kt | 1 - .../java/one/mixin/android/db/MarketDao.kt | 1 - .../one/mixin/android/db/MixinDatabase.kt | 6 ++--- .../java/one/mixin/android/db/OutputDao.kt | 2 -- .../one/mixin/android/db/RawTransactionDao.kt | 2 -- .../android/db/pending/PendingDatabaseImp.kt | 5 ++-- .../java/one/mixin/android/fts/FtsDatabase.kt | 4 +-- .../android/ui/landing/RestoreFragment.kt | 4 +-- .../one/mixin/android/util/backup/Backup.kt | 10 +++---- .../android/util/database/DatabaseUtil.kt | 26 ++++++++++--------- 10 files changed, 27 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/one/mixin/android/db/InscriptionCollectionDao.kt b/app/src/main/java/one/mixin/android/db/InscriptionCollectionDao.kt index 4f3713004b..f0b9274644 100644 --- a/app/src/main/java/one/mixin/android/db/InscriptionCollectionDao.kt +++ b/app/src/main/java/one/mixin/android/db/InscriptionCollectionDao.kt @@ -5,7 +5,6 @@ import androidx.room.Query import kotlinx.coroutines.flow.Flow import one.mixin.android.vo.InscriptionCollection import one.mixin.android.vo.InscriptionItem -import one.mixin.android.vo.safe.SafeCollection @Dao interface InscriptionCollectionDao : BaseDao { diff --git a/app/src/main/java/one/mixin/android/db/MarketDao.kt b/app/src/main/java/one/mixin/android/db/MarketDao.kt index 3507d3a8c9..6d8989a317 100644 --- a/app/src/main/java/one/mixin/android/db/MarketDao.kt +++ b/app/src/main/java/one/mixin/android/db/MarketDao.kt @@ -9,7 +9,6 @@ import androidx.room.RewriteQueriesToDropUnusedColumns import one.mixin.android.ui.wallet.alert.vo.CoinItem import one.mixin.android.vo.market.Market import one.mixin.android.vo.market.MarketItem -import one.mixin.android.vo.safe.TokenItem @Dao interface MarketDao : BaseDao { diff --git a/app/src/main/java/one/mixin/android/db/MixinDatabase.kt b/app/src/main/java/one/mixin/android/db/MixinDatabase.kt index 1f05ef30c3..bfd8459ca0 100644 --- a/app/src/main/java/one/mixin/android/db/MixinDatabase.kt +++ b/app/src/main/java/one/mixin/android/db/MixinDatabase.kt @@ -73,10 +73,10 @@ import one.mixin.android.db.converter.SafeDepositConverter import one.mixin.android.db.converter.SafeWithdrawalConverter import one.mixin.android.db.converter.TreasuryConverter import one.mixin.android.db.converter.WithdrawalMemoPossibilityConverter -import one.mixin.android.session.Session import one.mixin.android.ui.wallet.alert.vo.Alert import one.mixin.android.util.GsonHelper import one.mixin.android.util.SINGLE_DB_EXECUTOR +import one.mixin.android.util.database.dbDir import one.mixin.android.util.debug.getContent import one.mixin.android.util.reportException import one.mixin.android.vo.Address @@ -127,7 +127,6 @@ import one.mixin.android.vo.safe.RawTransaction import one.mixin.android.vo.safe.SafeSnapshot import one.mixin.android.vo.safe.Token import one.mixin.android.vo.safe.TokensExtra -import timber.log.Timber import java.io.File import java.util.concurrent.Executors import kotlin.math.max @@ -294,8 +293,7 @@ abstract class MixinDatabase : RoomDatabase() { fun getDatabase(context: Context): MixinDatabase { synchronized(lock) { if (INSTANCE == null) { - val dir = File(context.filesDir, Session.getAccount()?.identityNumber ?: "temp") - if (!dir.exists()) dir.mkdirs() + val dir = dbDir(context) val builder = Room.databaseBuilder(context, MixinDatabase::class.java, File(dir, DB_NAME).absolutePath) .openHelperFactory( diff --git a/app/src/main/java/one/mixin/android/db/OutputDao.kt b/app/src/main/java/one/mixin/android/db/OutputDao.kt index e8580539b1..cf8eae0f2f 100644 --- a/app/src/main/java/one/mixin/android/db/OutputDao.kt +++ b/app/src/main/java/one/mixin/android/db/OutputDao.kt @@ -4,9 +4,7 @@ import androidx.lifecycle.LiveData import androidx.paging.PagingSource import androidx.room.Dao import androidx.room.Query -import kotlinx.coroutines.flow.Flow import one.mixin.android.ui.home.web3.components.InscriptionState -import one.mixin.android.vo.InscriptionItem import one.mixin.android.vo.UtxoItem import one.mixin.android.vo.safe.Output import one.mixin.android.vo.safe.SafeCollectible diff --git a/app/src/main/java/one/mixin/android/db/RawTransactionDao.kt b/app/src/main/java/one/mixin/android/db/RawTransactionDao.kt index c9ad770286..49a849f4bb 100644 --- a/app/src/main/java/one/mixin/android/db/RawTransactionDao.kt +++ b/app/src/main/java/one/mixin/android/db/RawTransactionDao.kt @@ -2,9 +2,7 @@ package one.mixin.android.db import androidx.room.Dao import androidx.room.Query -import one.mixin.android.extension.thirtyDaysAgo import one.mixin.android.vo.safe.RawTransaction -import one.mixin.android.vo.safe.RawTransactionType @Dao interface RawTransactionDao : BaseDao { diff --git a/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt b/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt index bc55d3403e..0605bbfdee 100644 --- a/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt +++ b/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt @@ -14,8 +14,8 @@ import one.mixin.android.Constants.DataBase.PENDING_DB_NAME import one.mixin.android.db.FloodMessageDao import one.mixin.android.db.JobDao import one.mixin.android.db.insertNoReplace -import one.mixin.android.session.Session import one.mixin.android.util.GsonHelper +import one.mixin.android.util.database.dbDir import one.mixin.android.util.debug.getContent import one.mixin.android.vo.FloodMessage import one.mixin.android.vo.Job @@ -49,8 +49,7 @@ abstract class PendingDatabaseImp : RoomDatabase(), PendingDatabase { ): PendingDatabaseImp { synchronized(lock) { if (INSTANCE == null) { - val dir = File(context.filesDir, Session.getAccount()?.identityNumber ?: "temp") - if (!dir.exists()) dir.mkdirs() + val dir = dbDir(context) val builder = Room.databaseBuilder( context, diff --git a/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt b/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt index 98026339c0..7410608f00 100644 --- a/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt +++ b/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt @@ -7,6 +7,7 @@ import androidx.room.RoomDatabase import androidx.sqlite.db.SupportSQLiteDatabase import one.mixin.android.Constants.DataBase.FTS_DB_NAME import one.mixin.android.session.Session +import one.mixin.android.util.database.dbDir import java.io.File @Database( @@ -27,8 +28,7 @@ abstract class FtsDatabase : RoomDatabase() { fun getDatabase(context: Context): FtsDatabase { synchronized(lock) { if (INSTANCE == null) { - val dir = File(context.filesDir, Session.getAccount()?.identityNumber ?: "temp") - if (!dir.exists()) dir.mkdirs() + val dir = dbDir(context) val builder = Room.databaseBuilder( context, diff --git a/app/src/main/java/one/mixin/android/ui/landing/RestoreFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/RestoreFragment.kt index 58cb996add..f3bbd32b5c 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/RestoreFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/RestoreFragment.kt @@ -26,7 +26,7 @@ import one.mixin.android.extension.putBoolean import one.mixin.android.extension.showConfirmDialog import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.transfer.TransferActivity -import one.mixin.android.util.database.localDbFile +import one.mixin.android.util.database.dbDir import one.mixin.android.util.rxpermission.RxPermissions import one.mixin.android.util.viewBinding @@ -104,7 +104,7 @@ class RestoreFragment : BaseFragment(R.layout.fragment_restore) { if (!dbFile.exists()) { return@withContext null } - dbFile = localDbFile(requireContext()) + dbFile = dbDir(requireContext()) if (!dbFile.exists()) { return@withContext null } diff --git a/app/src/main/java/one/mixin/android/util/backup/Backup.kt b/app/src/main/java/one/mixin/android/util/backup/Backup.kt index a0decebea9..634aa6a503 100644 --- a/app/src/main/java/one/mixin/android/util/backup/Backup.kt +++ b/app/src/main/java/one/mixin/android/util/backup/Backup.kt @@ -24,7 +24,7 @@ import one.mixin.android.extension.getDisplayPath import one.mixin.android.extension.getLegacyBackupPath import one.mixin.android.extension.getMediaPath import one.mixin.android.extension.getOldBackupPath -import one.mixin.android.util.database.localDbFile +import one.mixin.android.util.database.dbDir import timber.log.Timber import java.io.File import java.io.FileInputStream @@ -38,7 +38,7 @@ suspend fun backup( context: Context, callback: (Result) -> Unit, ) = coroutineScope { - val dbFile = context.getDatabasePath(DB_NAME) ?: localDbFile(context) + val dbFile = context.getDatabasePath(DB_NAME) ?: dbDir(context) if (dbFile == null) { withContext(Dispatchers.Main) { Timber.e("No database files found") @@ -197,7 +197,7 @@ suspend fun backupApi29( } return@withContext } - val dbFile = context.getDatabasePath(DB_NAME) ?: localDbFile(context) + val dbFile = context.getDatabasePath(DB_NAME) ?: dbDir(context) if (dbFile == null) { Timber.e("No database files found") withContext(Dispatchers.Main) { @@ -267,7 +267,7 @@ suspend fun restore( ?: return@withContext callback(Result.NOT_FOUND) var file = context.getDatabasePath(DB_NAME) if (!file.exists()){ - file = localDbFile(context) + file = dbDir(context) } try { if (file.exists()) { @@ -318,7 +318,7 @@ suspend fun restoreApi29( } return@withContext } - val file = localDbFile(context) ?: return@withContext + val file = dbDir(context) ?: return@withContext try { val inputStream = context.contentResolver.openInputStream(backupDb.uri) if (inputStream == null) { diff --git a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt index 7e162c1604..aca43244dd 100644 --- a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt +++ b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt @@ -15,7 +15,7 @@ import java.io.File @SuppressLint("ObsoleteSdkInt") suspend fun clearJobsAndRawTransaction(context: Context, identityNumber: String) = withContext(Dispatchers.IO) { - val dir = File(context.filesDir, identityNumber) + val dir = dbDir(context) val supportsDeferForeignKeys = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP val dbFile = File(dir, Constants.DataBase.DB_NAME) if (!dbFile.exists()) { @@ -51,11 +51,6 @@ suspend fun clearJobsAndRawTransaction(context: Context, identityNumber: String) } } -fun legacyDatabaseExists(context: Context): Boolean { - val dbFile = context.getDatabasePath(Constants.DataBase.DB_NAME) - return dbFile.exists() && dbFile.length() > 0 -} - fun migrationDbFile(context: Context) { if (Session.getAccount() == null) { return @@ -109,7 +104,7 @@ fun migrationDbFile(context: Context) { } } -private fun checkpoint(dbFile: File){ +private fun checkpoint(dbFile: File) { if (!dbFile.exists()) return var db: SQLiteDatabase? = null try { @@ -132,9 +127,16 @@ private fun moveDbFile(file: File, dir: File) { file.moveTo(File(dir, file.name)) } -fun localDbFile(context: Context): File? { - if (Session.getAccount() == null) { - return null +fun dbDir(context: Context): File { + val baseDir = File(context.filesDir.parent, "database") + val dir = File(baseDir, Session.getAccount()?.identityNumber ?: "temp") + if (!dir.exists()) { + dir.mkdirs() } - return File(context.filesDir, Session.getAccount()!!.identityNumber) -} \ No newline at end of file + return dir +} + +fun legacyDatabaseExists(context: Context): Boolean { + val dbFile = context.getDatabasePath(Constants.DataBase.DB_NAME) + return dbFile.exists() && dbFile.length() > 0 +} From 948d441af5d9111a06dbe528da3f667e9229c803 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Wed, 27 Nov 2024 16:46:03 +0800 Subject: [PATCH 04/42] Refactor: optimize dependency injection and ViewModel architecture --- .../one/mixin/android/MixinApplication.kt | 8 +- .../one/mixin/android/db/DatabaseProvider.kt | 60 +++++++ .../one/mixin/android/db/MixinDatabase.kt | 13 +- .../android/db/pending/PendingDatabaseImp.kt | 5 + .../java/one/mixin/android/di/AppModule.kt | 2 +- .../di/{BaseDbModule.kt => DatabaseModule.kt} | 79 +++------- .../java/one/mixin/android/fts/FtsDatabase.kt | 5 + .../android/repository/AccountRepository.kt | 4 - .../android/ui/common/PinCodeFragment.kt | 4 +- .../one/mixin/android/ui/home/MainActivity.kt | 117 ++------------ .../mixin/android/ui/home/MainViewModel.kt | 149 ++++++++++++++++++ .../android/ui/landing/LoadingFragment.kt | 1 + .../android/ui/landing/LoadingViewModel.kt | 135 ---------------- .../ui/landing/MnemonicPhraseFragment.kt | 34 ++-- .../android/ui/landing/MobileFragment.kt | 5 +- .../android/ui/landing/SetupNameFragment.kt | 7 +- .../android/ui/landing/SetupPinFragment.kt | 3 +- .../mixin/android/ui/landing/TimeFragment.kt | 6 +- .../android/ui/landing/UpgradeFragment.kt | 3 +- .../ui/landing/VerificationFragment.kt | 5 +- .../landing/components/MnemonicPhraseInput.kt | 12 +- .../landing/components/MnemonicPhrasePage.kt | 4 +- .../landing/components/SetPinLoadingPage.kt | 4 +- .../LandingViewModel.kt} | 105 +++++++++--- .../ui/landing/viewmodel/LoadingViewModel.kt | 108 +++++++++++++ .../android/ui/setting/AccountFragment.kt | 9 ++ .../android/ui/setting/EmergencyViewModel.kt | 14 -- .../setting/VerificationEmergencyFragment.kt | 5 +- app/src/main/res/layout/fragment_account.xml | 19 +++ 29 files changed, 538 insertions(+), 387 deletions(-) create mode 100644 app/src/main/java/one/mixin/android/db/DatabaseProvider.kt rename app/src/main/java/one/mixin/android/di/{BaseDbModule.kt => DatabaseModule.kt} (80%) create mode 100644 app/src/main/java/one/mixin/android/ui/home/MainViewModel.kt delete mode 100644 app/src/main/java/one/mixin/android/ui/landing/LoadingViewModel.kt rename app/src/main/java/one/mixin/android/ui/landing/{MobileViewModel.kt => viewmodel/LandingViewModel.kt} (52%) create mode 100644 app/src/main/java/one/mixin/android/ui/landing/viewmodel/LoadingViewModel.kt diff --git a/app/src/main/java/one/mixin/android/MixinApplication.kt b/app/src/main/java/one/mixin/android/MixinApplication.kt index 4ccab39899..c448e42452 100644 --- a/app/src/main/java/one/mixin/android/MixinApplication.kt +++ b/app/src/main/java/one/mixin/android/MixinApplication.kt @@ -47,6 +47,7 @@ import one.mixin.android.crypto.MixinSignalProtocolLogger import one.mixin.android.crypto.PrivacyPreference.clearPrivacyPreferences import one.mixin.android.crypto.removeValueFromEncryptedPreferences import one.mixin.android.crypto.db.SignalDatabase +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.MixinDatabase import one.mixin.android.di.AppModule.API_UA import one.mixin.android.di.ApplicationScope @@ -91,6 +92,7 @@ import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject import kotlin.system.exitProcess +@SuppressLint("UnsafeOptInUsageError") open class MixinApplication : Application(), Application.ActivityLifecycleCallbacks, @@ -121,6 +123,9 @@ open class MixinApplication : fun inject(app: MixinApplication) } + @Inject + lateinit var databaseProvider: DatabaseProvider + private fun getWorkerFactory() = EntryPointAccessors.fromApplication(this, HiltWorkerFactoryEntryPoint::class.java).getHiltWorkerFactory() private fun getJobManager() = EntryPointAccessors.fromApplication(this, MixinJobManagerEntryPoint::class.java).getMixinJobManager() @@ -285,10 +290,11 @@ open class MixinApplication : } } } + reject() } fun reject() { - MixinDatabase.destroy() + databaseProvider.closeAllDatabases() val entryPoint = EntryPointAccessors.fromApplication( this@MixinApplication, diff --git a/app/src/main/java/one/mixin/android/db/DatabaseProvider.kt b/app/src/main/java/one/mixin/android/db/DatabaseProvider.kt new file mode 100644 index 0000000000..2ec23e97f6 --- /dev/null +++ b/app/src/main/java/one/mixin/android/db/DatabaseProvider.kt @@ -0,0 +1,60 @@ +package one.mixin.android.db + +import android.content.Context +import one.mixin.android.fts.FtsDatabase +import one.mixin.android.db.pending.PendingDatabase +import one.mixin.android.db.pending.PendingDatabaseImp +import one.mixin.android.session.Session +import javax.inject.Inject + +class DatabaseProvider @Inject constructor( + private val context: Context, +) { + private var mixinDatabase: MixinDatabase? = null + private var ftsDatabase: FtsDatabase? = null + private var pendingDatabase: PendingDatabaseImp? = null + + @Synchronized + fun getMixinDatabase(): MixinDatabase { + return mixinDatabase ?: throw IllegalStateException("MixinDatabase is not initialized") + } + + @Synchronized + fun getFtsDatabase(): FtsDatabase { + return ftsDatabase ?: throw IllegalStateException("FtsDatabase is not initialized") + } + + @Synchronized + fun getPendingDatabase(): PendingDatabase { + return pendingDatabase ?: throw IllegalStateException("PendingDatabase is not initialized") + } + + private var identityNumber: String? = null + @Synchronized + fun initAllDatabases() { + val identityNumber = requireNotNull(Session.getAccount()?.identityNumber) + if (identityNumber == this.identityNumber) return + + mixinDatabase?.close() + val db = MixinDatabase.getDatabase(context) + mixinDatabase = db + + ftsDatabase?.close() + ftsDatabase = FtsDatabase.getDatabase(context) + + pendingDatabase?.close() + pendingDatabase = PendingDatabaseImp.getDatabase(context, db.floodMessageDao(), db.jobDao()) + } + + @Synchronized + fun closeAllDatabases() { + mixinDatabase?.close() + mixinDatabase = null + + ftsDatabase?.close() + ftsDatabase = null + + pendingDatabase?.close() + pendingDatabase = null + } +} \ No newline at end of file diff --git a/app/src/main/java/one/mixin/android/db/MixinDatabase.kt b/app/src/main/java/one/mixin/android/db/MixinDatabase.kt index bfd8459ca0..9fc4122c34 100644 --- a/app/src/main/java/one/mixin/android/db/MixinDatabase.kt +++ b/app/src/main/java/one/mixin/android/db/MixinDatabase.kt @@ -278,20 +278,18 @@ abstract class MixinDatabase : RoomDatabase() { abstract fun marketCapRankDao(): MarketCapRankDao + override fun close() { + INSTANCE = null + super.close() + } + companion object { private var INSTANCE: MixinDatabase? = null - - private val lock = Any() private var supportSQLiteDatabase: SupportSQLiteDatabase? = null - fun destroy() { - INSTANCE = null - } - @Suppress("UNUSED_ANONYMOUS_PARAMETER") @SuppressLint("RestrictedApi") fun getDatabase(context: Context): MixinDatabase { - synchronized(lock) { if (INSTANCE == null) { val dir = dbDir(context) val builder = @@ -385,7 +383,6 @@ abstract class MixinDatabase : RoomDatabase() { INSTANCE = builder.build() } return INSTANCE as MixinDatabase - } } fun query(query: String): String? { diff --git a/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt b/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt index 0605bbfdee..63c0258823 100644 --- a/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt +++ b/app/src/main/java/one/mixin/android/db/pending/PendingDatabaseImp.kt @@ -37,6 +37,11 @@ abstract class PendingDatabaseImp : RoomDatabase(), PendingDatabase { abstract override fun jobDao(): JobDao + override fun close() { + super.close() + INSTANCE = null + } + companion object { private var INSTANCE: PendingDatabaseImp? = null diff --git a/app/src/main/java/one/mixin/android/di/AppModule.kt b/app/src/main/java/one/mixin/android/di/AppModule.kt index 82011afd49..5e8e3e653a 100644 --- a/app/src/main/java/one/mixin/android/di/AppModule.kt +++ b/app/src/main/java/one/mixin/android/di/AppModule.kt @@ -122,7 +122,7 @@ import javax.inject.Singleton import kotlin.math.abs @InstallIn(SingletonComponent::class) -@Module(includes = [(BaseDbModule::class)]) +@Module(includes = [(DatabaseModule::class)]) object AppModule { private const val xServerTime = "X-Server-Time" private const val xRequestId = "X-Request-Id" diff --git a/app/src/main/java/one/mixin/android/di/BaseDbModule.kt b/app/src/main/java/one/mixin/android/di/DatabaseModule.kt similarity index 80% rename from app/src/main/java/one/mixin/android/di/BaseDbModule.kt rename to app/src/main/java/one/mixin/android/di/DatabaseModule.kt index c85864db0c..12ff7b7026 100644 --- a/app/src/main/java/one/mixin/android/di/BaseDbModule.kt +++ b/app/src/main/java/one/mixin/android/di/DatabaseModule.kt @@ -6,221 +6,184 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import one.mixin.android.crypto.db.SignalDatabase +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.MixinDatabase import one.mixin.android.db.pending.PendingDatabase -import one.mixin.android.db.pending.PendingDatabaseImp import one.mixin.android.fts.FtsDatabase import javax.inject.Singleton @InstallIn(SingletonComponent::class) @Module -internal object BaseDbModule { +internal object DatabaseModule { @Singleton @Provides fun provideSignalDb(app: Application) = SignalDatabase.getDatabase(app) @Singleton @Provides - fun provideFtsDb(app: Application) = FtsDatabase.getDatabase(app) + fun provideRatchetSenderKeyDao(db: SignalDatabase) = db.ratchetSenderKeyDao() @Singleton @Provides - fun provideRatchetSenderKeyDao(db: SignalDatabase) = db.ratchetSenderKeyDao() + fun provideDatbaseProvider(app: Application) = DatabaseProvider(app) - @Singleton @Provides - fun provideDb(app: Application) = MixinDatabase.getDatabase(app) + fun provideAppDatabase( + databaseProvider: DatabaseProvider + ): MixinDatabase { + return databaseProvider.getMixinDatabase() + } + + @Provides + fun provideFtsDatabase( + databaseProvider: DatabaseProvider + ): FtsDatabase { + return databaseProvider.getFtsDatabase() + } - @Singleton @Provides fun providePendingDatabase( - app: Application, - mixinDatabase: MixinDatabase, - ): PendingDatabase = PendingDatabaseImp.getDatabase(app.applicationContext, mixinDatabase.floodMessageDao(), mixinDatabase.jobDao()) + databaseProvider: DatabaseProvider + ): PendingDatabase { + return databaseProvider.getPendingDatabase() + } - @Singleton @Provides fun provideUserDao(db: MixinDatabase) = db.userDao() - @Singleton @Provides fun provideSessionParticipantDao(db: MixinDatabase) = db.participantSessionDao() - @Singleton @Provides fun provideConversationDao(db: MixinDatabase) = db.conversationDao() - @Singleton @Provides fun provideMessageDao(db: MixinDatabase) = db.messageDao() - @Singleton @Provides fun providePendingMessageDao(pendingDatabase: PendingDatabase) = pendingDatabase.pendingMessageDao() - @Singleton @Provides fun provideParticipantDao(db: MixinDatabase) = db.participantDao() - @Singleton @Provides fun provideOffsetDao(db: MixinDatabase) = db.offsetDao() - @Singleton @Provides fun provideAssetDao(db: MixinDatabase) = db.assetDao() - @Singleton @Provides fun provideTokenDao(db: MixinDatabase) = db.tokenDao() - @Singleton @Provides fun provideTokensExtraDao(db: MixinDatabase) = db.tokensExtraDao() - @Singleton @Provides fun provideSnapshotDao(db: MixinDatabase) = db.snapshotDao() - @Singleton @Provides fun provideSafeSnapshotDao(db: MixinDatabase) = db.safeSnapshotDao() - @Singleton @Provides fun provideMessageHistoryDao(db: MixinDatabase) = db.messageHistoryDao() - @Singleton @Provides fun provideStickerAlbumDao(db: MixinDatabase) = db.stickerAlbumDao() - @Singleton @Provides fun provideStickerDao(db: MixinDatabase) = db.stickerDao() - @Singleton @Provides fun provideHyperlinkDao(db: MixinDatabase) = db.hyperlinkDao() - @Singleton @Provides fun providesAppDao(db: MixinDatabase) = db.appDao() - @Singleton @Provides fun providesFloodMessageDao(db: PendingDatabase) = db.floodMessageDao() - @Singleton @Provides fun providesJobDao(db: PendingDatabase) = db.jobDao() - @Singleton @Provides fun providesAddressDao(db: MixinDatabase) = db.addressDao() - @Singleton @Provides fun providesResendSessionMessageDao(db: MixinDatabase) = db.resendSessionMessageDao() - @Singleton @Provides fun providesStickerRelationshipDao(db: MixinDatabase) = db.stickerRelationshipDao() - @Singleton @Provides fun providesHotAssetDao(db: MixinDatabase) = db.topAssetDao() - @Singleton @Provides fun providesFavoriteAppDao(db: MixinDatabase) = db.favoriteAppDao() - @Singleton @Provides fun providesMentionMessageDao(db: MixinDatabase) = db.mentionMessageDao() - @Singleton @Provides fun providesCircleDao(db: MixinDatabase) = db.circleDao() - @Singleton @Provides fun providesCircleConversationDao(db: MixinDatabase) = db.circleConversationDao() - @Singleton @Provides fun providesTraceDao(db: MixinDatabase) = db.traceDao() - @Singleton @Provides fun providesTranscriptDao(db: MixinDatabase) = db.transcriptDao() - @Singleton @Provides fun providesPinMessageDao(db: MixinDatabase) = db.pinMessageDao() - @Singleton @Provides fun providesPropertyDao(db: MixinDatabase) = db.propertyDao() - @Singleton @Provides fun providesRemoteMessageStatusDao(db: MixinDatabase) = db.remoteMessageStatusDao() - @Singleton @Provides fun providesExpiredMessageDao(db: MixinDatabase) = db.expiredMessageDao() - @Singleton @Provides fun providesConversationExtDao(db: MixinDatabase) = db.conversationExtDao() - @Singleton @Provides fun providesChainDao(db: MixinDatabase) = db.chainDao() - @Singleton @Provides fun provideOutputDao(db: MixinDatabase) = db.outputDao() - @Singleton @Provides fun provideDepositDao(db: MixinDatabase) = db.depositDao() - @Singleton @Provides fun provideRawTransactionDao(db: MixinDatabase) = db.rawTransactionDao() - @Singleton @Provides fun provideInscriptionCollectionDao(db: MixinDatabase) = db.inscriptionCollectionDao() - @Singleton @Provides fun provideInscriptionDao(db: MixinDatabase) = db.inscriptionDao() - @Singleton @Provides fun provideHistoryPriceDao(db: MixinDatabase) = db.historyPriceDao() - @Singleton @Provides fun provideMarketDao(db: MixinDatabase) = db.marketDao() - @Singleton @Provides fun provideMarketCoinDao(db: MixinDatabase) = db.marketCoinDao() - @Singleton @Provides fun provideMarketFavoredDao(db: MixinDatabase) = db.marketFavoredDao() - @Singleton @Provides fun provideAlertDao(db: MixinDatabase) = db.alertDao() - @Singleton @Provides fun provideMarketCapRankDao(db: MixinDatabase) = db.marketCapRankDao() - -} +} \ No newline at end of file diff --git a/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt b/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt index 7410608f00..558071ac2c 100644 --- a/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt +++ b/app/src/main/java/one/mixin/android/fts/FtsDatabase.kt @@ -53,4 +53,9 @@ abstract class FtsDatabase : RoomDatabase() { abstract fun messageMetaDao(): MessageMetaDao abstract fun messageFtsDao(): MessageFtsDao + + override fun close() { + super.close() + INSTANCE = null + } } diff --git a/app/src/main/java/one/mixin/android/repository/AccountRepository.kt b/app/src/main/java/one/mixin/android/repository/AccountRepository.kt index 0be6195da1..9b27424008 100644 --- a/app/src/main/java/one/mixin/android/repository/AccountRepository.kt +++ b/app/src/main/java/one/mixin/android/repository/AccountRepository.kt @@ -108,10 +108,6 @@ class AccountRepository fun update(request: AccountUpdateRequest): Observable> = accountService.update(request) - fun updateSession(request: SessionRequest) = accountService.updateSession(request) - - fun deviceCheck() = accountService.deviceCheck() - fun join(conversationId: String): Observable> { return conversationService.join(conversationId) } diff --git a/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt b/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt index 42587c6473..061ffbcb22 100644 --- a/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt @@ -26,6 +26,7 @@ import one.mixin.android.session.Session import one.mixin.android.session.decryptPinToken import one.mixin.android.ui.landing.InitializeActivity import one.mixin.android.ui.landing.RestoreActivity +import one.mixin.android.ui.landing.viewmodel.LandingViewModel import one.mixin.android.util.ErrorHandler import one.mixin.android.util.database.clearJobsAndRawTransaction import one.mixin.android.vo.Account @@ -82,6 +83,7 @@ abstract class PinCodeFragment( } protected suspend fun handleAccount( + landingViewModel: LandingViewModel, response: MixinResponse, sessionKey: EdKeyPair, action: () -> Unit, @@ -102,6 +104,7 @@ abstract class PinCodeFragment( Session.storeEd25519Seed(privateKey.base64Encode()) Session.storePinToken(pinToken.base64Encode()) Session.storeAccount(account) + landingViewModel.initAllDatabases() if (Session.hasPhone()) { // Remove mnemonic if user has phone on sign in removeValueFromEncryptedPreferences(requireContext(), Constants.Tip.MNEMONIC) @@ -123,7 +126,6 @@ abstract class PinCodeFragment( RestoreActivity.show(requireContext()) } } - MixinApplication.get().reject() activity?.finish() } diff --git a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt index deba576b8e..3996c94c15 100644 --- a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt +++ b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt @@ -13,6 +13,7 @@ import android.os.Build import android.os.Bundle import android.os.PowerManager import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.core.content.getSystemService import androidx.fragment.app.DialogFragment @@ -190,30 +191,12 @@ class MainActivity : BlazeBaseActivity() { @Inject lateinit var jobManager: MixinJobManager - @Inject - lateinit var conversationService: ConversationService - - @Inject - lateinit var userService: UserService - - @Inject - lateinit var conversationDao: ConversationDao - - @Inject - lateinit var userDao: UserDao - - @Inject - lateinit var userRepo: UserRepository - - @Inject - lateinit var accountRepo: AccountRepository - - @Inject - lateinit var participantDao: ParticipantDao @Inject lateinit var tip: Tip + private val mainViewModel by viewModels() + private val appUpdateManager by lazy { AppUpdateManagerFactory.create(this) } private val updatedListener = InstallStateUpdatedListener { state -> @@ -280,6 +263,8 @@ class MainActivity : BlazeBaseActivity() { return } + mainViewModel.initAllDatabases() + MixinApplication.get().isOnline.set(true) if (checkNeedGo2MigrationPage()) { InitializeActivity.showDBUpgrade(this) @@ -594,7 +579,7 @@ class MainActivity : BlazeBaseActivity() { return } runIntervalTask(SAFETY_NET_INTERVAL_KEY, INTERVAL_24_HOURS) { - accountRepo.deviceCheck().subscribeOn(Schedulers.io()) + mainViewModel.deviceCheck().subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .autoDispose(stopScope) .subscribe( @@ -614,7 +599,7 @@ class MainActivity : BlazeBaseActivity() { val client = SafetyNet.getClient(this) val task = client.attest(nonce, BuildConfig.SAFETYNET_API_KEY) task.addOnSuccessListener { safetyResp -> - accountRepo.updateSession(SessionRequest(deviceCheckToken = safetyResp.jwsResult)) + mainViewModel.updateSession(SessionRequest(deviceCheckToken = safetyResp.jwsResult)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .autoDispose(stopScope) @@ -750,7 +735,7 @@ class MainActivity : BlazeBaseActivity() { val userId = intent.getStringExtra(TRANSFER) ?: return if (Session.getAccount()?.hasPin == true) { lifecycleScope.launch { - val user = userRepo.refreshUser(userId) ?: return@launch + val user = mainViewModel.refreshUser(userId) ?: return@launch TransferFragment.newInstance(buildEmptyTransferBiometricItem(user)) .showNow(supportFragmentManager, TransferFragment.TAG) } @@ -764,93 +749,11 @@ class MainActivity : BlazeBaseActivity() { clearCodeAfterConsume(intent, "conversation_id") Maybe.just(conversationId).map { val innerIntent: Intent? - var conversation = conversationDao.findConversationById(conversationId) - if (conversation == null) { - val response = - conversationService.getConversation(conversationId).execute().body() - if (response != null && response.isSuccess) { - response.data?.let { data -> - var ownerId: String = data.creatorId - if (data.category == ConversationCategory.CONTACT.name) { - ownerId = - data.participants.find { p -> p.userId != Session.getAccountId() }!!.userId - } else if (data.category == ConversationCategory.GROUP.name) { - ownerId = data.creatorId - } - var c = conversationDao.findConversationById(data.conversationId) - if (c == null) { - c = - Conversation( - data.conversationId, - ownerId, - data.category, - data.name, - data.iconUrl, - data.announcement, - data.codeUrl, - "", - data.createdAt, - null, - null, - null, - 0, - ConversationStatus.SUCCESS.ordinal, - null, - ) - conversation = c - conversationDao.upsert(c) - } else { - conversationDao.updateConversation( - data.conversationId, - ownerId, - data.category, - data.name, - data.announcement, - data.muteUntil, - data.createdAt, - data.expireIn, - ConversationStatus.SUCCESS.ordinal, - ) - } - - val participants = mutableListOf() - val userIdList = mutableListOf() - for (p in data.participants) { - val item = - Participant(conversationId, p.userId, p.role, p.createdAt!!) - if (p.role == ParticipantRole.OWNER.name) { - participants.add(0, item) - } else { - participants.add(item) - } - - val u = userDao.findUser(p.userId) - if (u == null) { - userIdList.add(p.userId) - } - } - if (userIdList.isNotEmpty()) { - jobManager.addJobInBackground(RefreshUserJob(userIdList)) - } - participantDao.insertList(participants) - } - } - } + val conversation = mainViewModel.syncConverstion(conversationId) if (conversation?.isGroupConversation() == true) { innerIntent = ConversationActivity.putIntent(this, conversationId) } else { - var user = userDao.findOwnerByConversationId(conversationId) - if (user == null) { - val response = - userService.getUserById(conversation!!.ownerId!!).execute() - .body() - if (response != null && response.isSuccess) { - response.data?.let { u -> - runBlocking { userRepo.upsert(u) } - user = u - } - } - } + val user = mainViewModel.syncOwnerByConversationId(conversationId) innerIntent = ConversationActivity.putIntent(this, conversationId, user?.userId) } runOnUiThread { dismissDialog() } diff --git a/app/src/main/java/one/mixin/android/ui/home/MainViewModel.kt b/app/src/main/java/one/mixin/android/ui/home/MainViewModel.kt new file mode 100644 index 0000000000..92d481f203 --- /dev/null +++ b/app/src/main/java/one/mixin/android/ui/home/MainViewModel.kt @@ -0,0 +1,149 @@ +package one.mixin.android.ui.home + +import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.runBlocking +import one.mixin.android.api.handleMixinResponse +import one.mixin.android.api.request.SessionRequest +import one.mixin.android.api.service.AccountService +import one.mixin.android.api.service.ConversationService +import one.mixin.android.api.service.UserService +import one.mixin.android.db.DatabaseProvider +import one.mixin.android.job.MixinJobManager +import one.mixin.android.job.RefreshUserJob +import one.mixin.android.session.Session +import one.mixin.android.vo.Conversation +import one.mixin.android.vo.ConversationCategory +import one.mixin.android.vo.ConversationStatus +import one.mixin.android.vo.Participant +import one.mixin.android.vo.ParticipantRole +import one.mixin.android.vo.User +import javax.inject.Inject + +@HiltViewModel +class MainViewModel +@Inject +internal constructor( + private val databaseProvider: DatabaseProvider, + private val jobManager: MixinJobManager, + private val accountService: AccountService, + private val userService: UserService, + private val conversationService: ConversationService, +) : ViewModel() { + + fun initAllDatabases() = databaseProvider.initAllDatabases() + + fun updateSession(request: SessionRequest) = accountService.updateSession(request) + + fun deviceCheck() = accountService.deviceCheck() + + fun syncOwnerByConversationId(conversationId: String): User? { + val conversation = databaseProvider.getMixinDatabase().conversationDao().findConversationById(conversationId) + if (conversation == null) { + return null + } + var user = databaseProvider.getMixinDatabase().userDao().findOwnerByConversationId(conversationId) + if (user == null) { + val response = userService.getUserById(conversation.ownerId!!).execute().body() + if (response != null && response.isSuccess) { + response.data?.let { u -> + runBlocking { databaseProvider.getMixinDatabase().userDao().upsert(u) } + user = u + } + } + } + return user + } + + fun syncConverstion(conversationId: String): Conversation? { + var conversation = databaseProvider.getMixinDatabase().conversationDao().findConversationById(conversationId) + if (conversation != null) return conversation + val response = + conversationService.getConversation(conversationId).execute().body() + if (response != null && response.isSuccess) { + response.data?.let { data -> + var ownerId: String = data.creatorId + if (data.category == ConversationCategory.CONTACT.name) { + ownerId = + data.participants.find { p -> p.userId != Session.getAccountId() }!!.userId + } else if (data.category == ConversationCategory.GROUP.name) { + ownerId = data.creatorId + } + var c = databaseProvider.getMixinDatabase().conversationDao().findConversationById(data.conversationId) + if (c == null) { + c = + Conversation( + data.conversationId, + ownerId, + data.category, + data.name, + data.iconUrl, + data.announcement, + data.codeUrl, + "", + data.createdAt, + null, + null, + null, + 0, + ConversationStatus.SUCCESS.ordinal, + null, + ) + conversation = c + databaseProvider.getMixinDatabase().conversationDao().upsert(c) + } else { + databaseProvider.getMixinDatabase().conversationDao().updateConversation( + data.conversationId, + ownerId, + data.category, + data.name, + data.announcement, + data.muteUntil, + data.createdAt, + data.expireIn, + ConversationStatus.SUCCESS.ordinal, + ) + } + + val participants = mutableListOf() + val userIdList = mutableListOf() + for (p in data.participants) { + val item = + Participant(conversationId, p.userId, p.role, p.createdAt!!) + if (p.role == ParticipantRole.OWNER.name) { + participants.add(0, item) + } else { + participants.add(item) + } + + val u = databaseProvider.getMixinDatabase().userDao().findUser(p.userId) + if (u == null) { + userIdList.add(p.userId) + } + } + if (userIdList.isNotEmpty()) { + jobManager.addJobInBackground(RefreshUserJob(userIdList)) + } + databaseProvider.getMixinDatabase().participantDao().insertList(participants) + } + } + return conversation + } + + suspend fun refreshUser(id: String): User? { + val user = databaseProvider.getMixinDatabase().userDao().suspendFindUserById(id) + if (user != null) return user + + return handleMixinResponse( + invokeNetwork = { + userService.getUserByIdSuspend(id) + }, + successBlock = { + it.data?.let { u -> + databaseProvider.getMixinDatabase().userDao().upsert(u) + return@handleMixinResponse u + } + }, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/one/mixin/android/ui/landing/LoadingFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/LoadingFragment.kt index 95e556d284..dba379bbd8 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/LoadingFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/LoadingFragment.kt @@ -38,6 +38,7 @@ import one.mixin.android.session.Session import one.mixin.android.session.decryptPinToken import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.home.MainActivity +import one.mixin.android.ui.landing.viewmodel.LoadingViewModel import one.mixin.android.ui.tip.TipActivity import one.mixin.android.ui.tip.TipBundle import one.mixin.android.ui.tip.TipType diff --git a/app/src/main/java/one/mixin/android/ui/landing/LoadingViewModel.kt b/app/src/main/java/one/mixin/android/ui/landing/LoadingViewModel.kt deleted file mode 100644 index dc0b9b1cc7..0000000000 --- a/app/src/main/java/one/mixin/android/ui/landing/LoadingViewModel.kt +++ /dev/null @@ -1,135 +0,0 @@ -package one.mixin.android.ui.landing - -import androidx.collection.ArrayMap -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import one.mixin.android.Constants.ALLOW_INTERVAL -import one.mixin.android.MixinApplication -import one.mixin.android.api.MixinResponse -import one.mixin.android.api.request.SessionSecretRequest -import one.mixin.android.api.response.UserSession -import one.mixin.android.api.service.AccountService -import one.mixin.android.api.service.SignalKeyService -import one.mixin.android.api.service.UserService -import one.mixin.android.crypto.db.SenderKeyDao -import one.mixin.android.crypto.db.SessionDao -import one.mixin.android.crypto.db.SignalDatabase -import one.mixin.android.crypto.vo.SenderKey -import one.mixin.android.crypto.vo.Session -import one.mixin.android.extension.getDeviceId -import one.mixin.android.job.RefreshOneTimePreKeysJob -import one.mixin.android.repository.ConversationRepository -import one.mixin.android.vo.ParticipantSession -import javax.inject.Inject -import kotlin.math.abs - -@HiltViewModel -class LoadingViewModel - @Inject - internal constructor( - private val signalKeyService: SignalKeyService, - private val accountService: AccountService, - private val userService: UserService, - private val conversationRepo: ConversationRepository, - ) : ViewModel() { - private val sessionDao: SessionDao = - SignalDatabase.getDatabase(MixinApplication.appContext).sessionDao() - - private val senderKeyDao: SenderKeyDao = - SignalDatabase.getDatabase(MixinApplication.appContext).senderKeyDao() - - suspend fun pushAsyncSignalKeys(): MixinResponse = - withContext(Dispatchers.IO) { - val start = System.currentTimeMillis() - val signalKeys = RefreshOneTimePreKeysJob.generateKeys() - val response = signalKeyService.pushSignalKeys(signalKeys).await() - val time = System.currentTimeMillis() - start - if (time < 2000) { - delay(time) - } - return@withContext response - } - - suspend fun updateSignalSession() { - withContext(Dispatchers.IO) { - val sessions = sessionDao.syncGetSessionAddress() - val userIds = sessions.map { it.address } - val response = userService.fetchSessionsSuspend(userIds) - val sessionMap = ArrayMap() - val userSessionMap = ArrayMap() - if (response.isSuccess) { - response.data?.asSequence()?.forEach { item -> - if (item.platform == "Android" || item.platform == "iOS") { - val deviceId = item.sessionId.getDeviceId() - sessionMap[item.userId] = deviceId - userSessionMap[item.userId] = item - } - } - } - if (sessionMap.isEmpty()) { - return@withContext - } - val newSession = mutableListOf() - for (s in sessions) { - sessionMap[s.address]?.let { d -> - newSession.add(Session(s.address, d, s.record, s.timestamp)) - } - } - sessionDao.insertList(newSession) - val senderKeys = senderKeyDao.syncGetSenderKeys() - senderKeys.forEach { key -> - if (!key.senderId.endsWith(":1")) { - return@forEach - } - val userId = key.senderId.substring(0, key.senderId.length - 2) - sessionMap[userId]?.let { d -> - senderKeyDao.insert(SenderKey(key.groupId, "$userId:$d", key.record)) - } - } - - val participants = conversationRepo.getAllParticipants() - val newParticipantSession = mutableListOf() - participants.forEach { p -> - userSessionMap[p.userId]?.let { userSession -> - val ps = ParticipantSession(p.conversationId, p.userId, sessionId = userSession.sessionId, publicKey = userSession.publicKey) - newParticipantSession.add(ps) - } - } - conversationRepo.insertParticipantSession(newParticipantSession) - } - } - - fun pingServer( - callback: () -> Unit, - elseCallBack: (e: Exception?) -> Unit, - ): Job { - return viewModelScope.launch { - try { - val response = - withContext(coroutineContext + Dispatchers.IO) { - accountService.ping().execute() - } - response.headers()["X-Server-Time"]?.toLong()?.let { serverTime -> - if (abs(serverTime / 1000000 - System.currentTimeMillis()) < ALLOW_INTERVAL) { // 10 minutes - callback.invoke() - } else { - elseCallBack.invoke(null) - } - } - } catch (e: Exception) { - elseCallBack.invoke(e) - } - } - } - - suspend fun modifySessionSecret(request: SessionSecretRequest) = - withContext(Dispatchers.IO) { - accountService.modifySessionSecret(request) - } - } diff --git a/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt index 6489ad42b7..b4b4ed51f5 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt @@ -34,7 +34,6 @@ import one.mixin.android.crypto.toEntropy import one.mixin.android.crypto.toMnemonic import one.mixin.android.databinding.FragmentComposeBinding import one.mixin.android.extension.base64Encode -import one.mixin.android.extension.clear import one.mixin.android.extension.decodeBase64 import one.mixin.android.extension.defaultSharedPreferences import one.mixin.android.extension.getStringDeviceId @@ -49,6 +48,7 @@ import one.mixin.android.session.decryptPinToken import one.mixin.android.tip.Tip import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.landing.components.MnemonicPhrasePage +import one.mixin.android.ui.landing.viewmodel.LandingViewModel import one.mixin.android.ui.landing.vo.MnemonicPhraseState import one.mixin.android.util.ErrorHandler.Companion.NEED_CAPTCHA import one.mixin.android.util.GsonHelper @@ -76,7 +76,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { } } - private val mobileViewModel by viewModels() + private val landingViewModel by viewModels() private val binding by viewBinding(FragmentComposeBinding::bind) private var errorInfo by mutableStateOf(null) @@ -107,7 +107,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { private fun anonymousRequest(words: List? = null) { lifecycleScope.launch { - mobileViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Creating) + landingViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Creating) val sessionKey = generateEd25519KeyPair() val edKey = if (!words.isNullOrEmpty()) { val w = words.let { @@ -142,7 +142,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { val signature = initFromSeedAndSign(edKey.privateKey.toTypedArray().toByteArray(), GsonHelper.customGson.toJson(message).toByteArray()) val r = handleMixinResponse( invokeNetwork = { - mobileViewModel.anonymousRequest(edKey.publicKey.hexString(), messageHex, signature.hexString()) + landingViewModel.anonymousRequest(edKey.publicKey.hexString(), messageHex, signature.hexString()) }, successBlock = { r -> @@ -150,7 +150,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { }, exceptionBlock = { t -> - mobileViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) + landingViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) errorInfo = t.message Timber.e(t) true @@ -161,7 +161,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { initAndLoadCaptcha(sessionKey, edKey, messageHex, signature.hexString()) } else { errorInfo = requireContext().getMixinErrorStringByCode(r.errorCode, r.errorDescription) - mobileViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) + landingViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) } true } @@ -210,7 +210,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { lifecycleScope.launch { val r = handleMixinResponse( invokeNetwork = { - mobileViewModel.anonymousRequest(edKey.publicKey.hexString(), messageHex, signatureHex, hCaptchaResponse, gRecaptchaResponse) + landingViewModel.anonymousRequest(edKey.publicKey.hexString(), messageHex, signatureHex, hCaptchaResponse, gRecaptchaResponse) }, successBlock = { r -> @@ -218,7 +218,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { }, exceptionBlock = { t -> - mobileViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) + landingViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) errorInfo = t.message Timber.e(t) true @@ -226,7 +226,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { failureBlock = { r -> errorInfo = requireContext().getMixinErrorStringByCode(r.errorCode, r.errorDescription) - mobileViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) + landingViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) true } ) @@ -244,7 +244,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { if (r != null) { errorInfo = requireActivity().getMixinErrorStringByCode(r.errorCode, r.errorDescription) } - mobileViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) + landingViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) } } } @@ -256,7 +256,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { val sessionSecret = sessionKey.publicKey.base64Encode() val r = handleMixinResponse( invokeNetwork = { - mobileViewModel.create( + landingViewModel.create( verificationId, AccountRequest( purpose = VerificationPurpose.ANONYMOUS_SESSION.name, @@ -272,7 +272,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { }, exceptionBlock = { t -> - mobileViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) + landingViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) errorInfo = t.message Timber.e(t) true @@ -280,7 +280,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { failureBlock = { r -> errorInfo = requireContext().getMixinErrorStringByCode(r.errorCode, r.errorDescription) - mobileViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) + landingViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) true } ) @@ -294,10 +294,11 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { Session.storeEd25519Seed(privateKey.base64Encode()) Session.storePinToken(pinToken.base64Encode()) Session.storeAccount(account) + landingViewModel.initAllDatabases() defaultSharedPreferences.putString(DEVICE_ID, requireContext().getStringDeviceId()) when { account.fullName.isNullOrBlank() -> { - mobileViewModel.upsertUser(account.toUser()) + landingViewModel.upsertUser(account.toUser()) InitializeActivity.showSetupName(requireContext()) } @@ -305,14 +306,13 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { RestoreActivity.show(requireContext()) } } - mobileViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Success) - MixinApplication.get().reject() + landingViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Success) activity?.finish() } else { if (r != null) { errorInfo = requireActivity().getMixinErrorStringByCode(r.errorCode, r.errorDescription) } - mobileViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) + landingViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure) } } } diff --git a/app/src/main/java/one/mixin/android/ui/landing/MobileFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/MobileFragment.kt index ef22f71755..4588f9238c 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/MobileFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/MobileFragment.kt @@ -37,6 +37,7 @@ import one.mixin.android.extension.tickVibrate import one.mixin.android.extension.viewDestroyed import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.landing.LandingActivity.Companion.ARGS_PIN +import one.mixin.android.ui.landing.viewmodel.LandingViewModel import one.mixin.android.util.ErrorHandler import one.mixin.android.util.ErrorHandler.Companion.NEED_CAPTCHA import one.mixin.android.util.isAnonymousNumber @@ -75,7 +76,7 @@ class MobileFragment: BaseFragment(R.layout.fragment_mobile) { } } - private val mobileViewModel by viewModels() + private val landingViewModel by viewModels() private val binding by viewBinding(FragmentMobileBinding::bind) private lateinit var countryPicker: CountryPicker @@ -239,7 +240,7 @@ class MobileFragment: BaseFragment(R.layout.fragment_mobile) { } } binding.continueBn.displayedChild = 1 - mobileViewModel.loginVerification(verificationRequest) + landingViewModel.loginVerification(verificationRequest) .autoDispose(stopScope).subscribe( { r: MixinResponse -> if (!r.isSuccess) { diff --git a/app/src/main/java/one/mixin/android/ui/landing/SetupNameFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/SetupNameFragment.kt index 2ebb268fb8..f6981d2cd8 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/SetupNameFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/SetupNameFragment.kt @@ -23,6 +23,7 @@ import one.mixin.android.job.MixinJobManager import one.mixin.android.session.Session import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.home.MainActivity +import one.mixin.android.ui.landing.viewmodel.LandingViewModel import one.mixin.android.util.ErrorHandler import one.mixin.android.util.reportException import one.mixin.android.util.viewBinding @@ -32,7 +33,7 @@ import javax.inject.Inject @AndroidEntryPoint class SetupNameFragment : BaseFragment(R.layout.fragment_setup_name) { - private val mobileViewModel by viewModels() + private val landingViewModel by viewModels() private val binding by viewBinding(FragmentSetupNameBinding::bind) @Inject @@ -54,7 +55,7 @@ class SetupNameFragment : BaseFragment(R.layout.fragment_setup_name) { nameFab.show() nameCover.visibility = VISIBLE val accountUpdateRequest = AccountUpdateRequest(nameEt.text.toString()) - mobileViewModel.update(accountUpdateRequest) + landingViewModel.update(accountUpdateRequest) .autoDispose(stopScope).subscribe( { r: MixinResponse -> nameFab.hide() @@ -65,7 +66,7 @@ class SetupNameFragment : BaseFragment(R.layout.fragment_setup_name) { } r.data?.let { data -> Session.storeAccount(data) - mobileViewModel.insertUser(data.toUser()) + landingViewModel.insertUser(data.toUser()) } nameEt.hideKeyboard() diff --git a/app/src/main/java/one/mixin/android/ui/landing/SetupPinFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/SetupPinFragment.kt index e70e702092..64452e0fec 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/SetupPinFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/SetupPinFragment.kt @@ -19,6 +19,7 @@ import one.mixin.android.ui.landing.components.QuizPage import one.mixin.android.ui.landing.components.SetPinLoadingPage import one.mixin.android.ui.landing.components.SetPinPage import one.mixin.android.ui.landing.components.SetupPinPage +import one.mixin.android.ui.landing.viewmodel.LandingViewModel import one.mixin.android.util.viewBinding @AndroidEntryPoint @@ -33,7 +34,7 @@ class SetupPinFragment : BaseFragment(R.layout.fragment_compose) { } } - private val mobileViewModel by viewModels() + private val landingViewModel by viewModels() private val binding by viewBinding(FragmentComposeBinding::bind) enum class SetupPinDestination { diff --git a/app/src/main/java/one/mixin/android/ui/landing/TimeFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/TimeFragment.kt index 12c15e15aa..8073828dd0 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/TimeFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/TimeFragment.kt @@ -13,6 +13,8 @@ import one.mixin.android.extension.putBoolean import one.mixin.android.extension.shaking import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.home.MainActivity +import one.mixin.android.ui.landing.viewmodel.LandingViewModel + import one.mixin.android.util.ErrorHandler import one.mixin.android.util.reportException import one.mixin.android.util.viewBinding @@ -25,7 +27,7 @@ class TimeFragment : BaseFragment(R.layout.fragment_time) { fun newInstance() = TimeFragment() } - private val loadingViewModel by viewModels() + private val landingViewModel by viewModels() private val binding by viewBinding(FragmentTimeBinding::bind) override fun onResume() { @@ -51,7 +53,7 @@ class TimeFragment : BaseFragment(R.layout.fragment_time) { everybodyPb.visibility = View.VISIBLE continueTv.visibility = View.INVISIBLE currentJob = - loadingViewModel.pingServer( + landingViewModel.pingServer( { if (isAdded) { everybodyPb.visibility = View.INVISIBLE diff --git a/app/src/main/java/one/mixin/android/ui/landing/UpgradeFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/UpgradeFragment.kt index e6420c3699..da5356a888 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/UpgradeFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/UpgradeFragment.kt @@ -18,6 +18,7 @@ import one.mixin.android.db.runInTransaction import one.mixin.android.extension.withArgs import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.home.MainActivity +import one.mixin.android.ui.landing.viewmodel.LandingViewModel import one.mixin.android.util.viewBinding @AndroidEntryPoint @@ -34,7 +35,7 @@ class UpgradeFragment : BaseFragment(R.layout.fragment_upgrade) { } } - private val viewModel by viewModels() + private val viewModel by viewModels() private val binding by viewBinding(FragmentUpgradeBinding::bind) private val type: Int by lazy { requireArguments().getInt(ARGS_TYPE) } diff --git a/app/src/main/java/one/mixin/android/ui/landing/VerificationFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/VerificationFragment.kt index 3687d7a060..193af2f474 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/VerificationFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/VerificationFragment.kt @@ -48,6 +48,7 @@ import one.mixin.android.ui.landing.MobileFragment.Companion.ARGS_PHONE_NUM import one.mixin.android.ui.landing.MobileFragment.Companion.FROM_CHANGE_PHONE_ACCOUNT import one.mixin.android.ui.landing.MobileFragment.Companion.FROM_DELETE_ACCOUNT import one.mixin.android.ui.landing.MobileFragment.Companion.FROM_LANDING +import one.mixin.android.ui.landing.viewmodel.LandingViewModel import one.mixin.android.ui.setting.VerificationEmergencyIdFragment import one.mixin.android.ui.setting.delete.DeleteAccountPinBottomSheetDialogFragment import one.mixin.android.util.ErrorHandler @@ -84,7 +85,7 @@ class VerificationFragment : PinCodeFragment(R.layout.fragment_verification) { } } - private val viewModel by viewModels() + private val viewModel by viewModels() @Inject lateinit var tip: Tip @@ -262,7 +263,7 @@ class VerificationFragment : PinCodeFragment(R.layout.fragment_verification) { handleMixinResponse( invokeNetwork = { viewModel.create(requireArguments().getString(ARGS_ID)!!, accountRequest) }, successBlock = { response -> - handleAccount(response, sessionKey) { + handleAccount(viewModel, response, sessionKey) { defaultSharedPreferences.putInt(PREF_LOGIN_FROM, FROM_LOGIN) } }, diff --git a/app/src/main/java/one/mixin/android/ui/landing/components/MnemonicPhraseInput.kt b/app/src/main/java/one/mixin/android/ui/landing/components/MnemonicPhraseInput.kt index 1b2a57c738..2012ec6080 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/components/MnemonicPhraseInput.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/components/MnemonicPhraseInput.kt @@ -76,7 +76,7 @@ import one.mixin.android.extension.getClipboardManager import one.mixin.android.extension.toHex import one.mixin.android.session.Session import one.mixin.android.tip.Tip -import one.mixin.android.ui.wallet.WalletViewModel +import one.mixin.android.ui.landing.viewmodel.LandingViewModel import one.mixin.android.util.getMixinErrorStringByCode @Composable @@ -93,7 +93,7 @@ fun MnemonicPhraseInput( var loading by remember { mutableStateOf(false) } var errorInfo by remember { mutableStateOf("") } val context = LocalContext.current - val walletViewModel = hiltViewModel() + val landingViewModel = hiltViewModel() val coroutineScope = rememberCoroutineScope() val focusManager = LocalFocusManager.current var currentText by remember { mutableStateOf("") } @@ -240,11 +240,11 @@ fun MnemonicPhraseInput( val selfId = Session.getAccountId()!! val seed = tip?.getOrRecoverTipPriv(context, pin!!)?.getOrThrow() val edKey = tip?.getMnemonicEdKey(context, pin!!, seed!!) - val r = walletViewModel.saltExport( + val r = landingViewModel.saltExport( ExportRequest( publicKey = edKey!!.publicKey.toHex(), signature = initFromSeedAndSign(edKey.privateKey, selfId.toByteArray()).toHex(), - pinBase64 = walletViewModel.getEncryptedTipBody(selfId, pin!!), + pinBase64 = landingViewModel.getEncryptedTipBody(selfId, pin!!), ) ) r.data?.let { @@ -413,11 +413,11 @@ fun MnemonicPhraseInput( val selfId = Session.getAccountId()!! val seed = tip?.getOrRecoverTipPriv(context, pin!!)?.getOrThrow() val edKey = tip?.getMnemonicEdKey(context, pin!!, seed!!) - val r = walletViewModel.saltExport( + val r = landingViewModel.saltExport( ExportRequest( publicKey = edKey!!.publicKey.toHex(), signature = initFromSeedAndSign(edKey.privateKey, selfId.toByteArray()).toHex(), - pinBase64 = walletViewModel.getEncryptedTipBody(selfId, pin!!), + pinBase64 = landingViewModel.getEncryptedTipBody(selfId, pin!!), ) ) r.data?.let { diff --git a/app/src/main/java/one/mixin/android/ui/landing/components/MnemonicPhrasePage.kt b/app/src/main/java/one/mixin/android/ui/landing/components/MnemonicPhrasePage.kt index 9cefc3b7aa..0d51950c49 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/components/MnemonicPhrasePage.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/components/MnemonicPhrasePage.kt @@ -28,8 +28,8 @@ import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import one.mixin.android.R import one.mixin.android.compose.theme.MixinAppTheme -import one.mixin.android.ui.landing.MobileViewModel import one.mixin.android.ui.landing.vo.MnemonicPhraseState +import one.mixin.android.ui.landing.viewmodel.LandingViewModel @Composable fun MnemonicPhrasePage( @@ -37,7 +37,7 @@ fun MnemonicPhrasePage( errorInfo: String?, requestCaptcha: () -> Unit ) { - val viewModel = hiltViewModel() + val viewModel = hiltViewModel() val mnemonicPhraseState by viewModel.mnemonicPhraseState.observeAsState(MnemonicPhraseState.Initial) MixinAppTheme { Column(modifier = Modifier.padding(horizontal = 20.dp)) { diff --git a/app/src/main/java/one/mixin/android/ui/landing/components/SetPinLoadingPage.kt b/app/src/main/java/one/mixin/android/ui/landing/components/SetPinLoadingPage.kt index d907ac0160..7c41a6682a 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/components/SetPinLoadingPage.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/components/SetPinLoadingPage.kt @@ -33,12 +33,12 @@ import one.mixin.android.Constants import one.mixin.android.R import one.mixin.android.compose.theme.MixinAppTheme import one.mixin.android.extension.openUrl -import one.mixin.android.ui.landing.MobileViewModel import one.mixin.android.ui.landing.vo.SetupState +import one.mixin.android.ui.landing.viewmodel.LandingViewModel @Composable fun SetPinLoadingPage(next: () -> Unit) { - val viewModel = hiltViewModel() + val viewModel = hiltViewModel() val coroutineScope = rememberCoroutineScope() val setupState by viewModel.setupState.observeAsState(SetupState.Loading) val context = LocalContext.current diff --git a/app/src/main/java/one/mixin/android/ui/landing/MobileViewModel.kt b/app/src/main/java/one/mixin/android/ui/landing/viewmodel/LandingViewModel.kt similarity index 52% rename from app/src/main/java/one/mixin/android/ui/landing/MobileViewModel.kt rename to app/src/main/java/one/mixin/android/ui/landing/viewmodel/LandingViewModel.kt index 0493cd0070..32fb4b27b2 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/MobileViewModel.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/viewmodel/LandingViewModel.kt @@ -1,5 +1,6 @@ -package one.mixin.android.ui.landing +package one.mixin.android.ui.landing.viewmodel +import androidx.collection.ArrayMap import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel @@ -9,44 +10,95 @@ import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import one.mixin.android.Constants +import one.mixin.android.MixinApplication import one.mixin.android.api.MixinResponse import one.mixin.android.api.request.AccountRequest import one.mixin.android.api.request.AccountUpdateRequest import one.mixin.android.api.request.DeactivateVerificationRequest +import one.mixin.android.api.request.EmergencyRequest +import one.mixin.android.api.request.SessionSecretRequest import one.mixin.android.api.request.VerificationPurpose import one.mixin.android.api.request.VerificationRequest +import one.mixin.android.api.response.ExportRequest +import one.mixin.android.api.response.UserSession import one.mixin.android.api.response.VerificationResponse +import one.mixin.android.api.service.AccountService +import one.mixin.android.api.service.EmergencyService +import one.mixin.android.api.service.SignalKeyService +import one.mixin.android.api.service.UserService import one.mixin.android.crypto.PinCipher -import one.mixin.android.job.MixinJobManager +import one.mixin.android.crypto.db.SenderKeyDao +import one.mixin.android.crypto.db.SessionDao +import one.mixin.android.crypto.db.SignalDatabase +import one.mixin.android.crypto.vo.SenderKey +import one.mixin.android.crypto.vo.Session +import one.mixin.android.db.DatabaseProvider +import one.mixin.android.db.MixinDatabase +import one.mixin.android.db.insertUpdate +import one.mixin.android.extension.getDeviceId +import one.mixin.android.job.RefreshOneTimePreKeysJob import one.mixin.android.repository.AccountRepository import one.mixin.android.repository.UserRepository import one.mixin.android.tip.TipBody import one.mixin.android.ui.landing.vo.MnemonicPhraseState import one.mixin.android.ui.landing.vo.SetupState import one.mixin.android.vo.Account +import one.mixin.android.vo.ParticipantSession import one.mixin.android.vo.User import javax.inject.Inject +import kotlin.math.abs @HiltViewModel -class MobileViewModel +class LandingViewModel @Inject internal constructor( - private val accountRepository: AccountRepository, - private val userRepository: UserRepository, - private val jobManager: MixinJobManager, + private val databaseProvider: DatabaseProvider, + private val accountService: AccountService, + private val emergencyService: EmergencyService, private val pinCipher: PinCipher, ) : ViewModel() { + fun initAllDatabases() = databaseProvider.initAllDatabases() + + fun pingServer( + callback: () -> Unit, + elseCallBack: (e: Exception?) -> Unit, + ): Job { + return viewModelScope.launch { + try { + val response = + withContext(coroutineContext + Dispatchers.IO) { + accountService.ping().execute() + } + response.headers()["X-Server-Time"]?.toLong()?.let { serverTime -> + if (abs(serverTime / 1000000 - System.currentTimeMillis()) < Constants.ALLOW_INTERVAL) { // 10 minutes + callback.invoke() + } else { + elseCallBack.invoke(null) + } + } + } catch (e: Exception) { + elseCallBack.invoke(e) + } + } + } + fun loginVerification(request: VerificationRequest): Observable> = - accountRepository.verificationObserver(request).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) + accountService.verificationObserver(request).subscribeOn(Schedulers.io()).observeOn( + AndroidSchedulers.mainThread()) fun verification(request: VerificationRequest): Observable> = - accountRepository.verificationObserver(request).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) + accountService.verificationObserver(request).subscribeOn(Schedulers.io()).observeOn( + AndroidSchedulers.mainThread()) fun upsertUser(u: User) = viewModelScope.launch(Dispatchers.IO) { - userRepository.upsert(u) + initAllDatabases() + databaseProvider.getMixinDatabase().userDao().upsert(u) } suspend fun create( @@ -54,7 +106,7 @@ internal constructor( request: AccountRequest, ): MixinResponse = withContext(Dispatchers.IO) { - accountRepository.create(id, request) + accountService.create(id, request) } suspend fun changePhone( @@ -63,7 +115,7 @@ internal constructor( pin: String, saltBase64: String? = null, ): MixinResponse = - accountRepository.changePhone( + accountService.changePhone( id, AccountRequest( verificationCode, @@ -77,25 +129,30 @@ internal constructor( id: String, code: String, ): Observable> = - accountRepository.deactiveVerification( + accountService.deactiveVerification( id, DeactivateVerificationRequest(VerificationPurpose.DEACTIVATED.name, code), ).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) fun update(request: AccountUpdateRequest): Observable> = - accountRepository.update(request).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) + accountService.update(request).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) fun insertUser(user: User) = viewModelScope.launch(Dispatchers.IO) { - userRepository.upsert(user) + initAllDatabases() + databaseProvider.getMixinDatabase().userDao().insertUpdate(user, databaseProvider.getMixinDatabase().appDao()) } fun updatePhone( id: String, phone: String, - ) = userRepository.updatePhone(id, phone) + ) = { + initAllDatabases() + databaseProvider.getMixinDatabase().userDao().updatePhone(id, phone) + } - private val _mnemonicPhraseState = MutableLiveData(MnemonicPhraseState.Initial) + private val _mnemonicPhraseState = + MutableLiveData(MnemonicPhraseState.Initial) val mnemonicPhraseState: LiveData get() = _mnemonicPhraseState fun updateMnemonicPhraseState(state: MnemonicPhraseState){ @@ -103,7 +160,7 @@ internal constructor( } suspend fun anonymousRequest(publicKeyHex: String, messageHex: String, signatureHex: String, hCaptchaResponse: String? = null, gRecaptchaResponse: String? = null): MixinResponse { - val r = accountRepository.verification( + val r = accountService.verification( VerificationRequest( purpose = VerificationPurpose.ANONYMOUS_SESSION.name, masterPublicHex = publicKeyHex, @@ -128,4 +185,16 @@ internal constructor( userId: String, pin: String, ): String = pinCipher.encryptPin(pin, TipBody.forExport(userId)) -} + + suspend fun saltExport(exportRequest: ExportRequest) = accountService.saltExport(exportRequest) + + suspend fun createVerifyEmergency( + id: String, + request: EmergencyRequest, + ) = emergencyService.createVerify(id, request) + + suspend fun loginVerifyEmergency( + id: String, + request: EmergencyRequest, + ) = emergencyService.loginVerify(id, request) +} \ No newline at end of file diff --git a/app/src/main/java/one/mixin/android/ui/landing/viewmodel/LoadingViewModel.kt b/app/src/main/java/one/mixin/android/ui/landing/viewmodel/LoadingViewModel.kt new file mode 100644 index 0000000000..bb9ce84d2b --- /dev/null +++ b/app/src/main/java/one/mixin/android/ui/landing/viewmodel/LoadingViewModel.kt @@ -0,0 +1,108 @@ +package one.mixin.android.ui.landing.viewmodel + +import androidx.collection.ArrayMap +import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.withContext +import one.mixin.android.api.MixinResponse +import one.mixin.android.api.request.SessionSecretRequest +import one.mixin.android.api.response.UserSession +import one.mixin.android.api.service.AccountService +import one.mixin.android.api.service.SignalKeyService +import one.mixin.android.api.service.UserService +import one.mixin.android.crypto.db.SignalDatabase +import one.mixin.android.crypto.vo.SenderKey +import one.mixin.android.crypto.vo.Session +import one.mixin.android.db.DatabaseProvider +import one.mixin.android.db.MixinDatabase +import one.mixin.android.extension.getDeviceId +import one.mixin.android.job.RefreshOneTimePreKeysJob +import one.mixin.android.vo.ParticipantSession +import javax.inject.Inject +import kotlin.collections.set +import kotlin.sequences.forEach + +@HiltViewModel +class LoadingViewModel +@Inject +internal constructor( + private val databaseProvider: DatabaseProvider, + private val signalDatabase: SignalDatabase, + private val accountService: AccountService, + private val signalKeyService: SignalKeyService, + private val userService: UserService, +) : ViewModel() { + + suspend fun pushAsyncSignalKeys(): MixinResponse = + withContext(Dispatchers.IO) { + val start = System.currentTimeMillis() + val signalKeys = RefreshOneTimePreKeysJob.Companion.generateKeys() + val response = signalKeyService.pushSignalKeys(signalKeys).await() + val time = System.currentTimeMillis() - start + if (time < 2000) { + delay(time) + } + return@withContext response + } + + suspend fun updateSignalSession() { + withContext(Dispatchers.IO) { + val sessions = signalDatabase.sessionDao().syncGetSessionAddress() + val userIds = sessions.map { it.address } + val response = userService.fetchSessionsSuspend(userIds) + val sessionMap = ArrayMap() + val userSessionMap = ArrayMap() + if (response.isSuccess) { + response.data?.asSequence()?.forEach { item -> + if (item.platform == "Android" || item.platform == "iOS") { + val deviceId = item.sessionId.getDeviceId() + sessionMap[item.userId] = deviceId + userSessionMap[item.userId] = item + } + } + } + if (sessionMap.isEmpty()) { + return@withContext + } + val newSession = mutableListOf() + for (s in sessions) { + sessionMap[s.address]?.let { d -> + newSession.add(Session(s.address, d, s.record, s.timestamp)) + } + } + signalDatabase.sessionDao().insertList(newSession) + val senderKeys = signalDatabase.senderKeyDao().syncGetSenderKeys() + senderKeys.forEach { key -> + if (!key.senderId.endsWith(":1")) { + return@forEach + } + val userId = key.senderId.substring(0, key.senderId.length - 2) + sessionMap[userId]?.let { d -> + signalDatabase.senderKeyDao().insert(SenderKey(key.groupId, "$userId:$d", key.record)) + } + } + databaseProvider.initAllDatabases() + val participants = databaseProvider.getMixinDatabase().participantDao().getAllParticipants() + val newParticipantSession = mutableListOf() + participants.forEach { p -> + userSessionMap[p.userId]?.let { userSession -> + val ps = ParticipantSession( + p.conversationId, + p.userId, + sessionId = userSession.sessionId, + publicKey = userSession.publicKey + ) + newParticipantSession.add(ps) + } + } + databaseProvider.getMixinDatabase().participantSessionDao().insertListSuspend(newParticipantSession) + } + } + + suspend fun modifySessionSecret(request: SessionSecretRequest) = + withContext(Dispatchers.IO) { + accountService.modifySessionSecret(request) + } +} \ No newline at end of file diff --git a/app/src/main/java/one/mixin/android/ui/setting/AccountFragment.kt b/app/src/main/java/one/mixin/android/ui/setting/AccountFragment.kt index 5c41c79004..84da657542 100644 --- a/app/src/main/java/one/mixin/android/ui/setting/AccountFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/setting/AccountFragment.kt @@ -44,6 +44,15 @@ class AccountFragment : BaseFragment(R.layout.fragment_account) { securityRl.setOnClickListener { navTo(SecurityFragment.newInstance(), SecurityFragment.TAG) } + logOutRl.setOnClickListener { + // if (!Session.hasPhone() && !Session.saltExported()) { + // BackupMnemonicPhraseWarningBottomSheetDialogFragment.newInstance() + // .show(parentFragmentManager, BackupMnemonicPhraseWarningBottomSheetDialogFragment.TAG) + // } else { + LogoutPinBottomSheetDialogFragment.newInstance() + .showNow(parentFragmentManager, VerifyBottomSheetDialogFragment.TAG) + // } + } deleteRl.setOnClickListener { navTo(DeleteAccountFragment.newInstance(), DeleteAccountFragment.TAG) } diff --git a/app/src/main/java/one/mixin/android/ui/setting/EmergencyViewModel.kt b/app/src/main/java/one/mixin/android/ui/setting/EmergencyViewModel.kt index 9909e6d0df..2915d9b3ab 100644 --- a/app/src/main/java/one/mixin/android/ui/setting/EmergencyViewModel.kt +++ b/app/src/main/java/one/mixin/android/ui/setting/EmergencyViewModel.kt @@ -24,21 +24,7 @@ class EmergencyViewModel accountRepository.createEmergency(request) } - suspend fun createVerifyEmergency( - id: String, - request: EmergencyRequest, - ) = - withContext(Dispatchers.IO) { - accountRepository.createVerifyEmergency(id, request) - } - suspend fun loginVerifyEmergency( - id: String, - request: EmergencyRequest, - ) = - withContext(Dispatchers.IO) { - accountRepository.loginVerifyEmergency(id, request) - } suspend fun findFriendsNotBot() = userRepository.findFriendsNotBot() diff --git a/app/src/main/java/one/mixin/android/ui/setting/VerificationEmergencyFragment.kt b/app/src/main/java/one/mixin/android/ui/setting/VerificationEmergencyFragment.kt index 9ab58d726b..d5bfc3b30d 100644 --- a/app/src/main/java/one/mixin/android/ui/setting/VerificationEmergencyFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/setting/VerificationEmergencyFragment.kt @@ -28,6 +28,7 @@ import one.mixin.android.tip.TipBody import one.mixin.android.tip.exception.TipNetworkException import one.mixin.android.ui.common.PinCodeFragment import one.mixin.android.ui.landing.LandingActivity.Companion.ARGS_PIN +import one.mixin.android.ui.landing.viewmodel.LandingViewModel import one.mixin.android.util.viewBinding import one.mixin.android.vo.Account import one.mixin.android.vo.User @@ -65,7 +66,7 @@ class VerificationEmergencyFragment : PinCodeFragment(R.layout.fragment_verifica private val from by lazy { requireArguments().getInt(ARGS_FROM) } private val userIdentityNumber: String? by lazy { requireArguments().getString(ARGS_IDENTITY_NUMBER) } - private val viewModel by viewModels() + private val viewModel by viewModels() private val binding by viewBinding(FragmentVerificationEmergencyBinding::bind) @@ -160,7 +161,7 @@ class VerificationEmergencyFragment : PinCodeFragment(R.layout.fragment_verifica handleMixinResponse( invokeNetwork = { viewModel.loginVerifyEmergency(verificationId, buildLoginEmergencyRequest(sessionKey)) }, successBlock = { response -> - handleAccount(response, sessionKey) { + handleAccount(viewModel, response, sessionKey) { defaultSharedPreferences.putInt(PREF_LOGIN_FROM, FROM_EMERGENCY) } }, diff --git a/app/src/main/res/layout/fragment_account.xml b/app/src/main/res/layout/fragment_account.xml index cae3791050..80f807a461 100644 --- a/app/src/main/res/layout/fragment_account.xml +++ b/app/src/main/res/layout/fragment_account.xml @@ -81,6 +81,25 @@ android:layout_height="@dimen/setting_divider" android:background="?attr/bg_window" /> + + + + + Date: Wed, 27 Nov 2024 18:44:53 +0800 Subject: [PATCH 05/42] Job inject --- .../java/one/mixin/android/db/DaoExtension.kt | 6 +- .../one/mixin/android/db/MixinDatabase.kt | 2 +- .../one/mixin/android/di/DatabaseModule.kt | 6 +- .../java/one/mixin/android/job/BaseJob.kt | 272 +++++++----------- .../one/mixin/android/job/CheckBalanceJob.kt | 2 +- .../one/mixin/android/job/ConversationJob.kt | 56 +++- .../one/mixin/android/job/ConvertDataJob.kt | 2 +- .../one/mixin/android/job/DecryptMessage.kt | 2 +- .../java/one/mixin/android/job/Injector.kt | 110 +++---- .../one/mixin/android/job/MessageDeleteJob.kt | 2 +- .../android/job/RefreshConversationJob.kt | 59 +++- .../one/mixin/android/job/RefreshDappJob.kt | 65 ++++- .../one/mixin/android/job/RefreshOffsetJob.kt | 2 +- .../job/RefreshStickerAndRelatedAlbumJob.kt | 2 +- .../one/mixin/android/job/RefreshTokensJob.kt | 6 +- .../one/mixin/android/job/RefreshUserJob.kt | 4 +- .../android/job/RestoreTransactionJob.kt | 4 +- .../android/job/SendAttachmentMessageJob.kt | 4 +- .../one/mixin/android/job/SendMessageJob.kt | 2 +- .../android/job/SendProcessSignalKeyJob.kt | 2 +- .../mixin/android/job/SendTranscriptJob.kt | 2 +- .../mixin/android/job/TranscriptDeleteJob.kt | 2 +- .../android/job/UpdateRelationshipJob.kt | 6 +- 23 files changed, 348 insertions(+), 272 deletions(-) diff --git a/app/src/main/java/one/mixin/android/db/DaoExtension.kt b/app/src/main/java/one/mixin/android/db/DaoExtension.kt index b550e68fb1..06477802e6 100644 --- a/app/src/main/java/one/mixin/android/db/DaoExtension.kt +++ b/app/src/main/java/one/mixin/android/db/DaoExtension.kt @@ -194,7 +194,7 @@ suspend fun OutputDao.insertUnspentOutputs(outputs: List) = fun MixinDatabase.deleteMessageById(messageId: String) { runInTransaction { pinMessageDao().deleteByMessageId(messageId) - mentionMessageDao().deleteMessage(messageId) + messageMentionDao().deleteMessage(messageId) messageDao().deleteMessageById(messageId) remoteMessageStatusDao().deleteByMessageId(messageId) expiredMessageDao().deleteByMessageId(messageId) @@ -207,7 +207,7 @@ fun MixinDatabase.deleteMessageById( ) { runInTransaction { pinMessageDao().deleteByMessageId(messageId) - mentionMessageDao().deleteMessage(messageId) + messageMentionDao().deleteMessage(messageId) messageDao().deleteMessageById(messageId) conversationExtDao().decrement(conversationId) remoteMessageStatusDao().deleteByMessageId(messageId) @@ -219,7 +219,7 @@ fun MixinDatabase.deleteMessageById( fun MixinDatabase.deleteMessageByIds(messageIds: List) { runInTransaction { pinMessageDao().deleteByIds(messageIds) - mentionMessageDao().deleteMessage(messageIds) + messageMentionDao().deleteMessage(messageIds) messageDao().deleteMessageById(messageIds) remoteMessageStatusDao().deleteByMessageIds(messageIds) expiredMessageDao().deleteByMessageId(messageIds) diff --git a/app/src/main/java/one/mixin/android/db/MixinDatabase.kt b/app/src/main/java/one/mixin/android/db/MixinDatabase.kt index 9fc4122c34..e068769a4a 100644 --- a/app/src/main/java/one/mixin/android/db/MixinDatabase.kt +++ b/app/src/main/java/one/mixin/android/db/MixinDatabase.kt @@ -236,7 +236,7 @@ abstract class MixinDatabase : RoomDatabase() { abstract fun favoriteAppDao(): FavoriteAppDao - abstract fun mentionMessageDao(): MessageMentionDao + abstract fun messageMentionDao(): MessageMentionDao abstract fun circleDao(): CircleDao diff --git a/app/src/main/java/one/mixin/android/di/DatabaseModule.kt b/app/src/main/java/one/mixin/android/di/DatabaseModule.kt index 12ff7b7026..c252a12105 100644 --- a/app/src/main/java/one/mixin/android/di/DatabaseModule.kt +++ b/app/src/main/java/one/mixin/android/di/DatabaseModule.kt @@ -25,7 +25,9 @@ internal object DatabaseModule { @Singleton @Provides - fun provideDatbaseProvider(app: Application) = DatabaseProvider(app) + fun provideDatabaseProvider(app: Application): DatabaseProvider { + return DatabaseProvider(app) + } @Provides fun provideAppDatabase( @@ -122,7 +124,7 @@ internal object DatabaseModule { fun providesFavoriteAppDao(db: MixinDatabase) = db.favoriteAppDao() @Provides - fun providesMentionMessageDao(db: MixinDatabase) = db.mentionMessageDao() + fun providesMentionMessageDao(db: MixinDatabase) = db.messageMentionDao() @Provides fun providesCircleDao(db: MixinDatabase) = db.circleDao() diff --git a/app/src/main/java/one/mixin/android/job/BaseJob.kt b/app/src/main/java/one/mixin/android/job/BaseJob.kt index 69caed646f..56e027174b 100644 --- a/app/src/main/java/one/mixin/android/job/BaseJob.kt +++ b/app/src/main/java/one/mixin/android/job/BaseJob.kt @@ -8,6 +8,7 @@ import dagger.hilt.EntryPoint import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.CoroutineScope +import one.mixin.android.MixinApplication import one.mixin.android.api.ClientErrorException import one.mixin.android.api.ExpiredTokenException import one.mixin.android.api.LocalJobException @@ -40,6 +41,7 @@ import one.mixin.android.db.CircleConversationDao import one.mixin.android.db.CircleDao import one.mixin.android.db.ConversationDao import one.mixin.android.db.ConversationExtDao +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.ExpiredMessageDao import one.mixin.android.db.FavoriteAppDao import one.mixin.android.db.HistoryPriceDao @@ -76,9 +78,6 @@ import one.mixin.android.db.UserDao import one.mixin.android.db.pending.PendingDatabase import one.mixin.android.di.ApplicationScope import one.mixin.android.fts.FtsDatabase -import one.mixin.android.repository.ConversationRepository -import one.mixin.android.repository.TokenRepository -import one.mixin.android.repository.UserRepository import one.mixin.android.tip.Tip import one.mixin.android.util.reportException import one.mixin.android.vo.LinkState @@ -100,15 +99,7 @@ abstract class BaseJob(params: Params) : Job(params) { @Inject @Transient - lateinit var ftsDatabase: FtsDatabase - - @Inject - @Transient - lateinit var mixinDatabase: MixinDatabase - - @Inject - @Transient - lateinit var pendingDatabase: PendingDatabase + lateinit var databaseProvider: DatabaseProvider @Inject @Transient @@ -160,224 +151,179 @@ abstract class BaseJob(params: Params) : Job(params) { @Inject @Transient - lateinit var messageDao: MessageDao + lateinit var chatWebSocket: ChatWebSocket @Inject @Transient - lateinit var messageHistoryDao: MessageHistoryDao + lateinit var signalProtocol: SignalProtocol @Inject @Transient - lateinit var userDao: UserDao + lateinit var encryptedProtocol: EncryptedProtocol - @Inject @Transient - lateinit var conversationDao: ConversationDao - @Inject - @Transient - lateinit var conversationExtDao: ConversationExtDao + lateinit var linkState: LinkState - @Inject @Transient - lateinit var participantDao: ParticipantDao - @Inject - @Transient - lateinit var participantSessionDao: ParticipantSessionDao + lateinit var tip: Tip - @Inject @Transient - lateinit var offsetDao: OffsetDao - @Inject - @Transient - lateinit var assetDao: AssetDao + lateinit var tipCounterSynced: TipCounterSyncedLiveData @Inject @Transient - lateinit var tokenDao: TokenDao + lateinit var tipService: TipService @Inject @Transient - lateinit var tokensExtraDao: TokensExtraDao + lateinit var web3Service: Web3Service - @Inject + @ApplicationScope @Transient - lateinit var snapshotDao: SnapshotDao - @Inject - @Transient - lateinit var chainDao: ChainDao + lateinit var applicationScope: CoroutineScope - @Inject @Transient - lateinit var chatWebSocket: ChatWebSocket - @Inject - @Transient - lateinit var conversationRepo: ConversationRepository + lateinit var jobSenderKey: JobSenderKey - @Inject - @Transient - lateinit var userRepo: UserRepository + @delegate:Transient + val database: MixinDatabase by lazy { + requireNotNull(databaseProvider) { "DatabaseProvider not initialized" } + databaseProvider.getMixinDatabase() + } - @Inject - @Transient - lateinit var assetRepo: TokenRepository + @delegate:Transient + val ftsDatabase: FtsDatabase by lazy { databaseProvider.getFtsDatabase() } - @Inject - @Transient - lateinit var stickerDao: StickerDao + @delegate:Transient + val pendingDatabase: PendingDatabase by lazy { databaseProvider.getPendingDatabase() } - @Inject - @Transient - lateinit var hyperlinkDao: HyperlinkDao + @delegate:Transient + val messageDao: MessageDao by lazy { databaseProvider.getMixinDatabase().messageDao() } - @Inject - @Transient - lateinit var stickerAlbumDao: StickerAlbumDao + @delegate:Transient + val messageHistoryDao: MessageHistoryDao by lazy { databaseProvider.getMixinDatabase().messageHistoryDao() } - @Inject - @Transient - lateinit var stickerRelationshipDao: StickerRelationshipDao + @delegate:Transient + val userDao: UserDao by lazy { databaseProvider.getMixinDatabase().userDao() } - @Inject - @Transient - lateinit var addressDao: AddressDao + @delegate:Transient + val conversationDao: ConversationDao by lazy { databaseProvider.getMixinDatabase().conversationDao() } - @Inject - @Transient - lateinit var topAssetDao: TopAssetDao + @delegate:Transient + val conversationExtDao: ConversationExtDao by lazy { databaseProvider.getMixinDatabase().conversationExtDao() } - @Inject - @Transient - lateinit var jobDao: JobDao + @delegate:Transient + val participantDao: ParticipantDao by lazy { databaseProvider.getMixinDatabase().participantDao() } - @Inject - @Transient - lateinit var favoriteAppDao: FavoriteAppDao + @delegate:Transient + val participantSessionDao: ParticipantSessionDao by lazy { databaseProvider.getMixinDatabase().participantSessionDao() } - @Inject - @Transient - lateinit var messageMentionDao: MessageMentionDao + @delegate:Transient + val offsetDao: OffsetDao by lazy { databaseProvider.getMixinDatabase().offsetDao() } - @Inject - @Transient - lateinit var appDao: AppDao + @delegate:Transient + val assetDao: AssetDao by lazy { databaseProvider.getMixinDatabase().assetDao() } - @Inject - @Transient - lateinit var circleDao: CircleDao + @delegate:Transient + val tokenDao: TokenDao by lazy { databaseProvider.getMixinDatabase().tokenDao() } - @Inject - @Transient - lateinit var circleConversationDao: CircleConversationDao + @delegate:Transient + val tokensExtraDao: TokensExtraDao by lazy { databaseProvider.getMixinDatabase().tokensExtraDao() } - @Inject - @Transient - lateinit var transcriptMessageDao: TranscriptMessageDao + @delegate:Transient + val snapshotDao: SnapshotDao by lazy { databaseProvider.getMixinDatabase().snapshotDao() } - @Inject - @Transient - lateinit var pinMessageDao: PinMessageDao + @delegate:Transient + val chainDao: ChainDao by lazy { databaseProvider.getMixinDatabase().chainDao() } - @Inject - @Transient - lateinit var propertyDao: PropertyDao + @delegate:Transient + val stickerDao: StickerDao by lazy { databaseProvider.getMixinDatabase().stickerDao() } - @Inject - @Transient - lateinit var remoteMessageStatusDao: RemoteMessageStatusDao + @delegate:Transient + val hyperlinkDao: HyperlinkDao by lazy { databaseProvider.getMixinDatabase().hyperlinkDao() } - @Inject - @Transient - lateinit var expiredMessageDao: ExpiredMessageDao + @delegate:Transient + val stickerAlbumDao: StickerAlbumDao by lazy { databaseProvider.getMixinDatabase().stickerAlbumDao() } - @Inject - @Transient - lateinit var outputDao: OutputDao + @delegate:Transient + val stickerRelationshipDao: StickerRelationshipDao by lazy { databaseProvider.getMixinDatabase().stickerRelationshipDao() } - @Inject - @Transient - lateinit var rawTransactionDao: RawTransactionDao + @delegate:Transient + val addressDao: AddressDao by lazy { databaseProvider.getMixinDatabase().addressDao() } - @Inject - @Transient - lateinit var safeSnapshotDao: SafeSnapshotDao + @delegate:Transient + val topAssetDao: TopAssetDao by lazy { databaseProvider.getMixinDatabase().topAssetDao() } - @Inject - @Transient - lateinit var inscriptionDao: InscriptionDao + @delegate:Transient + val jobDao: JobDao by lazy { databaseProvider.getMixinDatabase().jobDao() } - @Inject - @Transient - lateinit var marketDao: MarketDao + @delegate:Transient + val favoriteAppDao: FavoriteAppDao by lazy { databaseProvider.getMixinDatabase().favoriteAppDao() } - @Inject - @Transient - lateinit var marketFavoredDao: MarketFavoredDao + @delegate:Transient + val messageMentionDao: MessageMentionDao by lazy { databaseProvider.getMixinDatabase().messageMentionDao() } - @Inject - @Transient - lateinit var alertDao: AlertDao + @delegate:Transient + val appDao: AppDao by lazy { databaseProvider.getMixinDatabase().appDao() } - @Inject - @Transient - lateinit var marketCapRankDao: MarketCapRankDao + @delegate:Transient + val circleDao: CircleDao by lazy { databaseProvider.getMixinDatabase().circleDao() } - @Inject - @Transient - lateinit var marketCoinDao: MarketCoinDao + @delegate:Transient + val circleConversationDao: CircleConversationDao by lazy { databaseProvider.getMixinDatabase().circleConversationDao() } - @Inject - @Transient - lateinit var historyPriceDao: HistoryPriceDao + @delegate:Transient + val transcriptMessageDao: TranscriptMessageDao by lazy { databaseProvider.getMixinDatabase().transcriptDao() } - @Inject - @Transient - lateinit var inscriptionCollectionDao: InscriptionCollectionDao + @delegate:Transient + val pinMessageDao: PinMessageDao by lazy { databaseProvider.getMixinDatabase().pinMessageDao() } - @Inject - @Transient - lateinit var signalProtocol: SignalProtocol + @delegate:Transient + val propertyDao: PropertyDao by lazy { databaseProvider.getMixinDatabase().propertyDao() } - @Inject - @Transient - lateinit var encryptedProtocol: EncryptedProtocol + @delegate:Transient + val remoteMessageStatusDao: RemoteMessageStatusDao by lazy { databaseProvider.getMixinDatabase().remoteMessageStatusDao() } - @Transient - @Inject - lateinit var appDatabase: MixinDatabase + @delegate:Transient + val expiredMessageDao: ExpiredMessageDao by lazy { databaseProvider.getMixinDatabase().expiredMessageDao() } - @Transient - @Inject - lateinit var linkState: LinkState + @delegate:Transient + val outputDao: OutputDao by lazy { databaseProvider.getMixinDatabase().outputDao() } - @Transient - @Inject - lateinit var tip: Tip + @delegate:Transient + val rawTransactionDao: RawTransactionDao by lazy { databaseProvider.getMixinDatabase().rawTransactionDao() } - @Transient - @Inject - lateinit var tipCounterSynced: TipCounterSyncedLiveData + @delegate:Transient + val safeSnapshotDao: SafeSnapshotDao by lazy { databaseProvider.getMixinDatabase().safeSnapshotDao() } - @Inject - @Transient - lateinit var tipService: TipService + @delegate:Transient + val inscriptionDao: InscriptionDao by lazy { databaseProvider.getMixinDatabase().inscriptionDao() } - @Inject - @Transient - lateinit var web3Service: Web3Service + @delegate:Transient + val marketDao: MarketDao by lazy { databaseProvider.getMixinDatabase().marketDao() } - @ApplicationScope - @Transient - @Inject - lateinit var applicationScope: CoroutineScope + @delegate:Transient + val marketFavoredDao: MarketFavoredDao by lazy { databaseProvider.getMixinDatabase().marketFavoredDao() } - @Transient - @Inject - lateinit var jobSenderKey: JobSenderKey + @delegate:Transient + val alertDao: AlertDao by lazy { databaseProvider.getMixinDatabase().alertDao() } + + @delegate:Transient + val marketCapRankDao: MarketCapRankDao by lazy { databaseProvider.getMixinDatabase().marketCapRankDao() } + + @delegate:Transient + val marketCoinDao: MarketCoinDao by lazy { databaseProvider.getMixinDatabase().marketCoinDao() } + + @delegate:Transient + val historyPriceDao: HistoryPriceDao by lazy { databaseProvider.getMixinDatabase().historyPriceDao() } + + @delegate:Transient + val inscriptionCollectionDao: InscriptionCollectionDao by lazy { databaseProvider.getMixinDatabase().inscriptionCollectionDao() } open fun shouldRetry(throwable: Throwable): Boolean { if (throwable is SocketTimeoutException) { diff --git a/app/src/main/java/one/mixin/android/job/CheckBalanceJob.kt b/app/src/main/java/one/mixin/android/job/CheckBalanceJob.kt index d0a013209f..8353cb18c9 100644 --- a/app/src/main/java/one/mixin/android/job/CheckBalanceJob.kt +++ b/app/src/main/java/one/mixin/android/job/CheckBalanceJob.kt @@ -29,7 +29,7 @@ class CheckBalanceJob( for (asset in assets) { val tokensExtra = tokensExtraDao.findByAsset(asset) val token = tokenDao.findTokenByAsset(asset) ?: continue - mixinDatabase.withTransaction { + database.withTransaction { val value = calcBalanceByAssetId(asset) if (tokensExtra == null) { tokensExtraDao.insertSuspend(TokensExtra(token.assetId, token.asset, false, value.toPlainString(), nowInUtc())) diff --git a/app/src/main/java/one/mixin/android/job/ConversationJob.kt b/app/src/main/java/one/mixin/android/job/ConversationJob.kt index 9803704396..203527a7de 100644 --- a/app/src/main/java/one/mixin/android/job/ConversationJob.kt +++ b/app/src/main/java/one/mixin/android/job/ConversationJob.kt @@ -13,8 +13,13 @@ import one.mixin.android.api.request.ParticipantAction import one.mixin.android.api.request.ParticipantRequest import one.mixin.android.api.response.ConversationResponse import one.mixin.android.event.ConversationEvent +import one.mixin.android.event.GroupEvent import one.mixin.android.extension.networkConnected +import one.mixin.android.extension.putBoolean +import one.mixin.android.extension.sharedPreferences +import one.mixin.android.session.Session import one.mixin.android.util.ErrorHandler +import one.mixin.android.vo.ConversationBuilder import one.mixin.android.vo.ConversationCategory import one.mixin.android.vo.ConversationStatus import one.mixin.android.vo.Participant @@ -131,7 +136,7 @@ class ConversationJob( if (r != null && r.isSuccess && r.data != null) { val cr = r.data!! if (type == TYPE_CREATE) { - conversationRepo.insertOrUpdateConversation(cr) + insertOrUpdateConversation(cr) val participants = mutableListOf() cr.participants.mapTo(participants) { Participant(cr.conversationId, it.userId, it.role, cr.createdAt) @@ -170,4 +175,53 @@ class ConversationJob( override fun cancel() { } + + fun insertOrUpdateConversation(data: ConversationResponse) { + var ownerId: String = data.creatorId + if (data.category == ConversationCategory.CONTACT.name) { + ownerId = data.participants.find { it.userId != Session.getAccountId() }!!.userId + } + var c = conversationDao.findConversationById(data.conversationId) + if (c == null) { + val builder = ConversationBuilder(data.conversationId, data.createdAt, ConversationStatus.SUCCESS.ordinal) + c = + builder.setOwnerId(ownerId) + .setCategory(data.category) + .setName(data.name) + .setIconUrl(data.iconUrl) + .setAnnouncement(data.announcement) + .setMuteUntil(data.muteUntil) + .setCodeUrl(data.codeUrl) + .setExpireIn(data.expireIn) + .build() + conversationDao.upsert(c) + if (!c.announcement.isNullOrBlank()) { + RxBus.publish(GroupEvent(data.conversationId)) + MixinApplication.appContext.sharedPreferences(RefreshConversationJob.PREFERENCES_CONVERSATION).putBoolean(data.conversationId, true) + } + } else { + val status = + if (data.participants.find { Session.getAccountId() == it.userId } != null) { + ConversationStatus.SUCCESS.ordinal + } else { + ConversationStatus.QUIT.ordinal + } + conversationDao.updateConversation( + data.conversationId, + ownerId, + data.category, + data.name, + data.announcement, + data.muteUntil, + data.createdAt, + data.expireIn, + status, + ) + if (data.announcement.isNotBlank() && c.announcement != data.announcement) { + RxBus.publish(GroupEvent(data.conversationId)) + MixinApplication.appContext.sharedPreferences(RefreshConversationJob.PREFERENCES_CONVERSATION).putBoolean(data.conversationId, true) + } + } + } + } diff --git a/app/src/main/java/one/mixin/android/job/ConvertDataJob.kt b/app/src/main/java/one/mixin/android/job/ConvertDataJob.kt index 50b02c68d2..0672eba0fe 100644 --- a/app/src/main/java/one/mixin/android/job/ConvertDataJob.kt +++ b/app/src/main/java/one/mixin/android/job/ConvertDataJob.kt @@ -24,7 +24,7 @@ class ConvertDataJob( } override fun onAdded() { - appDatabase.insertMessage(message) + database.insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) } diff --git a/app/src/main/java/one/mixin/android/job/DecryptMessage.kt b/app/src/main/java/one/mixin/android/job/DecryptMessage.kt index 3a7394d7b5..ac00222788 100644 --- a/app/src/main/java/one/mixin/android/job/DecryptMessage.kt +++ b/app/src/main/java/one/mixin/android/job/DecryptMessage.kt @@ -280,7 +280,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { app = handleMixinResponse( invokeNetwork = { - userApi.getUserByIdSuspend(id) + userService.getUserByIdSuspend(id) }, defaultErrorHandle = {}, defaultExceptionHandle = {}, diff --git a/app/src/main/java/one/mixin/android/job/Injector.kt b/app/src/main/java/one/mixin/android/job/Injector.kt index 62290c6345..454a1a15e3 100644 --- a/app/src/main/java/one/mixin/android/job/Injector.kt +++ b/app/src/main/java/one/mixin/android/job/Injector.kt @@ -20,6 +20,7 @@ import one.mixin.android.db.CircleConversationDao import one.mixin.android.db.CircleDao import one.mixin.android.db.ConversationDao import one.mixin.android.db.ConversationExtDao +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.ExpiredMessageDao import one.mixin.android.db.HyperlinkDao import one.mixin.android.db.JobDao @@ -63,55 +64,7 @@ open class Injector { lateinit var jobManager: MixinJobManager @Inject - lateinit var ftsDatabase: FtsDatabase - - @Inject - lateinit var messageDao: MessageDao - - @Inject - lateinit var pendingMessagesDao: PendingMessageDao - - @Inject - lateinit var messageHistoryDao: MessageHistoryDao - - @Inject - lateinit var userDao: UserDao - - @Inject - lateinit var appDao: AppDao - - @Inject - lateinit var jobDao: JobDao - - @Inject - lateinit var conversationDao: ConversationDao - - @Inject - lateinit var conversationExtDao: ConversationExtDao - - @Inject - lateinit var participantDao: ParticipantDao - - @Inject - lateinit var participantSessionDao: ParticipantSessionDao - - @Inject - lateinit var snapshotDao: SnapshotDao - - @Inject - lateinit var safeSnapshotDao: SafeSnapshotDao - - @Inject - lateinit var tokenDao: TokenDao - - @Inject - lateinit var circleDao: CircleDao - - @Inject - lateinit var circleConversationDao: CircleConversationDao - - @Inject - lateinit var traceDao: TraceDao + lateinit var databaseProvider: DatabaseProvider @Inject lateinit var circleService: CircleService @@ -119,53 +72,56 @@ open class Injector { @Inject lateinit var chatWebSocket: ChatWebSocket - @Inject - lateinit var stickerDao: StickerDao - - @Inject - lateinit var messageMentionDao: MessageMentionDao - @Inject lateinit var signalProtocol: SignalProtocol @Inject lateinit var encryptedProtocol: EncryptedProtocol - @Inject - lateinit var ratchetSenderKeyDao: RatchetSenderKeyDao - - @Inject - lateinit var resendMessageDao: ResendSessionMessageDao - - @Inject - lateinit var hyperlinkDao: HyperlinkDao - - @Inject - lateinit var userApi: UserService - @Inject lateinit var conversationService: ConversationService @Inject - lateinit var transcriptMessageDao: TranscriptMessageDao + lateinit var userService: UserService @Inject - lateinit var pinMessageDao: PinMessageDao - - @Inject - lateinit var remoteMessageStatusDao: RemoteMessageStatusDao - - @Inject - lateinit var expiredMessageDao: ExpiredMessageDao + lateinit var ratchetSenderKeyDao: RatchetSenderKeyDao @Inject - lateinit var database: MixinDatabase + lateinit var resendMessageDao: ResendSessionMessageDao @ApplicationScope @Transient @Inject lateinit var applicationScope: CoroutineScope + val database: MixinDatabase by lazy { databaseProvider.getMixinDatabase() } + val ftsDatabase: FtsDatabase by lazy { databaseProvider.getFtsDatabase() } + + val messageDao: MessageDao by lazy { databaseProvider.getMixinDatabase().messageDao() } + val pendingMessagesDao: PendingMessageDao by lazy { databaseProvider.getPendingDatabase().pendingMessageDao() } + val messageHistoryDao: MessageHistoryDao by lazy { databaseProvider.getMixinDatabase().messageHistoryDao() } + val userDao: UserDao by lazy { databaseProvider.getMixinDatabase().userDao() } + val appDao: AppDao by lazy { databaseProvider.getMixinDatabase().appDao() } + val jobDao: JobDao by lazy { databaseProvider.getMixinDatabase().jobDao() } + val conversationDao: ConversationDao by lazy { databaseProvider.getMixinDatabase().conversationDao() } + val conversationExtDao: ConversationExtDao by lazy { databaseProvider.getMixinDatabase().conversationExtDao() } + val participantDao: ParticipantDao by lazy { databaseProvider.getMixinDatabase().participantDao() } + val participantSessionDao: ParticipantSessionDao by lazy { databaseProvider.getMixinDatabase().participantSessionDao() } + val snapshotDao: SnapshotDao by lazy { databaseProvider.getMixinDatabase().snapshotDao() } + val safeSnapshotDao: SafeSnapshotDao by lazy { databaseProvider.getMixinDatabase().safeSnapshotDao() } + val tokenDao: TokenDao by lazy { databaseProvider.getMixinDatabase().tokenDao() } + val circleDao: CircleDao by lazy { databaseProvider.getMixinDatabase().circleDao() } + val circleConversationDao: CircleConversationDao by lazy { databaseProvider.getMixinDatabase().circleConversationDao() } + val traceDao: TraceDao by lazy { databaseProvider.getMixinDatabase().traceDao() } + val stickerDao: StickerDao by lazy { databaseProvider.getMixinDatabase().stickerDao() } + val messageMentionDao: MessageMentionDao by lazy { databaseProvider.getMixinDatabase().messageMentionDao() } + val hyperlinkDao: HyperlinkDao by lazy { databaseProvider.getMixinDatabase().hyperlinkDao() } + val transcriptMessageDao: TranscriptMessageDao by lazy { databaseProvider.getMixinDatabase().transcriptDao() } + val pinMessageDao: PinMessageDao by lazy { databaseProvider.getMixinDatabase().pinMessageDao() } + val remoteMessageStatusDao: RemoteMessageStatusDao by lazy { databaseProvider.getMixinDatabase().remoteMessageStatusDao() } + val expiredMessageDao: ExpiredMessageDao by lazy { databaseProvider.getMixinDatabase().expiredMessageDao() } + @InstallIn(SingletonComponent::class) @EntryPoint interface InjectorEntryPoint { @@ -201,7 +157,7 @@ open class Injector { var user = userDao.findUser(userId) if (user == null && forceSync) { try { - val call = userApi.getUserById(userId).execute() + val call = userService.getUserById(userId).execute() val response = call.body() if (response != null && response.isSuccess && response.data != null) { response.data?.let { u -> diff --git a/app/src/main/java/one/mixin/android/job/MessageDeleteJob.kt b/app/src/main/java/one/mixin/android/job/MessageDeleteJob.kt index 173482a0f8..d4dc907059 100644 --- a/app/src/main/java/one/mixin/android/job/MessageDeleteJob.kt +++ b/app/src/main/java/one/mixin/android/job/MessageDeleteJob.kt @@ -32,7 +32,7 @@ class MessageDeleteJob( DB_DELETE_LIMIT, ) ftsDatabase.deleteByMessageIds(ids) - appDatabase.deleteMessageByIds(ids) + database.deleteMessageByIds(ids) MessageFlow.delete(conversationId, ids) } val currentRowId = messageDao.findLastMessageRowId(conversationId) diff --git a/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt b/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt index 2a27f3ce92..51b2326f88 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt @@ -1,8 +1,17 @@ package one.mixin.android.job import com.birbit.android.jobqueue.Params +import one.mixin.android.MixinApplication +import one.mixin.android.RxBus +import one.mixin.android.api.response.ConversationResponse import one.mixin.android.db.insertUpdate +import one.mixin.android.event.GroupEvent +import one.mixin.android.extension.putBoolean +import one.mixin.android.extension.sharedPreferences import one.mixin.android.session.Session +import one.mixin.android.vo.ConversationBuilder +import one.mixin.android.vo.ConversationCategory +import one.mixin.android.vo.ConversationStatus import one.mixin.android.vo.Participant import one.mixin.android.vo.ParticipantRole import one.mixin.android.vo.SYSTEM_USER @@ -31,7 +40,7 @@ class RefreshConversationJob(val conversationId: String, private val skipRefresh val response = call.body() if (response != null && response.isSuccess) { response.data?.let { data -> - conversationRepo.insertOrUpdateConversation(data) + insertOrUpdateConversation(data) val participants = mutableListOf() val conversationUserIds = mutableListOf() for (p in data.participants) { @@ -73,4 +82,52 @@ class RefreshConversationJob(val conversationId: String, private val skipRefresh } } } + + fun insertOrUpdateConversation(data: ConversationResponse) { + var ownerId: String = data.creatorId + if (data.category == ConversationCategory.CONTACT.name) { + ownerId = data.participants.find { it.userId != Session.getAccountId() }!!.userId + } + var c = conversationDao.findConversationById(data.conversationId) + if (c == null) { + val builder = ConversationBuilder(data.conversationId, data.createdAt, ConversationStatus.SUCCESS.ordinal) + c = + builder.setOwnerId(ownerId) + .setCategory(data.category) + .setName(data.name) + .setIconUrl(data.iconUrl) + .setAnnouncement(data.announcement) + .setMuteUntil(data.muteUntil) + .setCodeUrl(data.codeUrl) + .setExpireIn(data.expireIn) + .build() + conversationDao.upsert(c) + if (!c.announcement.isNullOrBlank()) { + RxBus.publish(GroupEvent(data.conversationId)) + MixinApplication.appContext.sharedPreferences(RefreshConversationJob.PREFERENCES_CONVERSATION).putBoolean(data.conversationId, true) + } + } else { + val status = + if (data.participants.find { Session.getAccountId() == it.userId } != null) { + ConversationStatus.SUCCESS.ordinal + } else { + ConversationStatus.QUIT.ordinal + } + conversationDao.updateConversation( + data.conversationId, + ownerId, + data.category, + data.name, + data.announcement, + data.muteUntil, + data.createdAt, + data.expireIn, + status, + ) + if (data.announcement.isNotBlank() && c.announcement != data.announcement) { + RxBus.publish(GroupEvent(data.conversationId)) + MixinApplication.appContext.sharedPreferences(RefreshConversationJob.PREFERENCES_CONVERSATION).putBoolean(data.conversationId, true) + } + } + } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshDappJob.kt b/app/src/main/java/one/mixin/android/job/RefreshDappJob.kt index 46db59d3a3..106684c634 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshDappJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshDappJob.kt @@ -3,7 +3,9 @@ package one.mixin.android.job import com.birbit.android.jobqueue.Params import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking +import one.mixin.android.Constants.Account.PREF_ROUTE_BOT_PK import one.mixin.android.Constants.Account.PREF_WEB3_BOT_PK +import one.mixin.android.Constants.RouteConfig.ROUTE_BOT_USER_ID import one.mixin.android.Constants.RouteConfig.WEB3_BOT_USER_ID import one.mixin.android.MixinApplication import one.mixin.android.RxBus @@ -28,7 +30,7 @@ class RefreshDappJob : BaseJob( override fun onRun(): Unit = runBlocking { - userRepo.getBotPublicKey(WEB3_BOT_USER_ID, false) + getBotPublicKey(WEB3_BOT_USER_ID, false) val response = web3Service.dapps() if (response.isSuccess && response.data != null) { val gson = GsonHelper.customGson @@ -59,10 +61,69 @@ class RefreshDappJob : BaseJob( } RxBus.publish(WCChangeEvent()) } else if (response.errorCode == 401) { - userRepo.getBotPublicKey(WEB3_BOT_USER_ID, true) + getBotPublicKey(WEB3_BOT_USER_ID, true) } else { delay(3000) jobManager.addJobInBackground(RefreshDappJob()) } } + + suspend fun findBotPublicKey( + conversationId: String, + botId: String, + ): String? { + return participantSessionDao.findBotPublicKey(conversationId, botId) + } + + suspend fun fetchSessionsSuspend(ids: List) = userService.fetchSessionsSuspend(ids) + + suspend fun saveSession(participantSession: ParticipantSession) { + participantSessionDao.insertSuspend(participantSession) + } + + suspend fun getBotPublicKey(botId: String, force: Boolean) { + if (botId != ROUTE_BOT_USER_ID && botId != WEB3_BOT_USER_ID) return + + val key = + findBotPublicKey( + generateConversationId( + botId, + Session.getAccountId()!!, + ), + botId, + ) + if (key != null && !force) { + if (botId == ROUTE_BOT_USER_ID) { + MixinApplication.appContext.defaultSharedPreferences.putString(PREF_ROUTE_BOT_PK, key) + } else if (botId == WEB3_BOT_USER_ID) { + MixinApplication.appContext.defaultSharedPreferences.putString(PREF_WEB3_BOT_PK, key) + } + } else { + val sessionResponse = fetchSessionsSuspend(listOf(botId)) + if (sessionResponse.isSuccess) { + val sessionData = requireNotNull(sessionResponse.data)[0] + saveSession( + ParticipantSession( + generateConversationId( + sessionData.userId, + Session.getAccountId()!!, + ), + sessionData.userId, + sessionData.sessionId, + publicKey = sessionData.publicKey, + ), + ) + if (botId == ROUTE_BOT_USER_ID) { + MixinApplication.appContext.defaultSharedPreferences.putString(PREF_ROUTE_BOT_PK, sessionData.publicKey) + } else if (botId == WEB3_BOT_USER_ID) { + MixinApplication.appContext.defaultSharedPreferences.putString(PREF_WEB3_BOT_PK, sessionData.publicKey) + } + } else { + throw MixinResponseException( + sessionResponse.errorCode, + sessionResponse.errorDescription, + ) + } + } + } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshOffsetJob.kt b/app/src/main/java/one/mixin/android/job/RefreshOffsetJob.kt index 0d5fc04ee1..493307d060 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshOffsetJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshOffsetJob.kt @@ -57,7 +57,7 @@ class RefreshOffsetJob : MixinJob( } } pendingDatabase.makeMessageStatus(m.status, m.messageId, callback) - mixinDatabase.makeMessageStatus(m.status, m.messageId, callback) + database.makeMessageStatus(m.status, m.messageId, callback) offsetDao.insert(Offset(STATUS_OFFSET, m.updatedAt)) } if (blazeMessages.isNotEmpty() && blazeMessages.last().updatedAt.getEpochNano() == status) { diff --git a/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt b/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt index 6812e7426a..b1c27d8868 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt @@ -59,7 +59,7 @@ class RefreshStickerAndRelatedAlbumJob(private val stickerId: String) : BaseJob( } else { null } - mixinDatabase.runInTransaction { + database.runInTransaction { for (s in stickers) { stickerDao.insertUpdate(s) relationships?.add(StickerRelationship(albumId, s.stickerId)) diff --git a/app/src/main/java/one/mixin/android/job/RefreshTokensJob.kt b/app/src/main/java/one/mixin/android/job/RefreshTokensJob.kt index 1d28f8d9df..5ddbad8828 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshTokensJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshTokensJob.kt @@ -26,7 +26,7 @@ class RefreshTokensJob( val response = tokenService.getAssetByIdSuspend(assetId) if (response.isSuccess && response.data != null) { response.data?.let { - assetRepo.insert(it) + tokenDao.insert(it) refreshChainById(it.chainId) } if (conversationId != null && messageId != null) { @@ -39,7 +39,7 @@ class RefreshTokensJob( val response = tokenService.fetchTokenSuspend(tokenIds) if (response.isSuccess && response.data != null) { val list = response.data as List - assetRepo.insertList(list) + tokenDao.insertList(list) } refreshChains() refreshFiats() @@ -50,7 +50,7 @@ class RefreshTokensJob( val response = tokenService.fetchAllTokenSuspend() if (response.isSuccess && response.data != null) { val list = response.data as List - assetRepo.insertList(list) + tokenDao.insertList(list) } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshUserJob.kt b/app/src/main/java/one/mixin/android/job/RefreshUserJob.kt index f1189e071b..b50da46242 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshUserJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshUserJob.kt @@ -44,7 +44,7 @@ class RefreshUserJob( val response = userService.getUserById(userIds[0]).execute().body() if (response != null && response.isSuccess) { response.data?.let { data -> - userRepo.upsert(data) + userDao.upsert(data) refreshConversationAvatar() } } @@ -52,7 +52,7 @@ class RefreshUserJob( val response = userService.getUsers(userIds).execute().body() if (response != null && response.isSuccess) { response.data?.let { data -> - userRepo.upsertList(data) + userDao.upsertList(data) refreshConversationAvatar() } } diff --git a/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt b/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt index bbfe64785d..9f8c47c40c 100644 --- a/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt +++ b/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt @@ -133,7 +133,7 @@ class RestoreTransactionJob : BaseJob( MessageCategory.SYSTEM_SAFE_SNAPSHOT.name } val message = createMessage(UUID.randomUUID().toString(), conversationId, data.userId, category, inscriptionHash ?: "", data.createdAt, MessageStatus.DELIVERED.name, SafeSnapshotType.snapshot.name, null, data.getSnapshotId) - appDatabase.insertMessage(message) + database.insertMessage(message) if (inscriptionHash != null) { jobManager.addJobInBackground(SyncInscriptionMessageJob(conversationId, message.messageId, inscriptionHash, data.getSnapshotId)) } @@ -161,7 +161,7 @@ class RestoreTransactionJob : BaseJob( Participant(conversationId, senderId, "", createdAt), Participant(conversationId, recipientId, "", createdAt), ) - appDatabase.runInTransaction { + database.runInTransaction { conversationDao.upsert(conversation) participantDao.insertList(participants) } diff --git a/app/src/main/java/one/mixin/android/job/SendAttachmentMessageJob.kt b/app/src/main/java/one/mixin/android/job/SendAttachmentMessageJob.kt index fc99f861d2..b494c42fcc 100644 --- a/app/src/main/java/one/mixin/android/job/SendAttachmentMessageJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendAttachmentMessageJob.kt @@ -65,13 +65,13 @@ class SendAttachmentMessageJob( messageDao.updateMediaSize(message.mediaSize ?: 0, mId) MessageFlow.update(message.conversationId, message.messageId) } else { - mixinDatabase.insertMessage(message) + database.insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) } } else { val mId = messageDao.findMessageIdById(message.messageId) if (mId == null) { - mixinDatabase.insertMessage(message) + database.insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) } } diff --git a/app/src/main/java/one/mixin/android/job/SendMessageJob.kt b/app/src/main/java/one/mixin/android/job/SendMessageJob.kt index 5dbaafb16c..0722bd2150 100644 --- a/app/src/main/java/one/mixin/android/job/SendMessageJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendMessageJob.kt @@ -95,7 +95,7 @@ open class SendMessageJob( } } if (!message.isTranscript()) { - mixinDatabase.insertMessage(message) + database.insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) ftsDatabase.insertOrReplaceMessageFts4(message) } diff --git a/app/src/main/java/one/mixin/android/job/SendProcessSignalKeyJob.kt b/app/src/main/java/one/mixin/android/job/SendProcessSignalKeyJob.kt index d9eaed6b4d..71ad6caa15 100644 --- a/app/src/main/java/one/mixin/android/job/SendProcessSignalKeyJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendProcessSignalKeyJob.kt @@ -30,7 +30,7 @@ class SendProcessSignalKeyJob( } } else if (action == ProcessSignalKeyAction.REMOVE_PARTICIPANT) { Session.getAccountId()?.let { - appDatabase.clearParticipant(data.conversationId, participantId!!) + database.clearParticipant(data.conversationId, participantId!!) signalProtocol.clearSenderKey(data.conversationId, it) RxBus.publish(SenderKeyChange(data.conversationId)) } diff --git a/app/src/main/java/one/mixin/android/job/SendTranscriptJob.kt b/app/src/main/java/one/mixin/android/job/SendTranscriptJob.kt index 16a9d1beea..2fd385706e 100644 --- a/app/src/main/java/one/mixin/android/job/SendTranscriptJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendTranscriptJob.kt @@ -59,7 +59,7 @@ class SendTranscriptJob( } } ftsDatabase.insertFts4(stringBuffer.toString(), message.conversationId, message.messageId, message.category, message.userId, message.createdAt) - appDatabase.insertMessage(message) + database.insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) transcriptMessages.forEach { transcript -> if (transcript.isAttachment()) { diff --git a/app/src/main/java/one/mixin/android/job/TranscriptDeleteJob.kt b/app/src/main/java/one/mixin/android/job/TranscriptDeleteJob.kt index 73c9c12bf1..ec8509053c 100644 --- a/app/src/main/java/one/mixin/android/job/TranscriptDeleteJob.kt +++ b/app/src/main/java/one/mixin/android/job/TranscriptDeleteJob.kt @@ -22,7 +22,7 @@ class TranscriptDeleteJob(private val messageIds: List) : BaseJob(Params override fun onRun() { val cIds = messageDao.findConversationsByMessages(messageIds) messageIds.forEach { messageId -> - mixinDatabase.deleteMessageById(messageId) + database.deleteMessageById(messageId) ftsDatabase.deleteByMessageId(messageId) transcriptMessageDao.getTranscript(messageId).forEach { transcriptMessage -> if (transcriptMessage.isAttachment()) { diff --git a/app/src/main/java/one/mixin/android/job/UpdateRelationshipJob.kt b/app/src/main/java/one/mixin/android/job/UpdateRelationshipJob.kt index ce59ce9f6b..aca6c43749 100644 --- a/app/src/main/java/one/mixin/android/job/UpdateRelationshipJob.kt +++ b/app/src/main/java/one/mixin/android/job/UpdateRelationshipJob.kt @@ -72,11 +72,11 @@ class UpdateRelationshipJob( } } - private suspend fun updateUser(u: User) { + private fun updateUser(u: User) { if (u.app != null) { u.appId = u.app!!.appId - userRepo.insertApp(u.app!!) + appDao.insert(u.app!!) } - userRepo.upsert(u) + userDao.upsert(u) } } From 0abe2f30573310ade3b5e76acb320c6a4e2d85e5 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Wed, 27 Nov 2024 21:43:54 +0800 Subject: [PATCH 06/42] Update dependency injection and transient field management --- .../AsyncProcessTransferAttachmentFileJob.kt | 4 +- .../android/job/AttachmentDownloadJob.kt | 24 ++-- .../android/job/AttachmentMigrationJob.kt | 18 +-- .../java/one/mixin/android/job/BackupJob.kt | 4 +- .../java/one/mixin/android/job/BaseJob.kt | 135 ++++++------------ .../one/mixin/android/job/CheckBalanceJob.kt | 18 +-- .../android/job/CleanupQuoteContentJob.kt | 8 +- .../one/mixin/android/job/CleanupThumbJob.kt | 2 +- .../one/mixin/android/job/ClearFts4Job.kt | 2 +- .../one/mixin/android/job/ConversationJob.kt | 16 +-- .../one/mixin/android/job/ConvertDataJob.kt | 6 +- .../one/mixin/android/job/ConvertVideoJob.kt | 12 +- .../one/mixin/android/job/FavoriteAppJob.kt | 8 +- .../mixin/android/job/GenerateAvatarJob.kt | 10 +- .../one/mixin/android/job/InitializeJob.kt | 2 +- .../job/InscriptionCollectionMigrationJob.kt | 4 +- .../android/job/InscriptionMigrationJob.kt | 4 +- .../one/mixin/android/job/MessageDeleteJob.kt | 20 +-- .../one/mixin/android/job/MigratedFts4Job.kt | 16 +-- .../java/one/mixin/android/job/MixinJob.kt | 12 +- .../mixin/android/job/RefreshAddressJob.kt | 2 +- .../one/mixin/android/job/RefreshAlertsJob.kt | 10 +- .../one/mixin/android/job/RefreshAssetsJob.kt | 16 +-- .../one/mixin/android/job/RefreshCircleJob.kt | 10 +- .../mixin/android/job/RefreshContactJob.kt | 2 +- .../android/job/RefreshConversationJob.kt | 16 +-- .../one/mixin/android/job/RefreshDappJob.kt | 4 +- .../one/mixin/android/job/RefreshMarketJob.kt | 4 +- .../mixin/android/job/RefreshMarketsJob.kt | 10 +- .../one/mixin/android/job/RefreshOffsetJob.kt | 10 +- .../one/mixin/android/job/RefreshPriceJob.kt | 4 +- .../mixin/android/job/RefreshSessionJob.kt | 2 +- .../mixin/android/job/RefreshSnapshotsJob.kt | 6 +- .../android/job/RefreshStickerAlbumJob.kt | 16 +-- .../job/RefreshStickerAndRelatedAlbumJob.kt | 16 +-- .../mixin/android/job/RefreshStickerJob.kt | 2 +- .../one/mixin/android/job/RefreshTokensJob.kt | 16 +-- .../mixin/android/job/RefreshTopAssetsJob.kt | 8 +- .../one/mixin/android/job/RefreshUserJob.kt | 6 +- .../mixin/android/job/RemoveStickersJob.kt | 4 +- .../android/job/RestoreTransactionJob.kt | 28 ++-- .../android/job/SendAttachmentMessageJob.kt | 28 ++-- .../one/mixin/android/job/SendGiphyJob.kt | 6 +- .../one/mixin/android/job/SendMessageJob.kt | 52 +++---- .../android/job/SendProcessSignalKeyJob.kt | 4 +- .../job/SendTranscriptAttachmentMessageJob.kt | 24 ++-- .../mixin/android/job/SendTranscriptJob.kt | 16 +-- .../one/mixin/android/job/StorageCleanJob.kt | 2 +- .../job/SyncInscriptionCollectionJob.kt | 2 +- .../android/job/SyncInscriptionMessageJob.kt | 12 +- .../mixin/android/job/SyncInscriptionsJob.kt | 10 +- .../one/mixin/android/job/SyncOutputJob.kt | 4 +- .../job/TranscriptAttachmentDownloadJob.kt | 24 ++-- .../job/TranscriptAttachmentMigrationJob.kt | 4 +- .../job/TranscriptAttachmentUpdateJob.kt | 12 +- .../mixin/android/job/TranscriptDeleteJob.kt | 22 +-- .../mixin/android/job/UpdateFavoriteJob.kt | 4 +- .../android/job/UpdateRelationshipJob.kt | 12 +- .../one/mixin/android/ui/home/MainActivity.kt | 1 - 59 files changed, 354 insertions(+), 402 deletions(-) diff --git a/app/src/main/java/one/mixin/android/job/AsyncProcessTransferAttachmentFileJob.kt b/app/src/main/java/one/mixin/android/job/AsyncProcessTransferAttachmentFileJob.kt index 4134fda459..89e9a81a24 100644 --- a/app/src/main/java/one/mixin/android/job/AsyncProcessTransferAttachmentFileJob.kt +++ b/app/src/main/java/one/mixin/android/job/AsyncProcessTransferAttachmentFileJob.kt @@ -34,7 +34,7 @@ class AsyncProcessTransferAttachmentFileJob(private val folder: File) : BaseJob( if (f.isFile && f.length() > 0) { val messageId = f.name if (messageId.isUUID()) { - val transferMessage = transcriptMessageDao.findAttachmentMessage(messageId) + val transferMessage = transcriptMessageDao().findAttachmentMessage(messageId) transferMessage?.mediaUrl?.let { mediaUrl -> val dir = context.getTranscriptDirPath() if (!dir.exists()) { @@ -42,7 +42,7 @@ class AsyncProcessTransferAttachmentFileJob(private val folder: File) : BaseJob( } f.copy(File(dir, mediaUrl)) } - val message = messageDao.findAttachmentMessage(messageId) + val message = messageDao().findAttachmentMessage(messageId) if (message?.mediaUrl != null) { val extensionName = message.mediaUrl.getExtensionName() val outFile = diff --git a/app/src/main/java/one/mixin/android/job/AttachmentDownloadJob.kt b/app/src/main/java/one/mixin/android/job/AttachmentDownloadJob.kt index f81faeaa10..fe0dbbad1d 100644 --- a/app/src/main/java/one/mixin/android/job/AttachmentDownloadJob.kt +++ b/app/src/main/java/one/mixin/android/job/AttachmentDownloadJob.kt @@ -73,7 +73,7 @@ class AttachmentDownloadJob( it.cancel() } } - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) removeJob() @@ -111,14 +111,14 @@ class AttachmentDownloadJob( val result = decryptAttachment(it) if (result) { val attachmentExtra = GsonHelper.customGson.toJson(AttachmentExtra(attachmentResponse.attachment_id, message.messageId, attachmentResponse.created_at, shareable)) - messageDao.updateMessageContent(attachmentExtra, message.messageId) + messageDao().updateMessageContent(attachmentExtra, message.messageId) } } removeJob() } else { removeJob() Log.e(TAG, "get attachment url failed") - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) } @@ -129,7 +129,7 @@ class AttachmentDownloadJob( throwable: Throwable?, ) { super.onCancel(cancelReason, throwable) - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) removeJob() @@ -137,7 +137,7 @@ class AttachmentDownloadJob( override fun onAdded() { super.onAdded() - messageDao.updateMediaStatus(MediaStatus.PENDING.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.PENDING.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) RxBus.publish(loadingEvent(message.messageId, 0f)) } @@ -179,14 +179,14 @@ class AttachmentDownloadJob( try { call!!.execute() } catch (e: Exception) { - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) destination.delete() return false } if (response.code == 404) { - messageDao.updateMediaStatus(MediaStatus.EXPIRED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.EXPIRED.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) destination.delete() @@ -221,7 +221,7 @@ class AttachmentDownloadJob( } } imageFile.copyFromInputStream(attachmentCipherInputStream) - messageDao.updateMedia(message.messageId, imageFile.name, imageFile.length(), MediaStatus.DONE.name) + messageDao().updateMedia(message.messageId, imageFile.name, imageFile.length(), MediaStatus.DONE.name) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) } else if (message.category.endsWith("_DATA")) { @@ -236,7 +236,7 @@ class AttachmentDownloadJob( MixinApplication.get().getDocumentPath() .createDocumentTemp(message.conversationId, message.messageId, extensionName) dataFile.copyFromInputStream(attachmentCipherInputStream) - messageDao.updateMedia(message.messageId, dataFile.name, dataFile.length(), MediaStatus.DONE.name) + messageDao().updateMedia(message.messageId, dataFile.name, dataFile.length(), MediaStatus.DONE.name) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) } else if (message.category.endsWith("_VIDEO")) { @@ -254,7 +254,7 @@ class AttachmentDownloadJob( MixinApplication.get().getVideoPath() .createVideoTemp(message.conversationId, message.messageId, extensionName) videoFile.copyFromInputStream(attachmentCipherInputStream) - messageDao.updateMedia(message.messageId, videoFile.name, videoFile.length(), MediaStatus.DONE.name) + messageDao().updateMedia(message.messageId, videoFile.name, videoFile.length(), MediaStatus.DONE.name) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) } else if (message.category.endsWith("_AUDIO")) { @@ -268,14 +268,14 @@ class AttachmentDownloadJob( MixinApplication.get().getAudioPath() .createAudioTemp(message.conversationId, message.messageId, "ogg") audioFile.copyFromInputStream(attachmentCipherInputStream) - messageDao.updateMedia(message.messageId, audioFile.name, audioFile.length(), MediaStatus.DONE.name) + messageDao().updateMedia(message.messageId, audioFile.name, audioFile.length(), MediaStatus.DONE.name) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) } destination.delete() return true } else { - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) attachmentProcess.remove(message.messageId) destination.delete() return false diff --git a/app/src/main/java/one/mixin/android/job/AttachmentMigrationJob.kt b/app/src/main/java/one/mixin/android/job/AttachmentMigrationJob.kt index 1a2c2121c3..b5cfd5d3d8 100644 --- a/app/src/main/java/one/mixin/android/job/AttachmentMigrationJob.kt +++ b/app/src/main/java/one/mixin/android/job/AttachmentMigrationJob.kt @@ -48,16 +48,16 @@ class AttachmentMigrationJob : BaseJob(Params(PRIORITY_LOWER).groupBy(GROUP_ID). override fun onRun() = runBlocking { val startTime = System.currentTimeMillis() - var migrationLast = propertyDao.findValueByKey(PREF_MIGRATION_ATTACHMENT_LAST)?.toLongOrNull() ?: -1 + var migrationLast = propertyDao().findValueByKey(PREF_MIGRATION_ATTACHMENT_LAST)?.toLongOrNull() ?: -1 if (migrationLast == -1L) { - migrationLast = messageDao.getLastMessageRowid() - propertyDao.insertSuspend(Property(PREF_MIGRATION_ATTACHMENT_LAST, migrationLast.toString(), nowInUtc())) + migrationLast = messageDao().getLastMessageRowid() + propertyDao().insertSuspend(Property(PREF_MIGRATION_ATTACHMENT_LAST, migrationLast.toString(), nowInUtc())) } if (!hasWritePermission()) return@runBlocking - val offset = propertyDao.findValueByKey(PREF_MIGRATION_ATTACHMENT_OFFSET)?.toLongOrNull() ?: 0 - val list = messageDao.findAttachmentMigration(migrationLast, EACH, offset) + val offset = propertyDao().findValueByKey(PREF_MIGRATION_ATTACHMENT_OFFSET)?.toLongOrNull() ?: 0 + val list = messageDao().findAttachmentMigration(migrationLast, EACH, offset) list.forEach { attachment -> val fromFile = attachment.getFile(MixinApplication.appContext) ?: return@forEach if (!fromFile.exists()) { @@ -141,22 +141,22 @@ class AttachmentMigrationJob : BaseJob(Params(PRIORITY_LOWER).groupBy(GROUP_ID). } Timber.d("Attachment migration ${fromFile.absolutePath} ${toFile.absolutePath}") if (attachment.mediaUrl != toFile.name) { - messageDao.updateMediaMessageUrl(toFile.name, attachment.messageId) + messageDao().updateMediaMessageUrl(toFile.name, attachment.messageId) MessageFlow.update(attachment.conversationId, attachment.messageId) } } - propertyDao.insertSuspend(Property(PREF_MIGRATION_ATTACHMENT_OFFSET, (offset + list.size).toString(), nowInUtc())) + propertyDao().insertSuspend(Property(PREF_MIGRATION_ATTACHMENT_OFFSET, (offset + list.size).toString(), nowInUtc())) Timber.d("Attachment migration handle ${offset + list.size} file cost: ${System.currentTimeMillis() - startTime} ms") if (list.size < EACH) { Timber.d("Attachment start delete ancient media path") MixinApplication.appContext.getAncientMediaPath()?.deleteRecursively() Timber.d("Attachment delete ancient media path completed!!!") - if (propertyDao.findValueByKey(PREF_MIGRATION_TRANSCRIPT_ATTACHMENT)?.toBoolean() != true) { + if (propertyDao().findValueByKey(PREF_MIGRATION_TRANSCRIPT_ATTACHMENT)?.toBoolean() != true) { Timber.d("Attachment start delete media path") MixinApplication.appContext.getMediaPath(true)?.deleteRecursively() Timber.d("Attachment delete media path completed!!!") } - propertyDao.updateValueByKey(PREF_MIGRATION_ATTACHMENT, false.toString()) + propertyDao().updateValueByKey(PREF_MIGRATION_ATTACHMENT, false.toString()) Timber.d("Attachment migration completed!!!") } else { jobManager.addJobInBackground(AttachmentMigrationJob()) diff --git a/app/src/main/java/one/mixin/android/job/BackupJob.kt b/app/src/main/java/one/mixin/android/job/BackupJob.kt index d8669aef9d..5830bd4539 100644 --- a/app/src/main/java/one/mixin/android/job/BackupJob.kt +++ b/app/src/main/java/one/mixin/android/job/BackupJob.kt @@ -51,7 +51,7 @@ class BackupJob(private val force: Boolean = false, private val delete: Boolean } if (force) { internalBackup(context) - } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && propertyDao.findValueByKey(PREF_BACKUP)?.toBooleanStrictOrNull() == true) { + } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && propertyDao().findValueByKey(PREF_BACKUP)?.toBooleanStrictOrNull() == true) { val option = PropertyHelper.findValueByKey(BACKUP_PERIOD, 0) if (option in 1..3) { val currentTime = System.currentTimeMillis() @@ -72,7 +72,7 @@ class BackupJob(private val force: Boolean = false, private val delete: Boolean if (delete) { findOldBackupSync(MixinApplication.appContext)?.deleteRecursively() findOldBackupSync(MixinApplication.appContext, true)?.deleteRecursively() - propertyDao.updateValueByKey(Constants.Account.Migration.PREF_MIGRATION_BACKUP, false.toString()) + propertyDao().updateValueByKey(Constants.Account.Migration.PREF_MIGRATION_BACKUP, false.toString()) } } diff --git a/app/src/main/java/one/mixin/android/job/BaseJob.kt b/app/src/main/java/one/mixin/android/job/BaseJob.kt index 56e027174b..89a556fdfe 100644 --- a/app/src/main/java/one/mixin/android/job/BaseJob.kt +++ b/app/src/main/java/one/mixin/android/job/BaseJob.kt @@ -190,140 +190,93 @@ abstract class BaseJob(params: Params) : Job(params) { @Inject lateinit var jobSenderKey: JobSenderKey - @delegate:Transient - val database: MixinDatabase by lazy { - requireNotNull(databaseProvider) { "DatabaseProvider not initialized" } - databaseProvider.getMixinDatabase() - } + fun database(): MixinDatabase = databaseProvider.getMixinDatabase() - @delegate:Transient - val ftsDatabase: FtsDatabase by lazy { databaseProvider.getFtsDatabase() } + fun pendingDatabase(): PendingDatabase = databaseProvider.getPendingDatabase() - @delegate:Transient - val pendingDatabase: PendingDatabase by lazy { databaseProvider.getPendingDatabase() } + fun ftsDatabase(): FtsDatabase = databaseProvider.getFtsDatabase() - @delegate:Transient - val messageDao: MessageDao by lazy { databaseProvider.getMixinDatabase().messageDao() } + fun messageDao(): MessageDao = database().messageDao() - @delegate:Transient - val messageHistoryDao: MessageHistoryDao by lazy { databaseProvider.getMixinDatabase().messageHistoryDao() } + fun messageHistoryDao(): MessageHistoryDao = database().messageHistoryDao() - @delegate:Transient - val userDao: UserDao by lazy { databaseProvider.getMixinDatabase().userDao() } + fun userDao(): UserDao = database().userDao() - @delegate:Transient - val conversationDao: ConversationDao by lazy { databaseProvider.getMixinDatabase().conversationDao() } + fun conversationDao(): ConversationDao = database().conversationDao() - @delegate:Transient - val conversationExtDao: ConversationExtDao by lazy { databaseProvider.getMixinDatabase().conversationExtDao() } + fun conversationExtDao(): ConversationExtDao = database().conversationExtDao() - @delegate:Transient - val participantDao: ParticipantDao by lazy { databaseProvider.getMixinDatabase().participantDao() } + fun participantDao(): ParticipantDao = database().participantDao() - @delegate:Transient - val participantSessionDao: ParticipantSessionDao by lazy { databaseProvider.getMixinDatabase().participantSessionDao() } + fun participantSessionDao(): ParticipantSessionDao = database().participantSessionDao() - @delegate:Transient - val offsetDao: OffsetDao by lazy { databaseProvider.getMixinDatabase().offsetDao() } + fun offsetDao(): OffsetDao = database().offsetDao() - @delegate:Transient - val assetDao: AssetDao by lazy { databaseProvider.getMixinDatabase().assetDao() } + fun assetDao(): AssetDao = database().assetDao() - @delegate:Transient - val tokenDao: TokenDao by lazy { databaseProvider.getMixinDatabase().tokenDao() } + fun tokenDao(): TokenDao = database().tokenDao() - @delegate:Transient - val tokensExtraDao: TokensExtraDao by lazy { databaseProvider.getMixinDatabase().tokensExtraDao() } + fun tokensExtraDao(): TokensExtraDao = database().tokensExtraDao() - @delegate:Transient - val snapshotDao: SnapshotDao by lazy { databaseProvider.getMixinDatabase().snapshotDao() } + fun snapshotDao(): SnapshotDao = database().snapshotDao() - @delegate:Transient - val chainDao: ChainDao by lazy { databaseProvider.getMixinDatabase().chainDao() } + fun chainDao(): ChainDao = database().chainDao() - @delegate:Transient - val stickerDao: StickerDao by lazy { databaseProvider.getMixinDatabase().stickerDao() } + fun stickerDao(): StickerDao = database().stickerDao() - @delegate:Transient - val hyperlinkDao: HyperlinkDao by lazy { databaseProvider.getMixinDatabase().hyperlinkDao() } + fun hyperlinkDao(): HyperlinkDao = database().hyperlinkDao() - @delegate:Transient - val stickerAlbumDao: StickerAlbumDao by lazy { databaseProvider.getMixinDatabase().stickerAlbumDao() } + fun stickerAlbumDao(): StickerAlbumDao = database().stickerAlbumDao() - @delegate:Transient - val stickerRelationshipDao: StickerRelationshipDao by lazy { databaseProvider.getMixinDatabase().stickerRelationshipDao() } + fun stickerRelationshipDao(): StickerRelationshipDao = database().stickerRelationshipDao() - @delegate:Transient - val addressDao: AddressDao by lazy { databaseProvider.getMixinDatabase().addressDao() } + fun addressDao(): AddressDao = database().addressDao() - @delegate:Transient - val topAssetDao: TopAssetDao by lazy { databaseProvider.getMixinDatabase().topAssetDao() } + fun topAssetDao(): TopAssetDao = database().topAssetDao() - @delegate:Transient - val jobDao: JobDao by lazy { databaseProvider.getMixinDatabase().jobDao() } + fun jobDao(): JobDao = database().jobDao() - @delegate:Transient - val favoriteAppDao: FavoriteAppDao by lazy { databaseProvider.getMixinDatabase().favoriteAppDao() } + fun favoriteAppDao(): FavoriteAppDao = database().favoriteAppDao() - @delegate:Transient - val messageMentionDao: MessageMentionDao by lazy { databaseProvider.getMixinDatabase().messageMentionDao() } + fun messageMentionDao(): MessageMentionDao = database().messageMentionDao() - @delegate:Transient - val appDao: AppDao by lazy { databaseProvider.getMixinDatabase().appDao() } + fun appDao(): AppDao = database().appDao() - @delegate:Transient - val circleDao: CircleDao by lazy { databaseProvider.getMixinDatabase().circleDao() } + fun circleDao(): CircleDao = database().circleDao() - @delegate:Transient - val circleConversationDao: CircleConversationDao by lazy { databaseProvider.getMixinDatabase().circleConversationDao() } + fun circleConversationDao(): CircleConversationDao = database().circleConversationDao() - @delegate:Transient - val transcriptMessageDao: TranscriptMessageDao by lazy { databaseProvider.getMixinDatabase().transcriptDao() } + fun transcriptMessageDao(): TranscriptMessageDao = database().transcriptDao() - @delegate:Transient - val pinMessageDao: PinMessageDao by lazy { databaseProvider.getMixinDatabase().pinMessageDao() } + fun pinMessageDao(): PinMessageDao = database().pinMessageDao() - @delegate:Transient - val propertyDao: PropertyDao by lazy { databaseProvider.getMixinDatabase().propertyDao() } + fun propertyDao(): PropertyDao = database().propertyDao() - @delegate:Transient - val remoteMessageStatusDao: RemoteMessageStatusDao by lazy { databaseProvider.getMixinDatabase().remoteMessageStatusDao() } + fun remoteMessageStatusDao(): RemoteMessageStatusDao = database().remoteMessageStatusDao() - @delegate:Transient - val expiredMessageDao: ExpiredMessageDao by lazy { databaseProvider.getMixinDatabase().expiredMessageDao() } + fun expiredMessageDao(): ExpiredMessageDao = database().expiredMessageDao() - @delegate:Transient - val outputDao: OutputDao by lazy { databaseProvider.getMixinDatabase().outputDao() } + fun outputDao(): OutputDao = database().outputDao() - @delegate:Transient - val rawTransactionDao: RawTransactionDao by lazy { databaseProvider.getMixinDatabase().rawTransactionDao() } + fun rawTransactionDao(): RawTransactionDao = database().rawTransactionDao() - @delegate:Transient - val safeSnapshotDao: SafeSnapshotDao by lazy { databaseProvider.getMixinDatabase().safeSnapshotDao() } + fun safeSnapshotDao(): SafeSnapshotDao = database().safeSnapshotDao() - @delegate:Transient - val inscriptionDao: InscriptionDao by lazy { databaseProvider.getMixinDatabase().inscriptionDao() } + fun inscriptionDao(): InscriptionDao = database().inscriptionDao() - @delegate:Transient - val marketDao: MarketDao by lazy { databaseProvider.getMixinDatabase().marketDao() } + fun marketDao(): MarketDao = database().marketDao() - @delegate:Transient - val marketFavoredDao: MarketFavoredDao by lazy { databaseProvider.getMixinDatabase().marketFavoredDao() } + fun marketFavoredDao(): MarketFavoredDao = database().marketFavoredDao() - @delegate:Transient - val alertDao: AlertDao by lazy { databaseProvider.getMixinDatabase().alertDao() } + fun alertDao(): AlertDao = database().alertDao() - @delegate:Transient - val marketCapRankDao: MarketCapRankDao by lazy { databaseProvider.getMixinDatabase().marketCapRankDao() } + fun marketCapRankDao(): MarketCapRankDao = database().marketCapRankDao() - @delegate:Transient - val marketCoinDao: MarketCoinDao by lazy { databaseProvider.getMixinDatabase().marketCoinDao() } + fun marketCoinDao(): MarketCoinDao = database().marketCoinDao() - @delegate:Transient - val historyPriceDao: HistoryPriceDao by lazy { databaseProvider.getMixinDatabase().historyPriceDao() } + fun historyPriceDao(): HistoryPriceDao = database().historyPriceDao() - @delegate:Transient - val inscriptionCollectionDao: InscriptionCollectionDao by lazy { databaseProvider.getMixinDatabase().inscriptionCollectionDao() } + fun inscriptionCollectionDao(): InscriptionCollectionDao = database().inscriptionCollectionDao() open fun shouldRetry(throwable: Throwable): Boolean { if (throwable is SocketTimeoutException) { diff --git a/app/src/main/java/one/mixin/android/job/CheckBalanceJob.kt b/app/src/main/java/one/mixin/android/job/CheckBalanceJob.kt index 8353cb18c9..e0dc0a3a85 100644 --- a/app/src/main/java/one/mixin/android/job/CheckBalanceJob.kt +++ b/app/src/main/java/one/mixin/android/job/CheckBalanceJob.kt @@ -22,19 +22,19 @@ class CheckBalanceJob( override fun onRun() = runBlocking { Timber.d("$TAG start checkBalance assetId size: ${assets.size}") - val nonExistIds = assets.minus(tokenDao.findExistByKernelAssetId(assets).toSet()) + val nonExistIds = assets.minus(tokenDao().findExistByKernelAssetId(assets).toSet()) if (nonExistIds.isNotEmpty()) { syncToken(nonExistIds) } for (asset in assets) { - val tokensExtra = tokensExtraDao.findByAsset(asset) - val token = tokenDao.findTokenByAsset(asset) ?: continue - database.withTransaction { + val tokensExtra = tokensExtraDao().findByAsset(asset) + val token = tokenDao().findTokenByAsset(asset) ?: continue + database().withTransaction { val value = calcBalanceByAssetId(asset) if (tokensExtra == null) { - tokensExtraDao.insertSuspend(TokensExtra(token.assetId, token.asset, false, value.toPlainString(), nowInUtc())) + tokensExtraDao().insertSuspend(TokensExtra(token.assetId, token.asset, false, value.toPlainString(), nowInUtc())) } else { - tokensExtraDao.updateBalanceByAssetId(token.assetId, value.toPlainString(), nowInUtc()) + tokensExtraDao().updateBalanceByAssetId(token.assetId, value.toPlainString(), nowInUtc()) } } } @@ -46,7 +46,7 @@ class CheckBalanceJob( return } val tokens = requireNotNull(resp.data) - tokenDao.insertList(tokens) + tokenDao().insertList(tokens) return } @@ -58,9 +58,9 @@ class CheckBalanceJob( var result = amount val outputs = if (offset == 0) { - outputDao.findUnspentOutputsByAsset(BALANCE_LIMIT, asset) + outputDao().findUnspentOutputsByAsset(BALANCE_LIMIT, asset) } else { - outputDao.findUnspentOutputsByAssetOffset(BALANCE_LIMIT, asset, offset) + outputDao().findUnspentOutputsByAssetOffset(BALANCE_LIMIT, asset, offset) } if (outputs.isEmpty()) return amount result += outputs.map { BigDecimal(it.amount) }.sumOf { it } diff --git a/app/src/main/java/one/mixin/android/job/CleanupQuoteContentJob.kt b/app/src/main/java/one/mixin/android/job/CleanupQuoteContentJob.kt index f96b68b9e2..c23d9720d2 100644 --- a/app/src/main/java/one/mixin/android/job/CleanupQuoteContentJob.kt +++ b/app/src/main/java/one/mixin/android/job/CleanupQuoteContentJob.kt @@ -16,11 +16,11 @@ class CleanupQuoteContentJob(private val rowId: Long) : BaseJob(Params(PRIORITY_ override fun onRun() = runBlocking { val gson = GsonHelper.customGson - val list = messageDao.findBigQuoteMessage(rowId, 100) + val list = messageDao().findBigQuoteMessage(rowId, 100) list.forEach { quoteMinimal -> - val quoteMsg = messageDao.findQuoteMessageItemById(quoteMinimal.conversationId, quoteMinimal.quoteMessageId) + val quoteMsg = messageDao().findQuoteMessageItemById(quoteMinimal.conversationId, quoteMinimal.quoteMessageId) if (quoteMsg == null) { - messageDao.updateQuoteContentNullByQuoteMessageId(quoteMinimal.conversationId, quoteMinimal.quoteMessageId) + messageDao().updateQuoteContentNullByQuoteMessageId(quoteMinimal.conversationId, quoteMinimal.quoteMessageId) } else { quoteMsg.thumbImage = if ((quoteMsg.thumbImage?.length ?: 0) > Constants.MAX_THUMB_IMAGE_LENGTH) { @@ -28,7 +28,7 @@ class CleanupQuoteContentJob(private val rowId: Long) : BaseJob(Params(PRIORITY_ } else { quoteMsg.thumbImage } - messageDao.updateQuoteContentByQuoteId(quoteMinimal.conversationId, quoteMinimal.quoteMessageId, gson.toJson(quoteMsg)) + messageDao().updateQuoteContentByQuoteId(quoteMinimal.conversationId, quoteMinimal.quoteMessageId, gson.toJson(quoteMsg)) } } Timber.e("process ${list.size}") diff --git a/app/src/main/java/one/mixin/android/job/CleanupThumbJob.kt b/app/src/main/java/one/mixin/android/job/CleanupThumbJob.kt index 27b135c959..d4e3fa52dd 100644 --- a/app/src/main/java/one/mixin/android/job/CleanupThumbJob.kt +++ b/app/src/main/java/one/mixin/android/job/CleanupThumbJob.kt @@ -13,7 +13,7 @@ class CleanupThumbJob : BaseJob(Params(PRIORITY_LOWER).groupBy(GROUP_ID).persist override fun onRun() = runBlocking { - messageDao.cleanupBigThumb() + messageDao().cleanupBigThumb() PropertyHelper.updateKeyValue(Constants.Account.PREF_CLEANUP_THUMB, false) } } diff --git a/app/src/main/java/one/mixin/android/job/ClearFts4Job.kt b/app/src/main/java/one/mixin/android/job/ClearFts4Job.kt index a123d36bc7..81bb98508c 100644 --- a/app/src/main/java/one/mixin/android/job/ClearFts4Job.kt +++ b/app/src/main/java/one/mixin/android/job/ClearFts4Job.kt @@ -16,7 +16,7 @@ class ClearFts4Job : override fun onRun() = runBlocking(SINGLE_DB_THREAD) { - val count = messageDao.deleteFts() + val count = messageDao().deleteFts() if (count > 0) { jobManager.addJobInBackground(ClearFts4Job()) } else { diff --git a/app/src/main/java/one/mixin/android/job/ConversationJob.kt b/app/src/main/java/one/mixin/android/job/ConversationJob.kt index 203527a7de..a2f2a1e813 100644 --- a/app/src/main/java/one/mixin/android/job/ConversationJob.kt +++ b/app/src/main/java/one/mixin/android/job/ConversationJob.kt @@ -74,7 +74,7 @@ class ConversationJob( private fun updateConversationStatusFailure() { request?.conversationId?.let { - conversationDao.updateConversationStatusById(it, ConversationStatus.FAILURE.ordinal) + conversationDao().updateConversationStatusById(it, ConversationStatus.FAILURE.ordinal) } } @@ -141,16 +141,16 @@ class ConversationJob( cr.participants.mapTo(participants) { Participant(cr.conversationId, it.userId, it.role, cr.createdAt) } - participantDao.insertList(participants) + participantDao().insertList(participants) cr.participantSessions?.let { jobSenderKey.syncParticipantSession(cr.conversationId, it) } jobManager.addJobInBackground(GenerateAvatarJob(cr.conversationId)) } else if (type == TYPE_MUTE) { if (cr.category == ConversationCategory.CONTACT.name) { - recipientId?.let { userDao.updateMuteUntil(it, cr.muteUntil) } + recipientId?.let { userDao().updateMuteUntil(it, cr.muteUntil) } } else { - conversationId?.let { conversationDao.updateGroupMuteUntil(it, cr.muteUntil) } + conversationId?.let { conversationDao().updateGroupMuteUntil(it, cr.muteUntil) } } } else { RxBus.publish(ConversationEvent(type, true)) @@ -161,7 +161,7 @@ class ConversationJob( } if (type == TYPE_CREATE) { request?.let { - conversationDao.updateConversationStatusById( + conversationDao().updateConversationStatusById( request.conversationId, ConversationStatus.FAILURE.ordinal, ) @@ -181,7 +181,7 @@ class ConversationJob( if (data.category == ConversationCategory.CONTACT.name) { ownerId = data.participants.find { it.userId != Session.getAccountId() }!!.userId } - var c = conversationDao.findConversationById(data.conversationId) + var c = conversationDao().findConversationById(data.conversationId) if (c == null) { val builder = ConversationBuilder(data.conversationId, data.createdAt, ConversationStatus.SUCCESS.ordinal) c = @@ -194,7 +194,7 @@ class ConversationJob( .setCodeUrl(data.codeUrl) .setExpireIn(data.expireIn) .build() - conversationDao.upsert(c) + conversationDao().upsert(c) if (!c.announcement.isNullOrBlank()) { RxBus.publish(GroupEvent(data.conversationId)) MixinApplication.appContext.sharedPreferences(RefreshConversationJob.PREFERENCES_CONVERSATION).putBoolean(data.conversationId, true) @@ -206,7 +206,7 @@ class ConversationJob( } else { ConversationStatus.QUIT.ordinal } - conversationDao.updateConversation( + conversationDao().updateConversation( data.conversationId, ownerId, data.category, diff --git a/app/src/main/java/one/mixin/android/job/ConvertDataJob.kt b/app/src/main/java/one/mixin/android/job/ConvertDataJob.kt index 0672eba0fe..746261170e 100644 --- a/app/src/main/java/one/mixin/android/job/ConvertDataJob.kt +++ b/app/src/main/java/one/mixin/android/job/ConvertDataJob.kt @@ -24,13 +24,13 @@ class ConvertDataJob( } override fun onAdded() { - database.insertMessage(message) + database().insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) } override fun cancel() { isCancelled = true - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) removeJob() } @@ -48,7 +48,7 @@ class ConvertDataJob( val extensionName = message.name?.getExtensionName() val file = MixinApplication.appContext.getDocumentPath().createDocumentTemp(message.conversationId, message.messageId, extensionName) file.copyFromInputStream(inputStream) - messageDao.updateMediaMessageUrl(file.name, message.messageId) + messageDao().updateMediaMessageUrl(file.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) jobManager.addJobInBackground( diff --git a/app/src/main/java/one/mixin/android/job/ConvertVideoJob.kt b/app/src/main/java/one/mixin/android/job/ConvertVideoJob.kt index fc36d50809..784e6e7075 100644 --- a/app/src/main/java/one/mixin/android/job/ConvertVideoJob.kt +++ b/app/src/main/java/one/mixin/android/job/ConvertVideoJob.kt @@ -111,9 +111,9 @@ class ConvertVideoJob( ) // insert message with mediaSize 0L // for show video place holder in chat list before convert video - val mId = messageDao.findMessageIdById(message.messageId) + val mId = messageDao().findMessageIdById(message.messageId) if (mId == null) { - database.insertMessage(message) + database().insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) } } @@ -252,9 +252,9 @@ class ConvertVideoJob( if (error != null) MessageStatus.FAILED.name else MessageStatus.SENDING.name, ) if (error == null) { - messageDao.updateMediaMessageUrl(videoFile.name, messageId) - messageDao.updateMessageContent(null, messageId) - messageDao.updateMediaDuration(duration.toString(), messageId) + messageDao().updateMediaMessageUrl(videoFile.name, messageId) + messageDao().updateMessageContent(null, messageId) + messageDao().updateMediaDuration(duration.toString(), messageId) MessageFlow.update(message.conversationId, message.messageId) jobManager.addJobInBackground(SendAttachmentMessageJob(message)) } @@ -264,7 +264,7 @@ class ConvertVideoJob( override fun cancel() { isCancelled = true - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, messageId) MessageFlow.update(conversationId, messageId) removeJob() } diff --git a/app/src/main/java/one/mixin/android/job/FavoriteAppJob.kt b/app/src/main/java/one/mixin/android/job/FavoriteAppJob.kt index ec503241c3..ed3ce13c98 100644 --- a/app/src/main/java/one/mixin/android/job/FavoriteAppJob.kt +++ b/app/src/main/java/one/mixin/android/job/FavoriteAppJob.kt @@ -20,17 +20,17 @@ class FavoriteAppJob(vararg val userIds: String?) : BaseJob( userService.getUserFavoriteApps(userId).run { if (isSuccess) { data?.let { data -> - favoriteAppDao.deleteByUserId(userId) - favoriteAppDao.insertList(data) + favoriteAppDao().deleteByUserId(userId) + favoriteAppDao().insertList(data) data.map { app -> app.appId }.filter { id -> - appDao.findAppById(id) == null || userDao.suspendFindUserById(id) == null + appDao().findAppById(id) == null || userDao().suspendFindUserById(id) == null }.let { ids -> if (ids.isEmpty()) return@forEach val response = userService.fetchUsers(ids) if (response.isSuccess) { response.data?.apply { - userDao.insertUpdateList(this, appDao) + userDao().insertUpdateList(this, appDao()) } } } diff --git a/app/src/main/java/one/mixin/android/job/GenerateAvatarJob.kt b/app/src/main/java/one/mixin/android/job/GenerateAvatarJob.kt index c51c4b9b77..c12a0b6d3a 100644 --- a/app/src/main/java/one/mixin/android/job/GenerateAvatarJob.kt +++ b/app/src/main/java/one/mixin/android/job/GenerateAvatarJob.kt @@ -58,17 +58,17 @@ class GenerateAvatarJob( val users = mutableListOf() texts = ArrayMap() if (list == null) { - users.addAll(participantDao.getParticipantsAvatar(groupId)) + users.addAll(participantDao().getParticipantsAvatar(groupId)) } else { - val us = runBlocking { userDao.findMultiUsersByIds(list.toSet()) } + val us = runBlocking { userDao().findMultiUsersByIds(list.toSet()) } users.addAll(us) } val name = getIconUrlName(groupId, users) val f = applicationContext.getGroupAvatarPath(name, false) - val icon = conversationDao.getGroupIconUrl(groupId) + val icon = conversationDao().getGroupIconUrl(groupId) if (f.exists()) { if (f.absolutePath != name) { - conversationDao.updateGroupIconUrl(groupId, f.absolutePath) + conversationDao().updateGroupIconUrl(groupId, f.absolutePath) } RxBus.publish(AvatarEvent(groupId, f.absolutePath)) return@runBlocking @@ -90,7 +90,7 @@ class GenerateAvatarJob( } catch (e: Exception) { } } - conversationDao.updateGroupIconUrl(groupId, f.absolutePath) + conversationDao().updateGroupIconUrl(groupId, f.absolutePath) RxBus.publish(AvatarEvent(groupId, f.absolutePath)) } diff --git a/app/src/main/java/one/mixin/android/job/InitializeJob.kt b/app/src/main/java/one/mixin/android/job/InitializeJob.kt index 35d4a5ee2d..c6f772373e 100644 --- a/app/src/main/java/one/mixin/android/job/InitializeJob.kt +++ b/app/src/main/java/one/mixin/android/job/InitializeJob.kt @@ -34,7 +34,7 @@ class InitializeJob(private val botId: String, private val botName: String) : defaultExceptionHandle = {}, successBlock = { it.data?.let { u -> - userDao.insertUpdate(u, appDao) + userDao().insertUpdate(u, appDao()) return@handleMixinResponse } }, diff --git a/app/src/main/java/one/mixin/android/job/InscriptionCollectionMigrationJob.kt b/app/src/main/java/one/mixin/android/job/InscriptionCollectionMigrationJob.kt index 5322ee57ac..46c9fbc82e 100644 --- a/app/src/main/java/one/mixin/android/job/InscriptionCollectionMigrationJob.kt +++ b/app/src/main/java/one/mixin/android/job/InscriptionCollectionMigrationJob.kt @@ -14,7 +14,7 @@ class InscriptionCollectionMigrationJob : BaseJob(Params(PRIORITY_LOWER).groupBy override fun onRun() = runBlocking { - val allHash = inscriptionCollectionDao.allCollectionHash() + val allHash = inscriptionCollectionDao().allCollectionHash() allHash.forEach { if (!syncInscriptionCollection(it)) { // Wait next timing @@ -28,7 +28,7 @@ class InscriptionCollectionMigrationJob : BaseJob(Params(PRIORITY_LOWER).groupBy val collectionResponse = tokenService.getInscriptionCollection(collectionHash) if (collectionResponse.isSuccess) { val inscriptionCollection = collectionResponse.data ?: return false - inscriptionCollectionDao.insert(inscriptionCollection) + inscriptionCollectionDao().insert(inscriptionCollection) return true } else { Timber.e(collectionResponse.errorDescription) diff --git a/app/src/main/java/one/mixin/android/job/InscriptionMigrationJob.kt b/app/src/main/java/one/mixin/android/job/InscriptionMigrationJob.kt index 96f413982e..46c3d8160f 100644 --- a/app/src/main/java/one/mixin/android/job/InscriptionMigrationJob.kt +++ b/app/src/main/java/one/mixin/android/job/InscriptionMigrationJob.kt @@ -20,7 +20,7 @@ class InscriptionMigrationJob : BaseJob(Params(PRIORITY_LOWER).groupBy(GROUP_ID) override fun onRun() = runBlocking { syncOutputs(0) - val hash = outputDao.findUnspentInscriptionHash() + val hash = outputDao().findUnspentInscriptionHash() if (hash.isNotEmpty()) { jobManager.addJobInBackground(SyncInscriptionsJob(hash)) } @@ -40,7 +40,7 @@ class InscriptionMigrationJob : BaseJob(Params(PRIORITY_LOWER).groupBy(GROUP_ID) outputs.filterNot { it.inscriptionHash.isNullOrEmpty() }.apply { - outputDao.insertUnspentOutputs(this) + outputDao().insertUnspentOutputs(this) }.mapNotNull { it.inscriptionHash }.apply { if (isNotEmpty()) { jobManager.addJobInBackground(SyncInscriptionsJob(this)) diff --git a/app/src/main/java/one/mixin/android/job/MessageDeleteJob.kt b/app/src/main/java/one/mixin/android/job/MessageDeleteJob.kt index d4dc907059..dc32878860 100644 --- a/app/src/main/java/one/mixin/android/job/MessageDeleteJob.kt +++ b/app/src/main/java/one/mixin/android/job/MessageDeleteJob.kt @@ -23,26 +23,26 @@ class MessageDeleteJob( override fun onRun() = runBlocking { val deleteTimes = - messageDao.countDeleteMessageByConversationId(conversationId) / DB_DELETE_LIMIT + 1 + messageDao().countDeleteMessageByConversationId(conversationId) / DB_DELETE_LIMIT + 1 repeat(deleteTimes) { val ids = - messageDao.getMessageIdsByConversationId( + messageDao().getMessageIdsByConversationId( conversationId, lastRowId, DB_DELETE_LIMIT, ) - ftsDatabase.deleteByMessageIds(ids) - database.deleteMessageByIds(ids) + ftsDatabase().deleteByMessageIds(ids) + database().deleteMessageByIds(ids) MessageFlow.delete(conversationId, ids) } - val currentRowId = messageDao.findLastMessageRowId(conversationId) + val currentRowId = messageDao().findLastMessageRowId(conversationId) if (deleteConversation && currentRowId == null) { - conversationDao.deleteConversationById(conversationId) - conversationExtDao.deleteConversationById(conversationId) + conversationDao().deleteConversationById(conversationId) + conversationExtDao().deleteConversationById(conversationId) } else { - remoteMessageStatusDao.countUnread(conversationId) - conversationDao.refreshLastMessageId(conversationId) - conversationExtDao.refreshCountByConversationId(conversationId) + remoteMessageStatusDao().countUnread(conversationId) + conversationDao().refreshLastMessageId(conversationId) + conversationExtDao().refreshCountByConversationId(conversationId) } } } diff --git a/app/src/main/java/one/mixin/android/job/MigratedFts4Job.kt b/app/src/main/java/one/mixin/android/job/MigratedFts4Job.kt index 78a5ad0ec7..670ab107e2 100644 --- a/app/src/main/java/one/mixin/android/job/MigratedFts4Job.kt +++ b/app/src/main/java/one/mixin/android/job/MigratedFts4Job.kt @@ -23,10 +23,10 @@ class MigratedFts4Job : BaseJob(Params(PRIORITY_LOWER).groupBy(GROUP_ID).persist override fun onRun() = runBlocking { - var lastRowId = propertyDao.findValueByKey(FTS_NEED_MIGRATED_LAST_ROW_ID)?.toLongOrNull() ?: 0L + var lastRowId = propertyDao().findValueByKey(FTS_NEED_MIGRATED_LAST_ROW_ID)?.toLongOrNull() ?: 0L if (lastRowId == -1L) return@runBlocking if (lastRowId == 0L) { // Get the rowid of the current last message - val currentLastId = messageDao.getLastMessageRowId() + val currentLastId = messageDao().getLastMessageRowId() if (currentLastId == null) { // No data, no migration required PropertyHelper.updateKeyValue(FTS_NEED_MIGRATED_LAST_ROW_ID, -1) return@runBlocking @@ -34,32 +34,32 @@ class MigratedFts4Job : BaseJob(Params(PRIORITY_LOWER).groupBy(GROUP_ID).persist lastRowId = currentLastId + 1 // It is easy to obtain data that is less than or equal to it. } } - val messages = messageDao.findFtsMessages(lastRowId, MIGRATED_LIMIT) + val messages = messageDao().findFtsMessages(lastRowId, MIGRATED_LIMIT) messages.forEach { message -> if (message.isTranscript()) { val content = - transcriptMessageDao.getTranscriptsById(message.messageId).filter { it.isText() || it.isPost() || it.isData() || it.isContact() } + transcriptMessageDao().getTranscriptsById(message.messageId).filter { it.isText() || it.isPost() || it.isData() || it.isContact() } .map { transcript -> if (transcript.isData()) { transcript.mediaName } else { if (transcript.isContact()) { - transcript.sharedUserId?.let { userId -> userDao.findUser(userId) }?.fullName + transcript.sharedUserId?.let { userId -> userDao().findUser(userId) }?.fullName } else { transcript.content } } }.filter { it.isNullOrBlank().not() }.joinToString("").joinWhiteSpace() - ftsDatabase.insertFts4(content.joinWhiteSpace(), message.conversationId, message.messageId, message.category, message.userId, message.createdAt) + ftsDatabase().insertFts4(content.joinWhiteSpace(), message.conversationId, message.messageId, message.category, message.userId, message.createdAt) } else { - ftsDatabase.insertOrReplaceMessageFts4(message) + ftsDatabase().insertOrReplaceMessageFts4(message) } } if (messages.size < MIGRATED_LIMIT) { PropertyHelper.updateKeyValue(FTS_NEED_MIGRATED_LAST_ROW_ID, -1) PropertyHelper.updateKeyValue(ClearFts4Job.FTS_CLEAR, true) } else { - lastRowId = messageDao.getMessageRowid(messages.last().messageId) ?: lastRowId + lastRowId = messageDao().getMessageRowid(messages.last().messageId) ?: lastRowId PropertyHelper.updateKeyValue(FTS_NEED_MIGRATED_LAST_ROW_ID, lastRowId) jobManager.addJobInBackground(MigratedFts4Job()) } diff --git a/app/src/main/java/one/mixin/android/job/MixinJob.kt b/app/src/main/java/one/mixin/android/job/MixinJob.kt index 797f65ac9e..1335a60f87 100644 --- a/app/src/main/java/one/mixin/android/job/MixinJob.kt +++ b/app/src/main/java/one/mixin/android/job/MixinJob.kt @@ -79,7 +79,7 @@ abstract class MixinJob( val preKeyBundle = createPreKeyBundle(keys[0]) signalProtocol.processSession(recipientId, preKeyBundle) } else { - participantSessionDao.insertParticipantSessionSent(ParticipantSessionSent(conversationId, recipientId, sessionId, SenderKeyStatus.UNKNOWN.ordinal)) + participantSessionDao().insertParticipantSessionSent(ParticipantSessionSent(conversationId, recipientId, sessionId, SenderKeyStatus.UNKNOWN.ordinal)) return false } @@ -93,7 +93,7 @@ abstract class MixinJob( return sendSenderKey(conversationId, recipientId, sessionId) } if (result.success) { - participantSessionDao.insertParticipantSessionSent(ParticipantSessionSent(conversationId, recipientId, sessionId, SenderKeyStatus.SENT.ordinal)) + participantSessionDao().insertParticipantSessionSent(ParticipantSessionSent(conversationId, recipientId, sessionId, SenderKeyStatus.SENT.ordinal)) } return result.success } @@ -173,7 +173,7 @@ abstract class MixinJob( } protected fun checkConversation(conversationId: String) { - val conversation = conversationDao.findConversationById(conversationId) ?: return + val conversation = conversationDao().findConversationById(conversationId) ?: return if (conversation.isGroupConversation()) { jobSenderKey.syncConversation(conversation.conversationId) } else { @@ -190,8 +190,8 @@ abstract class MixinJob( ) val response = conversationApi.create(request).execute().body() if (response != null && response.isSuccess && response.data != null && !isCancelled) { - conversationDao.updateConversationStatusById(conversation.conversationId, ConversationStatus.SUCCESS.ordinal) - conversationDao.updateConversationExpireInById(conversation.conversationId, response.data?.expireIn) + conversationDao().updateConversationStatusById(conversation.conversationId, ConversationStatus.SUCCESS.ordinal) + conversationDao().updateConversationExpireInById(conversation.conversationId, response.data?.expireIn) val sessionParticipants = response.data!!.participantSessions.let { resp -> @@ -200,7 +200,7 @@ abstract class MixinJob( } } sessionParticipants?.let { - participantSessionDao.replaceAll(conversation.conversationId, it) + participantSessionDao().replaceAll(conversation.conversationId, it) } return response.data?.expireIn } else { diff --git a/app/src/main/java/one/mixin/android/job/RefreshAddressJob.kt b/app/src/main/java/one/mixin/android/job/RefreshAddressJob.kt index 29f7e42d1c..2e6452a2af 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshAddressJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshAddressJob.kt @@ -15,7 +15,7 @@ class RefreshAddressJob(private val assetId: String) : BaseJob( val response = addressService.addresses(assetId).execute().body() if (response != null && response.isSuccess && response.data != null) { response.data?.let { - addressDao.insertList(it) + addressDao().insertList(it) } } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshAlertsJob.kt b/app/src/main/java/one/mixin/android/job/RefreshAlertsJob.kt index d6b21e07f4..1483ffa843 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshAlertsJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshAlertsJob.kt @@ -27,7 +27,7 @@ class RefreshAlertsJob : BaseJob( successBlock = { response -> val list = response.data!! list.map{it.coinId}.distinct().mapNotNull { coinId -> - val m = marketDao.findMarketById(coinId) + val m = marketDao().findMarketById(coinId) if (m != null) null else coinId }.let { ids -> @@ -36,8 +36,8 @@ class RefreshAlertsJob : BaseJob( } } runInTransaction { - alertDao.deleteAll() - alertDao.insertList(list) + alertDao().deleteAll() + alertDao().insertList(list) } }, requestSession = { @@ -65,8 +65,8 @@ class RefreshAlertsJob : BaseJob( ) } ?: emptyList() } - marketCoinDao.insertList(coins) - marketDao.insertList(list) + marketCoinDao().insertList(coins) + marketDao().insertList(list) }, requestSession = { userService.fetchSessionsSuspend(listOf(ROUTE_BOT_USER_ID)) diff --git a/app/src/main/java/one/mixin/android/job/RefreshAssetsJob.kt b/app/src/main/java/one/mixin/android/job/RefreshAssetsJob.kt index 82ef745a2c..db1e03bc52 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshAssetsJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshAssetsJob.kt @@ -23,7 +23,7 @@ class RefreshAssetsJob( val response = assetService.getAssetByIdSuspend(assetId) if (response.isSuccess && response.data != null) { response.data?.let { - assetDao.insert(it) + assetDao().insert(it) refreshChainById(it.chainId) } } @@ -34,11 +34,11 @@ class RefreshAssetsJob( response.data?.map { it.assetId }?.let { ids -> - assetDao.findAllAssetIdSuspend().subtract(ids.toSet()).chunked(100).forEach { - assetDao.zeroClearSuspend(it) + assetDao().findAllAssetIdSuspend().subtract(ids.toSet()).chunked(100).forEach { + assetDao().zeroClearSuspend(it) } } - assetDao.insertList(list) + assetDao().insertList(list) } refreshChains() refreshFiats() @@ -58,8 +58,8 @@ class RefreshAssetsJob( val resp = assetService.getChains() if (resp.isSuccess) { resp.data?.let { chains -> - chains.subtract(chainDao.getChains().toSet()).let { - chainDao.insertList(it.toList()) + chains.subtract(chainDao().getChains().toSet()).let { + chainDao().insertList(it.toList()) } } } @@ -69,8 +69,8 @@ class RefreshAssetsJob( val resp = assetService.getChainById(chainId) if (resp.isSuccess) { resp.data?.let { chain -> - val isExits = chainDao.isExits(chain.chainId, chain.name, chain.symbol, chain.iconUrl, chain.threshold) != null - if (!isExits) chainDao.upsertSuspend(chain) + val isExits = chainDao().isExits(chain.chainId, chain.name, chain.symbol, chain.iconUrl, chain.threshold) != null + if (!isExits) chainDao().upsertSuspend(chain) } } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshCircleJob.kt b/app/src/main/java/one/mixin/android/job/RefreshCircleJob.kt index d256bf274b..510d4001ee 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshCircleJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshCircleJob.kt @@ -25,7 +25,7 @@ class RefreshCircleJob( circleResponse.data?.let { cList -> cList.forEach { c -> handleCircle(c) { circleConversation -> - if (conversationDao.findConversationById(circleConversation.conversationId) != null) return@handleCircle + if (conversationDao().findConversationById(circleConversation.conversationId) != null) return@handleCircle jobManager.addJobInBackground( RefreshConversationJob( circleConversation.conversationId, @@ -33,7 +33,7 @@ class RefreshCircleJob( ), ) } - circleDao.insertUpdate(c) + circleDao().insertUpdate(c) } } } @@ -42,7 +42,7 @@ class RefreshCircleJob( if (circleResponse?.isSuccess == true) { circleResponse.data?.let { c -> handleCircle(c) - circleDao.insertUpdate(c) + circleDao().insertUpdate(c) } } } @@ -66,10 +66,10 @@ class RefreshCircleJob( if (ccResponse?.isSuccess == true) { ccResponse.data?.let { ccList -> ccList.forEach { cc -> - circleConversationDao.insertUpdate(cc) + circleConversationDao().insertUpdate(cc) cc.userId?.let { uid -> if (!refreshUserIdSet.contains(uid)) { - val user = userDao.findUser(uid) + val user = userDao().findUser(uid) if (user == null) { refreshUserIdSet.add(uid) } diff --git a/app/src/main/java/one/mixin/android/job/RefreshContactJob.kt b/app/src/main/java/one/mixin/android/job/RefreshContactJob.kt index 748ea48428..fa42d39940 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshContactJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshContactJob.kt @@ -14,7 +14,7 @@ class RefreshContactJob : BaseJob(Params(PRIORITY_BACKGROUND).addTags(GROUP).req val response = contactService.friends().execute().body() if (response != null && response.isSuccess && response.data != null) { val users = response.data as List - userDao.insertUpdateList(users, appDao) + userDao().insertUpdateList(users, appDao()) } } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt b/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt index 51b2326f88..2df5951671 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt @@ -34,7 +34,7 @@ class RefreshConversationJob(val conversationId: String, private val skipRefresh if (conversationId == SYSTEM_USER || conversationId == Session.getAccountId()) { return } - val localData = participantDao.getRealParticipants(conversationId) + val localData = participantDao().getRealParticipants(conversationId) val call = conversationApi.getConversation(conversationId).execute() val response = call.body() @@ -53,7 +53,7 @@ class RefreshConversationJob(val conversationId: String, private val skipRefresh conversationUserIds.add(p.userId) } - participantDao.replaceAll(data.conversationId, participants) + participantDao().replaceAll(data.conversationId, participants) data.participantSessions?.let { jobSenderKey.syncParticipantSession(conversationId, it) } @@ -67,16 +67,16 @@ class RefreshConversationJob(val conversationId: String, private val skipRefresh if (skipRefreshCircle) return@let data.circles?.let { circles -> circles.forEach { - val circle = circleDao.findCircleById(it.circleId) + val circle = circleDao().findCircleById(it.circleId) if (circle == null) { val circleResponse = circleService.getCircle(it.circleId).execute().body() if (circleResponse?.isSuccess == true) { circleResponse.data?.let { item -> - circleDao.insert(item) + circleDao().insert(item) } } } - circleConversationDao.insertUpdate(it) + circleConversationDao().insertUpdate(it) } } } @@ -88,7 +88,7 @@ class RefreshConversationJob(val conversationId: String, private val skipRefresh if (data.category == ConversationCategory.CONTACT.name) { ownerId = data.participants.find { it.userId != Session.getAccountId() }!!.userId } - var c = conversationDao.findConversationById(data.conversationId) + var c = conversationDao().findConversationById(data.conversationId) if (c == null) { val builder = ConversationBuilder(data.conversationId, data.createdAt, ConversationStatus.SUCCESS.ordinal) c = @@ -101,7 +101,7 @@ class RefreshConversationJob(val conversationId: String, private val skipRefresh .setCodeUrl(data.codeUrl) .setExpireIn(data.expireIn) .build() - conversationDao.upsert(c) + conversationDao().upsert(c) if (!c.announcement.isNullOrBlank()) { RxBus.publish(GroupEvent(data.conversationId)) MixinApplication.appContext.sharedPreferences(RefreshConversationJob.PREFERENCES_CONVERSATION).putBoolean(data.conversationId, true) @@ -113,7 +113,7 @@ class RefreshConversationJob(val conversationId: String, private val skipRefresh } else { ConversationStatus.QUIT.ordinal } - conversationDao.updateConversation( + conversationDao().updateConversation( data.conversationId, ownerId, data.category, diff --git a/app/src/main/java/one/mixin/android/job/RefreshDappJob.kt b/app/src/main/java/one/mixin/android/job/RefreshDappJob.kt index 106684c634..ef7a257c6c 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshDappJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshDappJob.kt @@ -72,13 +72,13 @@ class RefreshDappJob : BaseJob( conversationId: String, botId: String, ): String? { - return participantSessionDao.findBotPublicKey(conversationId, botId) + return participantSessionDao().findBotPublicKey(conversationId, botId) } suspend fun fetchSessionsSuspend(ids: List) = userService.fetchSessionsSuspend(ids) suspend fun saveSession(participantSession: ParticipantSession) { - participantSessionDao.insertSuspend(participantSession) + participantSessionDao().insertSuspend(participantSession) } suspend fun getBotPublicKey(botId: String, force: Boolean) { diff --git a/app/src/main/java/one/mixin/android/job/RefreshMarketJob.kt b/app/src/main/java/one/mixin/android/job/RefreshMarketJob.kt index 4addb8a419..aebd11d122 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshMarketJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshMarketJob.kt @@ -18,8 +18,8 @@ class RefreshMarketJob(private val assetId: String) : BaseJob( val response = routeService.market(assetId) if (response.isSuccess && response.data != null) { response.data?.let { market-> - marketDao.insert(market) - marketCoinDao.insertList(market.assetIds?.map { assetId -> + marketDao().insert(market) + marketCoinDao().insertList(market.assetIds?.map { assetId -> MarketCoin( coinId = market.coinId, assetId = assetId, diff --git a/app/src/main/java/one/mixin/android/job/RefreshMarketsJob.kt b/app/src/main/java/one/mixin/android/job/RefreshMarketsJob.kt index 7d09a22484..aafe1bc44a 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshMarketsJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshMarketsJob.kt @@ -38,17 +38,17 @@ class RefreshMarketsJob(val category: String = "all") : BaseJob( now ) } - marketFavoredDao.insertList(marketExtraList) + marketFavoredDao().insertList(marketExtraList) } if (category == "all") { runInTransaction { - marketCapRankDao.deleteAll() - marketCapRankDao.insertList(list.map { + marketCapRankDao().deleteAll() + marketCapRankDao().insertList(list.map { MarketCapRank(it.coinId, it.marketCapRank, it.updatedAt) }) } } - marketDao.upsertList(list) + marketDao().upsertList(list) val ids = list.flatMap { market -> market.assetIds?.map { assetId -> MarketCoin( @@ -58,7 +58,7 @@ class RefreshMarketsJob(val category: String = "all") : BaseJob( ) } ?: emptyList() } - marketCoinDao.insertIgnoreList(ids) + marketCoinDao().insertIgnoreList(ids) }, requestSession = { userService.fetchSessionsSuspend(listOf(ROUTE_BOT_USER_ID)) diff --git a/app/src/main/java/one/mixin/android/job/RefreshOffsetJob.kt b/app/src/main/java/one/mixin/android/job/RefreshOffsetJob.kt index 493307d060..4ba0b0ff35 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshOffsetJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshOffsetJob.kt @@ -29,7 +29,7 @@ class RefreshOffsetJob : MixinJob( } override fun onRun() { - val statusOffset = offsetDao.getStatusOffset() + val statusOffset = offsetDao().getStatusOffset() var status = statusOffset?.getEpochNano() ?: firstInstallTime while (true) { @@ -41,7 +41,7 @@ class RefreshOffsetJob : MixinJob( } for (m in blazeMessages) { val callback = block@{ - val mh = messageHistoryDao.findMessageHistoryById(m.messageId) + val mh = messageHistoryDao().findMessageHistoryById(m.messageId) if (mh != null) { return@block } @@ -56,9 +56,9 @@ class RefreshOffsetJob : MixinJob( pendingMessageStatusLruCache.put(m.messageId, m.status) } } - pendingDatabase.makeMessageStatus(m.status, m.messageId, callback) - database.makeMessageStatus(m.status, m.messageId, callback) - offsetDao.insert(Offset(STATUS_OFFSET, m.updatedAt)) + pendingDatabase().makeMessageStatus(m.status, m.messageId, callback) + database().makeMessageStatus(m.status, m.messageId, callback) + offsetDao().insert(Offset(STATUS_OFFSET, m.updatedAt)) } if (blazeMessages.isNotEmpty() && blazeMessages.last().updatedAt.getEpochNano() == status) { break diff --git a/app/src/main/java/one/mixin/android/job/RefreshPriceJob.kt b/app/src/main/java/one/mixin/android/job/RefreshPriceJob.kt index 71f054448a..2e9da9acdf 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshPriceJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshPriceJob.kt @@ -26,14 +26,14 @@ class RefreshPriceJob(private val assetId: String) : BaseJob( if (response.isSuccess && response.data != null) { response.data?.let { if (it.data.isEmpty()) return@let - historyPriceDao.insert(it) + historyPriceDao().insert(it) } } else if (response.errorCode == ErrorHandler.AUTHENTICATION) { val resp = userService.fetchSessionsSuspend(listOf(ROUTE_BOT_USER_ID)) if (resp.isSuccess) { val sessionData = requireNotNull(resp.data)[0] MixinApplication.appContext.defaultSharedPreferences.putString(PREF_ROUTE_BOT_PK, sessionData.publicKey) - participantSessionDao.insertSuspend(ParticipantSession(generateConversationId(sessionData.userId, Session.getAccountId()!!), sessionData.userId, sessionData.sessionId, publicKey = sessionData.publicKey)) + participantSessionDao().insertSuspend(ParticipantSession(generateConversationId(sessionData.userId, Session.getAccountId()!!), sessionData.userId, sessionData.sessionId, publicKey = sessionData.publicKey)) } } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshSessionJob.kt b/app/src/main/java/one/mixin/android/job/RefreshSessionJob.kt index ac51306733..754e3325c4 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshSessionJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshSessionJob.kt @@ -22,7 +22,7 @@ class RefreshSessionJob( ParticipantSession(conversationId, item.userId, item.sessionId, publicKey = item.publicKey) } if (!ps.isNullOrEmpty()) { - participantSessionDao.insertList(ps) + participantSessionDao().insertList(ps) } } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshSnapshotsJob.kt b/app/src/main/java/one/mixin/android/job/RefreshSnapshotsJob.kt index 5c9e89f37e..5abb115e20 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshSnapshotsJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshSnapshotsJob.kt @@ -25,7 +25,7 @@ class RefreshSnapshotsJob : BaseJob(Params(PRIORITY_BACKGROUND).singleInstanceBy val response = tokenService.getSnapshots(offset = offset, limit = LIMIT) if (response.isSuccess && response.data != null) { val snapshots = response.data as List - safeSnapshotDao.insertListSuspend(snapshots.map { + safeSnapshotDao().insertListSuspend(snapshots.map { if (it.opponentId.isEmpty()) { mapSnapshot(it) } else { @@ -33,7 +33,7 @@ class RefreshSnapshotsJob : BaseJob(Params(PRIORITY_BACKGROUND).singleInstanceBy } }) snapshots.forEach { item -> - if (tokenDao.simpleAsset(item.assetId) == null) { + if (tokenDao().simpleAsset(item.assetId) == null) { jobManager.addJobInBackground(RefreshTokensJob(item.assetId)) } } @@ -49,7 +49,7 @@ class RefreshSnapshotsJob : BaseJob(Params(PRIORITY_BACKGROUND).singleInstanceBy } private suspend fun mapSnapshot(snapshot: SafeSnapshot): SafeSnapshot { - val existingSnapshot = safeSnapshotDao.getSnapshotById(snapshot.snapshotId) + val existingSnapshot = safeSnapshotDao().getSnapshotById(snapshot.snapshotId) if (existingSnapshot != null && existingSnapshot.opponentId.isNotEmpty()) { val updatedSnapshot = snapshot.copy(opponentId = existingSnapshot.opponentId) return updatedSnapshot diff --git a/app/src/main/java/one/mixin/android/job/RefreshStickerAlbumJob.kt b/app/src/main/java/one/mixin/android/job/RefreshStickerAlbumJob.kt index 11f5979226..46c37ac22e 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshStickerAlbumJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshStickerAlbumJob.kt @@ -32,7 +32,7 @@ class RefreshStickerAlbumJob : BaseJob( val albums = (response.data as List).sortedBy { it.createdAt } val localLatestCreatedAt = - stickerAlbumDao.findLatestCreatedAt()?.let { createdAt -> + stickerAlbumDao().findLatestCreatedAt()?.let { createdAt -> parseCreatedAt(createdAt) } var hasNewAlbum = false @@ -40,18 +40,18 @@ class RefreshStickerAlbumJob : BaseJob( hasNewAlbum = true } - var maxOrder = stickerAlbumDao.findMaxOrder() ?: 0 + var maxOrder = stickerAlbumDao().findMaxOrder() ?: 0 for (a in albums) { - val localAlbum = stickerAlbumDao.findAlbumById(a.albumId) + val localAlbum = stickerAlbumDao().findAlbumById(a.albumId) if (localAlbum == null) { maxOrder++ a.added = a.banner.isNullOrBlank().not() a.orderedAt = maxOrder - stickerAlbumDao.insertSuspend(a) + stickerAlbumDao().insertSuspend(a) } else { a.added = localAlbum.added a.orderedAt = localAlbum.orderedAt - stickerAlbumDao.update(a) + stickerAlbumDao().update(a) } if (!hasNewAlbum && localLatestCreatedAt != null) { @@ -68,10 +68,10 @@ class RefreshStickerAlbumJob : BaseJob( val stickers = r.data as List val relationships = arrayListOf() for (s in stickers) { - stickerDao.insertUpdate(s) + stickerDao().insertUpdate(s) relationships.add(StickerRelationship(a.albumId, s.stickerId)) } - stickerRelationshipDao.insertList(relationships) + stickerRelationshipDao().insertList(relationships) } } @@ -82,7 +82,7 @@ class RefreshStickerAlbumJob : BaseJob( val sp = applicationContext.defaultSharedPreferences if (!sp.getBoolean("UpgradeMessageSticker", false)) { - stickerRelationshipDao.updateMessageStickerId() + stickerRelationshipDao().updateMessageStickerId() sp.putBoolean("UpgradeMessageSticker", true) } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt b/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt index b1c27d8868..477378e0b1 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt @@ -18,7 +18,7 @@ class RefreshStickerAndRelatedAlbumJob(private val stickerId: String) : BaseJob( override fun onRun() = runBlocking { - val localSticker = stickerDao.findStickerById(stickerId) + val localSticker = stickerDao().findStickerById(stickerId) var albumId: String? = null if (localSticker != null) { albumId = localSticker.albumId @@ -32,21 +32,21 @@ class RefreshStickerAndRelatedAlbumJob(private val stickerId: String) : BaseJob( } if (albumId.isNullOrBlank()) { - albumId?.let { stickerDao.updateAlbumId(stickerId, it) } + albumId?.let { stickerDao().updateAlbumId(stickerId, it) } return@runBlocking } - var album = stickerAlbumDao.findAlbumById(albumId) + var album = stickerAlbumDao().findAlbumById(albumId) if (album == null) { val albumResponse = accountService.getAlbumByIdSuspend(albumId) if (albumResponse.isSuccess && albumResponse.data != null) { album = albumResponse.data as StickerAlbum - stickerAlbumDao.insertSuspend(album) + stickerAlbumDao().insertSuspend(album) } } if (album == null || album.category == "PERSONAL") { - stickerDao.updateAlbumId(stickerId, albumId) + stickerDao().updateAlbumId(stickerId, albumId) return@runBlocking } @@ -59,13 +59,13 @@ class RefreshStickerAndRelatedAlbumJob(private val stickerId: String) : BaseJob( } else { null } - database.runInTransaction { + database().runInTransaction { for (s in stickers) { - stickerDao.insertUpdate(s) + stickerDao().insertUpdate(s) relationships?.add(StickerRelationship(albumId, s.stickerId)) } relationships?.let { rs -> - stickerRelationshipDao.insertList(rs) + stickerRelationshipDao().insertList(rs) } } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshStickerJob.kt b/app/src/main/java/one/mixin/android/job/RefreshStickerJob.kt index f346df4b56..8d0b9f8657 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshStickerJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshStickerJob.kt @@ -17,7 +17,7 @@ class RefreshStickerJob(private val stickerId: String) : BaseJob( val response = accountService.getStickerById(stickerId).execute().body() if (response != null && response.isSuccess && response.data != null) { val s = response.data as Sticker - stickerDao.insertUpdate(s) + stickerDao().insertUpdate(s) } } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshTokensJob.kt b/app/src/main/java/one/mixin/android/job/RefreshTokensJob.kt index 5ddbad8828..4d6ca7fde4 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshTokensJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshTokensJob.kt @@ -26,7 +26,7 @@ class RefreshTokensJob( val response = tokenService.getAssetByIdSuspend(assetId) if (response.isSuccess && response.data != null) { response.data?.let { - tokenDao.insert(it) + tokenDao().insert(it) refreshChainById(it.chainId) } if (conversationId != null && messageId != null) { @@ -35,11 +35,11 @@ class RefreshTokensJob( } } else { refreshAsset() - val tokenIds = tokenDao.findAllTokenIds() + val tokenIds = tokenDao().findAllTokenIds() val response = tokenService.fetchTokenSuspend(tokenIds) if (response.isSuccess && response.data != null) { val list = response.data as List - tokenDao.insertList(list) + tokenDao().insertList(list) } refreshChains() refreshFiats() @@ -50,7 +50,7 @@ class RefreshTokensJob( val response = tokenService.fetchAllTokenSuspend() if (response.isSuccess && response.data != null) { val list = response.data as List - tokenDao.insertList(list) + tokenDao().insertList(list) } } @@ -67,8 +67,8 @@ class RefreshTokensJob( val resp = tokenService.getChains() if (resp.isSuccess) { resp.data?.let { chains -> - chains.subtract(chainDao.getChains().toSet()).let { - chainDao.insertList(it.toList()) + chains.subtract(chainDao().getChains().toSet()).let { + chainDao().insertList(it.toList()) } } } @@ -78,8 +78,8 @@ class RefreshTokensJob( val resp = tokenService.getChainById(chainId) if (resp.isSuccess) { resp.data?.let { chain -> - val isExits = chainDao.isExits(chain.chainId, chain.name, chain.symbol, chain.iconUrl, chain.threshold) != null - if (!isExits) chainDao.upsertSuspend(chain) + val isExits = chainDao().isExits(chain.chainId, chain.name, chain.symbol, chain.iconUrl, chain.threshold) != null + if (!isExits) chainDao().upsertSuspend(chain) } } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshTopAssetsJob.kt b/app/src/main/java/one/mixin/android/job/RefreshTopAssetsJob.kt index 2ef9321379..490690b73a 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshTopAssetsJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshTopAssetsJob.kt @@ -25,15 +25,15 @@ class RefreshTopAssetsJob : BaseJob( if (response != null && response.isSuccess && response.data != null) { val assetList = response.data as List assetList.map { it.assetId }.chunked(200) { - launch { topAssetDao.deleteNotInIds(it) } + launch { topAssetDao().deleteNotInIds(it) } } - topAssetDao.insertListSuspend(assetList) + topAssetDao().insertListSuspend(assetList) val recentArray = MixinApplication.appContext.defaultSharedPreferences .getString(Constants.Account.PREF_RECENT_SEARCH_ASSETS, null)?.split("=") if (recentArray.isNullOrEmpty()) return@runBlocking - val recentList = tokenDao.suspendFindAssetsByIds(recentArray.take(2)) + val recentList = tokenDao().suspendFindAssetsByIds(recentArray.take(2)) if (recentList.isNullOrEmpty()) return@runBlocking val needUpdatePrice = arrayListOf() assetList.forEach { t -> @@ -46,7 +46,7 @@ class RefreshTopAssetsJob : BaseJob( } } if (needUpdatePrice.isNotEmpty()) { - tokenDao.suspendUpdatePrices(needUpdatePrice) + tokenDao().suspendUpdatePrices(needUpdatePrice) } } } diff --git a/app/src/main/java/one/mixin/android/job/RefreshUserJob.kt b/app/src/main/java/one/mixin/android/job/RefreshUserJob.kt index b50da46242..c510a98c18 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshUserJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshUserJob.kt @@ -27,7 +27,7 @@ class RefreshUserJob( refreshUsers(ids) return@runBlocking } - val existUsers = userDao.findUserExist(ids) + val existUsers = userDao().findUserExist(ids) val queryUsers = ids.filter { !existUsers.contains(it) @@ -44,7 +44,7 @@ class RefreshUserJob( val response = userService.getUserById(userIds[0]).execute().body() if (response != null && response.isSuccess) { response.data?.let { data -> - userDao.upsert(data) + userDao().upsert(data) refreshConversationAvatar() } } @@ -52,7 +52,7 @@ class RefreshUserJob( val response = userService.getUsers(userIds).execute().body() if (response != null && response.isSuccess) { response.data?.let { data -> - userDao.upsertList(data) + userDao().upsertList(data) refreshConversationAvatar() } } diff --git a/app/src/main/java/one/mixin/android/job/RemoveStickersJob.kt b/app/src/main/java/one/mixin/android/job/RemoveStickersJob.kt index d2148114ce..f6fb255344 100644 --- a/app/src/main/java/one/mixin/android/job/RemoveStickersJob.kt +++ b/app/src/main/java/one/mixin/android/job/RemoveStickersJob.kt @@ -11,9 +11,9 @@ class RemoveStickersJob(private val stickerIds: List) : override fun onRun() { if (stickerIds.isEmpty()) return - stickerRelationshipDao.getPersonalAlbumId()?.let { albumId -> + stickerRelationshipDao().getPersonalAlbumId()?.let { albumId -> for (i in stickerIds) { - stickerRelationshipDao.deleteByStickerId(i, albumId) + stickerRelationshipDao().deleteByStickerId(i, albumId) } } diff --git a/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt b/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt index 9f8c47c40c..7fed42f8ad 100644 --- a/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt +++ b/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt @@ -45,10 +45,10 @@ class RestoreTransactionJob : BaseJob( ) { while (true) { val transaction = - rawTransactionDao.findUnspentTransaction() ?: return@runBlocking + rawTransactionDao().findUnspentTransaction() ?: return@runBlocking val feeTraceId = uniqueObjectId(transaction.requestId, "FEE") - val feeTransaction = rawTransactionDao.findRawTransaction(feeTraceId, RawTransactionType.FEE.value) + val feeTransaction = rawTransactionDao().findRawTransaction(feeTraceId, RawTransactionType.FEE.value) try { Timber.e("Restore Transaction(${transaction.requestId}): Get Transaction") val response = utxoService.getTransactionsById(transaction.requestId) @@ -56,9 +56,9 @@ class RestoreTransactionJob : BaseJob( Timber.e("Restore Transaction(${transaction.requestId}): db begin") runInTransaction { Timber.e("Restore Transaction(${transaction.requestId}): update raw transaction ${transaction.requestId}") - rawTransactionDao.updateRawTransaction(transaction.requestId, OutputState.signed.name) + rawTransactionDao().updateRawTransaction(transaction.requestId, OutputState.signed.name) Timber.e("Restore Transaction(${transaction.requestId}): update raw transaction $feeTraceId") - rawTransactionDao.updateRawTransaction(feeTraceId, OutputState.signed.name) + rawTransactionDao().updateRawTransaction(feeTraceId, OutputState.signed.name) } Timber.e("Restore Transaction(${transaction.requestId}): db end") if (feeTransaction == null) { @@ -83,9 +83,9 @@ class RestoreTransactionJob : BaseJob( Timber.e("Restore Transaction(${transaction.requestId}): db begin") runInTransaction { Timber.e("Restore Transaction(${transaction.requestId}): update raw transaction ${transaction.requestId}") - rawTransactionDao.updateRawTransaction(transaction.requestId, OutputState.signed.name) + rawTransactionDao().updateRawTransaction(transaction.requestId, OutputState.signed.name) Timber.e("Restore Transaction(${transaction.requestId}): update raw transaction $feeTraceId") - rawTransactionDao.updateRawTransaction(feeTraceId, OutputState.signed.name) + rawTransactionDao().updateRawTransaction(feeTraceId, OutputState.signed.name) } Timber.e("Restore Transaction(${transaction.requestId}): db end") if (feeTransaction == null && transaction.receiverId.isNotBlank()) { @@ -94,8 +94,8 @@ class RestoreTransactionJob : BaseJob( } else { Timber.e("Restore Transaction(${transaction.requestId}): Post Transaction Error ${transactionRsp.errorDescription}") reportException(e = Throwable("Transaction Error ${transactionRsp.errorDescription}")) - rawTransactionDao.updateRawTransaction(transaction.requestId, OutputState.signed.name) - rawTransactionDao.updateRawTransaction(feeTraceId, OutputState.signed.name) + rawTransactionDao().updateRawTransaction(transaction.requestId, OutputState.signed.name) + rawTransactionDao().updateRawTransaction(feeTraceId, OutputState.signed.name) } jobManager.addJobInBackground(SyncOutputJob()) } else if (response.errorCode >= 500) { @@ -122,7 +122,7 @@ class RestoreTransactionJob : BaseJob( opponentId: String, inscriptionHash: String?, ) { - val user = userDao.findUser(opponentId) + val user = userDao().findUser(opponentId) if (user != null && user.userId != Session.getAccountId() && !user.notMessengerUser()) { val conversationId = generateConversationId(data.userId, opponentId) initConversation(conversationId, data.userId, opponentId) @@ -133,7 +133,7 @@ class RestoreTransactionJob : BaseJob( MessageCategory.SYSTEM_SAFE_SNAPSHOT.name } val message = createMessage(UUID.randomUUID().toString(), conversationId, data.userId, category, inscriptionHash ?: "", data.createdAt, MessageStatus.DELIVERED.name, SafeSnapshotType.snapshot.name, null, data.getSnapshotId) - database.insertMessage(message) + database().insertMessage(message) if (inscriptionHash != null) { jobManager.addJobInBackground(SyncInscriptionMessageJob(conversationId, message.messageId, inscriptionHash, data.getSnapshotId)) } @@ -146,7 +146,7 @@ class RestoreTransactionJob : BaseJob( senderId: String, recipientId: String, ) { - val c = conversationDao.findConversationById(conversationId) + val c = conversationDao().findConversationById(conversationId) if (c != null) return val createdAt = nowInUtc() val conversation = @@ -161,9 +161,9 @@ class RestoreTransactionJob : BaseJob( Participant(conversationId, senderId, "", createdAt), Participant(conversationId, recipientId, "", createdAt), ) - database.runInTransaction { - conversationDao.upsert(conversation) - participantDao.insertList(participants) + database().runInTransaction { + conversationDao().upsert(conversation) + participantDao().insertList(participants) } jobManager.addJobInBackground(RefreshConversationJob(conversationId)) } diff --git a/app/src/main/java/one/mixin/android/job/SendAttachmentMessageJob.kt b/app/src/main/java/one/mixin/android/job/SendAttachmentMessageJob.kt index b494c42fcc..42d7c858ad 100644 --- a/app/src/main/java/one/mixin/android/job/SendAttachmentMessageJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendAttachmentMessageJob.kt @@ -46,7 +46,7 @@ class SendAttachmentMessageJob( override fun cancel() { isCancelled = true - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) disposable?.let { @@ -60,25 +60,25 @@ class SendAttachmentMessageJob( override fun onAdded() { super.onAdded() if (message.isVideo()) { - val mId = messageDao.findMessageIdById(message.messageId) + val mId = messageDao().findMessageIdById(message.messageId) if (mId != null) { - messageDao.updateMediaSize(message.mediaSize ?: 0, mId) + messageDao().updateMediaSize(message.mediaSize ?: 0, mId) MessageFlow.update(message.conversationId, message.messageId) } else { - database.insertMessage(message) + database().insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) } } else { - val mId = messageDao.findMessageIdById(message.messageId) + val mId = messageDao().findMessageIdById(message.messageId) if (mId == null) { - database.insertMessage(message) + database().insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) } } - val conversation = conversationDao.findConversationById(message.conversationId) + val conversation = conversationDao().findConversationById(message.conversationId) conversation?.expireIn?.let { e -> if (e > 0) { - expiredMessageDao.insert( + expiredMessageDao().insert( ExpiredMessage( message.messageId, e, @@ -94,7 +94,7 @@ class SendAttachmentMessageJob( throwable: Throwable?, ) { super.onCancel(cancelReason, throwable) - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) removeJob() @@ -122,12 +122,12 @@ class SendAttachmentMessageJob( }.subscribe( { if (it) { - messageDao.updateMediaStatus(MediaStatus.DONE.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.DONE.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) removeJob() } else { - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) removeJob() @@ -136,7 +136,7 @@ class SendAttachmentMessageJob( { Timber.e("upload attachment error, ${it.getStackTraceString()}") reportException(it) - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) removeJob() @@ -206,7 +206,7 @@ class SendAttachmentMessageJob( toast(R.string.Upload_timeout) } } - messageDao.updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.CANCELED.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) attachmentProcess.remove(message.messageId) removeJob() @@ -251,7 +251,7 @@ class SendAttachmentMessageJob( val plainText = GsonHelper.customGson.toJson(transferMediaData) val encoded = plainText.base64Encode() message.content = encoded - messageDao.updateAttachmentMessage( + messageDao().updateAttachmentMessage( messageId = message.messageId, content = GsonHelper.customGson.toJson(AttachmentExtra(attachmentId = attachmentId, messageId = message.messageId, createdAt = attachResponse.created_at)), mediaMimeType = mimeType, diff --git a/app/src/main/java/one/mixin/android/job/SendGiphyJob.kt b/app/src/main/java/one/mixin/android/job/SendGiphyJob.kt index 601853c1bc..c7851f5254 100644 --- a/app/src/main/java/one/mixin/android/job/SendGiphyJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendGiphyJob.kt @@ -57,8 +57,8 @@ class SendGiphyJob( MediaStatus.PENDING, MessageStatus.SENDING.name, ) - messageDao.insert(message) - conversationDao.updateLastMessageId(message.messageId, message.createdAt, message.conversationId) + messageDao().insert(message) + conversationDao().updateLastMessageId(message.messageId, message.createdAt, message.conversationId) MessageFlow.insert(message.conversationId, message.messageId) } @@ -103,7 +103,7 @@ class SendGiphyJob( MediaStatus.PENDING, MessageStatus.SENDING.name, ) - messageDao.updateGiphyMessage(messageId, file.name, mediaSize, thumbnail) + messageDao().updateGiphyMessage(messageId, file.name, mediaSize, thumbnail) MessageFlow.update(message.conversationId, message.messageId) jobManager.addJobInBackground(SendAttachmentMessageJob(message)) } diff --git a/app/src/main/java/one/mixin/android/job/SendMessageJob.kt b/app/src/main/java/one/mixin/android/job/SendMessageJob.kt index 0722bd2150..7ceac5821a 100644 --- a/app/src/main/java/one/mixin/android/job/SendMessageJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendMessageJob.kt @@ -80,7 +80,7 @@ open class SendMessageJob( if (alreadyExistMessage) { return } - val conversation = conversationDao.findConversationById(message.conversationId) + val conversation = conversationDao().findConversationById(message.conversationId) if (conversation != null) { if (message.isRecall()) { recallMessage(message.conversationId) @@ -89,20 +89,20 @@ open class SendMessageJob( message.content?.let { content -> content.findLastUrl()?.let { message.hyperlink = it - parseHyperlink(it, hyperlinkDao) + parseHyperlink(it, hyperlinkDao()) } - parseMentionData(content, message.messageId, message.conversationId, userDao, messageMentionDao, message.userId) + parseMentionData(content, message.messageId, message.conversationId, userDao(), messageMentionDao(), message.userId) } } if (!message.isTranscript()) { - database.insertMessage(message) + database().insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) - ftsDatabase.insertOrReplaceMessageFts4(message) + ftsDatabase().insertOrReplaceMessageFts4(message) } conversation.expireIn?.let { e -> if (e > 0) { - expiredMessageDao.insert( + expiredMessageDao().insert( ExpiredMessage( message.messageId, e, @@ -119,15 +119,15 @@ open class SendMessageJob( private fun recallMessage(conversationId: String) { recallMessageId ?: return - messageDao.findMessageById(recallMessageId)?.let { msg -> + messageDao().findMessageById(recallMessageId)?.let { msg -> RxBus.publish(RecallEvent(msg.messageId)) - messageDao.recallFailedMessage(msg.messageId) - messageDao.recallMessage(msg.messageId) - messageDao.recallPinMessage(msg.messageId, msg.conversationId) - pinMessageDao.deleteByMessageId(msg.messageId) - messageMentionDao.deleteMessage(msg.messageId) - remoteMessageStatusDao.deleteByMessageId(recallMessageId) - remoteMessageStatusDao.updateConversationUnseen(msg.conversationId) + messageDao().recallFailedMessage(msg.messageId) + messageDao().recallMessage(msg.messageId) + messageDao().recallPinMessage(msg.messageId, msg.conversationId) + pinMessageDao().deleteByMessageId(msg.messageId) + messageMentionDao().deleteMessage(msg.messageId) + remoteMessageStatusDao().deleteByMessageId(recallMessageId) + remoteMessageStatusDao().updateConversationUnseen(msg.conversationId) msg.mediaUrl?.getFilePath()?.let { File(it).let { file -> if (file.exists() && file.isFile) { @@ -136,24 +136,24 @@ open class SendMessageJob( } } - messageDao.findQuoteMessageItemById(message.conversationId, msg.messageId)?.let { quoteMsg -> + messageDao().findQuoteMessageItemById(message.conversationId, msg.messageId)?.let { quoteMsg -> quoteMsg.thumbImage = if ((quoteMsg.thumbImage?.length ?: 0) > MAX_THUMB_IMAGE_LENGTH) { DEFAULT_THUMB_IMAGE } else { quoteMsg.thumbImage } - messageDao.updateQuoteContentByQuoteId( + messageDao().updateQuoteContentByQuoteId( message.conversationId, msg.messageId, GsonHelper.customGson.toJson(quoteMsg), ) } - MessageFlow.update(conversationId, messageDao.findQuoteMessageIdByQuoteId(conversationId, recallMessageId)) + MessageFlow.update(conversationId, messageDao().findQuoteMessageIdByQuoteId(conversationId, recallMessageId)) jobManager.cancelJobByMixinJobId(msg.messageId) } MessageFlow.update(conversationId, recallMessageId) - ftsDatabase.deleteByMessageId(recallMessageId) + ftsDatabase().deleteByMessageId(recallMessageId) } override fun onCancel( @@ -170,11 +170,11 @@ open class SendMessageJob( return } jobManager.saveJob(this) - val conversation = conversationDao.findConversationById(message.conversationId) + val conversation = conversationDao().findConversationById(message.conversationId) val expiredMessageCallback = fun(expireIn: Long?) { expireIn?.let { e -> // Update local expiration time after success if (expireIn > 0) { - expiredMessageDao.updateExpiredMessage( + expiredMessageDao().updateExpiredMessage( message.messageId, currentTimeSeconds() + e, ) @@ -256,13 +256,13 @@ open class SendMessageJob( // Workaround No session key, can't encrypt message, send PLAIN directly if (participantSessionKey?.publicKey == null) { message.category = message.category.replace("ENCRYPTED_", "PLAIN_") - messageDao.updateCategoryById(message.messageId, message.category) + messageDao().updateCategoryById(message.messageId, message.category) sendPlainMessage(conversation, callback) return } val extensionSessionKey = - Session.getExtensionSessionId().notNullWithElse({ participantSessionDao.getParticipantSessionKeyBySessionId(message.conversationId, accountId, it) }, null) + Session.getExtensionSessionId().notNullWithElse({ participantSessionDao().getParticipantSessionKeyBySessionId(message.conversationId, accountId, it) }, null) val keyPair = Session.getEd25519KeyPair() ?: return val plaintext = @@ -300,12 +300,12 @@ open class SendMessageJob( private fun getBotSessionKey(accountId: String): ParticipantSessionKey? = if (recipientId != null) { - participantSessionDao.getParticipantSessionKeyByUserId( + participantSessionDao().getParticipantSessionKeyByUserId( message.conversationId, recipientId!!, ) } else { - participantSessionDao.getParticipantSessionKeyWithoutSelf( + participantSessionDao().getParticipantSessionKeyWithoutSelf( message.conversationId, accountId, ) @@ -351,12 +351,12 @@ open class SendMessageJob( } private fun getMentionData(messageId: String): List? { - return messageMentionDao.getMentionData(messageId)?.run { + return messageMentionDao().getMentionData(messageId)?.run { GsonHelper.customGson.fromJson(this, Array::class.java).map { it.identityNumber }.toSet() }?.run { - userDao.findMultiUserIdsByIdentityNumbers(this) + userDao().findMultiUserIdsByIdentityNumbers(this) } } } diff --git a/app/src/main/java/one/mixin/android/job/SendProcessSignalKeyJob.kt b/app/src/main/java/one/mixin/android/job/SendProcessSignalKeyJob.kt index 71ad6caa15..e0b66488f2 100644 --- a/app/src/main/java/one/mixin/android/job/SendProcessSignalKeyJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendProcessSignalKeyJob.kt @@ -30,7 +30,7 @@ class SendProcessSignalKeyJob( } } else if (action == ProcessSignalKeyAction.REMOVE_PARTICIPANT) { Session.getAccountId()?.let { - database.clearParticipant(data.conversationId, participantId!!) + database().clearParticipant(data.conversationId, participantId!!) signalProtocol.clearSenderKey(data.conversationId, it) RxBus.publish(SenderKeyChange(data.conversationId)) } @@ -42,7 +42,7 @@ class SendProcessSignalKeyJob( ParticipantSession(data.conversationId, item.userId, item.sessionId, publicKey = item.publicKey) } if (!ps.isNullOrEmpty()) { - participantSessionDao.insertList(ps) + participantSessionDao().insertList(ps) } RxBus.publish(SenderKeyChange(data.conversationId, participantId)) } diff --git a/app/src/main/java/one/mixin/android/job/SendTranscriptAttachmentMessageJob.kt b/app/src/main/java/one/mixin/android/job/SendTranscriptAttachmentMessageJob.kt index 141c3a8733..8047de0cbb 100644 --- a/app/src/main/java/one/mixin/android/job/SendTranscriptAttachmentMessageJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendTranscriptAttachmentMessageJob.kt @@ -60,13 +60,13 @@ class SendTranscriptAttachmentMessageJob( } } removeJob() - transcriptMessageDao.updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) + transcriptMessageDao().updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) } override fun onRun() { if (transcriptMessage.isPlain() == encryptCategory.isPlain()) { if (transcriptMessage.mediaCreatedAt?.within24Hours() == true && transcriptMessage.isValidAttachment()) { - transcriptMessageDao.updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.DONE.name) + transcriptMessageDao().updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.DONE.name) sendMessage() return } @@ -82,9 +82,9 @@ class SendTranscriptAttachmentMessageJob( null } if (attachmentExtra != null && attachmentExtra.createdAt?.within24Hours() == true) { - val m = messageDao.findMessageById(transcriptMessage.messageId) + val m = messageDao().findMessageById(transcriptMessage.messageId) if (m != null && transcriptMessage.type == m.category && m.isValidAttachment()) { - transcriptMessageDao.updateTranscript( + transcriptMessageDao().updateTranscript( transcriptMessage.transcriptId, transcriptMessage.messageId, attachmentExtra.attachmentId, @@ -98,7 +98,7 @@ class SendTranscriptAttachmentMessageJob( } } } - transcriptMessageDao.updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.PENDING.name) + transcriptMessageDao().updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.PENDING.name) disposable = conversationApi.requestAttachment().map { val file = File(requireNotNull(Uri.parse(transcriptMessage.absolutePath()).path)) @@ -115,14 +115,14 @@ class SendTranscriptAttachmentMessageJob( removeJob() } else { removeJob() - transcriptMessageDao.updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) + transcriptMessageDao().updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) } }, { Timber.e("upload attachment error, ${it.getStackTraceString()}") reportException(it) removeJob() - transcriptMessageDao.updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) + transcriptMessageDao().updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) }, ) } @@ -189,7 +189,7 @@ class SendTranscriptAttachmentMessageJob( removeJob() return true } - transcriptMessageDao.updateTranscript( + transcriptMessageDao().updateTranscript( transcriptMessage.transcriptId, transcriptMessage.messageId, attachResponse.attachment_id, @@ -202,12 +202,12 @@ class SendTranscriptAttachmentMessageJob( } private fun sendMessage() { - if (transcriptMessageDao.hasUploadedAttachment(parentId ?: transcriptMessage.transcriptId) == 0) { - messageDao.findMessageById(parentId ?: transcriptMessage.transcriptId)?.let { msg -> + if (transcriptMessageDao().hasUploadedAttachment(parentId ?: transcriptMessage.transcriptId) == 0) { + messageDao().findMessageById(parentId ?: transcriptMessage.transcriptId)?.let { msg -> val transcripts = mutableSetOf() getTranscripts(parentId ?: transcriptMessage.transcriptId, transcripts) msg.content = GsonHelper.customGson.toJson(transcripts) - messageDao.updateMediaStatus(MediaStatus.DONE.name, parentId ?: transcriptMessage.transcriptId) + messageDao().updateMediaStatus(MediaStatus.DONE.name, parentId ?: transcriptMessage.transcriptId) MessageFlow.update(msg.conversationId, msg.messageId) jobManager.addJob(SendMessageJob(msg)) } @@ -218,7 +218,7 @@ class SendTranscriptAttachmentMessageJob( transcriptId: String, list: MutableSet, ) { - val transcripts = transcriptMessageDao.getTranscript(transcriptId) + val transcripts = transcriptMessageDao().getTranscript(transcriptId) list.addAll(transcripts) transcripts.asSequence().apply { forEach { t -> diff --git a/app/src/main/java/one/mixin/android/job/SendTranscriptJob.kt b/app/src/main/java/one/mixin/android/job/SendTranscriptJob.kt index 2fd385706e..300f1c6aca 100644 --- a/app/src/main/java/one/mixin/android/job/SendTranscriptJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendTranscriptJob.kt @@ -42,7 +42,7 @@ class SendTranscriptJob( if (chatWebSocket.connected) { jobManager.start() } - val conversation = conversationDao.findConversationById(message.conversationId) + val conversation = conversationDao().findConversationById(message.conversationId) if (conversation != null) { val stringBuffer = StringBuffer() transcriptMessages.filter { it.isText() || it.isPost() || it.isData() || it.isContact() }.forEach { transcript -> @@ -50,7 +50,7 @@ class SendTranscriptJob( transcript.mediaName } else { if (transcript.isContact()) { - transcript.sharedUserId?.let { userId -> userDao.findUser(userId) }?.fullName + transcript.sharedUserId?.let { userId -> userDao().findUser(userId) }?.fullName } else { transcript.content }?.joinWhiteSpace()?.let { @@ -58,8 +58,8 @@ class SendTranscriptJob( } } } - ftsDatabase.insertFts4(stringBuffer.toString(), message.conversationId, message.messageId, message.category, message.userId, message.createdAt) - database.insertMessage(message) + ftsDatabase().insertFts4(stringBuffer.toString(), message.conversationId, message.messageId, message.category, message.userId, message.createdAt) + database().insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) transcriptMessages.forEach { transcript -> if (transcript.isAttachment()) { @@ -87,7 +87,7 @@ class SendTranscriptJob( } } } - transcriptMessageDao.insertList(transcriptMessages) + transcriptMessageDao().insertList(transcriptMessages) } else { reportException(Throwable("Insert failed, no conversation exist")) } @@ -102,7 +102,7 @@ class SendTranscriptJob( if (transcripts.any { t -> t.isAttachment() }) { val mediaSize = transcripts.sumOf { t -> t.mediaSize ?: 0 } - messageDao.updateMediaSize(mediaSize, message.messageId) + messageDao().updateMediaSize(mediaSize, message.messageId) MessageFlow.update(message.conversationId, message.messageId) transcripts.filter { t -> t.isAttachment() @@ -116,7 +116,7 @@ class SendTranscriptJob( jobManager.addJob(SendTranscriptAttachmentMessageJob(t, encryptCategory, message.messageId)) } } else { - messageDao.updateMediaStatus(MediaStatus.DONE.name, message.messageId) + messageDao().updateMediaStatus(MediaStatus.DONE.name, message.messageId) MessageFlow.update(message.conversationId, message.messageId) message.mediaStatus = MediaStatus.DONE.name message.content = GsonHelper.customGson.toJson(transcripts) @@ -128,7 +128,7 @@ class SendTranscriptJob( transcriptId: String, list: MutableSet, ) { - val transcripts = transcriptMessageDao.getTranscript(transcriptId) + val transcripts = transcriptMessageDao().getTranscript(transcriptId) list.addAll(transcripts) transcripts.asSequence().filter { t -> t.isTranscript() }.forEach { transcriptMessage -> getTranscripts(transcriptMessage.messageId, list) diff --git a/app/src/main/java/one/mixin/android/job/StorageCleanJob.kt b/app/src/main/java/one/mixin/android/job/StorageCleanJob.kt index d56fb4af37..35f4825286 100644 --- a/app/src/main/java/one/mixin/android/job/StorageCleanJob.kt +++ b/app/src/main/java/one/mixin/android/job/StorageCleanJob.kt @@ -34,7 +34,7 @@ class StorageCleanJob : dir.listFiles()?.forEach { file -> if (file.isFile) { val name = file.name.getFileNameNoEx() - if (name.isUUID() && messageDao.exists(name) == null) { // message's media file + if (name.isUUID() && messageDao().exists(name) == null) { // message's media file size += file.length() file.delete() Timber.e("delete ${file.absolutePath} ${size.fileSize()}") diff --git a/app/src/main/java/one/mixin/android/job/SyncInscriptionCollectionJob.kt b/app/src/main/java/one/mixin/android/job/SyncInscriptionCollectionJob.kt index 21a7dce543..d6b41f77c8 100644 --- a/app/src/main/java/one/mixin/android/job/SyncInscriptionCollectionJob.kt +++ b/app/src/main/java/one/mixin/android/job/SyncInscriptionCollectionJob.kt @@ -21,7 +21,7 @@ class SyncInscriptionCollectionJob(val hash: String) : BaseJob( val collectionResponse = tokenService.getInscriptionCollection(collectionHash) if (collectionResponse.isSuccess) { val inscriptionCollection = collectionResponse.data ?: return - inscriptionCollectionDao.insert(inscriptionCollection) + inscriptionCollectionDao().insert(inscriptionCollection) } else { Timber.e(collectionResponse.errorDescription) } diff --git a/app/src/main/java/one/mixin/android/job/SyncInscriptionMessageJob.kt b/app/src/main/java/one/mixin/android/job/SyncInscriptionMessageJob.kt index 8bf35fc1d7..cd7c7ab0e1 100644 --- a/app/src/main/java/one/mixin/android/job/SyncInscriptionMessageJob.kt +++ b/app/src/main/java/one/mixin/android/job/SyncInscriptionMessageJob.kt @@ -21,30 +21,30 @@ class SyncInscriptionMessageJob(val conversationId: String, val messageId: Strin } private suspend fun syncInscription() { - val inscriptionHash = hash ?: snapshotId?.let { safeSnapshotDao.findHashBySnapshotId(snapshotId) } ?: return - var inscription = inscriptionDao.findInscriptionByHash(inscriptionHash) + val inscriptionHash = hash ?: snapshotId?.let { safeSnapshotDao().findHashBySnapshotId(snapshotId) } ?: return + var inscription = inscriptionDao().findInscriptionByHash(inscriptionHash) if (inscription == null) { val response = tokenService.getInscriptionItem(inscriptionHash) if (response.isSuccess) { inscription = response.data ?: return - inscriptionDao.insert(inscription) + inscriptionDao().insert(inscription) } else { Timber.e(response.errorDescription) } } inscription ?: return - var inscriptionCollection = inscriptionCollectionDao.findInscriptionCollectionByHash(inscription.collectionHash) + var inscriptionCollection = inscriptionCollectionDao().findInscriptionCollectionByHash(inscription.collectionHash) if (inscriptionCollection == null) { val collectionResponse = tokenService.getInscriptionCollection(inscription.collectionHash) if (collectionResponse.isSuccess) { inscriptionCollection = collectionResponse.data ?: return - inscriptionCollectionDao.insert(inscriptionCollection) + inscriptionCollectionDao().insert(inscriptionCollection) } else { Timber.e(collectionResponse.errorDescription) } } inscriptionCollection ?: return - messageDao.updateMessageContent( + messageDao().updateMessageContent( GsonHelper.customGson.toJson( SafeCollectible( inscriptionCollection.collectionHash, diff --git a/app/src/main/java/one/mixin/android/job/SyncInscriptionsJob.kt b/app/src/main/java/one/mixin/android/job/SyncInscriptionsJob.kt index bf890fd99e..17dfaf87ed 100644 --- a/app/src/main/java/one/mixin/android/job/SyncInscriptionsJob.kt +++ b/app/src/main/java/one/mixin/android/job/SyncInscriptionsJob.kt @@ -18,28 +18,28 @@ class SyncInscriptionsJob(val hash: List) : BaseJob( } private suspend fun syncInscriptions() { - val local = inscriptionDao.getExitsHash(hash) + val local = inscriptionDao().getExitsHash(hash) (hash - local.toSet()).forEach { val response = tokenService.getInscriptionItem(it) if (response.isSuccess) { val inscription = response.data ?: return@forEach - inscriptionDao.insert(inscription) + inscriptionDao().insert(inscription) syncInscriptionCollection(inscription.collectionHash) } else { Timber.e(response.errorDescription) } } - inscriptionDao.getInscriptionCollectionIds(hash).forEach { + inscriptionDao().getInscriptionCollectionIds(hash).forEach { syncInscriptionCollection(it) } } private suspend fun syncInscriptionCollection(collectionHash: String) { - if (inscriptionCollectionDao.exits(collectionHash) == null) { + if (inscriptionCollectionDao().exits(collectionHash) == null) { val collectionResponse = tokenService.getInscriptionCollection(collectionHash) if (collectionResponse.isSuccess) { val inscriptionCollection = collectionResponse.data ?: return - inscriptionCollectionDao.insert(inscriptionCollection) + inscriptionCollectionDao().insert(inscriptionCollection) } else { Timber.e(collectionResponse.errorDescription) } diff --git a/app/src/main/java/one/mixin/android/job/SyncOutputJob.kt b/app/src/main/java/one/mixin/android/job/SyncOutputJob.kt index 44ed57ea4a..2a599cb235 100644 --- a/app/src/main/java/one/mixin/android/job/SyncOutputJob.kt +++ b/app/src/main/java/one/mixin/android/job/SyncOutputJob.kt @@ -23,7 +23,7 @@ class SyncOutputJob() : BaseJob( } private tailrec suspend fun syncOutputs() { - val latestOutputSequence = outputDao.findLatestOutputSequence() + val latestOutputSequence = outputDao().findLatestOutputSequence() Timber.d("$TAG sync outputs latestOutputCreatedAt: $latestOutputSequence") val userId = requireNotNull(Session.getAccountId()) val members = buildHashMembers(listOf(userId)) @@ -34,7 +34,7 @@ class SyncOutputJob() : BaseJob( } val outputs = (requireNotNull(resp.data) { "outputs can not be null or empty at this step" }) if (outputs.isNotEmpty()) { - outputDao.insertUnspentOutputs(outputs) + outputDao().insertUnspentOutputs(outputs) outputs.mapNotNull { it.inscriptionHash }.apply { if (isNotEmpty()) { jobManager.addJobInBackground(SyncInscriptionsJob(this)) diff --git a/app/src/main/java/one/mixin/android/job/TranscriptAttachmentDownloadJob.kt b/app/src/main/java/one/mixin/android/job/TranscriptAttachmentDownloadJob.kt index dbb2f1dff5..cd94d3480e 100644 --- a/app/src/main/java/one/mixin/android/job/TranscriptAttachmentDownloadJob.kt +++ b/app/src/main/java/one/mixin/android/job/TranscriptAttachmentDownloadJob.kt @@ -62,7 +62,7 @@ class TranscriptAttachmentDownloadJob( } } removeJob() - transcriptMessageDao.updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) + transcriptMessageDao().updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) } override fun getRetryLimit(): Int { @@ -75,7 +75,7 @@ class TranscriptAttachmentDownloadJob( return } jobManager.saveJob(this) - transcriptMessageDao.updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.PENDING.name) + transcriptMessageDao().updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.PENDING.name) val attachmentId = try { GsonHelper.customGson.fromJson( @@ -94,10 +94,10 @@ class TranscriptAttachmentDownloadJob( processTranscript() } } else { - transcriptMessageDao.updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) + transcriptMessageDao().updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) } } else { - transcriptMessageDao.updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) + transcriptMessageDao().updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) Timber.e(TAG, "get attachment url failed") } removeJob() @@ -108,14 +108,14 @@ class TranscriptAttachmentDownloadJob( throwable: Throwable?, ) { super.onCancel(cancelReason, throwable) - transcriptMessageDao.updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) + transcriptMessageDao().updateMediaStatus(transcriptMessage.transcriptId, transcriptMessage.messageId, MediaStatus.CANCELED.name) removeJob() } private fun processTranscript() { - if (transcriptMessageDao.hasUploadedAttachment(transcriptMessage.transcriptId) == 0) { - messageDao.findMessageById(transcriptMessage.transcriptId)?.let { - messageDao.updateMediaStatus(MediaStatus.DONE.name, transcriptMessage.transcriptId) + if (transcriptMessageDao().hasUploadedAttachment(transcriptMessage.transcriptId) == 0) { + messageDao().findMessageById(transcriptMessage.transcriptId)?.let { + messageDao().updateMediaStatus(MediaStatus.DONE.name, transcriptMessage.transcriptId) MessageFlow.update(it.conversationId, it.messageId) } } @@ -211,7 +211,7 @@ class TranscriptAttachmentDownloadJob( } } imageFile.copyFromInputStream(attachmentCipherInputStream) - transcriptMessageDao.updateMedia( + transcriptMessageDao().updateMedia( imageFile.name, imageFile.length(), MediaStatus.DONE.name, @@ -234,7 +234,7 @@ class TranscriptAttachmentDownloadJob( extensionName.notNullWithElse({ ".$it" }, ""), ) dataFile.copyFromInputStream(attachmentCipherInputStream) - transcriptMessageDao.updateMedia( + transcriptMessageDao().updateMedia( dataFile.name, dataFile.length(), MediaStatus.DONE.name, @@ -260,7 +260,7 @@ class TranscriptAttachmentDownloadJob( ".$extensionName", ) videoFile.copyFromInputStream(attachmentCipherInputStream) - transcriptMessageDao.updateMedia( + transcriptMessageDao().updateMedia( videoFile.name, videoFile.length(), MediaStatus.DONE.name, @@ -279,7 +279,7 @@ class TranscriptAttachmentDownloadJob( MixinApplication.get() .getTranscriptFile(transcriptMessage.messageId, ".ogg") audioFile.copyFromInputStream(attachmentCipherInputStream) - transcriptMessageDao.updateMedia( + transcriptMessageDao().updateMedia( audioFile.name, audioFile.length(), MediaStatus.DONE.name, diff --git a/app/src/main/java/one/mixin/android/job/TranscriptAttachmentMigrationJob.kt b/app/src/main/java/one/mixin/android/job/TranscriptAttachmentMigrationJob.kt index a1aca794d1..a02c7fb9e1 100644 --- a/app/src/main/java/one/mixin/android/job/TranscriptAttachmentMigrationJob.kt +++ b/app/src/main/java/one/mixin/android/job/TranscriptAttachmentMigrationJob.kt @@ -46,10 +46,10 @@ class TranscriptAttachmentMigrationJob : BaseJob(Params(PRIORITY_LOWER).groupBy( Timber.d("Transcript attachment migration old not exists") } - if (propertyDao.findValueByKey(Constants.Account.Migration.PREF_MIGRATION_ATTACHMENT)?.toBoolean() != true) { + if (propertyDao().findValueByKey(Constants.Account.Migration.PREF_MIGRATION_ATTACHMENT)?.toBoolean() != true) { MixinApplication.appContext.getMediaPath(true)?.deleteRecursively() } - propertyDao.updateValueByKey(Constants.Account.Migration.PREF_MIGRATION_TRANSCRIPT_ATTACHMENT, false.toString()) + propertyDao().updateValueByKey(Constants.Account.Migration.PREF_MIGRATION_TRANSCRIPT_ATTACHMENT, false.toString()) Timber.d("Transcript attachment migration completed!!!") } } diff --git a/app/src/main/java/one/mixin/android/job/TranscriptAttachmentUpdateJob.kt b/app/src/main/java/one/mixin/android/job/TranscriptAttachmentUpdateJob.kt index 954f139579..3329e5e180 100644 --- a/app/src/main/java/one/mixin/android/job/TranscriptAttachmentUpdateJob.kt +++ b/app/src/main/java/one/mixin/android/job/TranscriptAttachmentUpdateJob.kt @@ -20,28 +20,28 @@ class TranscriptAttachmentUpdateJob : BaseJob(Params(PRIORITY_LOWER).groupBy(GRO override fun onRun() = runBlocking { - val lastId = propertyDao.findValueByKey(PREF_MIGRATION_TRANSCRIPT_ATTACHMENT_LAST)?.toLong() ?: return@runBlocking - val list = transcriptMessageDao.findAttachmentMigration(lastId, EACH) + val lastId = propertyDao().findValueByKey(PREF_MIGRATION_TRANSCRIPT_ATTACHMENT_LAST)?.toLong() ?: return@runBlocking + val list = transcriptMessageDao().findAttachmentMigration(lastId, EACH) list.forEach { attachment -> if (attachment.mediaUrl?.isFileUri() == true) { val file = attachment.mediaUrl.toUri().toFile() if (file.exists()) { Timber.d("Transcript attachment update ${attachment.mediaUrl}") - transcriptMessageDao.updateMediaUrl(file.name, attachment.messageId) + transcriptMessageDao().updateMediaUrl(file.name, attachment.messageId) } else { val newFile = File("${MixinApplication.get().getTranscriptDirPath()}${File.separator}${file.name}") if (newFile.exists()) { Timber.d("Transcript attachment update ${newFile.absoluteFile}") - transcriptMessageDao.updateMediaUrl(file.name, attachment.messageId) + transcriptMessageDao().updateMediaUrl(file.name, attachment.messageId) } } } } if (list.size < EACH) { Timber.d("Transcript attachment update completed!!!") - propertyDao.deletePropertyByKey(PREF_MIGRATION_TRANSCRIPT_ATTACHMENT_LAST) + propertyDao().deletePropertyByKey(PREF_MIGRATION_TRANSCRIPT_ATTACHMENT_LAST) } else { - propertyDao.updateValueByKey(PREF_MIGRATION_TRANSCRIPT_ATTACHMENT_LAST, list.last().rowid.toString()) + propertyDao().updateValueByKey(PREF_MIGRATION_TRANSCRIPT_ATTACHMENT_LAST, list.last().rowid.toString()) jobManager.addJobInBackground(TranscriptAttachmentUpdateJob()) } } diff --git a/app/src/main/java/one/mixin/android/job/TranscriptDeleteJob.kt b/app/src/main/java/one/mixin/android/job/TranscriptDeleteJob.kt index ec8509053c..1a5b444690 100644 --- a/app/src/main/java/one/mixin/android/job/TranscriptDeleteJob.kt +++ b/app/src/main/java/one/mixin/android/job/TranscriptDeleteJob.kt @@ -20,13 +20,13 @@ class TranscriptDeleteJob(private val messageIds: List) : BaseJob(Params } override fun onRun() { - val cIds = messageDao.findConversationsByMessages(messageIds) + val cIds = messageDao().findConversationsByMessages(messageIds) messageIds.forEach { messageId -> - database.deleteMessageById(messageId) - ftsDatabase.deleteByMessageId(messageId) - transcriptMessageDao.getTranscript(messageId).forEach { transcriptMessage -> + database().deleteMessageById(messageId) + ftsDatabase().deleteByMessageId(messageId) + transcriptMessageDao().getTranscript(messageId).forEach { transcriptMessage -> if (transcriptMessage.isAttachment()) { - transcriptMessageDao.delete(transcriptMessage) + transcriptMessageDao().delete(transcriptMessage) transcriptMessage.absolutePath()?.let { url -> deleteAttachment(transcriptMessage.messageId, url) } @@ -36,8 +36,8 @@ class TranscriptDeleteJob(private val messageIds: List) : BaseJob(Params } } cIds.forEach { id -> - conversationDao.refreshLastMessageId(id) - conversationExtDao.refreshCountByConversationId(id) + conversationDao().refreshLastMessageId(id) + conversationExtDao().refreshCountByConversationId(id) MessageFlow.delete(id, messageIds) } } @@ -46,7 +46,7 @@ class TranscriptDeleteJob(private val messageIds: List) : BaseJob(Params messageId: String, mediaUrl: String, ) { - val count = transcriptMessageDao.countTranscriptByMessageId(messageId) + val count = transcriptMessageDao().countTranscriptByMessageId(messageId) if (count <= 1) { File(Uri.parse(mediaUrl).path!!).apply { if (exists()) { @@ -57,7 +57,7 @@ class TranscriptDeleteJob(private val messageIds: List) : BaseJob(Params } private fun deleteTranscript(transcriptMessage: TranscriptMessage) { - val list = transcriptMessageDao.getTranscript(transcriptMessage.messageId) + val list = transcriptMessageDao().getTranscript(transcriptMessage.messageId) if (list.isEmpty()) { return } else { @@ -65,7 +65,7 @@ class TranscriptDeleteJob(private val messageIds: List) : BaseJob(Params if (t.isTranscript()) { deleteTranscript(t) } else { - val count = transcriptMessageDao.countTranscriptByMessageId(t.messageId) + val count = transcriptMessageDao().countTranscriptByMessageId(t.messageId) if (count > 1) { return@forEach } else { @@ -74,7 +74,7 @@ class TranscriptDeleteJob(private val messageIds: List) : BaseJob(Params deleteAttachment(transcriptMessage.messageId, url) } } - transcriptMessageDao.delete(t) + transcriptMessageDao().delete(t) } } } diff --git a/app/src/main/java/one/mixin/android/job/UpdateFavoriteJob.kt b/app/src/main/java/one/mixin/android/job/UpdateFavoriteJob.kt index 1f631c4f91..a6fc9ac691 100644 --- a/app/src/main/java/one/mixin/android/job/UpdateFavoriteJob.kt +++ b/app/src/main/java/one/mixin/android/job/UpdateFavoriteJob.kt @@ -29,7 +29,7 @@ class UpdateFavoriteJob(private val symbol: String, private val coinId: String, defaultErrorHandle = {}, defaultExceptionHandle = {}, successBlock = { _ -> - marketFavoredDao.insert( + marketFavoredDao().insert( MarketFavored( coinId = coinId, isFavored = false, @@ -47,7 +47,7 @@ class UpdateFavoriteJob(private val symbol: String, private val coinId: String, defaultErrorHandle = {}, defaultExceptionHandle = {}, successBlock = { _ -> - marketFavoredDao.insert( + marketFavoredDao().insert( MarketFavored( coinId = coinId, isFavored = true, diff --git a/app/src/main/java/one/mixin/android/job/UpdateRelationshipJob.kt b/app/src/main/java/one/mixin/android/job/UpdateRelationshipJob.kt index aca6c43749..bebfd2b354 100644 --- a/app/src/main/java/one/mixin/android/job/UpdateRelationshipJob.kt +++ b/app/src/main/java/one/mixin/android/job/UpdateRelationshipJob.kt @@ -33,13 +33,13 @@ class UpdateRelationshipJob( } when { RelationshipAction.valueOf(request.action) == ADD -> - userDao.updateUserRelationship(request.user_id, UserRelationship.FRIEND.name) + userDao().updateUserRelationship(request.user_id, UserRelationship.FRIEND.name) RelationshipAction.valueOf(request.action) == REMOVE -> - userDao.updateUserRelationship(request.user_id, UserRelationship.STRANGER.name) + userDao().updateUserRelationship(request.user_id, UserRelationship.STRANGER.name) RelationshipAction.valueOf(request.action) == BLOCK -> - userDao.updateUserRelationship(request.user_id, UserRelationship.BLOCKING.name) + userDao().updateUserRelationship(request.user_id, UserRelationship.BLOCKING.name) RelationshipAction.valueOf(request.action) == UNBLOCK -> - userDao.updateUserRelationship(request.user_id, UserRelationship.STRANGER.name) + userDao().updateUserRelationship(request.user_id, UserRelationship.STRANGER.name) } } @@ -75,8 +75,8 @@ class UpdateRelationshipJob( private fun updateUser(u: User) { if (u.app != null) { u.appId = u.app!!.appId - appDao.insert(u.app!!) + appDao().insert(u.app!!) } - userDao.upsert(u) + userDao().upsert(u) } } diff --git a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt index 3996c94c15..190b608923 100644 --- a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt +++ b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt @@ -191,7 +191,6 @@ class MainActivity : BlazeBaseActivity() { @Inject lateinit var jobManager: MixinJobManager - @Inject lateinit var tip: Tip From 707b45fabf98fa89ccbe0ee6704d8e9d6b0cbeb1 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Thu, 28 Nov 2024 13:08:33 +0800 Subject: [PATCH 07/42] Injector --- .../mixin/android/job/BlazeMessageService.kt | 95 ++++---- .../mixin/android/job/DecryptCallMessage.kt | 10 +- .../one/mixin/android/job/DecryptMessage.kt | 216 +++++++++--------- .../java/one/mixin/android/job/Injector.kt | 72 +++--- .../android/job/NotificationGenerator.kt | 6 +- 5 files changed, 193 insertions(+), 206 deletions(-) diff --git a/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt b/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt index 797a6d93a1..d6a6f794a9 100644 --- a/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt +++ b/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt @@ -39,12 +39,12 @@ import one.mixin.android.RxBus import one.mixin.android.api.service.CircleService import one.mixin.android.api.service.ConversationService import one.mixin.android.api.service.MessageService +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.ExpiredMessageDao import one.mixin.android.db.JobDao import one.mixin.android.db.MessageDao import one.mixin.android.db.MixinDatabase import one.mixin.android.db.ParticipantDao -import one.mixin.android.db.RemoteMessageStatusDao import one.mixin.android.db.TranscriptMessageDao import one.mixin.android.db.deleteMessageById import one.mixin.android.db.flow.MessageFlow @@ -123,35 +123,11 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C lateinit var networkUtil: JobNetworkUtil @Inject - lateinit var database: MixinDatabase - - @Inject - lateinit var ftsDatabase: FtsDatabase - - @Inject - lateinit var pendingDatabase: PendingDatabase + lateinit var databaseProvider: DatabaseProvider @Inject lateinit var webSocket: ChatWebSocket - @Inject - lateinit var messageDao: MessageDao - - @Inject - lateinit var transcriptMessageDao: TranscriptMessageDao - - @Inject - lateinit var remoteMessageStatusDao: RemoteMessageStatusDao - - @Inject - lateinit var expiredMessageDao: ExpiredMessageDao - - @Inject - lateinit var participantDao: ParticipantDao - - @Inject - lateinit var jobDao: JobDao - @Inject lateinit var jobManager: MixinJobManager @@ -167,6 +143,17 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C @Inject lateinit var circleService: CircleService + fun database(): MixinDatabase = databaseProvider.getMixinDatabase() + fun pendingDatabase(): PendingDatabase = databaseProvider.getPendingDatabase() + fun ftsDatabase(): FtsDatabase = databaseProvider.getFtsDatabase() + + fun transcriptMessageDao(): TranscriptMessageDao = database().transcriptDao() + fun messageDao(): MessageDao = database().messageDao() + fun expiredMessageDao(): ExpiredMessageDao = database().expiredMessageDao() + fun participantDao(): ParticipantDao = database().participantDao() + fun jobDao(): JobDao = pendingDatabase().jobDao() + fun remoteMessageStatusDao() = database().remoteMessageStatusDao() + private val accountId = Session.getAccountId() private val gson = GsonHelper.customGson @@ -177,7 +164,7 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C private val destroyScope = scope(Lifecycle.Event.ON_DESTROY) private val hedwig: Hedwig by lazy { - HedwigImp(database, pendingDatabase, conversationService, circleService, jobManager, callState, lifecycleScope) + HedwigImp(database(), pendingDatabase(), conversationService, circleService, jobManager, callState, lifecycleScope) } override fun onBind(intent: Intent): IBinder? { @@ -204,14 +191,14 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C val expiredIn = event.expireIn if (expiredIn != null) { val currentTime = currentTimeSeconds() - if (expiredMessageDao.markRead(event.messageId, currentTime) > 0) { + if (expiredMessageDao().markRead(event.messageId, currentTime) > 0) { lifecycleScope.launch { withContext(Dispatchers.IO) { startExpiredJob(currentTime + expiredIn) } } } else { - expiredMessageDao.getExpiredMessageById(event.messageId)?.expireAt?.let { expiredAt -> + expiredMessageDao().getExpiredMessageById(event.messageId)?.expireAt?.let { expiredAt -> startExpiredJob(expiredAt) } } @@ -341,11 +328,11 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C } private fun startObserveAck() { - pendingDatabase.addObserver(ackObserver) + pendingDatabase().addObserver(ackObserver) } private fun stopObserveAck() { - pendingDatabase.removeObserver(ackObserver) + pendingDatabase().removeObserver(ackObserver) } private var ackJob: Job? = null @@ -379,11 +366,11 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C private var lastAckPendingCount = 0 private tailrec suspend fun processAck(): Boolean { - val ackMessages = jobDao.findAckJobs() + val ackMessages = jobDao().findAckJobs() if (ackMessages.isEmpty()) { return false } else if (ackMessages.size == 100) { - jobDao.getJobsCount().apply { + jobDao().getJobsCount().apply { if (this >= 10000 && this - lastAckPendingCount >= 10000) { lastAckPendingCount = this reportException("ack job count: $this", Exception()) @@ -399,7 +386,7 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C ) }, ) - jobDao.deleteList(ackMessages) + jobDao().deleteList(ackMessages) } catch (e: Exception) { Timber.e(e, "Send ack exception") } @@ -408,7 +395,7 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C } private suspend fun syncMessageStatusToExtension(sessionId: String) { - val jobs = jobDao.findCreateMessageJobs() + val jobs = jobDao().findCreateMessageJobs() if (jobs.isEmpty() || accountId == null) { return } @@ -421,18 +408,18 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C ), ) val encoded = plainText.toByteArray().base64Encode() - val bm = createParamBlazeMessage(createPlainJsonParam(participantDao.joinedConversationId(accountId) ?: generateConversationId(accountId, TEAM_MIXIN_USER_ID), accountId, encoded, sessionId)) + val bm = createParamBlazeMessage(createPlainJsonParam(participantDao().joinedConversationId(accountId) ?: generateConversationId(accountId, TEAM_MIXIN_USER_ID), accountId, encoded, sessionId)) jobManager.addJobInBackground(SendPlaintextJob(bm, PRIORITY_ACK_MESSAGE)) - jobDao.deleteList(jobs) + jobDao().deleteList(jobs) } } private fun startObserveStatus() { - database.invalidationTracker.addObserver(statusObserver) + database().invalidationTracker.addObserver(statusObserver) } private fun stopObserveStatus() { - database.invalidationTracker.removeObserver(statusObserver) + database().invalidationTracker.removeObserver(statusObserver) } private var statusJob: Job? = null @@ -444,11 +431,11 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C } private fun startObserveExpired() { - database.invalidationTracker.addObserver(expiredObserver) + database().invalidationTracker.addObserver(expiredObserver) } private fun stopObserveExpired() { - database.invalidationTracker.removeObserver(expiredObserver) + database().invalidationTracker.removeObserver(expiredObserver) } private var expiredJob: Job? = null @@ -477,7 +464,7 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C } private tailrec fun processStatus(): Boolean { - val list = remoteMessageStatusDao.findRemoteMessageStatus() + val list = remoteMessageStatusDao().findRemoteMessageStatus() if (list.isEmpty()) { return false } @@ -487,17 +474,17 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C BlazeAckMessage(msg.messageId, MessageStatus.READ.name), ) }.apply { - pendingDatabase.insertJobs(this) + pendingDatabase().insertJobs(this) } Session.getExtensionSessionId()?.let { _ -> val conversationId = list.first().conversationId list.map { msg -> createAckJob(CREATE_MESSAGE, BlazeAckMessage(msg.messageId, MessageStatus.READ.name, msg.expireAt), conversationId) }.let { jobs -> - pendingDatabase.insertJobs(jobs) + pendingDatabase().insertJobs(jobs) } } - remoteMessageStatusDao.deleteByMessageIds(list.map { it.messageId }) + remoteMessageStatusDao().deleteByMessageIds(list.map { it.messageId }) return if (list.size >= MARK_REMOTE_LIMIT) { statusJob?.ensureActive() processStatus() @@ -536,9 +523,9 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C private tailrec suspend fun processExpiredMessage() { val messages = - expiredMessageDao.getExpiredMessages(currentTimeSeconds(), DB_EXPIRED_LIMIT) + expiredMessageDao().getExpiredMessages(currentTimeSeconds(), DB_EXPIRED_LIMIT) if (messages.isEmpty()) { - val firstExpiredMessage = expiredMessageDao.getFirstExpiredMessage() + val firstExpiredMessage = expiredMessageDao().getFirstExpiredMessage() if (firstExpiredMessage == null) { nextExpirationTime = null } else { @@ -555,9 +542,9 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C } } else { val ids = messages.map { it.messageId } - val cIds = messageDao.findConversationsByMessages(ids) + val cIds = messageDao().findConversationsByMessages(ids) ids.forEach { messageId -> - val messageMedia = pendingDatabase.findMessageMediaById(messageId) ?: messageDao.findMessageMediaById(messageId) + val messageMedia = pendingDatabase().findMessageMediaById(messageId) ?: messageDao().findMessageMediaById(messageId) Timber.e("Expired job: delete messages ${messageMedia?.type} - ${messageMedia?.messageId}") messageMedia?.absolutePath( MixinApplication.appContext, @@ -569,15 +556,15 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C if (messageMedia?.isTranscript() == true) { jobManager.addJobInBackground(TranscriptDeleteJob(listOf(messageId))) } - pendingDatabase.deletePendingMessageById(messageId) - database.deleteMessageById(messageId) - ftsDatabase.deleteByMessageId(messageId) + pendingDatabase().deletePendingMessageById(messageId) + database().deleteMessageById(messageId) + ftsDatabase().deleteByMessageId(messageId) MessageFlow.delete(ANY_ID, messageId) } cIds.forEach { id -> - conversationDao.refreshLastMessageId(id) - conversationExtDao.refreshCountByConversationId(id) + conversationDao().refreshLastMessageId(id) + conversationExtDao().refreshCountByConversationId(id) } nextExpirationTime = null expiredJob?.ensureActive() diff --git a/app/src/main/java/one/mixin/android/job/DecryptCallMessage.kt b/app/src/main/java/one/mixin/android/job/DecryptCallMessage.kt index 9e937b363e..980efc6462 100644 --- a/app/src/main/java/one/mixin/android/job/DecryptCallMessage.kt +++ b/app/src/main/java/one/mixin/android/job/DecryptCallMessage.kt @@ -385,14 +385,14 @@ class DecryptCallMessage( private fun notifyServer(data: BlazeMessageData) { updateRemoteMessageStatus(data.messageId, MessageStatus.READ) - messageHistoryDao.insert(MessageHistory(data.messageId)) + messageHistoryDao().insert(MessageHistory(data.messageId)) } private fun updateRemoteMessageStatus( messageId: String, status: MessageStatus = MessageStatus.DELIVERED, ) { - jobDao.insertNoReplace(createAckJob(ACKNOWLEDGE_MESSAGE_RECEIPTS, BlazeAckMessage(messageId, status.name))) + jobDao().insertNoReplace(createAckJob(ACKNOWLEDGE_MESSAGE_RECEIPTS, BlazeAckMessage(messageId, status.name))) } private fun saveCallMessage( @@ -427,11 +427,11 @@ class DecryptCallMessage( } private fun insertCallMessage(message: Message) { - database.insertAndNotifyConversation(message) - database.conversationDao().findConversationById(message.conversationId)?.let { + database().insertAndNotifyConversation(message) + database().conversationDao().findConversationById(message.conversationId)?.let { val expiredIn = it.expireIn ?: return@let if (it.expireIn > 0) { - database.expiredMessageDao().insert(ExpiredMessage(message.messageId, expiredIn, null)) + database().expiredMessageDao().insert(ExpiredMessage(message.messageId, expiredIn, null)) } } } diff --git a/app/src/main/java/one/mixin/android/job/DecryptMessage.kt b/app/src/main/java/one/mixin/android/job/DecryptMessage.kt index ac00222788..2350c70c44 100644 --- a/app/src/main/java/one/mixin/android/job/DecryptMessage.kt +++ b/app/src/main/java/one/mixin/android/job/DecryptMessage.kt @@ -175,7 +175,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { } override fun isExistMessage(messageId: String): Boolean { - return pendingMessagesDao.findMessageIdById(messageId) != null || super.isExistMessage(messageId) + return pendingMessagesDao().findMessageIdById(messageId) != null || super.isExistMessage(messageId) } private fun processMessage(data: BlazeMessageData) { @@ -231,9 +231,9 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { if (data.conversationId == SYSTEM_USER || data.conversationId == accountId || data.userId == SYSTEM_USER) { return } - val p = participantSessionDao.getParticipantSession(data.conversationId, data.userId, data.sessionId) + val p = participantSessionDao().getParticipantSession(data.conversationId, data.userId, data.sessionId) if (p == null) { - participantSessionDao.insert(ParticipantSession(data.conversationId, data.userId, data.sessionId)) + participantSessionDao().insert(ParticipantSession(data.conversationId, data.userId, data.sessionId)) } } @@ -275,7 +275,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { val appCardData = gson.fromJson(message.content, AppCardData::class.java) appCardData.appId?.let { id -> runBlocking { - var app = appDao.findAppById(id) + var app = appDao().findAppById(id) if (app?.updatedAt != appCardData.updatedAt) { app = handleMixinResponse( @@ -286,7 +286,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { defaultExceptionHandle = {}, successBlock = { it.data?.let { u -> - userDao.insertUpdate(u, appDao) + userDao().insertUpdate(u, appDao()) u.app?.let { app -> replaceApp(app) } return@handleMixinResponse u.app } @@ -299,7 +299,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { } } insertMessage(message, data) - ftsDatabase.insertOrReplaceMessageFts4(message) + ftsDatabase().insertOrReplaceMessageFts4(message) updateRemoteMessageStatus(data.messageId, MessageStatus.DELIVERED) generateNotification(message, data) } @@ -359,8 +359,8 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { UUID.randomUUID().toString() } if (message != null) { - pinMessageDao.insert(PinMessage(messageId, message.conversationId, data.createdAt)) - database.insertMessage( + pinMessageDao().insert(PinMessage(messageId, message.conversationId, data.createdAt)) + database().insertMessage( createPinMessage( mid, data.conversationId, @@ -383,8 +383,8 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { // Notify pin message MessageFlow.update(message.conversationId, message.messageId) if (message.category.endsWith("_TEXT")) { - messageMentionDao.findMessageMentionById(message.messageId)?.let { mention -> - messageMentionDao.insert( + messageMentionDao().findMessageMentionById(message.messageId)?.let { mention -> + messageMentionDao().insert( MessageMention( mid, message.conversationId, @@ -406,18 +406,18 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { MessageStatus.READ.name, ) // Locally generated messages are inserted directly - pendingMessagesDao.insert(PendingMessage(m)) + pendingMessagesDao().insert(PendingMessage(m)) } if (index == transferPinData.messageIds.size - 1) { RxBus.publish(PinMessageEvent(data.conversationId, messageId)) } } } else if (transferPinData.action == PinAction.UNPIN.name) { - pinMessageDao.deleteByIds(transferPinData.messageIds) + pinMessageDao().deleteByIds(transferPinData.messageIds) MessageFlow.update(data.conversationId, transferPinData.messageIds) } updateRemoteMessageStatus(data.messageId, MessageStatus.READ) - messageHistoryDao.insert(MessageHistory(data.messageId)) + messageHistoryDao().insert(MessageHistory(data.messageId)) } } @@ -426,17 +426,17 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { val decoded = Base64.decode(data.data) val transferRecallData = gson.fromJson(String(decoded), RecallMessagePayload::class.java) // If the message is still in the cache but is called, insert the message table in advance - pendingMessagesDao.findMessageById(transferRecallData.messageId)?.let { - messageDao.insert(it) + pendingMessagesDao().findMessageById(transferRecallData.messageId)?.let { + messageDao().insert(it) } - messageDao.findMessageById(transferRecallData.messageId)?.let { msg -> + messageDao().findMessageById(transferRecallData.messageId)?.let { msg -> RxBus.publish(RecallEvent(msg.messageId)) - messageDao.recallFailedMessage(msg.messageId) - messageDao.recallMessage(msg.messageId) - ftsDatabase.deleteByMessageId(msg.messageId) - messageDao.recallPinMessage(msg.messageId, msg.conversationId) - pinMessageDao.deleteByMessageId(msg.messageId) - messageMentionDao.deleteMessage(msg.messageId) + messageDao().recallFailedMessage(msg.messageId) + messageDao().recallMessage(msg.messageId) + ftsDatabase().deleteByMessageId(msg.messageId) + messageDao().recallPinMessage(msg.messageId, msg.conversationId) + pinMessageDao().deleteByMessageId(msg.messageId) + messageMentionDao().deleteMessage(msg.messageId) if (msg.mediaUrl != null && mediaDownloaded(msg.mediaStatus)) { msg.mediaUrl.getFilePath()?.let { File(it).let { file -> @@ -446,29 +446,29 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { } } } - messageDao.findQuoteMessageItemById(data.conversationId, msg.messageId)?.let { quoteMsg -> + messageDao().findQuoteMessageItemById(data.conversationId, msg.messageId)?.let { quoteMsg -> quoteMsg.thumbImage = if ((quoteMsg.thumbImage?.length ?: 0) > Constants.MAX_THUMB_IMAGE_LENGTH) { Constants.DEFAULT_THUMB_IMAGE } else { quoteMsg.thumbImage } - messageDao.updateQuoteContentByQuoteId(data.conversationId, msg.messageId, gson.toJson(quoteMsg)) + messageDao().updateQuoteContentByQuoteId(data.conversationId, msg.messageId, gson.toJson(quoteMsg)) } jobManager.cancelJobByMixinJobId(msg.messageId) - if (messageDao.findLastMessageId(msg.conversationId) == msg.messageId) { + if (messageDao().findLastMessageId(msg.conversationId) == msg.messageId) { notificationManager.cancel(msg.conversationId.hashCode()) } MessageFlow.update(msg.conversationId, msg.messageId) - conversationDao.updateLastMessageId( + conversationDao().updateLastMessageId( msg.messageId, msg.createdAt, msg.conversationId, ) } updateRemoteMessageStatus(data.messageId, MessageStatus.READ) - messageHistoryDao.insert(MessageHistory(data.messageId)) + messageHistoryDao().insert(MessageHistory(data.messageId)) } } @@ -504,19 +504,19 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { if (m.status == MessageStatus.READ.name) { updateExpiredMessageList.add(Pair(m.messageId, m.expireAt)) } else if (m.status == MessageMentionStatus.MENTION_READ.name) { - messageMentionDao.markMentionRead(m.messageId) + messageMentionDao().markMentionRead(m.messageId) } } if (updateExpiredMessageList.isNotEmpty()) { val updateMessageIds = updateExpiredMessageList.map { it.first } lifecycleScope.launch(PENDING_DB_THREAD) { - remoteMessageStatusDao.deleteByMessageIds(updateMessageIds) - pendingMessagesDao.markReadIds(updateMessageIds) + remoteMessageStatusDao().deleteByMessageIds(updateMessageIds) + pendingMessagesDao().markReadIds(updateMessageIds) // Data that does not enter the message table will not enter the remote status table, do not consider - val updateConversationList = messageDao.findConversationsByMessages(updateMessageIds) + val updateConversationList = messageDao().findConversationsByMessages(updateMessageIds) updateConversationList.forEach { cId -> - remoteMessageStatusDao.updateConversationUnseen(cId) + remoteMessageStatusDao().updateConversationUnseen(cId) MessageFlow.update(cId, updateMessageIds) notificationManager.cancel(cId.hashCode()) } @@ -530,13 +530,13 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { map[true]?.forEach { val messageId = it.first val expireAt = it.second!! - expiredMessageDao.updateExpiredMessage(messageId, expireAt) + expiredMessageDao().updateExpiredMessage(messageId, expireAt) RxBus.publish(ExpiredEvent(messageId, null, expireAt)) } map[false]?.map { it.first }?.let { - expiredMessageDao.getExpiredMessageByIds(it) + expiredMessageDao().getExpiredMessageByIds(it) }?.forEach { localExpiredMessage -> // The old version mark read - expiredMessageDao.markRead(localExpiredMessage.messageId, currentTimeSeconds()) + expiredMessageDao().markRead(localExpiredMessage.messageId, currentTimeSeconds()) RxBus.publish(ExpiredEvent(localExpiredMessage.messageId, null, currentTimeSeconds() + localExpiredMessage.expireIn)) } } @@ -545,7 +545,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { } updateRemoteMessageStatus(data.messageId, MessageStatus.READ) - messageHistoryDao.insert(MessageHistory(data.messageId)) + messageHistoryDao().insert(MessageHistory(data.messageId)) } else if (data.category == MessageCategory.PLAIN_TEXT.name || data.category == MessageCategory.PLAIN_IMAGE.name || data.category == MessageCategory.PLAIN_VIDEO.name || @@ -575,7 +575,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { plainData: PlainJsonMessagePayload, ) { val messages = plainData.messages ?: return - val p = participantDao.findParticipantById(data.conversationId, data.userId) ?: return + val p = participantDao().findParticipantById(data.conversationId, data.userId) ?: return for (id in messages) { val resendMessage = resendMessageDao.findResendMessage(data.userId, data.sessionId, id) if (resendMessage != null) { @@ -583,7 +583,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { } val accountId = accountId ?: return // The messages that need to be resent are local data and do not exist in the cache database - val needResendMessage = messageDao.findMessageById(id, accountId) + val needResendMessage = messageDao().findMessageById(id, accountId) if (needResendMessage == null || needResendMessage.category == MessageCategory.MESSAGE_RECALL.name) { resendMessageDao.insert(ResendSessionMessage(id, data.userId, data.sessionId, 0, nowInUtc())) continue @@ -625,10 +625,10 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { quoteMessageId: String, ): QuoteMessageItem? { // If the message is still in the cache but is quoted, insert the message table in advance - pendingMessagesDao.findMessageById(quoteMessageId)?.let { - messageDao.insert(it) + pendingMessagesDao().findMessageById(quoteMessageId)?.let { + messageDao().insert(it) } - val quoteMsg = messageDao.findQuoteMessageItemById(conversationId, quoteMessageId) ?: return null + val quoteMsg = messageDao().findQuoteMessageItemById(conversationId, quoteMessageId) ?: return null quoteMsg.thumbImage = if ((quoteMsg.thumbImage?.length ?: 0) > Constants.MAX_THUMB_IMAGE_LENGTH) { Constants.DEFAULT_THUMB_IMAGE @@ -662,13 +662,13 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { ).apply { this.content?.findLastUrl()?.let { this.hyperlink = it - parseHyperlink(it, hyperlinkDao) + parseHyperlink(it, hyperlinkDao()) } } } else { if (quoteMessageItem.userId == accountId && data.userId != accountId) { quoteMe = true - messageMentionDao.insert(MessageMention(data.messageId, data.conversationId, "", false)) + messageMentionDao().insert(MessageMention(data.messageId, data.conversationId, "", false)) } createReplyTextMessage( data.messageId, @@ -683,9 +683,9 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { ) } } - val (mentions, mentionMe) = parseMentionData(plain, data.messageId, data.conversationId, userDao, messageMentionDao, data.userId) + val (mentions, mentionMe) = parseMentionData(plain, data.messageId, data.conversationId, userDao(), messageMentionDao(), data.userId) insertMessage(message, data) - ftsDatabase.insertOrReplaceMessageFts4(message) + ftsDatabase().insertOrReplaceMessageFts4(message) val userMap = mentions?.associate { it.identityNumber to it.fullName } generateNotification(message, data, userMap, quoteMe || mentionMe) } @@ -703,7 +703,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { data.status, ) insertMessage(message, data) - ftsDatabase.insertOrReplaceMessageFts4(message) + ftsDatabase().insertOrReplaceMessageFts4(message) generateNotification(message, data) } data.category.endsWith("_LOCATION") -> { @@ -830,7 +830,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { ) } insertMessage(message, data) - ftsDatabase.insertOrReplaceMessageFts4(message) + ftsDatabase().insertOrReplaceMessageFts4(message) lifecycleScope.launch { MixinApplication.appContext.autoDownload(autoDownloadDocument) { jobManager.addJobInBackground(AttachmentDownloadJob(message)) @@ -877,7 +877,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { String(Base64.decode(plainText)) } val mediaData = gson.fromJson(decoded, StickerMessagePayload::class.java) - val sticker = stickerDao.getStickerByUnique(mediaData.stickerId) + val sticker = stickerDao().getStickerByUnique(mediaData.stickerId) if (sticker == null || sticker.albumId.isNullOrBlank()) { jobManager.addJobInBackground(RefreshStickerJob(mediaData.stickerId)) } @@ -923,7 +923,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { insertMessage(message, data) val fullName = user?.fullName if (!fullName.isNullOrBlank()) { - ftsDatabase.insertOrReplaceMessageFts4(message) + ftsDatabase().insertOrReplaceMessageFts4(message) } generateNotification(message, data) } @@ -983,10 +983,10 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { if (transcripts.isEmpty()) { data.expireIn?.let { expireIn -> if (expireIn > 0) { - expiredMessageDao.insert(ExpiredMessage(data.messageId, expireIn, null)) + expiredMessageDao().insert(ExpiredMessage(data.messageId, expireIn, null)) } } - database.insertMessage( + database().insertMessage( createTranscriptMessage( data.messageId, data.conversationId, @@ -1008,7 +1008,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { transcript.mediaName } else { if (transcript.isContact()) { - transcript.sharedUserId?.let { userId -> userDao.findUser(userId) }?.fullName + transcript.sharedUserId?.let { userId -> userDao().findUser(userId) }?.fullName } else { transcript.content }?.joinWhiteSpace()?.let { @@ -1016,11 +1016,11 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { } } } - ftsDatabase.insertFts4(stringBuilder.toString(), data.conversationId, data.messageId, data.category, data.userId, data.createdAt) + ftsDatabase().insertFts4(stringBuilder.toString(), data.conversationId, data.messageId, data.category, data.userId, data.createdAt) transcripts.filter { t -> t.isSticker() || t.isContact() }.forEach { transcript -> transcript.stickerId?.let { stickerId -> - val sticker = stickerDao.getStickerByUnique(stickerId) + val sticker = stickerDao().getStickerByUnique(stickerId) if (sticker == null) { jobManager.addJobInBackground(RefreshStickerJob(stickerId)) } @@ -1095,9 +1095,9 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { data.createdAt, data.status, ) - transcriptMessageDao.insertList( + transcriptMessageDao().insertList( transcripts.filter { t -> - transcriptMessageDao.getTranscriptByIdSync(t.transcriptId, t.messageId) == null + transcriptMessageDao().getTranscriptByIdSync(t.transcriptId, t.messageId) == null }, ) if (!transcripts.any { t -> t.isAttachment() }) { @@ -1113,7 +1113,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { if (systemSession.action == SystemSessionMessageAction.PROVISION.name) { Session.storeExtensionSessionId(systemSession.sessionId) signalProtocol.deleteSession(systemSession.userId) - val conversations = conversationDao.getConversationsByUserId(systemSession.userId) + val conversations = conversationDao().getConversationsByUserId(systemSession.userId) val ps = conversations.filter { it.appId == null || it.capabilities?.contains(AppCap.ENCRYPTED.name) == true @@ -1121,7 +1121,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { ParticipantSession(it.conversationId, systemSession.userId, systemSession.sessionId, publicKey = systemSession.publicKey) } if (ps.isNotEmpty()) { - participantSessionDao.insertList(ps) + participantSessionDao().insertList(ps) } RxBus.publish(SessionEvent(SystemSessionMessageAction.PROVISION)) } else if (systemSession.action == SystemSessionMessageAction.DESTROY.name) { @@ -1130,7 +1130,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { } Session.deleteExtensionSessionId() signalProtocol.deleteSession(systemSession.userId) - participantSessionDao.deleteByUserIdAndSessionId(systemSession.userId, systemSession.sessionId) + participantSessionDao().deleteByUserIdAndSessionId(systemSession.userId, systemSession.sessionId) RxBus.publish(SessionEvent(SystemSessionMessageAction.DESTROY)) } } @@ -1153,9 +1153,9 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { snapshot.snapshotId, ) snapshot.transactionHash?.let { - snapshotDao.deletePendingSnapshotByHash(it) + snapshotDao().deletePendingSnapshotByHash(it) } - snapshotDao.insert(snapshot) + snapshotDao().insert(snapshot) insertMessage(message, data) jobManager.addJobInBackground(RefreshAssetsJob(snapshot.assetId)) @@ -1182,10 +1182,10 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { snapshot.snapshotId, ) if (!snapshot.depositHash.isNullOrEmpty()) { - safeSnapshotDao.deletePendingSnapshotByHash(snapshot.depositHash) - safeSnapshotDao.insert(snapshot.copy(type = SafeSnapshotType.snapshot.name, deposit = SafeDeposit(snapshot.depositHash, ""))) + safeSnapshotDao().deletePendingSnapshotByHash(snapshot.depositHash) + safeSnapshotDao().insert(snapshot.copy(type = SafeSnapshotType.snapshot.name, deposit = SafeDeposit(snapshot.depositHash, ""))) } else { - safeSnapshotDao.insert(snapshot.copy(type = SafeSnapshotType.snapshot.name)) + safeSnapshotDao().insert(snapshot.copy(type = SafeSnapshotType.snapshot.name)) } insertMessage(message, data) @@ -1214,7 +1214,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { ) insertMessage(message, data) - safeSnapshotDao.insert(snapshot) + safeSnapshotDao().insert(snapshot) jobManager.addJobInBackground(SyncInscriptionMessageJob(data.conversationId, data.messageId, snapshot.inscriptionHash, snapshot.snapshotId)) jobManager.addJobInBackground(SyncOutputJob()) if (snapshot.amount.toFloat() > 0) { @@ -1230,8 +1230,8 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { if (systemMessage.userId != null) { userId = systemMessage.userId } - if (userId == SYSTEM_USER && userDao.findUser(userId) == null) { - userDao.insert(createSystemUser()) + if (userId == SYSTEM_USER && userDao().findUser(userId) == null) { + userDao().insert(createSystemUser()) } val content = if (systemMessage.action == SystemConversationAction.EXPIRE.name) { @@ -1254,7 +1254,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { val accountId = accountId ?: return if (systemMessage.action == SystemConversationAction.ADD.name || systemMessage.action == SystemConversationAction.JOIN.name) { - participantDao.insert(Participant(data.conversationId, systemMessage.participantId!!, "", data.updatedAt)) + participantDao().insert(Participant(data.conversationId, systemMessage.participantId!!, "", data.updatedAt)) if (systemMessage.participantId == accountId) { jobManager.addJobInBackground(RefreshConversationJob(data.conversationId)) } else { @@ -1267,7 +1267,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { } } else if (systemMessage.action == SystemConversationAction.REMOVE.name || systemMessage.action == SystemConversationAction.EXIT.name) { if (systemMessage.participantId == accountId) { - conversationDao.updateConversationStatusById(data.conversationId, ConversationStatus.QUIT.ordinal) + conversationDao().updateConversationStatusById(data.conversationId, ConversationStatus.QUIT.ordinal) } syncUser(systemMessage.participantId!!) jobManager.addJobInBackground(GenerateAvatarJob(data.conversationId)) @@ -1281,7 +1281,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { } return } else if (systemMessage.action == SystemConversationAction.ROLE.name) { - participantDao.updateParticipantRole(data.conversationId, systemMessage.participantId!!, systemMessage.role ?: "") + participantDao().updateParticipantRole(data.conversationId, systemMessage.participantId!!, systemMessage.role ?: "") if (message.participantId != accountId || systemMessage.role.isNullOrEmpty()) { return } @@ -1309,24 +1309,24 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { SystemCircleMessageAction.ADD.name -> { val accountId = accountId ?: return val conversationId = systemMessage.conversationId ?: generateConversationId(accountId, systemMessage.userId ?: return) - if (circleDao.findCircleById(systemMessage.circleId) == null) { + if (circleDao().findCircleById(systemMessage.circleId) == null) { jobManager.addJobInBackground(RefreshCircleJob(systemMessage.circleId)) } val circleConversation = CircleConversation(conversationId, systemMessage.circleId, systemMessage.userId, data.updatedAt, null) systemMessage.userId?.let { userId -> syncUser(userId) } - circleConversationDao.insertUpdate(circleConversation) + circleConversationDao().insertUpdate(circleConversation) } SystemCircleMessageAction.REMOVE.name -> { val accountId = accountId ?: return val conversationId = systemMessage.conversationId ?: generateConversationId(accountId, systemMessage.userId ?: return) - circleConversationDao.deleteByIds(conversationId, systemMessage.circleId) + circleConversationDao().deleteByIds(conversationId, systemMessage.circleId) } SystemCircleMessageAction.DELETE.name -> { runInTransaction { - circleDao.deleteCircleById(systemMessage.circleId) - circleConversationDao.deleteByCircleId(systemMessage.circleId) + circleDao().deleteCircleById(systemMessage.circleId) + circleConversationDao().deleteByCircleId(systemMessage.circleId) } RxBus.publish(CircleDeleteEvent(systemMessage.circleId)) if (systemMessage.circleId == MixinApplication.appContext.defaultSharedPreferences.getString(Constants.CIRCLE.CIRCLE_ID, null)) { @@ -1361,7 +1361,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { if (data.category == MessageCategory.SIGNAL_KEY.name) { updateRemoteMessageStatus(data.messageId, MessageStatus.READ) pendingMessageStatusLruCache.remove(data.messageId) - messageHistoryDao.insert(MessageHistory(data.messageId)) + messageHistoryDao().insert(MessageHistory(data.messageId)) } else { updateRemoteMessageStatus(data.messageId, MessageStatus.DELIVERED) } @@ -1384,7 +1384,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { if (resendMessageId != null) { processRedecryptMessage(data, resendMessageId, plaintext) updateRemoteMessageStatus(data.messageId, MessageStatus.READ) - messageHistoryDao.insert(MessageHistory(data.messageId)) + messageHistoryDao().insert(MessageHistory(data.messageId)) } else { try { processDecryptSuccess(data, plaintext) @@ -1442,7 +1442,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { private fun insertInvalidMessage(data: BlazeMessageData) { val message = createMessage(data.messageId, data.conversationId, data.userId, data.category, data.data, data.createdAt, MessageStatus.UNKNOWN.name) - database.insertMessage(message) + database().insertMessage(message) MessageFlow.insert(data.conversationId, data.messageId) } @@ -1490,18 +1490,18 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { plainText: String, ) { if (data.category == MessageCategory.SIGNAL_TEXT.name) { - parseMentionData(plainText, messageId, data.conversationId, userDao, messageMentionDao, data.userId) - pendingMessagesDao.updateMessageContentAndStatus(plainText, data.status, messageId) - messageDao.updateMessageContentAndStatus(plainText, data.status, messageId) + parseMentionData(plainText, messageId, data.conversationId, userDao(), messageMentionDao(), data.userId) + pendingMessagesDao().updateMessageContentAndStatus(plainText, data.status, messageId) + messageDao().updateMessageContentAndStatus(plainText, data.status, messageId) MessageFlow.update(data.conversationId, data.messageId) } else if (data.category == MessageCategory.SIGNAL_POST.name) { - messageDao.updateMessageContentAndStatus(plainText, data.status, messageId) - pendingMessagesDao.updateMessageContentAndStatus(plainText, data.status, messageId) + messageDao().updateMessageContentAndStatus(plainText, data.status, messageId) + pendingMessagesDao().updateMessageContentAndStatus(plainText, data.status, messageId) MessageFlow.update(data.conversationId, data.messageId) } else if (data.category == MessageCategory.SIGNAL_LOCATION.name) { if (checkLocationData(plainText)) { - messageDao.updateMessageContentAndStatus(plainText, data.status, messageId) - pendingMessagesDao.updateMessageContentAndStatus(plainText, data.status, messageId) + messageDao().updateMessageContentAndStatus(plainText, data.status, messageId) + pendingMessagesDao().updateMessageContentAndStatus(plainText, data.status, messageId) MessageFlow.update(data.conversationId, data.messageId) } } else if (data.category == MessageCategory.SIGNAL_IMAGE.name || @@ -1512,7 +1512,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { val decoded = Base64.decode(plainText) val mediaData = gson.fromJson(String(decoded), AttachmentMessagePayload::class.java) val duration = mediaData.duration?.toString() - pendingMessagesDao.updateAttachmentMessage( + pendingMessagesDao().updateAttachmentMessage( messageId, gson.toJson(AttachmentExtra(attachmentId = mediaData.attachmentId, messageId = data.messageId, shareable = mediaData.shareable)), mediaData.mimeType, @@ -1528,7 +1528,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { MediaStatus.CANCELED.name, data.status, ) - messageDao.updateAttachmentMessage( + messageDao().updateAttachmentMessage( messageId, gson.toJson(AttachmentExtra(attachmentId = mediaData.attachmentId, messageId = data.messageId, shareable = mediaData.shareable)), mediaData.mimeType, @@ -1546,7 +1546,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { ) MessageFlow.update(data.conversationId, data.messageId) if (data.category == MessageCategory.SIGNAL_IMAGE.name || data.category == MessageCategory.SIGNAL_AUDIO.name) { - val message = messageDao.findMessageById(messageId) + val message = messageDao().findMessageById(messageId) if (message != null) { jobManager.addJobInBackground(AttachmentDownloadJob(message)) } @@ -1554,41 +1554,41 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { } else if (data.category == MessageCategory.SIGNAL_STICKER.name) { val decoded = Base64.decode(plainText) val stickerData = gson.fromJson(String(decoded), StickerMessagePayload::class.java) - val sticker = stickerDao.getStickerByUnique(stickerData.stickerId) + val sticker = stickerDao().getStickerByUnique(stickerData.stickerId) if (sticker == null || sticker.albumId.isNullOrBlank()) { jobManager.addJobInBackground(RefreshStickerJob(stickerData.stickerId)) } - pendingMessagesDao.updateStickerMessage(stickerData.stickerId, data.status, messageId) - messageDao.updateStickerMessage(stickerData.stickerId, data.status, messageId) + pendingMessagesDao().updateStickerMessage(stickerData.stickerId, data.status, messageId) + messageDao().updateStickerMessage(stickerData.stickerId, data.status, messageId) MessageFlow.update(data.conversationId, data.messageId) } else if (data.category == MessageCategory.SIGNAL_CONTACT.name) { val decoded = Base64.decode(plainText) val contactData = gson.fromJson(String(decoded), ContactMessagePayload::class.java) - pendingMessagesDao.updateContactMessage(contactData.userId, data.status, messageId) - messageDao.updateContactMessage(contactData.userId, data.status, messageId) + pendingMessagesDao().updateContactMessage(contactData.userId, data.status, messageId) + messageDao().updateContactMessage(contactData.userId, data.status, messageId) syncUser(contactData.userId) MessageFlow.update(data.conversationId, data.messageId) } else if (data.category == MessageCategory.SIGNAL_LIVE.name) { val decoded = Base64.decode(plainText) val liveData = gson.fromJson(String(decoded), LiveMessagePayload::class.java) - pendingMessagesDao.updateLiveMessage(liveData.width, liveData.height, liveData.url, liveData.thumbUrl, data.status, messageId) - messageDao.updateLiveMessage(liveData.width, liveData.height, liveData.url, liveData.thumbUrl, data.status, messageId) + pendingMessagesDao().updateLiveMessage(liveData.width, liveData.height, liveData.url, liveData.thumbUrl, data.status, messageId) + messageDao().updateLiveMessage(liveData.width, liveData.height, liveData.url, liveData.thumbUrl, data.status, messageId) MessageFlow.update(data.conversationId, data.messageId) } else if (data.category == MessageCategory.SIGNAL_TRANSCRIPT.name) { val decoded = Base64.decode(plainText) processTranscriptMessage(data, String(decoded))?.let { message -> - pendingMessagesDao.updateTranscriptMessage(message.content, message.mediaSize, message.mediaStatus, message.status, messageId) - messageDao.updateTranscriptMessage(message.content, message.mediaSize, message.mediaStatus, message.status, messageId) + pendingMessagesDao().updateTranscriptMessage(message.content, message.mediaSize, message.mediaStatus, message.status, messageId) + messageDao().updateTranscriptMessage(message.content, message.mediaSize, message.mediaStatus, message.status, messageId) MessageFlow.update(data.conversationId, data.messageId) } } - if (pendingMessagesDao.countMessageByQuoteId(data.conversationId, messageId) > 0 || messageDao.countMessageByQuoteId(data.conversationId, messageId) > 0) { + if (pendingMessagesDao().countMessageByQuoteId(data.conversationId, messageId) > 0 || messageDao().countMessageByQuoteId(data.conversationId, messageId) > 0) { findQuoteMessageItemById(data.conversationId, messageId)?.let { val quoteContent = gson.toJson(it) - messageDao.updateQuoteContentByQuoteId(data.conversationId, messageId, quoteContent) - pendingMessagesDao.updateQuoteContentByQuoteId(data.conversationId, messageId, quoteContent) + messageDao().updateQuoteContentByQuoteId(data.conversationId, messageId, quoteContent) + pendingMessagesDao().updateQuoteContentByQuoteId(data.conversationId, messageId, quoteContent) MessageFlow.update(data.conversationId, data.messageId) - MessageFlow.update(data.conversationId, messageDao.findQuoteMessageIdByQuoteId(data.conversationId, messageId)) + MessageFlow.update(data.conversationId, messageDao().findQuoteMessageIdByQuoteId(data.conversationId, messageId)) } } } @@ -1598,7 +1598,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { userId: String, sessionId: String?, ) { - val messages = pendingMessagesDao.findFailedMessages(conversationId, userId) + messageDao.findFailedMessages(conversationId, userId) + val messages = pendingMessagesDao().findFailedMessages(conversationId, userId) + messageDao().findFailedMessages(conversationId, userId) if (messages.isEmpty()) { return } @@ -1612,7 +1612,7 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { messageId: String, status: MessageStatus = MessageStatus.DELIVERED, ) { - jobDao.insertNoReplace(createAckJob(ACKNOWLEDGE_MESSAGE_RECEIPTS, BlazeAckMessage(messageId, status.name))) + jobDao().insertNoReplace(createAckJob(ACKNOWLEDGE_MESSAGE_RECEIPTS, BlazeAckMessage(messageId, status.name))) } private fun refreshSignalKeys(conversationId: String) { @@ -1694,26 +1694,26 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { // No need to insert message return } else { - expiredMessageDao.insert(ExpiredMessage(data.messageId, expireIn, expiredAt)) + expiredMessageDao().insert(ExpiredMessage(data.messageId, expireIn, expiredAt)) RxBus.publish(ExpiredEvent(data.messageId, null, expiredAt)) } } else { - expiredMessageDao.insert(ExpiredMessage(data.messageId, expireIn, null)) + expiredMessageDao().insert(ExpiredMessage(data.messageId, expireIn, null)) } } pendingMessageStatusLruCache.remove(message.messageId)?.let { status -> message.status = status } - pendingMessagesDao.insert(PendingMessage(message)) + pendingMessagesDao().insert(PendingMessage(message)) } private fun findMessage(messageId: String): Message? { - pendingMessagesDao.findMessageById(messageId).let { msg -> + pendingMessagesDao().findMessageById(messageId).let { msg -> if (msg != null) { return msg } else { - return messageDao.findMessageById(messageId) + return messageDao().findMessageById(messageId) } } } diff --git a/app/src/main/java/one/mixin/android/job/Injector.kt b/app/src/main/java/one/mixin/android/job/Injector.kt index 454a1a15e3..3c90ae6d7b 100644 --- a/app/src/main/java/one/mixin/android/job/Injector.kt +++ b/app/src/main/java/one/mixin/android/job/Injector.kt @@ -95,32 +95,32 @@ open class Injector { @Inject lateinit var applicationScope: CoroutineScope - val database: MixinDatabase by lazy { databaseProvider.getMixinDatabase() } - val ftsDatabase: FtsDatabase by lazy { databaseProvider.getFtsDatabase() } + fun database(): MixinDatabase = databaseProvider.getMixinDatabase() + fun ftsDatabase(): FtsDatabase = databaseProvider.getFtsDatabase() - val messageDao: MessageDao by lazy { databaseProvider.getMixinDatabase().messageDao() } - val pendingMessagesDao: PendingMessageDao by lazy { databaseProvider.getPendingDatabase().pendingMessageDao() } - val messageHistoryDao: MessageHistoryDao by lazy { databaseProvider.getMixinDatabase().messageHistoryDao() } - val userDao: UserDao by lazy { databaseProvider.getMixinDatabase().userDao() } - val appDao: AppDao by lazy { databaseProvider.getMixinDatabase().appDao() } - val jobDao: JobDao by lazy { databaseProvider.getMixinDatabase().jobDao() } - val conversationDao: ConversationDao by lazy { databaseProvider.getMixinDatabase().conversationDao() } - val conversationExtDao: ConversationExtDao by lazy { databaseProvider.getMixinDatabase().conversationExtDao() } - val participantDao: ParticipantDao by lazy { databaseProvider.getMixinDatabase().participantDao() } - val participantSessionDao: ParticipantSessionDao by lazy { databaseProvider.getMixinDatabase().participantSessionDao() } - val snapshotDao: SnapshotDao by lazy { databaseProvider.getMixinDatabase().snapshotDao() } - val safeSnapshotDao: SafeSnapshotDao by lazy { databaseProvider.getMixinDatabase().safeSnapshotDao() } - val tokenDao: TokenDao by lazy { databaseProvider.getMixinDatabase().tokenDao() } - val circleDao: CircleDao by lazy { databaseProvider.getMixinDatabase().circleDao() } - val circleConversationDao: CircleConversationDao by lazy { databaseProvider.getMixinDatabase().circleConversationDao() } - val traceDao: TraceDao by lazy { databaseProvider.getMixinDatabase().traceDao() } - val stickerDao: StickerDao by lazy { databaseProvider.getMixinDatabase().stickerDao() } - val messageMentionDao: MessageMentionDao by lazy { databaseProvider.getMixinDatabase().messageMentionDao() } - val hyperlinkDao: HyperlinkDao by lazy { databaseProvider.getMixinDatabase().hyperlinkDao() } - val transcriptMessageDao: TranscriptMessageDao by lazy { databaseProvider.getMixinDatabase().transcriptDao() } - val pinMessageDao: PinMessageDao by lazy { databaseProvider.getMixinDatabase().pinMessageDao() } - val remoteMessageStatusDao: RemoteMessageStatusDao by lazy { databaseProvider.getMixinDatabase().remoteMessageStatusDao() } - val expiredMessageDao: ExpiredMessageDao by lazy { databaseProvider.getMixinDatabase().expiredMessageDao() } + fun messageDao(): MessageDao = databaseProvider.getMixinDatabase().messageDao() + fun pendingMessagesDao(): PendingMessageDao = databaseProvider.getPendingDatabase().pendingMessageDao() + fun messageHistoryDao(): MessageHistoryDao = databaseProvider.getMixinDatabase().messageHistoryDao() + fun userDao(): UserDao = databaseProvider.getMixinDatabase().userDao() + fun appDao(): AppDao = databaseProvider.getMixinDatabase().appDao() + fun jobDao(): JobDao = databaseProvider.getMixinDatabase().jobDao() + fun conversationDao(): ConversationDao = databaseProvider.getMixinDatabase().conversationDao() + fun conversationExtDao(): ConversationExtDao = databaseProvider.getMixinDatabase().conversationExtDao() + fun participantDao(): ParticipantDao = databaseProvider.getMixinDatabase().participantDao() + fun participantSessionDao(): ParticipantSessionDao = databaseProvider.getMixinDatabase().participantSessionDao() + fun snapshotDao(): SnapshotDao = databaseProvider.getMixinDatabase().snapshotDao() + fun safeSnapshotDao(): SafeSnapshotDao = databaseProvider.getMixinDatabase().safeSnapshotDao() + fun tokenDao(): TokenDao = databaseProvider.getMixinDatabase().tokenDao() + fun circleDao(): CircleDao = databaseProvider.getMixinDatabase().circleDao() + fun circleConversationDao(): CircleConversationDao = databaseProvider.getMixinDatabase().circleConversationDao() + fun traceDao(): TraceDao = databaseProvider.getMixinDatabase().traceDao() + fun stickerDao(): StickerDao = databaseProvider.getMixinDatabase().stickerDao() + fun messageMentionDao(): MessageMentionDao = databaseProvider.getMixinDatabase().messageMentionDao() + fun hyperlinkDao(): HyperlinkDao = databaseProvider.getMixinDatabase().hyperlinkDao() + fun transcriptMessageDao(): TranscriptMessageDao = databaseProvider.getMixinDatabase().transcriptDao() + fun pinMessageDao(): PinMessageDao = databaseProvider.getMixinDatabase().pinMessageDao() + fun remoteMessageStatusDao(): RemoteMessageStatusDao = databaseProvider.getMixinDatabase().remoteMessageStatusDao() + fun expiredMessageDao(): ExpiredMessageDao = databaseProvider.getMixinDatabase().expiredMessageDao() @InstallIn(SingletonComponent::class) @EntryPoint @@ -154,14 +154,14 @@ open class Injector { conversationId: String? = null, forceSync: Boolean = true, ): User? { - var user = userDao.findUser(userId) + var user = userDao().findUser(userId) if (user == null && forceSync) { try { val call = userService.getUserById(userId).execute() val response = call.body() if (response != null && response.isSuccess && response.data != null) { response.data?.let { u -> - userDao.insertUpdate(u, appDao) + userDao().insertUpdate(u, appDao()) user = u } } @@ -178,11 +178,11 @@ open class Injector { if (data.conversationId == SYSTEM_USER || data.conversationId == Session.getAccountId()) { return } - var conversation = conversationDao.findConversationById(data.conversationId) + var conversation = conversationDao().findConversationById(data.conversationId) var status = conversation?.status ?: ConversationStatus.START.ordinal if (conversation == null) { conversation = createConversation(data.conversationId, null, data.userId, ConversationStatus.START.ordinal) - conversationDao.upsert(conversation) + conversationDao().upsert(conversation) status = refreshConversation(data.conversationId) } if (status == ConversationStatus.START.ordinal) { @@ -191,7 +191,7 @@ open class Injector { } protected open fun isExistMessage(messageId: String): Boolean = - messageDao.findMessageIdById(messageId) != null || messageHistoryDao.findMessageHistoryById(messageId) != null + messageDao().findMessageIdById(messageId) != null || messageHistoryDao().findMessageHistoryById(messageId) != null private fun refreshConversation(conversationId: String): Int { try { @@ -211,7 +211,7 @@ open class Injector { } else if (conversationData.category == ConversationCategory.GROUP.name) { syncUser(conversationData.creatorId) } - conversationDao.updateConversation( + conversationDao().updateConversation( conversationData.conversationId, ownerId, conversationData.category, @@ -228,7 +228,7 @@ open class Injector { remote.add(Participant(conversationId, p.userId, p.role, p.createdAt!!)) conversationUserIds.add(p.userId) } - participantDao.replaceAll(conversationId, remote) + participantDao().replaceAll(conversationId, remote) if (conversationUserIds.isNotEmpty()) { jobManager.addJobInBackground(RefreshUserJob(conversationUserIds, conversationId)) @@ -239,21 +239,21 @@ open class Injector { ParticipantSession(conversationId, it.userId, it.sessionId, publicKey = it.publicKey) } sessionParticipants?.let { - participantSessionDao.replaceAll(conversationId, it) + participantSessionDao().replaceAll(conversationId, it) } conversationData.circles?.let { circles -> circles.forEach { - val circle = circleDao.findCircleById(it.circleId) + val circle = circleDao().findCircleById(it.circleId) if (circle == null) { val circleResponse = circleService.getCircle(it.circleId).execute().body() if (circleResponse?.isSuccess == true) { circleResponse.data?.let { item -> - circleDao.insert(item) + circleDao().insert(item) } } } - circleConversationDao.insertUpdate(it) + circleConversationDao().insertUpdate(it) } } return status diff --git a/app/src/main/java/one/mixin/android/job/NotificationGenerator.kt b/app/src/main/java/one/mixin/android/job/NotificationGenerator.kt index 2126c507ef..8da703a728 100644 --- a/app/src/main/java/one/mixin/android/job/NotificationGenerator.kt +++ b/app/src/main/java/one/mixin/android/job/NotificationGenerator.kt @@ -87,7 +87,7 @@ object NotificationGenerator : Injector() { if (user.relationship == UserRelationship.BLOCKING.name) { return@launch } - val conversation = conversationDao.getConversationItem(message.conversationId) ?: return@launch + val conversation = conversationDao().getConversationItem(message.conversationId) ?: return@launch if (conversation.category == null) { return@launch } @@ -135,13 +135,13 @@ object NotificationGenerator : Injector() { var app: App? = null var isBot = user.isBot() if (user.isBot()) { - app = appDao.findAppById(requireNotNull(user.appId) { "Required userId was null." }) + app = appDao().findAppById(requireNotNull(user.appId) { "Required userId was null." }) } else if (message.isRepresentativeMessage(conversation)) { val representativeUser = syncUser(conversation.ownerId) if (representativeUser == null) { isBot = false } else if (representativeUser.appId != null) { - app = appDao.findAppById(requireNotNull(representativeUser.appId) { "Required appId was null." }) + app = appDao().findAppById(requireNotNull(representativeUser.appId) { "Required appId was null." }) isBot = representativeUser.isBot() } else { isBot = false From 15cdc7035277f7506eff07c7cf1802a05f0e2b6c Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Thu, 28 Nov 2024 20:18:45 +0800 Subject: [PATCH 08/42] Check db status --- .../java/one/mixin/android/job/BlazeMessageService.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt b/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt index d6a6f794a9..6d449c94f8 100644 --- a/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt +++ b/app/src/main/java/one/mixin/android/job/BlazeMessageService.kt @@ -240,10 +240,12 @@ class BlazeMessageService : LifecycleService(), NetworkEventProvider.Listener, C override fun onDestroy() { super.onDestroy() - hedwig.land() - stopObserveAck() - stopObserveStatus() - stopObserveExpired() + Session.getAccount()?.let{ + hedwig.land() + stopObserveAck() + stopObserveStatus() + stopObserveExpired() + } ackJob?.cancel() ackJob = null statusJob?.cancel() From 461fdcb8b8f4a66985bf9a9e3ccebd8617441ddf Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Fri, 29 Nov 2024 14:39:43 +0800 Subject: [PATCH 09/42] Fix move target --- .../main/java/one/mixin/android/util/database/DatabaseUtil.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt index aca43244dd..31a05ac717 100644 --- a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt +++ b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt @@ -60,7 +60,7 @@ fun migrationDbFile(context: Context) { if (!dbFile.exists() || dbFile.length() <= 0) { return } - val dir = File(dbFile.parent, Session.getAccount()!!.identityNumber) + val dir = dbDir(context) if (!dir.exists()) dir.mkdirs() checkpoint(dbFile) moveDbFile(dbFile, dir) From 9e7281775a03a901d9816ddc5b2cec896f9ec9e5 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Fri, 29 Nov 2024 14:46:53 +0800 Subject: [PATCH 10/42] Fix db migration --- .../one/mixin/android/ui/home/MainActivity.kt | 3 +- .../android/util/database/DatabaseUtil.kt | 43 ++++++++++++------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt index 46abd000d2..66e268242e 100644 --- a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt +++ b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt @@ -171,6 +171,7 @@ import one.mixin.android.util.ErrorHandler import one.mixin.android.util.NewVersionBulletin.Companion.PREF_NEW_VERSION import one.mixin.android.util.RomUtil import one.mixin.android.util.RootUtil +import one.mixin.android.util.database.databseFile import one.mixin.android.util.database.legacyDatabaseExists import one.mixin.android.util.reportException import one.mixin.android.util.rxpermission.RxPermissions @@ -495,7 +496,7 @@ class MainActivity : BlazeBaseActivity() { private fun checkNeedGo2MigrationPage(): Boolean { val currentVersion = try { - readVersion(getDatabasePath(DB_NAME)) + readVersion(databseFile(this)) } catch (e: Exception) { 0 } diff --git a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt index 31a05ac717..b05a8df635 100644 --- a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt +++ b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt @@ -7,6 +7,9 @@ import android.os.Build import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import one.mixin.android.Constants +import one.mixin.android.Constants.DataBase.DB_NAME +import one.mixin.android.Constants.DataBase.PENDING_DB_NAME +import one.mixin.android.Constants.DataBase.FTS_DB_NAME import one.mixin.android.extension.moveTo import one.mixin.android.session.Session import one.mixin.android.util.reportException @@ -17,7 +20,7 @@ suspend fun clearJobsAndRawTransaction(context: Context, identityNumber: String) withContext(Dispatchers.IO) { val dir = dbDir(context) val supportsDeferForeignKeys = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP - val dbFile = File(dir, Constants.DataBase.DB_NAME) + val dbFile = File(dir, DB_NAME) if (!dbFile.exists()) { return@withContext } @@ -56,7 +59,7 @@ fun migrationDbFile(context: Context) { return } - val dbFile = context.getDatabasePath(Constants.DataBase.DB_NAME) + val dbFile = legacyDatabaseFile(context) if (!dbFile.exists() || dbFile.length() <= 0) { return } @@ -65,41 +68,41 @@ fun migrationDbFile(context: Context) { checkpoint(dbFile) moveDbFile(dbFile, dir) dbFile.parent?.let { - checkpoint(File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}")) - checkpoint(File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}")) + checkpoint(File("$it${File.separator}${FTS_DB_NAME}")) + checkpoint(File("$it${File.separator}${PENDING_DB_NAME}")) moveDbFile( - File("$it${File.separator}${Constants.DataBase.DB_NAME}-shm"), dir + File("$it${File.separator}${DB_NAME}-shm"), dir ) moveDbFile( - File("$it${File.separator}${Constants.DataBase.DB_NAME}-wal"), dir + File("$it${File.separator}${DB_NAME}-wal"), dir ) moveDbFile( - File("$it${File.separator}${Constants.DataBase.DB_NAME}-journal"), dir + File("$it${File.separator}${DB_NAME}-journal"), dir ) moveDbFile( - File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}"), dir + File("$it${File.separator}${FTS_DB_NAME}"), dir ) moveDbFile( - File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}-shm"), dir + File("$it${File.separator}${FTS_DB_NAME}-shm"), dir ) moveDbFile( - File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}-wal"), dir + File("$it${File.separator}${FTS_DB_NAME}-wal"), dir ) moveDbFile( - File("$it${File.separator}${Constants.DataBase.FTS_DB_NAME}-journal"), dir + File("$it${File.separator}${FTS_DB_NAME}-journal"), dir ) moveDbFile( - File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}"), dir + File("$it${File.separator}${PENDING_DB_NAME}"), dir ) moveDbFile( - File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}-shm"), dir + File("$it${File.separator}${PENDING_DB_NAME}-shm"), dir ) moveDbFile( - File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}-wal"), dir + File("$it${File.separator}${PENDING_DB_NAME}-wal"), dir ) moveDbFile( - File("$it${File.separator}${Constants.DataBase.PENDING_DB_NAME}-journal"), dir + File("$it${File.separator}${PENDING_DB_NAME}-journal"), dir ) } } @@ -137,6 +140,14 @@ fun dbDir(context: Context): File { } fun legacyDatabaseExists(context: Context): Boolean { - val dbFile = context.getDatabasePath(Constants.DataBase.DB_NAME) + val dbFile = legacyDatabaseFile(context) return dbFile.exists() && dbFile.length() > 0 } + +fun legacyDatabaseFile(context: Context): File { + return context.getDatabasePath(DB_NAME) +} + +fun databseFile(context: Context): File { + return File(dbDir(context), DB_NAME) +} \ No newline at end of file From 51ef7edd52cb4510626c681a403f5b883fa5a3a4 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Fri, 29 Nov 2024 15:46:11 +0800 Subject: [PATCH 11/42] Remove transaction on DAO extension --- .../java/one/mixin/android/db/AlertDao.kt | 7 + .../mixin/android/db/CircleConversationDao.kt | 17 +++ .../java/one/mixin/android/db/CircleDao.kt | 25 ++++ .../java/one/mixin/android/db/DaoExtension.kt | 141 ++---------------- .../java/one/mixin/android/db/DepositDao.kt | 7 + .../one/mixin/android/db/MarketCapRankDao.kt | 8 + .../one/mixin/android/db/MixinDatabase.kt | 17 +-- .../android/db/RemoteMessageStatusDao.kt | 7 + .../one/mixin/android/db/StickerAlbumDao.kt | 17 +++ .../java/one/mixin/android/db/StickerDao.kt | 14 ++ .../main/java/one/mixin/android/db/UserDao.kt | 52 +++++++ .../one/mixin/android/job/DecryptMessage.kt | 6 +- .../one/mixin/android/job/FavoriteAppJob.kt | 1 - .../one/mixin/android/job/InitializeJob.kt | 2 +- .../java/one/mixin/android/job/Injector.kt | 2 +- .../mixin/android/job/RefreshAccountJob.kt | 2 +- .../one/mixin/android/job/RefreshAlertsJob.kt | 6 +- .../one/mixin/android/job/RefreshCircleJob.kt | 2 +- .../mixin/android/job/RefreshContactJob.kt | 1 - .../android/job/RefreshConversationJob.kt | 2 +- .../mixin/android/job/RefreshMarketsJob.kt | 10 +- .../android/job/RefreshStickerAlbumJob.kt | 2 +- .../job/RefreshStickerAndRelatedAlbumJob.kt | 2 +- .../mixin/android/job/RefreshStickerJob.kt | 2 +- .../android/job/RestoreTransactionJob.kt | 5 +- .../java/one/mixin/android/job/SendService.kt | 6 +- .../one/mixin/android/messenger/HedwigImp.kt | 2 +- .../android/repository/AccountRepository.kt | 8 +- .../android/repository/TokenRepository.kt | 9 +- .../android/repository/UserRepository.kt | 15 +- .../android/ui/common/BottomSheetViewModel.kt | 11 +- .../ui/common/message/ChatRoomHelper.kt | 6 +- .../ui/home/ConversationListViewModel.kt | 6 +- .../android/ui/landing/UpgradeFragment.kt | 3 +- .../ui/landing/viewmodel/LandingViewModel.kt | 6 +- .../one/mixin/android/util/backup/Backup.kt | 13 +- .../android/worker/RefreshContactWorker.kt | 1 - .../android/worker/RefreshStickerWorker.kt | 1 - 38 files changed, 219 insertions(+), 225 deletions(-) diff --git a/app/src/main/java/one/mixin/android/db/AlertDao.kt b/app/src/main/java/one/mixin/android/db/AlertDao.kt index 41aa1b8e1d..4fa714af88 100644 --- a/app/src/main/java/one/mixin/android/db/AlertDao.kt +++ b/app/src/main/java/one/mixin/android/db/AlertDao.kt @@ -3,6 +3,7 @@ package one.mixin.android.db import androidx.lifecycle.LiveData import androidx.room.Dao import androidx.room.Query +import androidx.room.Transaction import kotlinx.coroutines.flow.Flow import one.mixin.android.ui.wallet.alert.vo.Alert import one.mixin.android.ui.wallet.alert.vo.AlertGroup @@ -57,4 +58,10 @@ interface AlertDao : BaseDao { @Query("DELETE FROM market_alerts") fun deleteAll() + + @Transaction + fun deleteAndInsertList(list: List) { + deleteAll() + insertList(list) + } } \ No newline at end of file diff --git a/app/src/main/java/one/mixin/android/db/CircleConversationDao.kt b/app/src/main/java/one/mixin/android/db/CircleConversationDao.kt index cf78c90a57..24b3b480ce 100644 --- a/app/src/main/java/one/mixin/android/db/CircleConversationDao.kt +++ b/app/src/main/java/one/mixin/android/db/CircleConversationDao.kt @@ -2,10 +2,27 @@ package one.mixin.android.db import androidx.room.Dao import androidx.room.Query +import androidx.room.Transaction import one.mixin.android.vo.CircleConversation @Dao interface CircleConversationDao : BaseDao { + @Transaction + fun insertUpdate( + circleConversation: CircleConversation, + ) { + val c = + findCircleConversationByCircleId( + circleConversation.circleId, + circleConversation.conversationId, + ) + if (c == null) { + insert(circleConversation) + } else { + updateCheckPin(c, circleConversation) + } + } + @Query("UPDATE circle_conversations SET pin_time = :pinTime WHERE conversation_id = :conversationId AND circle_id = :circleId") suspend fun updateConversationPinTimeById( conversationId: String, diff --git a/app/src/main/java/one/mixin/android/db/CircleDao.kt b/app/src/main/java/one/mixin/android/db/CircleDao.kt index 8683c82ec4..f7442ea28c 100644 --- a/app/src/main/java/one/mixin/android/db/CircleDao.kt +++ b/app/src/main/java/one/mixin/android/db/CircleDao.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData import androidx.room.Dao import androidx.room.Query import androidx.room.RoomWarnings +import androidx.room.Transaction import androidx.room.Update import one.mixin.android.vo.Circle import one.mixin.android.vo.CircleOrder @@ -13,6 +14,30 @@ import one.mixin.android.vo.ConversationMinimal @Dao interface CircleDao : BaseDao { + @Transaction + fun insertUpdate( + circle: Circle, + ) { + val c = findCircleById(circle.circleId) + if (c == null) { + insert(circle) + } else { + update(circle) + } + } + + @Transaction + suspend fun insertUpdateSuspend( + circle: Circle, + ) { + val c = findCircleById(circle.circleId) + if (c == null) { + insert(circle) + } else { + update(circle) + } + } + @Query( """ SELECT c.* FROM circle_conversations cc diff --git a/app/src/main/java/one/mixin/android/db/DaoExtension.kt b/app/src/main/java/one/mixin/android/db/DaoExtension.kt index 06477802e6..a7e0d359a7 100644 --- a/app/src/main/java/one/mixin/android/db/DaoExtension.kt +++ b/app/src/main/java/one/mixin/android/db/DaoExtension.kt @@ -1,5 +1,6 @@ package one.mixin.android.db +import androidx.room.Transaction import kotlinx.coroutines.withContext import one.mixin.android.db.flow.MessageFlow import one.mixin.android.db.pending.PendingDatabase @@ -20,86 +21,6 @@ import one.mixin.android.vo.isMine import one.mixin.android.vo.safe.Output import timber.log.Timber -fun UserDao.insertUpdate( - user: User, - appDao: AppDao, -) { - runInTransaction { - if (user.app != null) { - user.appId = user.app!!.appId - appDao.insert(user.app!!) - } - val u = findUser(user.userId) - if (u == null) { - insert(user) - } else { - update(user) - } - } -} - -fun UserDao.insertUpdateList( - users: List, - appDao: AppDao, -) { - runInTransaction { - val apps = arrayListOf() - for (u in users) { - if (u.app != null) { - u.appId = u.app!!.appId - apps.add(u.app!!) - } - } - appDao.insertList(apps) - insertList(users) - } -} - -fun UserDao.updateRelationship( - user: User, - relationship: String, -) { - runInTransaction { - val u = findUser(user.userId) - if (u == null) { - insert(user) - } else { - user.relationship = relationship - update(user) - } - } -} - -fun StickerDao.insertUpdate(s: Sticker) { - runInTransaction { - val sticker = getStickerByUnique(s.stickerId) - if (sticker != null) { - s.lastUseAt = sticker.lastUseAt - } - if (s.createdAt == "") { - s.createdAt = System.currentTimeMillis().toString() - } - insert(s) - } -} - -fun CircleConversationDao.insertUpdate( - circleConversation: CircleConversation, -) { - runInTransaction { - val c = - findCircleConversationByCircleId( - circleConversation.circleId, - circleConversation.conversationId, - ) - if (c == null) { - insert(circleConversation) - } else { - updateCheckPin(c, circleConversation) - } - } -} - fun CircleConversationDao.updateCheckPin( oldCircleConversation: CircleConversation, newCircleConversation: CircleConversation, @@ -119,45 +40,6 @@ fun CircleConversationDao.updateCheckPin( } } -suspend fun CircleDao.insertUpdateSuspend( - circle: Circle, -) { - withTransaction { - val c = findCircleById(circle.circleId) - if (c == null) { - insert(circle) - } else { - update(circle) - } - } -} - -fun CircleDao.insertUpdate( - circle: Circle, -) { - runInTransaction { - val c = findCircleById(circle.circleId) - if (c == null) { - insert(circle) - } else { - update(circle) - } - } -} - -suspend fun StickerAlbumDao.insertUpdate( - album: StickerAlbum, -) { - withTransaction { - val a = findAlbumById(album.albumId) - if (a == null) { - insert(album) - } else { - update(album) - } - } -} - fun MixinDatabase.clearParticipant( conversationId: String, participantId: String, @@ -175,18 +57,17 @@ fun JobDao.insertNoReplace(job: Job) { } } +@Transaction suspend fun OutputDao.insertUnspentOutputs(outputs: List) = withContext(SINGLE_DB_THREAD) { - runInTransaction { - val signed = findSignedOutput(outputs.map { it.outputId }) - if (signed.isEmpty()) { - insertList(outputs) - } else { - Timber.e("Insert filter ${signed.joinToString(", ") }") - // Exclude signed data - val unsignedData = outputs.filterNot { signed.contains(it.outputId) } - insertList(unsignedData) - } + val signed = findSignedOutput(outputs.map { it.outputId }) + if (signed.isEmpty()) { + insertList(outputs) + } else { + Timber.e("Insert filter ${signed.joinToString(", ")}") + // Exclude signed data + val unsignedData = outputs.filterNot { signed.contains(it.outputId) } + insertList(unsignedData) } } @@ -287,4 +168,4 @@ fun MixinDatabase.insertMessage(message: Message) { messageDao().insert(message) conversationExtDao().increment(message.conversationId) conversationDao().updateLastMessageId(message.messageId, message.createdAt, message.conversationId) -} +} \ No newline at end of file diff --git a/app/src/main/java/one/mixin/android/db/DepositDao.kt b/app/src/main/java/one/mixin/android/db/DepositDao.kt index 081d0f4447..a6d1b3b445 100644 --- a/app/src/main/java/one/mixin/android/db/DepositDao.kt +++ b/app/src/main/java/one/mixin/android/db/DepositDao.kt @@ -2,6 +2,7 @@ package one.mixin.android.db import androidx.room.Dao import androidx.room.Query +import androidx.room.Transaction import one.mixin.android.vo.safe.DepositEntry import one.mixin.android.vo.safe.DestinationTag @@ -15,4 +16,10 @@ interface DepositDao : BaseDao { @Query("DELETE FROM deposit_entries WHERE chain_id=:chainId") fun deleteByChainId(chainId: String) + + @Transaction + fun deleteAndInsert(chainId: String, list: List) { + deleteByChainId(chainId) + insertList(list) + } } diff --git a/app/src/main/java/one/mixin/android/db/MarketCapRankDao.kt b/app/src/main/java/one/mixin/android/db/MarketCapRankDao.kt index 668ef9e69f..43e9973818 100644 --- a/app/src/main/java/one/mixin/android/db/MarketCapRankDao.kt +++ b/app/src/main/java/one/mixin/android/db/MarketCapRankDao.kt @@ -2,10 +2,18 @@ package one.mixin.android.db import androidx.room.Dao import androidx.room.Query +import androidx.room.Transaction +import one.mixin.android.vo.market.Market import one.mixin.android.vo.market.MarketCapRank @Dao interface MarketCapRankDao : BaseDao { @Query("DELETE FROM market_cap_ranks") fun deleteAll() + + @Transaction + fun deleteAndInsertList(list: List) { + deleteAll() + insertList(list) + } } \ No newline at end of file diff --git a/app/src/main/java/one/mixin/android/db/MixinDatabase.kt b/app/src/main/java/one/mixin/android/db/MixinDatabase.kt index e068769a4a..77184d99d1 100644 --- a/app/src/main/java/one/mixin/android/db/MixinDatabase.kt +++ b/app/src/main/java/one/mixin/android/db/MixinDatabase.kt @@ -409,7 +409,12 @@ abstract class MixinDatabase : RoomDatabase() { } fun checkPoint() { - supportSQLiteDatabase?.query("PRAGMA wal_checkpoint(FULL)")?.close() + supportSQLiteDatabase?.let { db -> + db.beginTransaction() + db.query("PRAGMA wal_checkpoint(FULL)")?.close() + db.setTransactionSuccessful() + db.endTransaction() + } } fun getWritableDatabase(): SupportSQLiteDatabase? { @@ -429,12 +434,4 @@ abstract class MixinDatabase : RoomDatabase() { } } } -} - -fun runInTransaction(block: () -> Unit) { - MixinDatabase.getDatabase(MixinApplication.appContext).runInTransaction(block) -} - -suspend fun withTransaction(block: suspend () -> Unit) { - MixinDatabase.getDatabase(MixinApplication.appContext).withTransaction(block) -} +} \ No newline at end of file diff --git a/app/src/main/java/one/mixin/android/db/RemoteMessageStatusDao.kt b/app/src/main/java/one/mixin/android/db/RemoteMessageStatusDao.kt index 2fb060684c..5b7341143f 100644 --- a/app/src/main/java/one/mixin/android/db/RemoteMessageStatusDao.kt +++ b/app/src/main/java/one/mixin/android/db/RemoteMessageStatusDao.kt @@ -2,6 +2,7 @@ package one.mixin.android.db import androidx.room.Dao import androidx.room.Query +import androidx.room.Transaction import one.mixin.android.Constants.MARK_REMOTE_LIMIT import one.mixin.android.vo.RemoteMessageStatus import one.mixin.android.vo.StatusMessage @@ -34,4 +35,10 @@ interface RemoteMessageStatusDao : BaseDao { @Query("SELECT message_id FROM remote_messages_status WHERE conversation_id = :conversationId AND status != 'READ' LIMIT 50") suspend fun getUnreadMessageIds(conversationId: String): List + + @Transaction + fun markReadAndUnseen(conversationId: String){ + markReadByConversationId(conversationId) + updateConversationUnseen(conversationId) + } } diff --git a/app/src/main/java/one/mixin/android/db/StickerAlbumDao.kt b/app/src/main/java/one/mixin/android/db/StickerAlbumDao.kt index 5a65cd9567..f4e9575d29 100644 --- a/app/src/main/java/one/mixin/android/db/StickerAlbumDao.kt +++ b/app/src/main/java/one/mixin/android/db/StickerAlbumDao.kt @@ -34,6 +34,11 @@ interface StickerAlbumDao : BaseDao { @Update(entity = StickerAlbum::class) suspend fun updateOrderedAt(order: StickerAlbumOrder) + @Transaction + suspend fun updateOrderedAt(stickerAlbumOrders: List) { + stickerAlbumOrders.forEach { o -> updateOrderedAt(o) } + } + @Update(entity = StickerAlbum::class) suspend fun updateAdded(added: StickerAlbumAdded) @@ -48,4 +53,16 @@ interface StickerAlbumDao : BaseDao { @Query("SELECT max(ordered_at) FROM sticker_albums") suspend fun findMaxOrder(): Int? + + @Transaction + suspend fun insertUpdate( + album: StickerAlbum, + ) { + val a = findAlbumById(album.albumId) + if (a == null) { + insert(album) + } else { + update(album) + } + } } diff --git a/app/src/main/java/one/mixin/android/db/StickerDao.kt b/app/src/main/java/one/mixin/android/db/StickerDao.kt index 602911104b..86da2d9399 100644 --- a/app/src/main/java/one/mixin/android/db/StickerDao.kt +++ b/app/src/main/java/one/mixin/android/db/StickerDao.kt @@ -3,10 +3,24 @@ package one.mixin.android.db import androidx.lifecycle.LiveData import androidx.room.Dao import androidx.room.Query +import androidx.room.Transaction import one.mixin.android.vo.Sticker @Dao interface StickerDao : BaseDao { + + @Transaction + fun insertUpdate(s: Sticker) { + val sticker = getStickerByUnique(s.stickerId) + if (sticker != null) { + s.lastUseAt = sticker.lastUseAt + } + if (s.createdAt == "") { + s.createdAt = System.currentTimeMillis().toString() + } + insert(s) + } + @Query("SELECT * FROM stickers WHERE last_use_at > 0 ORDER BY last_use_at DESC LIMIT 20") fun recentUsedStickers(): LiveData> diff --git a/app/src/main/java/one/mixin/android/db/UserDao.kt b/app/src/main/java/one/mixin/android/db/UserDao.kt index c37706deb5..39daaa7cd1 100644 --- a/app/src/main/java/one/mixin/android/db/UserDao.kt +++ b/app/src/main/java/one/mixin/android/db/UserDao.kt @@ -4,8 +4,10 @@ import androidx.lifecycle.LiveData import androidx.room.Dao import androidx.room.Query import androidx.room.RoomWarnings +import androidx.room.Transaction import kotlinx.coroutines.flow.Flow import one.mixin.android.db.BaseDao.Companion.ESCAPE_SUFFIX +import one.mixin.android.vo.App import one.mixin.android.vo.CallUser import one.mixin.android.vo.ForwardUser import one.mixin.android.vo.MentionUser @@ -14,6 +16,56 @@ import one.mixin.android.vo.UserItem @Dao interface UserDao : BaseDao { + + @Transaction + fun updateRelationship( + user: User, + relationship: String, + ) { + val u = findUser(user.userId) + if (u == null) { + insert(user) + } else { + user.relationship = relationship + update(user) + } + } + + + @Transaction + fun insertUpdateList( + users: List, + appDao: AppDao, + ) { + val apps = arrayListOf() + for (u in users) { + if (u.app != null) { + u.appId = u.app!!.appId + apps.add(u.app!!) + } + } + appDao.insertList(apps) + insertList(users) + } + + + @Transaction + fun insertUpdate( + user: User, + appDao: AppDao, + ) { + if (user.app != null) { + user.appId = user.app!!.appId + appDao.insert(user.app!!) + } + val u = findUser(user.userId) + if (u == null) { + insert(user) + } else { + update(user) + } + } + @Query("SELECT * FROM users WHERE relationship = 'FRIEND' ORDER BY full_name, identity_number ASC") fun findFriends(): LiveData> diff --git a/app/src/main/java/one/mixin/android/job/DecryptMessage.kt b/app/src/main/java/one/mixin/android/job/DecryptMessage.kt index 2350c70c44..6855ca236a 100644 --- a/app/src/main/java/one/mixin/android/job/DecryptMessage.kt +++ b/app/src/main/java/one/mixin/android/job/DecryptMessage.kt @@ -20,9 +20,7 @@ import one.mixin.android.crypto.vo.RatchetStatus import one.mixin.android.db.flow.MessageFlow import one.mixin.android.db.insertMessage import one.mixin.android.db.insertNoReplace -import one.mixin.android.db.insertUpdate import one.mixin.android.db.pending.PendingMessage -import one.mixin.android.db.runInTransaction import one.mixin.android.event.CircleDeleteEvent import one.mixin.android.event.ExpiredEvent import one.mixin.android.event.PinMessageEvent @@ -1717,4 +1715,8 @@ class DecryptMessage(private val lifecycleScope: CoroutineScope) : Injector() { } } } + + private fun runInTransaction(body: Runnable) { + database().runInTransaction(body) + } } diff --git a/app/src/main/java/one/mixin/android/job/FavoriteAppJob.kt b/app/src/main/java/one/mixin/android/job/FavoriteAppJob.kt index ed3ce13c98..64e6c9f02d 100644 --- a/app/src/main/java/one/mixin/android/job/FavoriteAppJob.kt +++ b/app/src/main/java/one/mixin/android/job/FavoriteAppJob.kt @@ -2,7 +2,6 @@ package one.mixin.android.job import com.birbit.android.jobqueue.Params import kotlinx.coroutines.runBlocking -import one.mixin.android.db.insertUpdateList class FavoriteAppJob(vararg val userIds: String?) : BaseJob( Params(PRIORITY_UI_HIGH) diff --git a/app/src/main/java/one/mixin/android/job/InitializeJob.kt b/app/src/main/java/one/mixin/android/job/InitializeJob.kt index c6f772373e..ddaf656ac6 100644 --- a/app/src/main/java/one/mixin/android/job/InitializeJob.kt +++ b/app/src/main/java/one/mixin/android/job/InitializeJob.kt @@ -5,7 +5,7 @@ import kotlinx.coroutines.runBlocking import one.mixin.android.api.handleMixinResponse import one.mixin.android.api.request.RelationshipAction import one.mixin.android.api.request.RelationshipRequest -import one.mixin.android.db.insertUpdate + class InitializeJob(private val botId: String, private val botName: String) : BaseJob(Params(PRIORITY_UI_HIGH).groupBy(GROUP_ID).requireWebSocketConnected().persist()) { diff --git a/app/src/main/java/one/mixin/android/job/Injector.kt b/app/src/main/java/one/mixin/android/job/Injector.kt index 3c90ae6d7b..c9bd2af4f6 100644 --- a/app/src/main/java/one/mixin/android/job/Injector.kt +++ b/app/src/main/java/one/mixin/android/job/Injector.kt @@ -40,7 +40,7 @@ import one.mixin.android.db.TokenDao import one.mixin.android.db.TraceDao import one.mixin.android.db.TranscriptMessageDao import one.mixin.android.db.UserDao -import one.mixin.android.db.insertUpdate + import one.mixin.android.db.pending.PendingMessageDao import one.mixin.android.di.ApplicationScope import one.mixin.android.fts.FtsDatabase diff --git a/app/src/main/java/one/mixin/android/job/RefreshAccountJob.kt b/app/src/main/java/one/mixin/android/job/RefreshAccountJob.kt index 1eeabb7469..4c69ec277d 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshAccountJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshAccountJob.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.runBlocking import one.mixin.android.MixinApplication import one.mixin.android.RxBus import one.mixin.android.db.MixinDatabase -import one.mixin.android.db.insertUpdate + import one.mixin.android.event.TipEvent import one.mixin.android.extension.defaultSharedPreferences import one.mixin.android.extension.putInt diff --git a/app/src/main/java/one/mixin/android/job/RefreshAlertsJob.kt b/app/src/main/java/one/mixin/android/job/RefreshAlertsJob.kt index 1483ffa843..ac89484055 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshAlertsJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshAlertsJob.kt @@ -3,7 +3,6 @@ package one.mixin.android.job import com.birbit.android.jobqueue.Params import kotlinx.coroutines.runBlocking import one.mixin.android.Constants.RouteConfig.ROUTE_BOT_USER_ID -import one.mixin.android.db.runInTransaction import one.mixin.android.extension.nowInUtc import one.mixin.android.ui.wallet.fiatmoney.requestRouteAPI import one.mixin.android.vo.market.MarketCoin @@ -35,10 +34,7 @@ class RefreshAlertsJob : BaseJob( refreshMark(ids) } } - runInTransaction { - alertDao().deleteAll() - alertDao().insertList(list) - } + alertDao().deleteAndInsertList(list) }, requestSession = { userService.fetchSessionsSuspend(listOf(ROUTE_BOT_USER_ID)) diff --git a/app/src/main/java/one/mixin/android/job/RefreshCircleJob.kt b/app/src/main/java/one/mixin/android/job/RefreshCircleJob.kt index 510d4001ee..a924b47b73 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshCircleJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshCircleJob.kt @@ -1,7 +1,7 @@ package one.mixin.android.job import com.birbit.android.jobqueue.Params -import one.mixin.android.db.insertUpdate + import one.mixin.android.vo.Circle import one.mixin.android.vo.CircleConversation diff --git a/app/src/main/java/one/mixin/android/job/RefreshContactJob.kt b/app/src/main/java/one/mixin/android/job/RefreshContactJob.kt index fa42d39940..b38df03a5f 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshContactJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshContactJob.kt @@ -1,7 +1,6 @@ package one.mixin.android.job import com.birbit.android.jobqueue.Params -import one.mixin.android.db.insertUpdateList import one.mixin.android.vo.User class RefreshContactJob : BaseJob(Params(PRIORITY_BACKGROUND).addTags(GROUP).requireNetwork().persist()) { diff --git a/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt b/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt index 2df5951671..33f192fdb4 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt @@ -4,7 +4,7 @@ import com.birbit.android.jobqueue.Params import one.mixin.android.MixinApplication import one.mixin.android.RxBus import one.mixin.android.api.response.ConversationResponse -import one.mixin.android.db.insertUpdate + import one.mixin.android.event.GroupEvent import one.mixin.android.extension.putBoolean import one.mixin.android.extension.sharedPreferences diff --git a/app/src/main/java/one/mixin/android/job/RefreshMarketsJob.kt b/app/src/main/java/one/mixin/android/job/RefreshMarketsJob.kt index aafe1bc44a..9816470f33 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshMarketsJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshMarketsJob.kt @@ -3,7 +3,6 @@ package one.mixin.android.job import com.birbit.android.jobqueue.Params import kotlinx.coroutines.runBlocking import one.mixin.android.Constants.RouteConfig.ROUTE_BOT_USER_ID -import one.mixin.android.db.runInTransaction import one.mixin.android.extension.nowInUtc import one.mixin.android.ui.wallet.fiatmoney.requestRouteAPI import one.mixin.android.vo.market.MarketCapRank @@ -41,12 +40,9 @@ class RefreshMarketsJob(val category: String = "all") : BaseJob( marketFavoredDao().insertList(marketExtraList) } if (category == "all") { - runInTransaction { - marketCapRankDao().deleteAll() - marketCapRankDao().insertList(list.map { - MarketCapRank(it.coinId, it.marketCapRank, it.updatedAt) - }) - } + marketCapRankDao().deleteAndInsertList(list.map { + MarketCapRank(it.coinId, it.marketCapRank, it.updatedAt) + }) } marketDao().upsertList(list) val ids = list.flatMap { market -> diff --git a/app/src/main/java/one/mixin/android/job/RefreshStickerAlbumJob.kt b/app/src/main/java/one/mixin/android/job/RefreshStickerAlbumJob.kt index 46c37ac22e..5eec52c30b 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshStickerAlbumJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshStickerAlbumJob.kt @@ -4,7 +4,7 @@ import com.birbit.android.jobqueue.Params import kotlinx.coroutines.runBlocking import one.mixin.android.MixinApplication import one.mixin.android.RxBus -import one.mixin.android.db.insertUpdate + import one.mixin.android.event.AlbumEvent import one.mixin.android.extension.defaultSharedPreferences import one.mixin.android.extension.putBoolean diff --git a/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt b/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt index 477378e0b1..08ef6831bc 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshStickerAndRelatedAlbumJob.kt @@ -2,7 +2,7 @@ package one.mixin.android.job import com.birbit.android.jobqueue.Params import kotlinx.coroutines.runBlocking -import one.mixin.android.db.insertUpdate + import one.mixin.android.vo.Sticker import one.mixin.android.vo.StickerAlbum import one.mixin.android.vo.StickerRelationship diff --git a/app/src/main/java/one/mixin/android/job/RefreshStickerJob.kt b/app/src/main/java/one/mixin/android/job/RefreshStickerJob.kt index 8d0b9f8657..1d65e98be1 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshStickerJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshStickerJob.kt @@ -1,7 +1,7 @@ package one.mixin.android.job import com.birbit.android.jobqueue.Params -import one.mixin.android.db.insertUpdate + import one.mixin.android.vo.Sticker class RefreshStickerJob(private val stickerId: String) : BaseJob( diff --git a/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt b/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt index 7fed42f8ad..2da714e1fe 100644 --- a/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt +++ b/app/src/main/java/one/mixin/android/job/RestoreTransactionJob.kt @@ -8,7 +8,6 @@ import one.mixin.android.api.request.TransactionRequest import one.mixin.android.api.response.TransactionResponse import one.mixin.android.db.flow.MessageFlow import one.mixin.android.db.insertMessage -import one.mixin.android.db.runInTransaction import one.mixin.android.extension.nowInUtc import one.mixin.android.session.Session import one.mixin.android.util.reportException @@ -54,7 +53,7 @@ class RestoreTransactionJob : BaseJob( val response = utxoService.getTransactionsById(transaction.requestId) if (response.isSuccess) { Timber.e("Restore Transaction(${transaction.requestId}): db begin") - runInTransaction { + database().runInTransaction { Timber.e("Restore Transaction(${transaction.requestId}): update raw transaction ${transaction.requestId}") rawTransactionDao().updateRawTransaction(transaction.requestId, OutputState.signed.name) Timber.e("Restore Transaction(${transaction.requestId}): update raw transaction $feeTraceId") @@ -81,7 +80,7 @@ class RestoreTransactionJob : BaseJob( Timber.e("Restore Transaction(${transaction.requestId}): Post Transaction Success") val transactionResponse = transactionRsp.data!!.first() Timber.e("Restore Transaction(${transaction.requestId}): db begin") - runInTransaction { + database().runInTransaction { Timber.e("Restore Transaction(${transaction.requestId}): update raw transaction ${transaction.requestId}") rawTransactionDao().updateRawTransaction(transaction.requestId, OutputState.signed.name) Timber.e("Restore Transaction(${transaction.requestId}): update raw transaction $feeTraceId") diff --git a/app/src/main/java/one/mixin/android/job/SendService.kt b/app/src/main/java/one/mixin/android/job/SendService.kt index fc2a699a55..cc8dda912e 100644 --- a/app/src/main/java/one/mixin/android/job/SendService.kt +++ b/app/src/main/java/one/mixin/android/job/SendService.kt @@ -10,7 +10,6 @@ import one.mixin.android.db.JobDao import one.mixin.android.db.MessageDao import one.mixin.android.db.MessageMentionDao import one.mixin.android.db.RemoteMessageStatusDao -import one.mixin.android.db.runInTransaction import one.mixin.android.extension.nowInUtc import one.mixin.android.session.Session import one.mixin.android.vo.EncryptCategory @@ -68,9 +67,6 @@ class SendService : IntentService("SendService") { val manager = getSystemService() manager?.cancel(conversationId.hashCode()) messageMentionDao.markMentionReadByConversationId(conversationId) - runInTransaction { - remoteMessageStatusDao.markReadByConversationId(conversationId) - remoteMessageStatusDao.updateConversationUnseen(conversationId) - } + remoteMessageStatusDao.markReadAndUnseen(conversationId) } } diff --git a/app/src/main/java/one/mixin/android/messenger/HedwigImp.kt b/app/src/main/java/one/mixin/android/messenger/HedwigImp.kt index a56a3fa222..c35227667d 100644 --- a/app/src/main/java/one/mixin/android/messenger/HedwigImp.kt +++ b/app/src/main/java/one/mixin/android/messenger/HedwigImp.kt @@ -10,7 +10,7 @@ import one.mixin.android.api.service.ConversationService import one.mixin.android.db.MixinDatabase import one.mixin.android.db.flow.MessageFlow import one.mixin.android.db.insertNoReplace -import one.mixin.android.db.insertUpdate + import one.mixin.android.db.pending.PendingDatabase import one.mixin.android.job.DecryptCallMessage import one.mixin.android.job.DecryptMessage diff --git a/app/src/main/java/one/mixin/android/repository/AccountRepository.kt b/app/src/main/java/one/mixin/android/repository/AccountRepository.kt index 9b27424008..eb69dc0eb4 100644 --- a/app/src/main/java/one/mixin/android/repository/AccountRepository.kt +++ b/app/src/main/java/one/mixin/android/repository/AccountRepository.kt @@ -18,7 +18,6 @@ import one.mixin.android.api.request.EmergencyRequest import one.mixin.android.api.request.LogoutRequest import one.mixin.android.api.request.PinRequest import one.mixin.android.api.request.RawTransactionsRequest -import one.mixin.android.api.request.SessionRequest import one.mixin.android.api.request.StickerAddRequest import one.mixin.android.api.request.VerificationRequest import one.mixin.android.api.response.AuthorizationResponse @@ -41,9 +40,6 @@ import one.mixin.android.db.StickerAlbumDao import one.mixin.android.db.StickerDao import one.mixin.android.db.StickerRelationshipDao import one.mixin.android.db.UserDao -import one.mixin.android.db.insertUpdate -import one.mixin.android.db.insertUpdateList -import one.mixin.android.db.withTransaction import one.mixin.android.extension.nowInUtcNano import one.mixin.android.extension.within24Hours import one.mixin.android.session.Session @@ -247,9 +243,7 @@ class AccountRepository fun observeSystemAlbumById(albumId: String) = stickerAlbumDao.observeSystemAlbumById(albumId) suspend fun updateAlbumOrders(stickerAlbumOrders: List) { - withTransaction { - stickerAlbumOrders.forEach { o -> stickerAlbumDao.updateOrderedAt(o) } - } + stickerAlbumDao.updateOrderedAt(stickerAlbumOrders) } suspend fun updateAlbumAdded(stickerAlbumAdded: StickerAlbumAdded) = stickerAlbumDao.updateAdded(stickerAlbumAdded) diff --git a/app/src/main/java/one/mixin/android/repository/TokenRepository.kt b/app/src/main/java/one/mixin/android/repository/TokenRepository.kt index d3704a284a..7693427b3a 100644 --- a/app/src/main/java/one/mixin/android/repository/TokenRepository.kt +++ b/app/src/main/java/one/mixin/android/repository/TokenRepository.kt @@ -68,7 +68,6 @@ import one.mixin.android.db.UserDao import one.mixin.android.db.flow.MessageFlow import one.mixin.android.db.insertMessage import one.mixin.android.db.provider.DataProvider -import one.mixin.android.db.runInTransaction import one.mixin.android.extension.hexStringToByteArray import one.mixin.android.extension.isUUID import one.mixin.android.extension.nowInUtc @@ -77,14 +76,12 @@ import one.mixin.android.extension.toast import one.mixin.android.extension.within6Hours import one.mixin.android.job.MixinJobManager import one.mixin.android.job.SyncInscriptionMessageJob -import one.mixin.android.session.Session import one.mixin.android.tip.wc.SortOrder import one.mixin.android.ui.home.web3.widget.MarketSort import one.mixin.android.ui.wallet.FilterParams import one.mixin.android.ui.wallet.adapter.SnapshotsMediator import one.mixin.android.ui.wallet.alert.vo.Alert import one.mixin.android.ui.wallet.alert.vo.AlertRequest -import one.mixin.android.ui.wallet.alert.vo.AlertStatus import one.mixin.android.ui.wallet.alert.vo.AlertUpdateRequest import one.mixin.android.ui.wallet.fiatmoney.requestRouteAPI import one.mixin.android.util.ErrorHandler @@ -101,7 +98,6 @@ import one.mixin.android.vo.PriceAndChange import one.mixin.android.vo.SafeBox import one.mixin.android.vo.SnapshotItem import one.mixin.android.vo.Trace -import one.mixin.android.vo.User import one.mixin.android.vo.UtxoItem import one.mixin.android.vo.assetIdToAsset import one.mixin.android.vo.createMessage @@ -244,10 +240,7 @@ class TokenRepository val signature = it.signature.hexStringToByteArray() verifyCurve25519Signature(message, signature, pub) }?.let { list -> - runInTransaction { - depositDao.deleteByChainId(chainId) - depositDao.insertList(list) - } + depositDao.deleteAndInsert(chainId, list) list.find { it.isPrimary } } }, diff --git a/app/src/main/java/one/mixin/android/repository/UserRepository.kt b/app/src/main/java/one/mixin/android/repository/UserRepository.kt index 9193d307fc..39f8331bc6 100644 --- a/app/src/main/java/one/mixin/android/repository/UserRepository.kt +++ b/app/src/main/java/one/mixin/android/repository/UserRepository.kt @@ -24,12 +24,7 @@ import one.mixin.android.db.ConversationDao import one.mixin.android.db.MixinDatabase import one.mixin.android.db.ParticipantSessionDao import one.mixin.android.db.UserDao -import one.mixin.android.db.insertUpdate -import one.mixin.android.db.insertUpdateList -import one.mixin.android.db.insertUpdateSuspend import one.mixin.android.db.provider.DataProvider -import one.mixin.android.db.runInTransaction -import one.mixin.android.db.updateRelationship import one.mixin.android.extension.defaultSharedPreferences import one.mixin.android.extension.oneWeekAgo import one.mixin.android.extension.putString @@ -265,7 +260,10 @@ class UserRepository suspend fun deleteCircle(circleId: String) = circleService.deleteCircle(circleId) - suspend fun deleteCircleById(circleId: String) = circleDao.deleteCircleByIdSuspend(circleId) + suspend fun deleteCircleById(circleId: String) { + circleDao.deleteCircleByIdSuspend(circleId) + circleConversationDao.deleteByCircleIdSuspend(circleId) + } suspend fun findConversationItemByCircleId(circleId: String) = circleDao.findConversationItemByCircleId(circleId) @@ -278,7 +276,7 @@ class UserRepository suspend fun sortCircleConversations(list: List?) = withContext(Dispatchers.IO) { - runInTransaction { + appDatabase.runInTransaction { list?.forEach { circleDao.updateOrderAt(it) } @@ -291,9 +289,6 @@ class UserRepository ) = circleConversationDao.deleteByIdsSuspend(conversationId, circleId) - suspend fun deleteByCircleId(circleId: String) = - circleConversationDao.deleteByCircleIdSuspend(circleId) - suspend fun insertCircleConversation(circleConversation: CircleConversation) = circleConversationDao.insertSuspend(circleConversation) diff --git a/app/src/main/java/one/mixin/android/ui/common/BottomSheetViewModel.kt b/app/src/main/java/one/mixin/android/ui/common/BottomSheetViewModel.kt index d345cdeaf4..89c01f2e72 100644 --- a/app/src/main/java/one/mixin/android/ui/common/BottomSheetViewModel.kt +++ b/app/src/main/java/one/mixin/android/ui/common/BottomSheetViewModel.kt @@ -37,7 +37,7 @@ import one.mixin.android.api.response.TransactionResponse import one.mixin.android.api.response.getTransactionResult import one.mixin.android.api.service.UtxoService import one.mixin.android.crypto.PinCipher -import one.mixin.android.db.runInTransaction +import one.mixin.android.db.DatabaseProvider import one.mixin.android.extension.escapeSql import one.mixin.android.extension.nowInUtc import one.mixin.android.extension.toHex @@ -117,6 +117,7 @@ import javax.inject.Inject class BottomSheetViewModel @Inject internal constructor( + private val databaseProvider: DatabaseProvider, private val accountRepository: AccountRepository, private val jobManager: MixinJobManager, private val userRepository: UserRepository, @@ -267,7 +268,7 @@ class BottomSheetViewModel val signFeeResult = SignResult(signFee.raw, signFee.change) rawRequest.add(TransactionRequest(signFeeResult.raw, feeTraceId)) Timber.e("Kernel Withdrawal($traceId): db begin") - runInTransaction { + databaseProvider.getMixinDatabase().runInTransaction { Timber.e("Kernel Withdrawal($traceId): db update fee Utxo ${feeUtxos.ids}") tokenRepository.updateUtxoToSigned(feeUtxos.ids) Timber.e("Kernel Withdrawal($traceId): db update Utxo ${withdrawalUtxos.ids}") @@ -312,7 +313,7 @@ class BottomSheetViewModel jobManager.addJobInBackground(CheckBalanceJob(arrayListOf(assetIdToAsset(assetId), assetIdToAsset(feeAssetId)))) } else { Timber.e("Kernel Withdrawal($traceId): db begin") - runInTransaction { + databaseProvider.getMixinDatabase().runInTransaction { if (signWithdrawalResult.change != null) { val changeOutput = changeToOutput(signWithdrawalResult.change, asset, changeMask, data.last().keys, withdrawalUtxos.lastOutput) Timber.e("Kernel Withdrawal($traceId): db insert change") @@ -423,7 +424,7 @@ class BottomSheetViewModel val signResult = SignResult(sign.raw, sign.change) Timber.e("Kernel Address Transaction($trace): db begin") withContext(SINGLE_DB_THREAD) { - runInTransaction { + databaseProvider.getMixinDatabase().runInTransaction { if (signResult.change != null) { val changeOutput = changeToOutput(signResult.change, asset, changeMask, data.last().keys, utxoWrapper.lastOutput) Timber.e("Kernel Address Transaction($trace): sign db insert change") @@ -506,7 +507,7 @@ class BottomSheetViewModel val signResult = SignResult(sign.raw, sign.change) Timber.e("Kernel Transaction($trace): db begin") withContext(SINGLE_DB_THREAD) { - runInTransaction { + databaseProvider.getMixinDatabase().runInTransaction { if (signResult.change != null) { val changeOutput = changeToOutput(signResult.change, asset, changeMask, data.last().keys, utxoWrapper.lastOutput) Timber.e("Kernel Transaction($trace): sign db insert change") diff --git a/app/src/main/java/one/mixin/android/ui/common/message/ChatRoomHelper.kt b/app/src/main/java/one/mixin/android/ui/common/message/ChatRoomHelper.kt index 0b24e9d247..edb1993ed5 100644 --- a/app/src/main/java/one/mixin/android/ui/common/message/ChatRoomHelper.kt +++ b/app/src/main/java/one/mixin/android/ui/common/message/ChatRoomHelper.kt @@ -3,11 +3,11 @@ package one.mixin.android.ui.common.message import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import one.mixin.android.db.ConversationDao +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.JobDao import one.mixin.android.db.MessageMentionDao import one.mixin.android.db.RemoteMessageStatusDao import one.mixin.android.db.insertNoReplace -import one.mixin.android.db.runInTransaction import one.mixin.android.di.ApplicationScope import one.mixin.android.fts.FtsDatabase import one.mixin.android.util.SINGLE_THREAD @@ -26,7 +26,7 @@ class ChatRoomHelper private val remoteMessageStatusDao: RemoteMessageStatusDao, private val messageMentionDao: MessageMentionDao, private val jobDao: JobDao, - private val ftsDbHelper: FtsDatabase, + private val databaseProvider: DatabaseProvider ) { fun saveDraft( conversationId: String, @@ -44,7 +44,7 @@ class ChatRoomHelper fun markMessageRead(conversationId: String) { applicationScope.launch(SINGLE_THREAD) { timeoutEarlyWarning({ - runInTransaction { + databaseProvider.getMixinDatabase().runInTransaction { remoteMessageStatusDao.markReadByConversationId(conversationId) remoteMessageStatusDao.zeroConversationUnseen(conversationId) } diff --git a/app/src/main/java/one/mixin/android/ui/home/ConversationListViewModel.kt b/app/src/main/java/one/mixin/android/ui/home/ConversationListViewModel.kt index 042333521b..f165166b7c 100644 --- a/app/src/main/java/one/mixin/android/ui/home/ConversationListViewModel.kt +++ b/app/src/main/java/one/mixin/android/ui/home/ConversationListViewModel.kt @@ -14,7 +14,6 @@ import one.mixin.android.api.request.CircleConversationRequest import one.mixin.android.api.request.ConversationRequest import one.mixin.android.api.request.ParticipantRequest import one.mixin.android.api.response.ConversationResponse -import one.mixin.android.db.withTransaction import one.mixin.android.extension.nowInUtc import one.mixin.android.job.ConversationJob import one.mixin.android.job.ConversationJob.Companion.TYPE_CREATE @@ -173,10 +172,7 @@ class ConversationListViewModel suspend fun deleteCircle(circleId: String) = userRepository.deleteCircle(circleId) suspend fun deleteCircleById(circleId: String) { - withTransaction { - userRepository.deleteCircleById(circleId) - userRepository.deleteByCircleId(circleId) - } + userRepository.deleteCircleById(circleId) } suspend fun insertCircle(circle: Circle) = userRepository.insertCircle(circle) diff --git a/app/src/main/java/one/mixin/android/ui/landing/UpgradeFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/UpgradeFragment.kt index da5356a888..e05a772cee 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/UpgradeFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/UpgradeFragment.kt @@ -14,7 +14,6 @@ import one.mixin.android.MixinApplication import one.mixin.android.R import one.mixin.android.databinding.FragmentUpgradeBinding import one.mixin.android.db.property.PropertyHelper -import one.mixin.android.db.runInTransaction import one.mixin.android.extension.withArgs import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.home.MainActivity @@ -53,7 +52,7 @@ class UpgradeFragment : BaseFragment(R.layout.fragment_upgrade) { binding.pb.isIndeterminate = true withContext(Dispatchers.IO) { PropertyHelper.checkMigrated() - runInTransaction { } + viewModel.lockAndUpgradeDatabase() } MainActivity.show(requireContext()) activity?.finish() diff --git a/app/src/main/java/one/mixin/android/ui/landing/viewmodel/LandingViewModel.kt b/app/src/main/java/one/mixin/android/ui/landing/viewmodel/LandingViewModel.kt index 32fb4b27b2..d7439f102b 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/viewmodel/LandingViewModel.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/viewmodel/LandingViewModel.kt @@ -39,7 +39,7 @@ import one.mixin.android.crypto.vo.SenderKey import one.mixin.android.crypto.vo.Session import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.MixinDatabase -import one.mixin.android.db.insertUpdate + import one.mixin.android.extension.getDeviceId import one.mixin.android.job.RefreshOneTimePreKeysJob import one.mixin.android.repository.AccountRepository @@ -64,6 +64,10 @@ internal constructor( ) : ViewModel() { fun initAllDatabases() = databaseProvider.initAllDatabases() + fun lockAndUpgradeDatabase() = databaseProvider.getMixinDatabase().runInTransaction { + // do nothing + } + fun pingServer( callback: () -> Unit, elseCallBack: (e: Exception?) -> Unit, diff --git a/app/src/main/java/one/mixin/android/util/backup/Backup.kt b/app/src/main/java/one/mixin/android/util/backup/Backup.kt index 634aa6a503..1f0f708d95 100644 --- a/app/src/main/java/one/mixin/android/util/backup/Backup.kt +++ b/app/src/main/java/one/mixin/android/util/backup/Backup.kt @@ -16,7 +16,6 @@ import one.mixin.android.Constants import one.mixin.android.Constants.DataBase.DB_NAME import one.mixin.android.db.MixinDatabase import one.mixin.android.db.property.PropertyHelper -import one.mixin.android.db.runInTransaction import one.mixin.android.extension.copyFromInputStream import one.mixin.android.extension.defaultSharedPreferences import one.mixin.android.extension.deleteOnExists @@ -68,10 +67,8 @@ suspend fun backup( val copyPath = "$backupDir${File.separator}$tmpName" var result: File? = null try { - runInTransaction { - MixinDatabase.checkPoint() - result = dbFile.copyTo(File(copyPath), overwrite = true) - } + MixinDatabase.checkPoint() + result = dbFile.copyTo(File(copyPath), overwrite = true) context.getOldBackupPath(false)?.deleteRecursively() } catch (e: Exception) { result?.delete() @@ -208,10 +205,8 @@ suspend fun backupApi29( val tmpFile = File(context.getMediaPath(), DB_NAME) try { val inputStream = dbFile.inputStream() - runInTransaction { - MixinDatabase.checkPoint() - tmpFile.outputStream().use { output -> inputStream.copyTo(output) } - } + MixinDatabase.checkPoint() + tmpFile.outputStream().use { output -> inputStream.copyTo(output) } var db: SQLiteDatabase? = null try { db = diff --git a/app/src/main/java/one/mixin/android/worker/RefreshContactWorker.kt b/app/src/main/java/one/mixin/android/worker/RefreshContactWorker.kt index a66ba5e46c..5eee358c44 100644 --- a/app/src/main/java/one/mixin/android/worker/RefreshContactWorker.kt +++ b/app/src/main/java/one/mixin/android/worker/RefreshContactWorker.kt @@ -8,7 +8,6 @@ import dagger.assisted.AssistedInject import one.mixin.android.api.service.ContactService import one.mixin.android.db.AppDao import one.mixin.android.db.UserDao -import one.mixin.android.db.insertUpdateList import one.mixin.android.vo.User @HiltWorker diff --git a/app/src/main/java/one/mixin/android/worker/RefreshStickerWorker.kt b/app/src/main/java/one/mixin/android/worker/RefreshStickerWorker.kt index 7e78406d59..40758008b6 100644 --- a/app/src/main/java/one/mixin/android/worker/RefreshStickerWorker.kt +++ b/app/src/main/java/one/mixin/android/worker/RefreshStickerWorker.kt @@ -8,7 +8,6 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedInject import one.mixin.android.api.service.AccountService import one.mixin.android.db.StickerDao -import one.mixin.android.db.insertUpdate import one.mixin.android.vo.Sticker @HiltWorker From b5701f5767b7d0f06e0e26083a005dad5eca83af Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Fri, 29 Nov 2024 15:58:47 +0800 Subject: [PATCH 12/42] Move old database files at login --- .../android/ui/common/PinCodeFragment.kt | 2 + .../one/mixin/android/ui/home/MainActivity.kt | 21 +--------- .../android/ui/landing/SetupNameFragment.kt | 2 + .../android/util/database/DatabaseUtil.kt | 42 ++++++++++++++++++- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt b/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt index 061ffbcb22..5eee3782b4 100644 --- a/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/common/PinCodeFragment.kt @@ -29,6 +29,7 @@ import one.mixin.android.ui.landing.RestoreActivity import one.mixin.android.ui.landing.viewmodel.LandingViewModel import one.mixin.android.util.ErrorHandler import one.mixin.android.util.database.clearJobsAndRawTransaction +import one.mixin.android.util.database.moveLegacyDatabaseFile import one.mixin.android.vo.Account import one.mixin.android.vo.User import one.mixin.android.vo.toUser @@ -104,6 +105,7 @@ abstract class PinCodeFragment( Session.storeEd25519Seed(privateKey.base64Encode()) Session.storePinToken(pinToken.base64Encode()) Session.storeAccount(account) + moveLegacyDatabaseFile(requireContext(), account) landingViewModel.initAllDatabases() if (Session.hasPhone()) { // Remove mnemonic if user has phone on sign in diff --git a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt index 66e268242e..61b54b672f 100644 --- a/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt +++ b/app/src/main/java/one/mixin/android/ui/home/MainActivity.kt @@ -45,8 +45,6 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext import one.mixin.android.BuildConfig import one.mixin.android.Constants import one.mixin.android.Constants.APP_VERSION @@ -60,7 +58,6 @@ import one.mixin.android.Constants.Account.PREF_LOGIN_VERIFY import one.mixin.android.Constants.Account.PREF_SYNC_CIRCLE import one.mixin.android.Constants.DEVICE_ID import one.mixin.android.Constants.DataBase.CURRENT_VERSION -import one.mixin.android.Constants.DataBase.DB_NAME import one.mixin.android.Constants.DataBase.MINI_VERSION import one.mixin.android.Constants.INTERVAL_24_HOURS import one.mixin.android.Constants.INTERVAL_7_DAYS @@ -69,15 +66,10 @@ import one.mixin.android.MixinApplication import one.mixin.android.R import one.mixin.android.RxBus import one.mixin.android.api.request.SessionRequest -import one.mixin.android.api.service.ConversationService -import one.mixin.android.api.service.UserService import one.mixin.android.crypto.Base64 import one.mixin.android.crypto.PrivacyPreference.getIsLoaded import one.mixin.android.crypto.PrivacyPreference.getIsSyncSession import one.mixin.android.databinding.ActivityMainBinding -import one.mixin.android.db.ConversationDao -import one.mixin.android.db.ParticipantDao -import one.mixin.android.db.UserDao import one.mixin.android.db.property.PropertyHelper import one.mixin.android.event.TipEvent import one.mixin.android.extension.alertDialogBuilder @@ -85,7 +77,6 @@ import one.mixin.android.extension.areBubblesAllowedCompat import one.mixin.android.extension.checkStorageNotLow import one.mixin.android.extension.colorFromAttribute import one.mixin.android.extension.defaultSharedPreferences -import one.mixin.android.extension.getLegacyBackupPath import one.mixin.android.extension.getStringDeviceId import one.mixin.android.extension.inTransaction import one.mixin.android.extension.indeterminateProgressDialog @@ -117,12 +108,9 @@ import one.mixin.android.job.RefreshFcmJob import one.mixin.android.job.RefreshFiatsJob import one.mixin.android.job.RefreshOneTimePreKeysJob import one.mixin.android.job.RefreshStickerAlbumJob -import one.mixin.android.job.RefreshUserJob import one.mixin.android.job.RestoreTransactionJob import one.mixin.android.job.SyncOutputJob import one.mixin.android.job.TranscriptAttachmentMigrationJob -import one.mixin.android.repository.AccountRepository -import one.mixin.android.repository.UserRepository import one.mixin.android.session.Session import one.mixin.android.tip.Tip import one.mixin.android.tip.wc.WCErrorEvent @@ -171,16 +159,11 @@ import one.mixin.android.util.ErrorHandler import one.mixin.android.util.NewVersionBulletin.Companion.PREF_NEW_VERSION import one.mixin.android.util.RomUtil import one.mixin.android.util.RootUtil -import one.mixin.android.util.database.databseFile +import one.mixin.android.util.database.databaseFile import one.mixin.android.util.database.legacyDatabaseExists import one.mixin.android.util.reportException import one.mixin.android.util.rxpermission.RxPermissions -import one.mixin.android.vo.Conversation -import one.mixin.android.vo.ConversationCategory -import one.mixin.android.vo.ConversationStatus import one.mixin.android.vo.Fiats -import one.mixin.android.vo.Participant -import one.mixin.android.vo.ParticipantRole import one.mixin.android.vo.isGroupConversation import one.mixin.android.web3.js.JsSigner import timber.log.Timber @@ -496,7 +479,7 @@ class MainActivity : BlazeBaseActivity() { private fun checkNeedGo2MigrationPage(): Boolean { val currentVersion = try { - readVersion(databseFile(this)) + readVersion(databaseFile(this)) } catch (e: Exception) { 0 } diff --git a/app/src/main/java/one/mixin/android/ui/landing/SetupNameFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/SetupNameFragment.kt index f6981d2cd8..39cdcc4e05 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/SetupNameFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/SetupNameFragment.kt @@ -24,6 +24,7 @@ import one.mixin.android.session.Session import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.home.MainActivity import one.mixin.android.ui.landing.viewmodel.LandingViewModel +import one.mixin.android.util.database.moveLegacyDatabaseFile import one.mixin.android.util.ErrorHandler import one.mixin.android.util.reportException import one.mixin.android.util.viewBinding @@ -66,6 +67,7 @@ class SetupNameFragment : BaseFragment(R.layout.fragment_setup_name) { } r.data?.let { data -> Session.storeAccount(data) + moveLegacyDatabaseFile(requireContext(), data) landingViewModel.insertUser(data.toUser()) } diff --git a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt index b05a8df635..c02728c604 100644 --- a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt +++ b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt @@ -2,17 +2,19 @@ package one.mixin.android.util.database import android.annotation.SuppressLint import android.content.Context +import android.database.Cursor import android.database.sqlite.SQLiteDatabase import android.os.Build import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import one.mixin.android.Constants import one.mixin.android.Constants.DataBase.DB_NAME import one.mixin.android.Constants.DataBase.PENDING_DB_NAME import one.mixin.android.Constants.DataBase.FTS_DB_NAME import one.mixin.android.extension.moveTo import one.mixin.android.session.Session import one.mixin.android.util.reportException +import one.mixin.android.vo.Account +import timber.log.Timber import java.io.File @SuppressLint("ObsoleteSdkInt") @@ -148,6 +150,42 @@ fun legacyDatabaseFile(context: Context): File { return context.getDatabasePath(DB_NAME) } -fun databseFile(context: Context): File { +fun databaseFile(context: Context): File { return File(dbDir(context), DB_NAME) +} + +fun moveLegacyDatabaseFile(context: Context, account: Account) { + val dbFile = legacyDatabaseFile(context) + if (!dbFile.exists() || dbFile.length() <= 0) { + return + } + var c: Cursor? = null + var db: SQLiteDatabase? = null + try { + db = + SQLiteDatabase.openDatabase( + dbFile.absolutePath, + null, + SQLiteDatabase.OPEN_READONLY, + ) + c = db.rawQuery("SELECT user_id FROM users WHERE relationship = 'ME'", null) + var userId: String? = null + if (c.moveToFirst()) { + userId = c.getString(0) + } + if (account.userId == userId){ + val dir = dbDir(context) + if (!dir.exists()) dir.mkdirs() + c?.close() + c = null + db?.close() + db = null + dbFile.moveTo(databaseFile(context)) + } + } catch (e: Exception) { + Timber.e(e) + } finally { + c?.close() + db?.close() + } } \ No newline at end of file From 1aabc243349e661cd48667fd54b214f292adb6f5 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Fri, 29 Nov 2024 16:13:11 +0800 Subject: [PATCH 13/42] Refactor ChatWebSocket to use DatabaseProvider directly --- app/src/main/java/one/mixin/android/di/AppModule.kt | 8 +++----- .../java/one/mixin/android/websocket/ChatWebSocket.kt | 10 ++++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/one/mixin/android/di/AppModule.kt b/app/src/main/java/one/mixin/android/di/AppModule.kt index 5e8e3e653a..35bfdd8c41 100644 --- a/app/src/main/java/one/mixin/android/di/AppModule.kt +++ b/app/src/main/java/one/mixin/android/di/AppModule.kt @@ -74,11 +74,10 @@ import one.mixin.android.crypto.EncryptedProtocol import one.mixin.android.crypto.JobSenderKey import one.mixin.android.crypto.PinCipher import one.mixin.android.crypto.SignalProtocol +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.MessageHistoryDao -import one.mixin.android.db.MixinDatabase import one.mixin.android.db.ParticipantDao import one.mixin.android.db.ParticipantSessionDao -import one.mixin.android.db.pending.PendingDatabase import one.mixin.android.extension.defaultSharedPreferences import one.mixin.android.extension.filterNonAscii import one.mixin.android.extension.getStringDeviceId @@ -433,15 +432,14 @@ object AppModule { @Provides @Singleton fun provideChatWebSocket( + databaseProvider: DatabaseProvider, @ApplicationScope applicationScope: CoroutineScope, okHttp: OkHttpClient, accountService: AccountService, - mixinDatabase: MixinDatabase, - pendingDatabase: PendingDatabase, jobManager: MixinJobManager, linkState: LinkState, ): ChatWebSocket = - ChatWebSocket(applicationScope, okHttp, accountService, mixinDatabase, pendingDatabase, jobManager, linkState) + ChatWebSocket(databaseProvider, applicationScope, okHttp, accountService, jobManager, linkState) @Provides @Singleton diff --git a/app/src/main/java/one/mixin/android/websocket/ChatWebSocket.kt b/app/src/main/java/one/mixin/android/websocket/ChatWebSocket.kt index 8ee0f4a028..73f1c835f2 100644 --- a/app/src/main/java/one/mixin/android/websocket/ChatWebSocket.kt +++ b/app/src/main/java/one/mixin/android/websocket/ChatWebSocket.kt @@ -18,6 +18,7 @@ import one.mixin.android.Constants.API.WS_URL import one.mixin.android.MixinApplication import one.mixin.android.api.ClientErrorException import one.mixin.android.api.service.AccountService +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.MixinDatabase import one.mixin.android.db.OffsetDao import one.mixin.android.db.insertNoReplace @@ -49,11 +50,10 @@ import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit class ChatWebSocket( + private var databaseProvider: DatabaseProvider, private var applicationScope: CoroutineScope, private val okHttpClient: OkHttpClient, private val accountService: AccountService, - private val mixinDatabase: MixinDatabase, - private val pendingDatabase: PendingDatabase, private val jobManager: MixinJobManager, private val linkState: LinkState, ) : WebSocketListener() { @@ -103,6 +103,12 @@ class ChatWebSocket( } } + val pendingDatabase: PendingDatabase + get () = databaseProvider.getPendingDatabase() + + val mixinDatabase: MixinDatabase + get () = databaseProvider.getMixinDatabase() + @Synchronized fun sendMessage( blazeMessage: BlazeMessage, From e1218e5672ac87cb0378967b60880962a96039b0 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Fri, 29 Nov 2024 17:04:02 +0800 Subject: [PATCH 14/42] More inject --- .../android/db/fetcher/MessageFetcher.kt | 7 ++++++- .../repository/ConversationRepository.kt | 21 ++++++++++--------- .../android/repository/TokenRepository.kt | 14 ++++++------- .../ui/common/message/CleanMessageHelper.kt | 9 ++++++-- .../ui/conversation/ConversationViewModel.kt | 1 - .../mixin/android/ui/player/MusicService.kt | 16 +++++++++----- .../mixin/android/ui/player/MusicViewModel.kt | 6 ++++-- .../android/util/database/DatabaseUtil.kt | 2 +- 8 files changed, 47 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/one/mixin/android/db/fetcher/MessageFetcher.kt b/app/src/main/java/one/mixin/android/db/fetcher/MessageFetcher.kt index 55c62ac6e7..1028f6c3b9 100644 --- a/app/src/main/java/one/mixin/android/db/fetcher/MessageFetcher.kt +++ b/app/src/main/java/one/mixin/android/db/fetcher/MessageFetcher.kt @@ -1,7 +1,9 @@ package one.mixin.android.db.fetcher import kotlinx.coroutines.withContext +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.MixinDatabase +import one.mixin.android.db.provider.DataProvider import one.mixin.android.db.provider.convertToMessageItems import one.mixin.android.util.SINGLE_FETCHER_THREAD import one.mixin.android.vo.MessageItem @@ -10,7 +12,7 @@ import javax.inject.Inject class MessageFetcher @Inject constructor( - val db: MixinDatabase, + val dataProvider: DatabaseProvider, ) { companion object { private const val SQL = """ @@ -52,6 +54,9 @@ class MessageFetcher private var canLoadAbove = true private var canLoadBelow = true + private val db : MixinDatabase + get() = dataProvider.getMixinDatabase() + suspend fun initMessages( conversationId: String, messageId: String? = null, diff --git a/app/src/main/java/one/mixin/android/repository/ConversationRepository.kt b/app/src/main/java/one/mixin/android/repository/ConversationRepository.kt index 915eb7302b..b3b6e0dc78 100644 --- a/app/src/main/java/one/mixin/android/repository/ConversationRepository.kt +++ b/app/src/main/java/one/mixin/android/repository/ConversationRepository.kt @@ -26,6 +26,7 @@ import one.mixin.android.db.AppDao import one.mixin.android.db.CircleConversationDao import one.mixin.android.db.ConversationDao import one.mixin.android.db.ConversationExtDao +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.JobDao import one.mixin.android.db.MessageDao import one.mixin.android.db.MessageMentionDao @@ -79,7 +80,7 @@ import javax.inject.Singleton class ConversationRepository @Inject internal constructor( - private val appDatabase: MixinDatabase, + private val databaseProvider: DatabaseProvider, private val messageDao: MessageDao, private val conversationDao: ConversationDao, private val conversationExtDao: ConversationExtDao, @@ -105,9 +106,9 @@ class ConversationRepository fun observeConversations(circleId: String?): DataSource.Factory = if (circleId == null) { - DataProvider.observeConversations(MixinDatabase.getDatabase(MixinApplication.appContext)) + DataProvider.observeConversations(databaseProvider.getMixinDatabase()) } else { - DataProvider.observeConversationsByCircleId(circleId, MixinDatabase.getDatabase(MixinApplication.appContext)) + DataProvider.observeConversationsByCircleId(circleId, databaseProvider.getMixinDatabase()) } suspend fun successConversationList(): List = @@ -118,7 +119,7 @@ class ConversationRepository participants: List, ) = withContext(SINGLE_DB_THREAD) { - appDatabase.runInTransaction { + databaseProvider.getMixinDatabase().runInTransaction { conversationDao.upsert(conversation) participantDao.insertList(participants) } @@ -128,7 +129,7 @@ class ConversationRepository conversation: Conversation, participants: List, ) { - appDatabase.runInTransaction { + databaseProvider.getMixinDatabase().runInTransaction { conversationDao.upsert(conversation) participantDao.insertList(participants) } @@ -167,7 +168,7 @@ class ConversationRepository emptyList() } else { val queryString = query.joinStar().replaceQuotationMark() - DataProvider.fuzzySearchMessage(ftsDbHelper, queryString, appDatabase, cancellationSignal) + DataProvider.fuzzySearchMessage(ftsDbHelper, queryString, databaseProvider.getMixinDatabase(), cancellationSignal) } fun fuzzySearchMessageDetail( @@ -176,14 +177,14 @@ class ConversationRepository cancellationSignal: CancellationSignal, ): DataSource.Factory { val queryString = query.joinStar().replaceQuotationMark() - return DataProvider.fuzzySearchMessageDetail(ftsDbHelper, queryString, conversationId, appDatabase, cancellationSignal) + return DataProvider.fuzzySearchMessageDetail(ftsDbHelper, queryString, conversationId, databaseProvider.getMixinDatabase(), cancellationSignal) } suspend fun fuzzySearchChat( query: String, cancellationSignal: CancellationSignal, ): List = - DataProvider.fuzzySearchChat(query, appDatabase, cancellationSignal) + DataProvider.fuzzySearchChat(query, databaseProvider.getMixinDatabase(), cancellationSignal) suspend fun indexUnread(conversationId: String) = conversationDao.indexUnread(conversationId) @@ -537,7 +538,7 @@ class ConversationRepository fun getPinMessages( conversationId: String, count: Int, - ) = DataProvider.getPinMessages(appDatabase, conversationId, count) + ) = DataProvider.getPinMessages(databaseProvider.getMixinDatabase(), conversationId, count) suspend fun findTranscriptMessageIndex( transcriptId: String, @@ -677,7 +678,7 @@ class ConversationRepository } fun insertMessage(message: Message) { - appDatabase.insertMessage(message) + databaseProvider.getMixinDatabase().insertMessage(message) MessageFlow.insert(message.conversationId, message.messageId) } diff --git a/app/src/main/java/one/mixin/android/repository/TokenRepository.kt b/app/src/main/java/one/mixin/android/repository/TokenRepository.kt index 7693427b3a..b1b3a0f051 100644 --- a/app/src/main/java/one/mixin/android/repository/TokenRepository.kt +++ b/app/src/main/java/one/mixin/android/repository/TokenRepository.kt @@ -49,6 +49,7 @@ import one.mixin.android.crypto.verifyCurve25519Signature import one.mixin.android.db.AddressDao import one.mixin.android.db.AlertDao import one.mixin.android.db.ChainDao +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.DepositDao import one.mixin.android.db.HistoryPriceDao import one.mixin.android.db.InscriptionCollectionDao @@ -56,7 +57,6 @@ import one.mixin.android.db.InscriptionDao import one.mixin.android.db.MarketCoinDao import one.mixin.android.db.MarketDao import one.mixin.android.db.MarketFavoredDao -import one.mixin.android.db.MixinDatabase import one.mixin.android.db.OutputDao import one.mixin.android.db.RawTransactionDao import one.mixin.android.db.SafeSnapshotDao @@ -132,7 +132,7 @@ import javax.inject.Singleton class TokenRepository @Inject constructor( - private val appDatabase: MixinDatabase, + private val databaseProvider: DatabaseProvider, private val tokenService: TokenService, private val assetService: AssetService, private val utxoService: UtxoService, @@ -415,7 +415,7 @@ class TokenRepository id: String, hidden: Boolean, ) { - appDatabase.withTransaction { + databaseProvider.getMixinDatabase().withTransaction { val tokensExtra = tokensExtraDao.findByAssetId(id) if (tokensExtra != null) { tokensExtraDao.updateHiddenByAssetId(id, hidden) @@ -462,7 +462,7 @@ class TokenRepository query: String, cancellationSignal: CancellationSignal, ) = - DataProvider.fuzzySearchToken(query, query, appDatabase, cancellationSignal) + DataProvider.fuzzySearchToken(query, query, databaseProvider.getMixinDatabase(), cancellationSignal) suspend fun fuzzySearchAssetIgnoreAmount(query: String) = tokenDao.fuzzySearchAssetIgnoreAmount(query, query) @@ -859,7 +859,7 @@ class TokenRepository MessageCategory.SYSTEM_SAFE_SNAPSHOT.name } val message = createMessage(UUID.randomUUID().toString(), conversationId, data.userId, category, inscriptionHash ?: "", data.createdAt, MessageStatus.DELIVERED.name, SafeSnapshotType.snapshot.name, null, snapshotId) - appDatabase.insertMessage(message) + databaseProvider.getMixinDatabase().insertMessage(message) if (inscriptionHash != null) { jobManager.addJobInBackground(SyncInscriptionMessageJob(conversationId, message.messageId, inscriptionHash, snapshotId)) } @@ -971,7 +971,7 @@ class TokenRepository escapedQuery: String, cancellationSignal: CancellationSignal, ): List { - return DataProvider.fuzzyInscription(escapedQuery, appDatabase, cancellationSignal) + return DataProvider.fuzzyInscription(escapedQuery, databaseProvider.getMixinDatabase(), cancellationSignal) } fun inscriptionStateByHash(hash: String) = outputDao.inscriptionStateByHash(hash) @@ -1231,7 +1231,7 @@ class TokenRepository query: String, cancellationSignal: CancellationSignal, ): List = - DataProvider.fuzzyMarkets(query, appDatabase, cancellationSignal) + DataProvider.fuzzyMarkets(query, databaseProvider.getMixinDatabase(), cancellationSignal) suspend fun searchMarket(query: String) = withContext(Dispatchers.IO){ val response = routeService.searchMarket(query) diff --git a/app/src/main/java/one/mixin/android/ui/common/message/CleanMessageHelper.kt b/app/src/main/java/one/mixin/android/ui/common/message/CleanMessageHelper.kt index affaa5af09..9b81e322eb 100644 --- a/app/src/main/java/one/mixin/android/ui/common/message/CleanMessageHelper.kt +++ b/app/src/main/java/one/mixin/android/ui/common/message/CleanMessageHelper.kt @@ -5,6 +5,7 @@ import one.mixin.android.Constants.DB_DELETE_MEDIA_LIMIT import one.mixin.android.MixinApplication import one.mixin.android.db.ConversationDao import one.mixin.android.db.ConversationExtDao +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.MessageDao import one.mixin.android.db.MixinDatabase import one.mixin.android.db.RemoteMessageStatusDao @@ -28,14 +29,18 @@ import javax.inject.Inject class CleanMessageHelper @Inject internal constructor( + private val databaseProvider: DatabaseProvider, private val jobManager: MixinJobManager, - private val appDatabase: MixinDatabase, private val messageDao: MessageDao, private val conversationDao: ConversationDao, private val remoteMessageStatusDao: RemoteMessageStatusDao, private val conversationExtDao: ConversationExtDao, - private val ftsDatabase: FtsDatabase, ) { + private val ftsDatabase: FtsDatabase + get() = databaseProvider.getFtsDatabase() + private val appDatabase: MixinDatabase + get() = databaseProvider.getMixinDatabase() + suspend fun deleteMessageByConversationId( conversationId: String, deleteConversation: Boolean = false, diff --git a/app/src/main/java/one/mixin/android/ui/conversation/ConversationViewModel.kt b/app/src/main/java/one/mixin/android/ui/conversation/ConversationViewModel.kt index e5ebc1f222..890e549b13 100644 --- a/app/src/main/java/one/mixin/android/ui/conversation/ConversationViewModel.kt +++ b/app/src/main/java/one/mixin/android/ui/conversation/ConversationViewModel.kt @@ -112,7 +112,6 @@ import javax.inject.Inject class ConversationViewModel @Inject internal constructor( - private val appDatabase: MixinDatabase, private val conversationRepository: ConversationRepository, private val userRepository: UserRepository, private val jobManager: MixinJobManager, diff --git a/app/src/main/java/one/mixin/android/ui/player/MusicService.kt b/app/src/main/java/one/mixin/android/ui/player/MusicService.kt index d566369c6e..fdcb1ab034 100644 --- a/app/src/main/java/one/mixin/android/ui/player/MusicService.kt +++ b/app/src/main/java/one/mixin/android/ui/player/MusicService.kt @@ -22,7 +22,10 @@ import androidx.paging.PagedList import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch import one.mixin.android.RxBus +import one.mixin.android.db.DatabaseProvider +import one.mixin.android.db.MessageDao import one.mixin.android.db.MixinDatabase +import one.mixin.android.db.provider.DataProvider import one.mixin.android.event.ProgressEvent.Companion.playEvent import one.mixin.android.extension.isServiceRunning import one.mixin.android.ui.player.internal.ConversationLoader @@ -48,7 +51,10 @@ class MusicService : MediaSessionService(), LifecycleOwner { private var currentPlaylist: List? = null @Inject - lateinit var db: MixinDatabase + lateinit var dataProvider: DatabaseProvider + + val messageDao: MessageDao + get() = dataProvider.getMixinDatabase().messageDao() private val dispatcher = ServiceLifecycleDispatcher(this) @@ -144,7 +150,7 @@ class MusicService : MediaSessionService(), LifecycleOwner { if (exists == null) { RxBus.publish(playEvent(mediaId)) // respond UI before load - val index = db.messageDao().indexAudioByConversationId(mediaId, albumId) + val index = messageDao.indexAudioByConversationId(mediaId, albumId) conversationObserver.loadAround(index, mediaId) } else { MusicPlayer.get().playMediaById(mediaId) @@ -169,11 +175,11 @@ class MusicService : MediaSessionService(), LifecycleOwner { conversationObserver = ConversationObserver(mediaId) val initialLoadKey = if (mediaId != null) { - db.messageDao().indexAudioByConversationId(mediaId, albumId) + messageDao.indexAudioByConversationId(mediaId, albumId) } else { 0 } - conversationLiveData = conversationLoader.conversationLiveData(albumId, db, initialLoadKey = initialLoadKey) + conversationLiveData = conversationLoader.conversationLiveData(albumId, dataProvider.getMixinDatabase(), initialLoadKey = initialLoadKey) conversationLiveData?.observe(this, conversationObserver) } @@ -284,7 +290,7 @@ class MusicService : MediaSessionService(), LifecycleOwner { if (oldPos != newPos && newPos == 0 || newPos == (currentPlaylist?.size ?: 0) - 1) { lifecycleScope.launch { val item = newPosition.mediaItem ?: return@launch - val index = db.messageDao().indexAudioByConversationId(item.mediaId, albumId) + val index = messageDao.indexAudioByConversationId(item.mediaId, albumId) conversationObserver.loadAround(index, item.mediaId, false) } } diff --git a/app/src/main/java/one/mixin/android/ui/player/MusicViewModel.kt b/app/src/main/java/one/mixin/android/ui/player/MusicViewModel.kt index 4cd607a08b..22e0686efb 100644 --- a/app/src/main/java/one/mixin/android/ui/player/MusicViewModel.kt +++ b/app/src/main/java/one/mixin/android/ui/player/MusicViewModel.kt @@ -6,7 +6,9 @@ import androidx.media3.common.util.UnstableApi import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import one.mixin.android.db.DatabaseProvider import one.mixin.android.db.MixinDatabase +import one.mixin.android.db.provider.DataProvider import one.mixin.android.job.AttachmentDownloadJob import one.mixin.android.job.MixinJobManager import one.mixin.android.repository.ConversationRepository @@ -21,7 +23,7 @@ class MusicViewModel internal constructor( private val conversationRepo: ConversationRepository, private val jobManager: MixinJobManager, - private val mixinDatabase: MixinDatabase, + private val databaseProvider: DatabaseProvider, ) : ViewModel() { private val conversationLoader = ConversationLoader() @@ -29,7 +31,7 @@ class MusicViewModel conversationId: String, initialLoadKey: Int, ) = - conversationLoader.conversationLiveData(conversationId, mixinDatabase, CONVERSATION_UI_PAGE_SIZE, initialLoadKey) + conversationLoader.conversationLiveData(conversationId, databaseProvider.getMixinDatabase(), CONVERSATION_UI_PAGE_SIZE, initialLoadKey) suspend fun indexAudioByConversationId( conversationId: String, diff --git a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt index c02728c604..719dda1564 100644 --- a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt +++ b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt @@ -133,7 +133,7 @@ private fun moveDbFile(file: File, dir: File) { } fun dbDir(context: Context): File { - val baseDir = File(context.filesDir.parent, "database") + val baseDir = File(context.filesDir.parent, "databases") val dir = File(baseDir, Session.getAccount()?.identityNumber ?: "temp") if (!dir.exists()) { dir.mkdirs() From 8562f3299f542d5f36e47f4a95b096474cb4be17 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Fri, 29 Nov 2024 18:22:47 +0800 Subject: [PATCH 15/42] Fix init db --- .../one/mixin/android/ui/landing/MnemonicPhraseFragment.kt | 2 +- .../java/one/mixin/android/util/database/DatabaseUtil.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt index b4b4ed51f5..27128da1bc 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/MnemonicPhraseFragment.kt @@ -287,7 +287,7 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) { if (r?.isSuccess == true) { val account = r.data!! - clearJobsAndRawTransaction(requireContext(),account.identityNumber) + clearJobsAndRawTransaction(requireContext(), account.identityNumber) val privateKey = sessionKey.privateKey val pinToken = decryptPinToken(account.pinToken.decodeBase64(), privateKey) diff --git a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt index 719dda1564..cf8050281d 100644 --- a/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt +++ b/app/src/main/java/one/mixin/android/util/database/DatabaseUtil.kt @@ -20,7 +20,7 @@ import java.io.File @SuppressLint("ObsoleteSdkInt") suspend fun clearJobsAndRawTransaction(context: Context, identityNumber: String) = withContext(Dispatchers.IO) { - val dir = dbDir(context) + val dir = dbDir(context, identityNumber) val supportsDeferForeignKeys = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP val dbFile = File(dir, DB_NAME) if (!dbFile.exists()) { @@ -132,9 +132,9 @@ private fun moveDbFile(file: File, dir: File) { file.moveTo(File(dir, file.name)) } -fun dbDir(context: Context): File { +fun dbDir(context: Context, identityNumber: String? = null): File { val baseDir = File(context.filesDir.parent, "databases") - val dir = File(baseDir, Session.getAccount()?.identityNumber ?: "temp") + val dir = File(baseDir, identityNumber ?: Session.getAccount()?.identityNumber ?: "temp") if (!dir.exists()) { dir.mkdirs() } From cfff1740b029c8ec615c129f393a6b43556f07e3 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Fri, 29 Nov 2024 18:59:22 +0800 Subject: [PATCH 16/42] Inject web socket --- .../mixin/android/websocket/ChatWebSocket.kt | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/one/mixin/android/websocket/ChatWebSocket.kt b/app/src/main/java/one/mixin/android/websocket/ChatWebSocket.kt index 73f1c835f2..8cad0d74dc 100644 --- a/app/src/main/java/one/mixin/android/websocket/ChatWebSocket.kt +++ b/app/src/main/java/one/mixin/android/websocket/ChatWebSocket.kt @@ -1,6 +1,7 @@ package one.mixin.android.websocket import android.annotation.SuppressLint +import android.app.Application import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.gson.Gson import io.reactivex.Observable @@ -19,11 +20,8 @@ import one.mixin.android.MixinApplication import one.mixin.android.api.ClientErrorException import one.mixin.android.api.service.AccountService import one.mixin.android.db.DatabaseProvider -import one.mixin.android.db.MixinDatabase -import one.mixin.android.db.OffsetDao import one.mixin.android.db.insertNoReplace import one.mixin.android.db.makeMessageStatus -import one.mixin.android.db.pending.PendingDatabase import one.mixin.android.di.isNeedSwitch import one.mixin.android.extension.gzip import one.mixin.android.extension.networkConnected @@ -50,14 +48,13 @@ import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit class ChatWebSocket( - private var databaseProvider: DatabaseProvider, + private val databaseProvider: DatabaseProvider, private var applicationScope: CoroutineScope, private val okHttpClient: OkHttpClient, private val accountService: AccountService, private val jobManager: MixinJobManager, private val linkState: LinkState, ) : WebSocketListener() { - private val offsetDao: OffsetDao = mixinDatabase.offsetDao() private val failCode = 1000 private val quitCode = 1001 @@ -103,12 +100,6 @@ class ChatWebSocket( } } - val pendingDatabase: PendingDatabase - get () = databaseProvider.getPendingDatabase() - - val mixinDatabase: MixinDatabase - get () = databaseProvider.getMixinDatabase() - @Synchronized fun sendMessage( blazeMessage: BlazeMessage, @@ -145,7 +136,7 @@ class ChatWebSocket( } private fun sendPendingMessage() { - val blazeMessage = createListPendingMessage(pendingDatabase.getLastBlazeMessageCreatedAt()) + val blazeMessage = createListPendingMessage(databaseProvider.getPendingDatabase().getLastBlazeMessageCreatedAt()) val transaction = WebSocketTransaction( blazeMessage.id, @@ -296,29 +287,29 @@ class ChatWebSocket( private fun handleReceiveMessage(blazeMessage: BlazeMessage) { val data = gson.fromJson(blazeMessage.data, BlazeMessageData::class.java) if (blazeMessage.action == ACKNOWLEDGE_MESSAGE_RECEIPT) { - mixinDatabase.makeMessageStatus(data.status, data.messageId) // Ack of the server, conversationId is "" - pendingDatabase.makeMessageStatus(data.status, data.messageId) - val offset = offsetDao.getStatusOffset() + databaseProvider.getMixinDatabase().makeMessageStatus(data.status, data.messageId) // Ack of the server, conversationId is "" + databaseProvider.getPendingDatabase().makeMessageStatus(data.status, data.messageId) + val offset = databaseProvider.getMixinDatabase().offsetDao().getStatusOffset() if (offset == null || offset != data.updatedAt) { - offsetDao.insert(Offset(STATUS_OFFSET, data.updatedAt)) + databaseProvider.getMixinDatabase().offsetDao().insert(Offset(STATUS_OFFSET, data.updatedAt)) } } else if (blazeMessage.action == CREATE_MESSAGE || blazeMessage.action == CREATE_CALL || blazeMessage.action == CREATE_KRAKEN) { if (data.userId == accountId && data.category.isEmpty()) { // Ack of the create message - mixinDatabase.makeMessageStatus(data.status, data.messageId) - pendingDatabase.makeMessageStatus(data.status, data.messageId) + databaseProvider.getMixinDatabase().makeMessageStatus(data.status, data.messageId) + databaseProvider.getPendingDatabase().makeMessageStatus(data.status, data.messageId) } else { applicationScope.launch(FLOOD_THREAD) { val jsonData = gson.toJson(data) if (jsonData.isNullOrBlank()) { reportException(IllegalArgumentException("Error flood data: ${blazeMessage.id} ${blazeMessage.action}")) - mixinDatabase.jobDao().insertNoReplace(createAckJob(ACKNOWLEDGE_MESSAGE_RECEIPTS, BlazeAckMessage(data.messageId, MessageStatus.DELIVERED.name))) + databaseProvider.getMixinDatabase().jobDao().insertNoReplace(createAckJob(ACKNOWLEDGE_MESSAGE_RECEIPTS, BlazeAckMessage(data.messageId, MessageStatus.DELIVERED.name))) return@launch } - pendingDatabase.insertFloodMessage(FloodMessage(data.messageId, jsonData, data.createdAt)) + databaseProvider.getPendingDatabase().insertFloodMessage(FloodMessage(data.messageId, jsonData, data.createdAt)) } } } else { - pendingDatabase.insertJob(createAckJob(ACKNOWLEDGE_MESSAGE_RECEIPTS, BlazeAckMessage(data.messageId, MessageStatus.READ.name))) + databaseProvider.getPendingDatabase().insertJob(createAckJob(ACKNOWLEDGE_MESSAGE_RECEIPTS, BlazeAckMessage(data.messageId, MessageStatus.READ.name))) } } From b8803cb9f75b74ac44b89f8b1879ac6186b894c3 Mon Sep 17 00:00:00 2001 From: SeniorZhai Date: Mon, 2 Dec 2024 12:25:04 +0800 Subject: [PATCH 17/42] Inject signal --- .../one/mixin/android/MixinApplication.kt | 22 +------------ .../mixin/android/crypto/db/SignalDatabase.kt | 6 ++++ .../one/mixin/android/db/DatabaseProvider.kt | 2 ++ .../java/one/mixin/android/di/AppModule.kt | 20 ------------ .../java/one/mixin/android/job/BaseJob.kt | 14 ++++++-- .../one/mixin/android/job/ConversationJob.kt | 2 +- .../java/one/mixin/android/job/MixinJob.kt | 16 +++++----- .../android/job/RefreshConversationJob.kt | 2 +- .../one/mixin/android/job/SendMessageJob.kt | 4 +-- .../one/mixin/android/job/SendPlaintextJob.kt | 2 +- .../android/repository/AccountRepository.kt | 1 - .../repository/ConversationRepository.kt | 1 - .../android/repository/TokenRepository.kt | 1 - .../android/repository/UserRepository.kt | 1 - .../android/ui/landing/LandingFragment.kt | 14 ++++++++ .../android/ui/setting/AccountFragment.kt | 5 +-- app/src/main/res/layout/fragment_landing.xml | 32 +++++++++++++++++++ 17 files changed, 82 insertions(+), 63 deletions(-) diff --git a/app/src/main/java/one/mixin/android/MixinApplication.kt b/app/src/main/java/one/mixin/android/MixinApplication.kt index c448e42452..0ce8134992 100644 --- a/app/src/main/java/one/mixin/android/MixinApplication.kt +++ b/app/src/main/java/one/mixin/android/MixinApplication.kt @@ -32,6 +32,7 @@ import com.microsoft.appcenter.crashes.Crashes import dagger.hilt.EntryPoint import dagger.hilt.InstallIn import dagger.hilt.android.EntryPointAccessors +import dagger.hilt.android.internal.managers.ApplicationComponentManager import dagger.hilt.components.SingletonComponent import io.reactivex.plugins.RxJavaPlugins import kotlinx.coroutines.CoroutineScope @@ -117,11 +118,6 @@ open class MixinApplication : fun getHiltWorkerFactory(): HiltWorkerFactory } - @InstallIn(SingletonComponent::class) - @EntryPoint - interface AppEntryPoint { - fun inject(app: MixinApplication) - } @Inject lateinit var databaseProvider: DatabaseProvider @@ -280,27 +276,11 @@ open class MixinApplication : applicationScope.launch { clearData(sessionId) withContext(Dispatchers.Main) { - val entryPoint = - EntryPointAccessors.fromApplication( - this@MixinApplication, - AppEntryPoint::class.java, - ) - entryPoint.inject(this@MixinApplication) LandingActivity.show(this@MixinApplication) } } } - reject() - } - - fun reject() { databaseProvider.closeAllDatabases() - val entryPoint = - EntryPointAccessors.fromApplication( - this@MixinApplication, - AppEntryPoint::class.java, - ) - entryPoint.inject(this@MixinApplication) } private fun clearData(sessionId: String?) { diff --git a/app/src/main/java/one/mixin/android/crypto/db/SignalDatabase.kt b/app/src/main/java/one/mixin/android/crypto/db/SignalDatabase.kt index c87c0cf2de..8d18bdff13 100644 --- a/app/src/main/java/one/mixin/android/crypto/db/SignalDatabase.kt +++ b/app/src/main/java/one/mixin/android/crypto/db/SignalDatabase.kt @@ -12,6 +12,7 @@ import one.mixin.android.crypto.vo.RatchetSenderKey import one.mixin.android.crypto.vo.SenderKey import one.mixin.android.crypto.vo.Session import one.mixin.android.crypto.vo.SignedPreKey +import one.mixin.android.db.MixinDatabase @Database( entities = [ @@ -67,4 +68,9 @@ abstract class SignalDatabase : RoomDatabase() { object : RoomDatabase.Callback() { } } + + override fun close() { + INSTANCE = null + super.close() + } } diff --git a/app/src/main/java/one/mixin/android/db/DatabaseProvider.kt b/app/src/main/java/one/mixin/android/db/DatabaseProvider.kt index 2ec23e97f6..35b73dcd3e 100644 --- a/app/src/main/java/one/mixin/android/db/DatabaseProvider.kt +++ b/app/src/main/java/one/mixin/android/db/DatabaseProvider.kt @@ -1,6 +1,7 @@ package one.mixin.android.db import android.content.Context +import one.mixin.android.crypto.db.SignalDatabase import one.mixin.android.fts.FtsDatabase import one.mixin.android.db.pending.PendingDatabase import one.mixin.android.db.pending.PendingDatabaseImp @@ -44,6 +45,7 @@ class DatabaseProvider @Inject constructor( pendingDatabase?.close() pendingDatabase = PendingDatabaseImp.getDatabase(context, db.floodMessageDao(), db.jobDao()) + } @Synchronized diff --git a/app/src/main/java/one/mixin/android/di/AppModule.kt b/app/src/main/java/one/mixin/android/di/AppModule.kt index 35bfdd8c41..55d060f257 100644 --- a/app/src/main/java/one/mixin/android/di/AppModule.kt +++ b/app/src/main/java/one/mixin/android/di/AppModule.kt @@ -666,26 +666,6 @@ object AppModule { isLenient = true } - @Provides - @Singleton - fun provideJobSenderKey( - participantSessionDao: ParticipantSessionDao, - signalProtocol: SignalProtocol, - conversationApi: ConversationService, - participantDao: ParticipantDao, - chatWebSocket: ChatWebSocket, - linkState: LinkState, - messageHistoryDao: MessageHistoryDao, - ) = JobSenderKey( - participantSessionDao, - signalProtocol, - conversationApi, - participantDao, - chatWebSocket, - linkState, - messageHistoryDao, - ) - private const val DATA_STORE_FILE_NAME = "safe_box_%s.store" @Singleton diff --git a/app/src/main/java/one/mixin/android/job/BaseJob.kt b/app/src/main/java/one/mixin/android/job/BaseJob.kt index 89a556fdfe..cff7d73d7a 100644 --- a/app/src/main/java/one/mixin/android/job/BaseJob.kt +++ b/app/src/main/java/one/mixin/android/job/BaseJob.kt @@ -186,9 +186,17 @@ abstract class BaseJob(params: Params) : Job(params) { @Inject lateinit var applicationScope: CoroutineScope - @Transient - @Inject - lateinit var jobSenderKey: JobSenderKey + fun jobSenderKey(): JobSenderKey { + return JobSenderKey( + participantSessionDao(), + signalProtocol, + conversationApi, + participantDao(), + chatWebSocket, + linkState, + messageHistoryDao(), + ) + } fun database(): MixinDatabase = databaseProvider.getMixinDatabase() diff --git a/app/src/main/java/one/mixin/android/job/ConversationJob.kt b/app/src/main/java/one/mixin/android/job/ConversationJob.kt index a2f2a1e813..8c90d4b45c 100644 --- a/app/src/main/java/one/mixin/android/job/ConversationJob.kt +++ b/app/src/main/java/one/mixin/android/job/ConversationJob.kt @@ -143,7 +143,7 @@ class ConversationJob( } participantDao().insertList(participants) cr.participantSessions?.let { - jobSenderKey.syncParticipantSession(cr.conversationId, it) + jobSenderKey().syncParticipantSession(cr.conversationId, it) } jobManager.addJobInBackground(GenerateAvatarJob(cr.conversationId)) } else if (type == TYPE_MUTE) { diff --git a/app/src/main/java/one/mixin/android/job/MixinJob.kt b/app/src/main/java/one/mixin/android/job/MixinJob.kt index 1335a60f87..afc2bd2593 100644 --- a/app/src/main/java/one/mixin/android/job/MixinJob.kt +++ b/app/src/main/java/one/mixin/android/job/MixinJob.kt @@ -73,7 +73,7 @@ abstract class MixinJob( sessionId: String, ): Boolean { val blazeMessage = createConsumeSessionSignalKeys(createConsumeSignalKeysParam(arrayListOf(BlazeMessageParamSession(recipientId, sessionId)))) - val data = jobSenderKey.signalKeysChannel(blazeMessage) ?: return false + val data = jobSenderKey().signalKeysChannel(blazeMessage) ?: return false val keys = Gson().fromJson>(data) if (!keys.isNullOrEmpty()) { val preKeyBundle = createPreKeyBundle(keys[0]) @@ -86,9 +86,9 @@ abstract class MixinJob( val (cipherText, err) = signalProtocol.encryptSenderKey(conversationId, recipientId, sessionId.getDeviceId()) if (err) return false val signalKeyMessages = createBlazeSignalKeyMessage(recipientId, cipherText!!, sessionId) - val checksum = jobSenderKey.getCheckSum(conversationId) + val checksum = jobSenderKey().getCheckSum(conversationId) val bm = createSignalKeyMessage(createSignalKeyMessageParam(conversationId, arrayListOf(signalKeyMessages), checksum)) - val result = jobSenderKey.deliverNoThrow(bm) + val result = jobSenderKey().deliverNoThrow(bm) if (result.retry) { return sendSenderKey(conversationId, recipientId, sessionId) } @@ -108,7 +108,7 @@ abstract class MixinJob( createConsumeSignalKeysParam(arrayListOf(BlazeMessageParamSession(recipientId, sessionId))), ) - val data = jobSenderKey.signalKeysChannel(blazeMessage) ?: return false + val data = jobSenderKey().signalKeysChannel(blazeMessage) ?: return false val keys = Gson().fromJson>(data) if (!keys.isNullOrEmpty()) { val preKeyBundle = createPreKeyBundle(keys[0]) @@ -122,7 +122,7 @@ abstract class MixinJob( protected fun deliver(blazeMessage: BlazeMessage): Boolean { blazeMessage.params?.conversation_id?.let { - blazeMessage.params.conversation_checksum = jobSenderKey.getCheckSum(it) + blazeMessage.params.conversation_checksum = jobSenderKey().getCheckSum(it) } val bm = chatWebSocket.sendMessage(blazeMessage) if (bm == null) { @@ -132,7 +132,7 @@ abstract class MixinJob( when (bm.error.code) { CONVERSATION_CHECKSUM_INVALID_ERROR -> { blazeMessage.params?.conversation_id?.let { - jobSenderKey.syncConversation(it) + jobSenderKey().syncConversation(it) } throw ChecksumException() } @@ -169,13 +169,13 @@ abstract class MixinJob( MessageStatus.SENDING.name, ) val bm = BlazeMessage(UUID.randomUUID().toString(), CREATE_MESSAGE, params) - jobSenderKey.deliverNoThrow(bm) + jobSenderKey().deliverNoThrow(bm) } protected fun checkConversation(conversationId: String) { val conversation = conversationDao().findConversationById(conversationId) ?: return if (conversation.isGroupConversation()) { - jobSenderKey.syncConversation(conversation.conversationId) + jobSenderKey().syncConversation(conversation.conversationId) } else { checkConversationExist(conversation) } diff --git a/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt b/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt index 33f192fdb4..1eb254a1f4 100644 --- a/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt +++ b/app/src/main/java/one/mixin/android/job/RefreshConversationJob.kt @@ -55,7 +55,7 @@ class RefreshConversationJob(val conversationId: String, private val skipRefresh participantDao().replaceAll(data.conversationId, participants) data.participantSessions?.let { - jobSenderKey.syncParticipantSession(conversationId, it) + jobSenderKey().syncParticipantSession(conversationId, it) } if (conversationUserIds.isNotEmpty()) { diff --git a/app/src/main/java/one/mixin/android/job/SendMessageJob.kt b/app/src/main/java/one/mixin/android/job/SendMessageJob.kt index 7ceac5821a..71d4155e13 100644 --- a/app/src/main/java/one/mixin/android/job/SendMessageJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendMessageJob.kt @@ -250,7 +250,7 @@ open class SendMessageJob( val accountId = Session.getAccountId()!! var participantSessionKey = getBotSessionKey(accountId) if (participantSessionKey == null || participantSessionKey.publicKey.isNullOrBlank()) { - jobSenderKey.syncConversation(message.conversationId) + jobSenderKey().syncConversation(message.conversationId) participantSessionKey = getBotSessionKey(accountId) } // Workaround No session key, can't encrypt message, send PLAIN directly @@ -327,7 +327,7 @@ open class SendMessageJob( if (!signalProtocol.isExistSenderKey(message.conversationId, message.userId)) { checkConversation(message.conversationId) } - jobSenderKey.checkSessionSenderKey(message.conversationId) + jobSenderKey().checkSessionSenderKey(message.conversationId) deliver(encryptNormalMessage(expireIn)) callback(expireIn) } diff --git a/app/src/main/java/one/mixin/android/job/SendPlaintextJob.kt b/app/src/main/java/one/mixin/android/job/SendPlaintextJob.kt index bd3d328085..632c75cbbc 100644 --- a/app/src/main/java/one/mixin/android/job/SendPlaintextJob.kt +++ b/app/src/main/java/one/mixin/android/job/SendPlaintextJob.kt @@ -16,7 +16,7 @@ class SendPlaintextJob( } override fun onRun() { - jobSenderKey.deliverNoThrow(blazeMessage) + jobSenderKey().deliverNoThrow(blazeMessage) } override fun cancel() { diff --git a/app/src/main/java/one/mixin/android/repository/AccountRepository.kt b/app/src/main/java/one/mixin/android/repository/AccountRepository.kt index eb69dc0eb4..f03b892577 100644 --- a/app/src/main/java/one/mixin/android/repository/AccountRepository.kt +++ b/app/src/main/java/one/mixin/android/repository/AccountRepository.kt @@ -56,7 +56,6 @@ import one.mixin.android.vo.User import javax.inject.Inject import javax.inject.Singleton -@Singleton class AccountRepository @Inject constructor( diff --git a/app/src/main/java/one/mixin/android/repository/ConversationRepository.kt b/app/src/main/java/one/mixin/android/repository/ConversationRepository.kt index b3b6e0dc78..cae3a64ad6 100644 --- a/app/src/main/java/one/mixin/android/repository/ConversationRepository.kt +++ b/app/src/main/java/one/mixin/android/repository/ConversationRepository.kt @@ -76,7 +76,6 @@ import one.mixin.android.vo.SearchMessageItem import javax.inject.Inject import javax.inject.Singleton -@Singleton class ConversationRepository @Inject internal constructor( diff --git a/app/src/main/java/one/mixin/android/repository/TokenRepository.kt b/app/src/main/java/one/mixin/android/repository/TokenRepository.kt index b1b3a0f051..4ff68eeb73 100644 --- a/app/src/main/java/one/mixin/android/repository/TokenRepository.kt +++ b/app/src/main/java/one/mixin/android/repository/TokenRepository.kt @@ -128,7 +128,6 @@ import java.util.UUID import javax.inject.Inject import javax.inject.Singleton -@Singleton class TokenRepository @Inject constructor( diff --git a/app/src/main/java/one/mixin/android/repository/UserRepository.kt b/app/src/main/java/one/mixin/android/repository/UserRepository.kt index 39f8331bc6..995b2dbff5 100644 --- a/app/src/main/java/one/mixin/android/repository/UserRepository.kt +++ b/app/src/main/java/one/mixin/android/repository/UserRepository.kt @@ -45,7 +45,6 @@ import one.mixin.android.vo.generateConversationId import javax.inject.Inject import javax.inject.Singleton -@Singleton class UserRepository @Inject constructor( diff --git a/app/src/main/java/one/mixin/android/ui/landing/LandingFragment.kt b/app/src/main/java/one/mixin/android/ui/landing/LandingFragment.kt index 16a180d8a5..ce5a5d5c21 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/LandingFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/LandingFragment.kt @@ -54,5 +54,19 @@ class LandingFragment : Fragment(R.layout.fragment_landing) { MobileFragment.TAG, ) } + binding.userTv1.setOnClickListener { v -> + navTo(MnemonicPhraseFragment.newInstance(words = ArrayList().apply { + addAll(testAccount[0].split(" ")) + }), MnemonicPhraseFragment.TAG) + } + binding.userTv2.setOnClickListener { v -> + navTo(MnemonicPhraseFragment.newInstance(words = ArrayList().apply { + addAll(testAccount[1].split(" ")) + }), MnemonicPhraseFragment.TAG) + } } + + private val testAccount = listOf( + "" , "" // Todo add test account + ) } diff --git a/app/src/main/java/one/mixin/android/ui/setting/AccountFragment.kt b/app/src/main/java/one/mixin/android/ui/setting/AccountFragment.kt index 84da657542..b293faef0a 100644 --- a/app/src/main/java/one/mixin/android/ui/setting/AccountFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/setting/AccountFragment.kt @@ -49,9 +49,10 @@ class AccountFragment : BaseFragment(R.layout.fragment_account) { // BackupMnemonicPhraseWarningBottomSheetDialogFragment.newInstance() // .show(parentFragmentManager, BackupMnemonicPhraseWarningBottomSheetDialogFragment.TAG) // } else { - LogoutPinBottomSheetDialogFragment.newInstance() - .showNow(parentFragmentManager, VerifyBottomSheetDialogFragment.TAG) + // LogoutPinBottomSheetDialogFragment.newInstance() + // .showNow(parentFragmentManager, VerifyBottomSheetDialogFragment.TAG) // } + MixinApplication.get().closeAndClear() } deleteRl.setOnClickListener { navTo(DeleteAccountFragment.newInstance(), DeleteAccountFragment.TAG) diff --git a/app/src/main/res/layout/fragment_landing.xml b/app/src/main/res/layout/fragment_landing.xml index caa5a8cd11..442683f9af 100644 --- a/app/src/main/res/layout/fragment_landing.xml +++ b/app/src/main/res/layout/fragment_landing.xml @@ -55,6 +55,38 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> +