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 1efa892733..9370970091 100644 --- a/app/src/main/java/one/mixin/android/repository/TokenRepository.kt +++ b/app/src/main/java/one/mixin/android/repository/TokenRepository.kt @@ -562,10 +562,6 @@ class TokenRepository fun getPendingDisplays() = safeSnapshotDao.getPendingDisplays() - suspend fun pendingDeposits( - asset: String, - ) = tokenService.pendingDeposits(asset) - suspend fun clearAllPendingDeposits() = safeSnapshotDao.clearAllPendingDeposits() suspend fun clearPendingDepositsByAssetId(assetId: String) = diff --git a/app/src/main/java/one/mixin/android/repository/Web3Repository.kt b/app/src/main/java/one/mixin/android/repository/Web3Repository.kt index a9f3e5ee87..2efb7d3203 100644 --- a/app/src/main/java/one/mixin/android/repository/Web3Repository.kt +++ b/app/src/main/java/one/mixin/android/repository/Web3Repository.kt @@ -16,6 +16,7 @@ import one.mixin.android.crypto.CryptoWalletHelper import one.mixin.android.db.TokenDao import one.mixin.android.db.property.Web3PropertyHelper import one.mixin.android.db.web3.Web3AddressDao +import one.mixin.android.db.web3.Web3ChainDao import one.mixin.android.db.web3.Web3TokenDao import one.mixin.android.db.web3.Web3TokensExtraDao import one.mixin.android.db.web3.Web3TransactionDao @@ -38,11 +39,13 @@ class Web3Repository @Inject constructor( @ApplicationContext private val context: Context, + val tokenService: TokenService, val routeService: RouteService, val web3TokenDao: Web3TokenDao, val web3TransactionDao: Web3TransactionDao, val web3TokensExtraDao: Web3TokensExtraDao, val web3AddressDao: Web3AddressDao, + val web3ChainDao: Web3ChainDao, val web3WalletDao: Web3WalletDao, val tokenRepository: TokenRepository, val userRepository: UserRepository @@ -211,6 +214,42 @@ constructor( suspend fun getWalletByDestination(destination: String) = web3AddressDao.getWalletByDestination(destination) + suspend fun getWalletAddresses(walletId: String) = routeService.getWalletAddresses(walletId) + + suspend fun getWalletAssets(walletId: String) = routeService.getWalletAssets(walletId) + + suspend fun insertWalletAddresses(addresses: List) { + web3AddressDao.insertList(addresses) + } + + suspend fun insertWalletAssets(assets: List) { + web3TokenDao.insertList(assets) + } + + suspend fun updateBalanceToZeroForMissingAssets(walletId: String, assetIds: List) { + web3TokenDao.updateBalanceToZeroForMissingAssets(walletId, assetIds) + } + + suspend fun updateAllBalancesToZero(walletId: String) { + web3TokenDao.updateAllBalancesToZero(walletId) + } + + suspend fun insertTokensExtra(extras: List) { + web3TokensExtraDao.insertList(extras) + } + + suspend fun findTokensExtraByAssetId(assetId: String, walletId: String): Web3TokensExtra? { + return web3TokensExtraDao.findByAssetId(assetId, walletId) + } + + suspend fun chainExists(chainId: String) = web3ChainDao.chainExists(chainId) + + suspend fun insertChain(chain: one.mixin.android.db.web3.vo.Web3Chain) { + web3ChainDao.insert(chain) + } + + suspend fun getChainById(chainId: String) = tokenService.getChainById(chainId) + // Only deposit display suspend fun getTokenByWalletAndAssetId(walletId: String, assetId: String): Web3TokenItem? { val localToken = web3TokenDao.web3TokenItemById(walletId, assetId) diff --git a/app/src/main/java/one/mixin/android/ui/address/TransferDestinationInputFragment.kt b/app/src/main/java/one/mixin/android/ui/address/TransferDestinationInputFragment.kt index 725221e55a..a589606367 100644 --- a/app/src/main/java/one/mixin/android/ui/address/TransferDestinationInputFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/address/TransferDestinationInputFragment.kt @@ -64,7 +64,6 @@ import one.mixin.android.util.isIcapAddress import one.mixin.android.util.rxpermission.RxPermissions import one.mixin.android.util.viewBinding import one.mixin.android.vo.Address -import one.mixin.android.vo.WalletCategory import one.mixin.android.vo.WithdrawalMemoPossibility import one.mixin.android.vo.safe.TokenItem import timber.log.Timber diff --git a/app/src/main/java/one/mixin/android/ui/common/refresh/PendingDepositRefreshHelper.kt b/app/src/main/java/one/mixin/android/ui/common/refresh/PendingDepositRefreshHelper.kt new file mode 100644 index 0000000000..7c58b334c0 --- /dev/null +++ b/app/src/main/java/one/mixin/android/ui/common/refresh/PendingDepositRefreshHelper.kt @@ -0,0 +1,79 @@ +package one.mixin.android.ui.common.refresh + +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import one.mixin.android.api.handleMixinResponse +import one.mixin.android.ui.wallet.WalletViewModel +import one.mixin.android.util.reportException +import one.mixin.android.vo.safe.toSnapshot +import timber.log.Timber + +object PendingDepositRefreshHelper { + + fun startRefreshData( + fragment: Fragment, + walletViewModel: WalletViewModel, + refreshJob: Job?, + onPendingDepositUpdated: (() -> Unit)? = null + ): Job? { + refreshJob?.cancel() + return fragment.lifecycleScope.launch(Dispatchers.IO) { + refreshPendingDepositData( + walletViewModel, + onPendingDepositUpdated + ) + } + } + + fun cancelRefreshData(refreshJob: Job?): Job? { + refreshJob?.cancel() + return null + } + + private suspend fun refreshPendingDepositData( + walletViewModel: WalletViewModel, + onPendingDepositUpdated: (() -> Unit)? = null + ) { + try { + while (true) { + handleMixinResponse( + invokeNetwork = { walletViewModel.allPendingDeposit() }, + exceptionBlock = { e -> + reportException(e) + false + }, + successBlock = { + val pendingDeposits = it.data ?: emptyList() + val destinationTags = walletViewModel.findDepositEntryDestinations() + pendingDeposits + .filter { pd -> + destinationTags.any { dt -> + dt.destination == pd.destination && (dt.tag.isNullOrBlank() || dt.tag == pd.tag) + } + } + .map { pd -> pd.toSnapshot() }.let { snapshots -> + // If there are no pending deposit snapshots belonging to the current user, clear all pending deposits + if (snapshots.isEmpty()) { + walletViewModel.clearAllPendingDeposits() + return@let + } + snapshots.map { it.assetId }.distinct().forEach { + walletViewModel.findOrSyncAsset(it) + } + walletViewModel.insertPendingDeposit(snapshots) + onPendingDepositUpdated?.invoke() + } + }, + ) + + delay(10_000) + } + } catch (e: Exception) { + Timber.e(e, "Error refreshing pending deposits") + } + } +} diff --git a/app/src/main/java/one/mixin/android/ui/common/PendingTransactionRefreshHelper.kt b/app/src/main/java/one/mixin/android/ui/common/refresh/PendingWeb3TransactionRefreshHelper.kt similarity index 93% rename from app/src/main/java/one/mixin/android/ui/common/PendingTransactionRefreshHelper.kt rename to app/src/main/java/one/mixin/android/ui/common/refresh/PendingWeb3TransactionRefreshHelper.kt index 13ac11a64e..c9a577a6ee 100644 --- a/app/src/main/java/one/mixin/android/ui/common/PendingTransactionRefreshHelper.kt +++ b/app/src/main/java/one/mixin/android/ui/common/refresh/PendingWeb3TransactionRefreshHelper.kt @@ -1,7 +1,8 @@ -package one.mixin.android.ui.common +package one.mixin.android.ui.common.refresh import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -12,7 +13,7 @@ import one.mixin.android.ui.home.web3.Web3ViewModel import one.mixin.android.web3.js.Web3Signer import timber.log.Timber -object PendingTransactionRefreshHelper { +object PendingWeb3TransactionRefreshHelper { fun startRefreshData( fragment: Fragment, @@ -22,7 +23,7 @@ object PendingTransactionRefreshHelper { onTransactionStatusUpdated: ((hash: String, newStatus: String) -> Unit)? = null ): Job? { refreshJob?.cancel() - return fragment.lifecycleScope.launch { + return fragment.lifecycleScope.launch(Dispatchers.IO) { refreshTransactionData( Web3Signer.currentWalletId, web3ViewModel, @@ -74,7 +75,7 @@ object PendingTransactionRefreshHelper { } } } - delay(5_000) + delay(10_000) } } } catch (e: Exception) { diff --git a/app/src/main/java/one/mixin/android/ui/common/refresh/WalletRefreshHelper.kt b/app/src/main/java/one/mixin/android/ui/common/refresh/WalletRefreshHelper.kt new file mode 100644 index 0000000000..289babd899 --- /dev/null +++ b/app/src/main/java/one/mixin/android/ui/common/refresh/WalletRefreshHelper.kt @@ -0,0 +1,95 @@ +package one.mixin.android.ui.common.refresh + +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import one.mixin.android.ui.home.web3.Web3ViewModel +import one.mixin.android.util.reportException +import timber.log.Timber + +object WalletRefreshHelper { + + fun startRefreshData( + fragment: Fragment, + web3ViewModel: Web3ViewModel, + walletId: String?, + refreshJob: Job?, + onWalletUpdated: (() -> Unit)? = null + ): Job? { + refreshJob?.cancel() + return fragment.lifecycleScope.launch(Dispatchers.IO) { + refreshWalletData( + web3ViewModel, + walletId, + onWalletUpdated + ) + } + } + + fun cancelRefreshData(refreshJob: Job?): Job? { + refreshJob?.cancel() + return null + } + + private suspend fun refreshWalletData( + web3ViewModel: Web3ViewModel, + walletId: String?, + onWalletUpdated: (() -> Unit)? = null + ) { + try { + while (true) { + if (walletId == null) { + val allWallets = web3ViewModel.getAllWallets() + if (allWallets.isEmpty()) { + Timber.w("No wallets found, stopping refresh") + break + } + + Timber.d("Found ${allWallets.size} wallets to refresh") + + for (wallet in allWallets) { + try { + web3ViewModel.refreshWalletAddresses(wallet.id) + + web3ViewModel.refreshWalletAssets(wallet.id) + + Timber.d("Successfully refreshed wallet: ${wallet.id}") + } catch (e: Exception) { + Timber.e(e, "Error refreshing wallet: ${wallet.id}") + reportException(e) + } + } + + onWalletUpdated?.invoke() + Timber.d("Successfully refreshed all ${allWallets.size} wallets") + } else { + val wallet = web3ViewModel.findWalletById(walletId) + if (wallet == null) { + Timber.w("Wallet not found: $walletId, stopping refresh") + break + } + + try { + web3ViewModel.refreshWalletAddresses(walletId) + + web3ViewModel.refreshWalletAssets(walletId) + + onWalletUpdated?.invoke() + Timber.d("Successfully refreshed wallet: $walletId") + + } catch (e: Exception) { + Timber.e(e, "Error refreshing wallet: $walletId") + reportException(e) + } + } + + delay(10_000) // 10 seconds refresh interval + } + } catch (e: Exception) { + Timber.e(e, "Error in wallet refresh loop for walletId: $walletId") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/one/mixin/android/ui/conversation/ConversationFragment.kt b/app/src/main/java/one/mixin/android/ui/conversation/ConversationFragment.kt index 9bcedf4c60..5a3a0a25d6 100644 --- a/app/src/main/java/one/mixin/android/ui/conversation/ConversationFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/conversation/ConversationFragment.kt @@ -126,7 +126,6 @@ import one.mixin.android.extension.isStickerSupport import one.mixin.android.extension.isVideo import one.mixin.android.extension.isWebp import one.mixin.android.extension.lateOneHours -import one.mixin.android.extension.navTo import one.mixin.android.extension.networkConnected import one.mixin.android.extension.nowInUtc import one.mixin.android.extension.openAsUrlOrWeb @@ -167,11 +166,9 @@ import one.mixin.android.ui.call.GroupUsersBottomSheetDialogFragment.Companion.G import one.mixin.android.ui.common.GroupBottomSheetDialogFragment import one.mixin.android.ui.common.LinkFragment import one.mixin.android.ui.common.UserBottomSheetDialogFragment -import one.mixin.android.ui.common.biometric.buildEmptyTransferBiometricItem import one.mixin.android.ui.common.message.ChatRoomHelper import one.mixin.android.ui.common.profile.ProfileBottomSheetDialogFragment import one.mixin.android.ui.common.showUserBottom -import one.mixin.android.ui.conversation.adapter.GalleryCallback import one.mixin.android.ui.conversation.adapter.MentionAdapter import one.mixin.android.ui.conversation.adapter.MentionAdapter.OnUserClickListener import one.mixin.android.ui.conversation.adapter.Menu @@ -205,9 +202,8 @@ import one.mixin.android.ui.sticker.StickerPreviewBottomSheetFragment import one.mixin.android.ui.tip.TipActivity import one.mixin.android.ui.tip.TipType import one.mixin.android.ui.wallet.AssetListBottomSheetDialogFragment -import one.mixin.android.ui.wallet.AssetListBottomSheetDialogFragment.Companion.TYPE_FROM_TRANSFER import one.mixin.android.ui.wallet.AssetListBottomSheetDialogFragment.Companion.ASSET_PREFERENCE -import one.mixin.android.ui.wallet.InputFragment +import one.mixin.android.ui.wallet.AssetListBottomSheetDialogFragment.Companion.TYPE_FROM_TRANSFER import one.mixin.android.ui.wallet.TransactionFragment import one.mixin.android.ui.wallet.WalletActivity import one.mixin.android.ui.web.WebActivity @@ -238,7 +234,6 @@ import one.mixin.android.vo.MessageItem import one.mixin.android.vo.MessageStatus import one.mixin.android.vo.ParticipantRole import one.mixin.android.vo.PinMessageData -import one.mixin.android.vo.Plan import one.mixin.android.vo.Sticker import one.mixin.android.vo.TranscriptData import one.mixin.android.vo.TranscriptMessage @@ -282,11 +277,9 @@ import one.mixin.android.widget.ChatControlView import one.mixin.android.widget.CircleProgress.Companion.STATUS_PLAY import one.mixin.android.widget.ContentEditText import one.mixin.android.widget.DraggableRecyclerView -import one.mixin.android.widget.DraggableRecyclerView.Companion.FLING_DOWN import one.mixin.android.widget.LinearSmoothScrollerCustom import one.mixin.android.widget.MixinHeadersDecoration import one.mixin.android.widget.buildBottomSheetView -import one.mixin.android.widget.gallery.internal.entity.Item import one.mixin.android.widget.gallery.ui.GalleryActivity.Companion.IS_VIDEO import one.mixin.android.widget.keyboard.KeyboardLayout.OnKeyboardHiddenListener import one.mixin.android.widget.keyboard.KeyboardLayout.OnKeyboardShownListener diff --git a/app/src/main/java/one/mixin/android/ui/conversation/adapter/MessageAdapter.kt b/app/src/main/java/one/mixin/android/ui/conversation/adapter/MessageAdapter.kt index bf99adcde6..ff769ad47d 100644 --- a/app/src/main/java/one/mixin/android/ui/conversation/adapter/MessageAdapter.kt +++ b/app/src/main/java/one/mixin/android/ui/conversation/adapter/MessageAdapter.kt @@ -92,7 +92,6 @@ import one.mixin.android.vo.AppCardData import one.mixin.android.vo.MessageCategory import one.mixin.android.vo.MessageItem import one.mixin.android.vo.MessageStatus -import one.mixin.android.vo.Plan import one.mixin.android.vo.User import one.mixin.android.vo.create import one.mixin.android.vo.isAppCard diff --git a/app/src/main/java/one/mixin/android/ui/conversation/chathistory/holder/LocationHolder.kt b/app/src/main/java/one/mixin/android/ui/conversation/chathistory/holder/LocationHolder.kt index dafa10912f..f58af9f650 100644 --- a/app/src/main/java/one/mixin/android/ui/conversation/chathistory/holder/LocationHolder.kt +++ b/app/src/main/java/one/mixin/android/ui/conversation/chathistory/holder/LocationHolder.kt @@ -1,6 +1,5 @@ package one.mixin.android.ui.conversation.chathistory.holder -import android.graphics.ColorFilter import android.view.View import android.view.ViewGroup import androidx.constraintlayout.widget.ConstraintLayout diff --git a/app/src/main/java/one/mixin/android/ui/conversation/link/parser/NewSchemeParser.kt b/app/src/main/java/one/mixin/android/ui/conversation/link/parser/NewSchemeParser.kt index b55c5bf09b..fd47d4ab5e 100644 --- a/app/src/main/java/one/mixin/android/ui/conversation/link/parser/NewSchemeParser.kt +++ b/app/src/main/java/one/mixin/android/ui/conversation/link/parser/NewSchemeParser.kt @@ -9,7 +9,6 @@ import one.mixin.android.api.request.TransferRequest import one.mixin.android.api.response.PaymentStatus import one.mixin.android.extension.defaultSharedPreferences import one.mixin.android.extension.isUUID -import one.mixin.android.extension.navTo import one.mixin.android.extension.nowInUtc import one.mixin.android.extension.putString import one.mixin.android.pay.parseExternalTransferUri @@ -30,7 +29,6 @@ import one.mixin.android.ui.conversation.link.CollectionBottomSheetDialogFragmen import one.mixin.android.ui.wallet.AssetListBottomSheetDialogFragment import one.mixin.android.ui.wallet.AssetListBottomSheetDialogFragment.Companion.ASSET_PREFERENCE import one.mixin.android.ui.wallet.AssetListBottomSheetDialogFragment.Companion.TYPE_FROM_TRANSFER -import one.mixin.android.ui.wallet.InputFragment import one.mixin.android.ui.wallet.NetworkFee import one.mixin.android.ui.wallet.WalletActivity import one.mixin.android.ui.wallet.transfer.TransferBottomSheetDialogFragment diff --git a/app/src/main/java/one/mixin/android/ui/home/web3/Web3ViewModel.kt b/app/src/main/java/one/mixin/android/ui/home/web3/Web3ViewModel.kt index 25fc81bd05..613e42aba6 100644 --- a/app/src/main/java/one/mixin/android/ui/home/web3/Web3ViewModel.kt +++ b/app/src/main/java/one/mixin/android/ui/home/web3/Web3ViewModel.kt @@ -14,6 +14,8 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import one.mixin.android.Constants +import one.mixin.android.Constants.RouteConfig.ROUTE_BOT_USER_ID import one.mixin.android.MixinApplication import one.mixin.android.R import one.mixin.android.api.MixinResponse @@ -23,9 +25,11 @@ import one.mixin.android.api.request.web3.EstimateFeeRequest import one.mixin.android.api.response.PaymentStatus import one.mixin.android.api.response.web3.StakeAccount import one.mixin.android.db.web3.vo.Web3Address +import one.mixin.android.db.web3.vo.Web3Chain import one.mixin.android.db.web3.vo.Web3RawTransaction import one.mixin.android.db.web3.vo.Web3Token import one.mixin.android.db.web3.vo.Web3TokenItem +import one.mixin.android.db.web3.vo.Web3TokensExtra import one.mixin.android.db.web3.vo.getChainFromName import one.mixin.android.extension.defaultSharedPreferences import one.mixin.android.job.MixinJobManager @@ -43,6 +47,7 @@ import one.mixin.android.ui.common.biometric.NftBiometricItem import one.mixin.android.ui.common.biometric.maxUtxoCount import one.mixin.android.ui.home.inscription.component.OwnerState import one.mixin.android.ui.oldwallet.AssetRepository +import one.mixin.android.ui.wallet.fiatmoney.requestRouteAPI import one.mixin.android.util.GsonHelper import one.mixin.android.util.mlkit.firstUrl import one.mixin.android.vo.Account @@ -420,22 +425,12 @@ internal constructor( return web3Repository.getAddressesByChainId(walletId, chainId) } - suspend fun getClassicWalletId(): String? = web3Repository.getClassicWalletId() - - suspend fun getTransactionsById(traceId: String) = tokenRepository.getTransactionsById(traceId) - - suspend fun findTokensByIds(walletId: String, assetIds: List): List = withContext(Dispatchers.IO) { - return@withContext web3Repository.findWeb3TokenItemsByIds(walletId, assetIds) - } - - suspend fun getRawTransactionByHashAndChain(hash: String, chainId: String) = tokenRepository.getRawTransactionByHashAndChain(hash, chainId) - - suspend fun getWalletName(walletId: String): String? = web3Repository.findWalletById(walletId)?.name - suspend fun findWalletById(walletId: String) = web3Repository.findWalletById(walletId) suspend fun getAddresses(walletId: String) = web3Repository.getAddresses(walletId) + suspend fun getAllWallets() = web3Repository.getAllWallets() + suspend fun getAddressesGroupedByDestination(walletId: String) = web3Repository.getAddressesGroupedByDestination(walletId) companion object { @@ -489,4 +484,117 @@ internal constructor( return@withContext null } } -} \ No newline at end of file + + suspend fun refreshWalletAddresses(walletId: String) = withContext(Dispatchers.IO) { + requestRouteAPI( + invokeNetwork = { + web3Repository.getWalletAddresses(walletId) + }, + successBlock = { response -> + val addressesResponse = response + if (addressesResponse.data.isNullOrEmpty().not()) { + Timber.d("Fetched ${addressesResponse.data?.size} addresses for wallet $walletId") + val web3Addresses = addressesResponse.data!! + web3Repository.insertWalletAddresses(web3Addresses) + Timber.d("Inserted ${web3Addresses.size} addresses into database") + } else { + Timber.d("No addresses found for wallet $walletId") + } + true + }, + failureBlock = { response -> + Timber.e("Failed to fetch addresses for wallet $walletId: ${response.errorCode} - ${response.errorDescription}") + false + }, + requestSession = { + userRepository.fetchSessionsSuspend(listOf(ROUTE_BOT_USER_ID)) + }, + defaultErrorHandle = {} + ) + } + + suspend fun refreshWalletAssets(walletId: String) = withContext(Dispatchers.IO) { + requestRouteAPI( + invokeNetwork = { + web3Repository.getWalletAssets(walletId) + }, + successBlock = { response -> + val assets = response.data + if (assets != null && assets.isNotEmpty()) { + Timber.d("Fetched ${assets.size} assets for wallet $walletId") + val assetIds = assets.map { it.assetId } + web3Repository.updateBalanceToZeroForMissingAssets(walletId, assetIds) + Timber.d("Updated missing assets to zero balance for wallet $walletId") + + val extrasToInsert = assets.filter { it.level < Constants.AssetLevel.UNKNOWN } + .mapNotNull { asset -> + val extra = web3Repository.findTokensExtraByAssetId(asset.assetId, walletId) + if (extra == null) { + Web3TokensExtra( + assetId = asset.assetId, + walletId = walletId, + hidden = true + ) + } else { + null + } + } + if (extrasToInsert.isNotEmpty()) { + web3Repository.insertTokensExtra(extrasToInsert) + } + + web3Repository.insertWalletAssets(assets) + refreshChains(assets.map { it.chainId }.distinct()) + Timber.d("Inserted ${assets.size} tokens into database") + } else { + Timber.d("No assets found for wallet $walletId") + web3Repository.updateAllBalancesToZero(walletId) + Timber.d("Updated all assets to zero balance for wallet $walletId") + } + true + }, + failureBlock = { response -> + Timber.e("Failed to fetch assets for wallet $walletId: ${response.errorCode} - ${response.errorDescription}") + false + }, + requestSession = { + userRepository.fetchSessionsSuspend(listOf(ROUTE_BOT_USER_ID)) + }, + defaultErrorHandle = {} + ) + } + + private suspend fun refreshChains(chainIds: List) { + chainIds.forEach { chainId -> + try { + if (web3Repository.chainExists(chainId) == null) { + val response = web3Repository.getChainById(chainId) + if (response.isSuccess) { + val chain = response.data + if (chain != null) { + web3Repository.insertChain( + Web3Chain( + chainId = chain.chainId, + name = chain.name, + symbol = chain.symbol, + iconUrl = chain.iconUrl, + threshold = chain.threshold, + ) + ) + Timber.d("Successfully inserted ${chain.name} chain into database") + } else { + Timber.d("No chain found for chainId: $chainId") + } + } else { + Timber.e("Failed to fetch chain $chainId: ${response.errorCode} - ${response.errorDescription}") + } + } else { + Timber.d("Chain $chainId already exists in local database, skipping fetch") + } + } catch (e: Exception) { + Timber.e(e, "Exception occurred while fetching chain $chainId") + } + } + } +} + diff --git a/app/src/main/java/one/mixin/android/ui/imageeditor/UriGlideRenderer.java b/app/src/main/java/one/mixin/android/ui/imageeditor/UriGlideRenderer.java index 299fb156db..952d8e514c 100644 --- a/app/src/main/java/one/mixin/android/ui/imageeditor/UriGlideRenderer.java +++ b/app/src/main/java/one/mixin/android/ui/imageeditor/UriGlideRenderer.java @@ -15,13 +15,18 @@ import android.renderscript.Element; import android.renderscript.RenderScript; import android.renderscript.ScriptIntrinsicBlur; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; + import com.bumptech.glide.Glide; import com.bumptech.glide.RequestBuilder; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.transition.Transition; + +import java.util.concurrent.ExecutionException; + import one.mixin.android.widget.imageeditor.Bounds; import one.mixin.android.widget.imageeditor.Renderer; import one.mixin.android.widget.imageeditor.RendererContext; @@ -29,8 +34,6 @@ import one.mixin.android.widget.imageeditor.model.EditorModel; import timber.log.Timber; -import java.util.concurrent.ExecutionException; - /** * Uses Glide to load an image and implements a {@link Renderer}. * 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 8d768360a1..93b3ea7efc 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 @@ -8,7 +8,6 @@ import android.view.View import android.view.View.GONE import android.view.View.INVISIBLE import android.view.View.VISIBLE -import android.view.inputmethod.EditorInfo import androidx.fragment.app.viewModels import com.uber.autodispose.autoDispose import dagger.hilt.android.AndroidEntryPoint 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 c753904ab1..e70e702092 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,7 +19,6 @@ 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.util.analytics.AnalyticsTracker import one.mixin.android.util.viewBinding @AndroidEntryPoint 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 4522411f44..92521bc15e 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 @@ -16,7 +16,6 @@ import one.mixin.android.databinding.FragmentUpgradeBinding import one.mixin.android.db.MixinDatabase import one.mixin.android.db.property.PropertyHelper import one.mixin.android.extension.withArgs -import one.mixin.android.job.MixinJobManager import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.home.MainActivity import one.mixin.android.util.viewBinding diff --git a/app/src/main/java/one/mixin/android/ui/landing/components/CreateAccountPage.kt b/app/src/main/java/one/mixin/android/ui/landing/components/CreateAccountPage.kt index ac28f726e4..338aaef73b 100644 --- a/app/src/main/java/one/mixin/android/ui/landing/components/CreateAccountPage.kt +++ b/app/src/main/java/one/mixin/android/ui/landing/components/CreateAccountPage.kt @@ -26,7 +26,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension -import com.checkout.threedsobfuscation.fa import one.mixin.android.R import one.mixin.android.compose.theme.MixinAppTheme import one.mixin.android.widget.components.MaterialWindowButton diff --git a/app/src/main/java/one/mixin/android/ui/media/pager/MediaPagerActivity.kt b/app/src/main/java/one/mixin/android/ui/media/pager/MediaPagerActivity.kt index 728785889f..bbb6b6d38e 100644 --- a/app/src/main/java/one/mixin/android/ui/media/pager/MediaPagerActivity.kt +++ b/app/src/main/java/one/mixin/android/ui/media/pager/MediaPagerActivity.kt @@ -80,7 +80,6 @@ import one.mixin.android.util.SensorOrientationChangeNotifier import one.mixin.android.util.SystemUIManager import one.mixin.android.util.VideoPlayer import one.mixin.android.util.reportEvent -import one.mixin.android.util.reportException import one.mixin.android.util.rxpermission.RxPermissions import one.mixin.android.vo.FixedMessageDataSource import one.mixin.android.vo.MediaStatus diff --git a/app/src/main/java/one/mixin/android/ui/oldwallet/AssetRepository.kt b/app/src/main/java/one/mixin/android/ui/oldwallet/AssetRepository.kt index d38b028b67..ba288f3c56 100644 --- a/app/src/main/java/one/mixin/android/ui/oldwallet/AssetRepository.kt +++ b/app/src/main/java/one/mixin/android/ui/oldwallet/AssetRepository.kt @@ -26,7 +26,6 @@ import one.mixin.android.db.ChainDao import one.mixin.android.db.SnapshotDao import one.mixin.android.db.TraceDao import one.mixin.android.db.web3.Web3WalletDao -import one.mixin.android.db.web3.vo.Web3Wallet import one.mixin.android.extension.within6Hours import one.mixin.android.util.ErrorHandler import one.mixin.android.util.ErrorHandler.Companion.FORBIDDEN diff --git a/app/src/main/java/one/mixin/android/ui/oldwallet/OutputBottomSheetDialogFragment.kt b/app/src/main/java/one/mixin/android/ui/oldwallet/OutputBottomSheetDialogFragment.kt index 3f5744d936..489e984f7b 100644 --- a/app/src/main/java/one/mixin/android/ui/oldwallet/OutputBottomSheetDialogFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/oldwallet/OutputBottomSheetDialogFragment.kt @@ -35,9 +35,9 @@ import one.mixin.android.util.ErrorHandler.Companion.INVALID_PIN_FORMAT import one.mixin.android.util.ErrorHandler.Companion.PIN_INCORRECT import one.mixin.android.util.ErrorHandler.Companion.TOO_SMALL import one.mixin.android.util.viewBinding -import one.mixin.android.vo.notMessengerUser import one.mixin.android.vo.Snapshot import one.mixin.android.vo.Trace +import one.mixin.android.vo.notMessengerUser import one.mixin.android.widget.BottomSheet @AndroidEntryPoint diff --git a/app/src/main/java/one/mixin/android/ui/qr/ImageUtil.java b/app/src/main/java/one/mixin/android/ui/qr/ImageUtil.java index 4fa218fab8..b552f13773 100644 --- a/app/src/main/java/one/mixin/android/ui/qr/ImageUtil.java +++ b/app/src/main/java/one/mixin/android/ui/qr/ImageUtil.java @@ -23,14 +23,16 @@ import android.graphics.Rect; import android.graphics.YuvImage; import android.util.Size; + import androidx.annotation.Nullable; import androidx.camera.core.ImageProxy; -import timber.log.Timber; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; +import timber.log.Timber; + /** * Utility class for image related operations. * diff --git a/app/src/main/java/one/mixin/android/ui/search/CancellationLimitOffsetDataSource.java b/app/src/main/java/one/mixin/android/ui/search/CancellationLimitOffsetDataSource.java index d101257938..354d4d037a 100644 --- a/app/src/main/java/one/mixin/android/ui/search/CancellationLimitOffsetDataSource.java +++ b/app/src/main/java/one/mixin/android/ui/search/CancellationLimitOffsetDataSource.java @@ -4,6 +4,7 @@ import android.database.Cursor; import android.os.CancellationSignal; import android.os.OperationCanceledException; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RestrictTo; @@ -11,14 +12,15 @@ import androidx.room.InvalidationTracker; import androidx.room.RoomDatabase; import androidx.room.RoomSQLiteQuery; -import one.mixin.android.util.CrashExceptionReportKt; -import timber.log.Timber; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; +import one.mixin.android.util.CrashExceptionReportKt; +import timber.log.Timber; + @SuppressLint("RestrictedApi") @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public abstract class CancellationLimitOffsetDataSource extends PositionalDataSource { diff --git a/app/src/main/java/one/mixin/android/ui/search/SearchAdapter.kt b/app/src/main/java/one/mixin/android/ui/search/SearchAdapter.kt index 039ddea0e5..791a8b0112 100644 --- a/app/src/main/java/one/mixin/android/ui/search/SearchAdapter.kt +++ b/app/src/main/java/one/mixin/android/ui/search/SearchAdapter.kt @@ -3,7 +3,6 @@ package one.mixin.android.ui.search import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.ViewGroup -import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import com.google.i18n.phonenumbers.PhoneNumberUtil import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersAdapter diff --git a/app/src/main/java/one/mixin/android/ui/search/holder/AssetHolder.kt b/app/src/main/java/one/mixin/android/ui/search/holder/AssetHolder.kt index 6867fa1a87..90fd010322 100644 --- a/app/src/main/java/one/mixin/android/ui/search/holder/AssetHolder.kt +++ b/app/src/main/java/one/mixin/android/ui/search/holder/AssetHolder.kt @@ -3,7 +3,6 @@ package one.mixin.android.ui.search.holder import android.annotation.SuppressLint import android.view.View import androidx.core.view.isVisible -import one.mixin.android.R import one.mixin.android.databinding.ItemSearchAssetBinding import one.mixin.android.extension.highLight import one.mixin.android.extension.numberFormat2 diff --git a/app/src/main/java/one/mixin/android/ui/setting/member/MixinMemberNotificationBottomSheetDialogFragment.kt b/app/src/main/java/one/mixin/android/ui/setting/member/MixinMemberNotificationBottomSheetDialogFragment.kt index 903a42ab1b..77b1b4a82a 100644 --- a/app/src/main/java/one/mixin/android/ui/setting/member/MixinMemberNotificationBottomSheetDialogFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/setting/member/MixinMemberNotificationBottomSheetDialogFragment.kt @@ -18,10 +18,8 @@ import one.mixin.android.R import one.mixin.android.api.response.MembershipOrder import one.mixin.android.extension.booleanFromAttribute import one.mixin.android.extension.dp -import one.mixin.android.extension.getParcelableCompat import one.mixin.android.extension.isNightMode import one.mixin.android.extension.withArgs -import one.mixin.android.ui.setting.ui.page.MixinMemberCancelPage import one.mixin.android.ui.setting.ui.page.MixinMemberNotificationPage import one.mixin.android.ui.viewmodel.MemberViewModel import one.mixin.android.util.SystemUIManager diff --git a/app/src/main/java/one/mixin/android/ui/setting/member/MixinMemberUpgradeBottomSheetDialogFragment.kt b/app/src/main/java/one/mixin/android/ui/setting/member/MixinMemberUpgradeBottomSheetDialogFragment.kt index fd959eee29..624d6163de 100644 --- a/app/src/main/java/one/mixin/android/ui/setting/member/MixinMemberUpgradeBottomSheetDialogFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/setting/member/MixinMemberUpgradeBottomSheetDialogFragment.kt @@ -25,7 +25,6 @@ import kotlinx.coroutines.launch import one.mixin.android.Constants import one.mixin.android.R import one.mixin.android.RxBus -import one.mixin.android.api.response.web3.SwapToken import one.mixin.android.event.MembershipEvent import one.mixin.android.extension.booleanFromAttribute import one.mixin.android.extension.isNightMode diff --git a/app/src/main/java/one/mixin/android/ui/setting/ui/components/MemberUpgradePaymentButton.kt b/app/src/main/java/one/mixin/android/ui/setting/ui/components/MemberUpgradePaymentButton.kt index 5322e95dbb..b2f9f5444e 100644 --- a/app/src/main/java/one/mixin/android/ui/setting/ui/components/MemberUpgradePaymentButton.kt +++ b/app/src/main/java/one/mixin/android/ui/setting/ui/components/MemberUpgradePaymentButton.kt @@ -24,7 +24,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment diff --git a/app/src/main/java/one/mixin/android/ui/setting/ui/components/MembershipPlanCard.kt b/app/src/main/java/one/mixin/android/ui/setting/ui/components/MembershipPlanCard.kt index 831206d04d..e745aa1a80 100644 --- a/app/src/main/java/one/mixin/android/ui/setting/ui/components/MembershipPlanCard.kt +++ b/app/src/main/java/one/mixin/android/ui/setting/ui/components/MembershipPlanCard.kt @@ -1,7 +1,6 @@ package one.mixin.android.ui.setting.ui.components import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -14,14 +13,12 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button import androidx.compose.material.ButtonDefaults -import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign diff --git a/app/src/main/java/one/mixin/android/ui/setting/ui/page/MixinMemberNotificationPage.kt b/app/src/main/java/one/mixin/android/ui/setting/ui/page/MixinMemberNotificationPage.kt index 20f4d25710..f78f8dfb2d 100644 --- a/app/src/main/java/one/mixin/android/ui/setting/ui/page/MixinMemberNotificationPage.kt +++ b/app/src/main/java/one/mixin/android/ui/setting/ui/page/MixinMemberNotificationPage.kt @@ -13,15 +13,9 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button import androidx.compose.material.ButtonDefaults -import androidx.compose.material.CircularProgressIndicator -import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -32,12 +26,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.launch import one.mixin.android.R -import one.mixin.android.api.response.MembershipOrder import one.mixin.android.compose.theme.MixinAppTheme -import one.mixin.android.ui.setting.member.MixinMemberNotificationBottomSheetDialogFragment import one.mixin.android.ui.setting.ui.components.MembershipIcon import one.mixin.android.ui.viewmodel.MemberViewModel diff --git a/app/src/main/java/one/mixin/android/ui/sticker/StickerManagementFragment.kt b/app/src/main/java/one/mixin/android/ui/sticker/StickerManagementFragment.kt index 39361a983d..8020794075 100644 --- a/app/src/main/java/one/mixin/android/ui/sticker/StickerManagementFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/sticker/StickerManagementFragment.kt @@ -1,10 +1,7 @@ package one.mixin.android.ui.sticker -import android.Manifest import android.annotation.SuppressLint -import android.app.Activity import android.content.Intent -import android.os.Build import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,24 +9,22 @@ import android.view.View.GONE import android.view.View.VISIBLE import android.view.ViewGroup import android.widget.CheckBox +import androidx.activity.result.PickVisualMediaRequest +import androidx.activity.result.contract.ActivityResultContracts import androidx.core.os.bundleOf import androidx.core.view.updateLayoutParams import androidx.fragment.app.viewModels import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.uber.autodispose.autoDispose import dagger.hilt.android.AndroidEntryPoint import one.mixin.android.R import one.mixin.android.databinding.FragmentStickerManagementBinding -import one.mixin.android.extension.REQUEST_GALLERY import one.mixin.android.extension.addFragment import one.mixin.android.extension.clear import one.mixin.android.extension.colorFromAttribute import one.mixin.android.extension.dp import one.mixin.android.extension.isWideScreen import one.mixin.android.extension.loadSticker -import one.mixin.android.extension.openGalleryFromSticker -import one.mixin.android.extension.openPermissionSetting import one.mixin.android.extension.realSize import one.mixin.android.extension.textColor import one.mixin.android.extension.viewDestroyed @@ -38,14 +33,9 @@ import one.mixin.android.ui.conversation.ConversationViewModel import one.mixin.android.ui.conversation.StickerFragment.Companion.ARGS_ALBUM_ID import one.mixin.android.ui.conversation.StickerFragment.Companion.PADDING import one.mixin.android.ui.conversation.adapter.StickerSpacingItemDecoration -import one.mixin.android.util.reportException -import one.mixin.android.util.rxpermission.RxPermissions import one.mixin.android.util.viewBinding import one.mixin.android.vo.Sticker import one.mixin.android.widget.lottie.RLottieImageView -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.PickVisualMediaRequest -import androidx.activity.result.contract.ActivityResultContracts @AndroidEntryPoint class StickerManagementFragment : BaseFragment() { diff --git a/app/src/main/java/one/mixin/android/ui/tip/wc/compose/ItemContent.kt b/app/src/main/java/one/mixin/android/ui/tip/wc/compose/ItemContent.kt index bfdecba0e5..1fa1053369 100644 --- a/app/src/main/java/one/mixin/android/ui/tip/wc/compose/ItemContent.kt +++ b/app/src/main/java/one/mixin/android/ui/tip/wc/compose/ItemContent.kt @@ -1,7 +1,6 @@ package one.mixin.android.ui.tip.wc.compose import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi @@ -30,7 +29,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.Placeholder import androidx.compose.ui.text.PlaceholderVerticalAlign import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.TextUnit diff --git a/app/src/main/java/one/mixin/android/ui/wallet/AllTransactionsFragment.kt b/app/src/main/java/one/mixin/android/ui/wallet/AllTransactionsFragment.kt index e09ed7a8ce..531251c0bf 100644 --- a/app/src/main/java/one/mixin/android/ui/wallet/AllTransactionsFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/wallet/AllTransactionsFragment.kt @@ -20,10 +20,10 @@ import com.google.android.material.datepicker.MaterialDatePicker import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersDecoration import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import one.mixin.android.R -import one.mixin.android.api.handleMixinResponse import one.mixin.android.databinding.FragmentAllTransactionsBinding import one.mixin.android.extension.addFragment import one.mixin.android.extension.dpToPx @@ -34,13 +34,13 @@ import one.mixin.android.extension.withArgs import one.mixin.android.tip.wc.SortOrder import one.mixin.android.ui.common.NonMessengerUserBottomSheetDialogFragment import one.mixin.android.ui.common.UserBottomSheetDialogFragment +import one.mixin.android.ui.common.refresh.PendingDepositRefreshHelper import one.mixin.android.ui.home.inscription.menu.SortMenuAdapter import one.mixin.android.ui.home.inscription.menu.SortMenuData import one.mixin.android.ui.wallet.TransactionFragment.Companion.ARGS_SNAPSHOT import one.mixin.android.ui.wallet.TransactionsFragment.Companion.ARGS_ASSET import one.mixin.android.ui.wallet.adapter.OnSnapshotListener import one.mixin.android.ui.wallet.adapter.SnapshotPagedAdapter -import one.mixin.android.util.reportException import one.mixin.android.util.viewBinding import one.mixin.android.vo.AddressItem import one.mixin.android.vo.Recipient @@ -48,7 +48,6 @@ import one.mixin.android.vo.SnapshotItem import one.mixin.android.vo.UserItem import one.mixin.android.vo.notMessengerUser import one.mixin.android.vo.safe.TokenItem -import one.mixin.android.vo.safe.toSnapshot import timber.log.Timber @AndroidEntryPoint @@ -72,6 +71,8 @@ class AllTransactionsFragment : BaseTransactionsFragment private val adapter = SnapshotPagedAdapter() + private var pendingDepositRefreshJob: Job? = null + private val userItem by lazy { requireArguments().getParcelableCompat(ARGS_USER, UserItem::class.java) } @@ -169,7 +170,20 @@ class AllTransactionsFragment : BaseTransactionsFragment } loadFilter() } - refreshAllPendingDeposit() + } + + override fun onResume() { + super.onResume() + pendingDepositRefreshJob = PendingDepositRefreshHelper.startRefreshData( + fragment = this, + walletViewModel = walletViewModel, + refreshJob = pendingDepositRefreshJob + ) + } + + override fun onPause() { + super.onPause() + pendingDepositRefreshJob = PendingDepositRefreshHelper.cancelRefreshData(pendingDepositRefreshJob) } private fun loadFilter() { @@ -246,40 +260,6 @@ class AllTransactionsFragment : BaseTransactionsFragment // Do noting } - private fun refreshAllPendingDeposit() = - lifecycleScope.launch { - handleMixinResponse( - invokeNetwork = { walletViewModel.allPendingDeposit() }, - exceptionBlock = { e -> - reportException(e) - false - }, - successBlock = { - val pendingDeposits = it.data ?: emptyList() - val destinationTags = walletViewModel.findDepositEntryDestinations() - pendingDeposits - .filter { pd -> - destinationTags.any { dt -> - dt.destination == pd.destination && (dt.tag.isNullOrBlank() || dt.tag == pd.tag) - } - } - .map { pd -> pd.toSnapshot() }.let { snapshots -> - // If there are no pending deposit snapshots belonging to the current user, clear all pending deposits - if (snapshots.isEmpty()) { - walletViewModel.clearAllPendingDeposits() - return@let - } - lifecycleScope.launch { - snapshots.map { it.assetId }.distinct().forEach { - walletViewModel.findOrSyncAsset(it) - } - walletViewModel.insertPendingDeposit(snapshots) - } - } - }, - ) - } - private fun bindLiveData() { bindLiveData(walletViewModel.allSnapshots(initialLoadKey = initialLoadKey, filterParams)) } diff --git a/app/src/main/java/one/mixin/android/ui/wallet/AllWeb3TransactionsFragment.kt b/app/src/main/java/one/mixin/android/ui/wallet/AllWeb3TransactionsFragment.kt index 720fea6ddd..59c01f2802 100644 --- a/app/src/main/java/one/mixin/android/ui/wallet/AllWeb3TransactionsFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/wallet/AllWeb3TransactionsFragment.kt @@ -1,7 +1,6 @@ package one.mixin.android.ui.wallet import android.os.Bundle -import android.util.Log import android.view.Gravity import android.view.LayoutInflater import android.view.View @@ -35,7 +34,7 @@ import one.mixin.android.extension.dpToPx import one.mixin.android.extension.getParcelableCompat import one.mixin.android.job.RefreshWeb3TransactionsJob import one.mixin.android.tip.wc.SortOrder -import one.mixin.android.ui.common.PendingTransactionRefreshHelper +import one.mixin.android.ui.common.refresh.PendingWeb3TransactionRefreshHelper import one.mixin.android.ui.home.inscription.menu.SortMenuAdapter import one.mixin.android.ui.home.inscription.menu.SortMenuData import one.mixin.android.ui.home.web3.Web3ViewModel @@ -197,8 +196,8 @@ class AllWeb3TransactionsFragment : BaseTransactionsFragment = listOf() private val assetsAdapter by lazy { WalletAssetAdapter(false) } + private var pendingDepositRefreshJob: Job? = null private var distance = 0 private var snackBar: Snackbar? = null @@ -242,7 +242,16 @@ class PrivacyWalletFragment : BaseFragment(R.layout.fragment_privacy_wallet), He jobManager.addJobInBackground(RefreshTokensJob()) jobManager.addJobInBackground(RefreshSnapshotsJob()) jobManager.addJobInBackground(SyncOutputJob()) - refreshAllPendingDeposit() + pendingDepositRefreshJob = PendingDepositRefreshHelper.startRefreshData( + fragment = this, + walletViewModel = walletViewModel, + refreshJob = pendingDepositRefreshJob + ) + } + + override fun onPause() { + super.onPause() + pendingDepositRefreshJob = PendingDepositRefreshHelper.cancelRefreshData(pendingDepositRefreshJob) } override fun onHiddenChanged(hidden: Boolean) { @@ -253,40 +262,6 @@ class PrivacyWalletFragment : BaseFragment(R.layout.fragment_privacy_wallet), He } } - private fun refreshAllPendingDeposit() = - lifecycleScope.launch { - handleMixinResponse( - invokeNetwork = { walletViewModel.allPendingDeposit() }, - exceptionBlock = { e -> - reportException(e) - false - }, - successBlock = { - val pendingDeposits = it.data ?: emptyList() - val destinationTags = walletViewModel.findDepositEntryDestinations() - pendingDeposits - .filter { pd -> - destinationTags.any { dt -> - dt.destination == pd.destination && (dt.tag.isNullOrBlank() || dt.tag == pd.tag) - } - } - .map { pd -> pd.toSnapshot() }.let { snapshots -> - // If there are no pending deposit snapshots belonging to the current user, clear all pending deposits - if (snapshots.isEmpty()) { - walletViewModel.clearAllPendingDeposits() - return@let - } - lifecycleScope.launch { - snapshots.map { it.assetId }.distinct().forEach { - walletViewModel.findOrSyncAsset(it) - } - walletViewModel.insertPendingDeposit(snapshots) - } - } - }, - ) - } - private var lastFiatCurrency :String? = null override fun onStop() { diff --git a/app/src/main/java/one/mixin/android/ui/wallet/TransactionsFragment.kt b/app/src/main/java/one/mixin/android/ui/wallet/TransactionsFragment.kt index 9fb7476a5b..168cb935a1 100644 --- a/app/src/main/java/one/mixin/android/ui/wallet/TransactionsFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/wallet/TransactionsFragment.kt @@ -17,7 +17,6 @@ import kotlinx.coroutines.withContext import one.mixin.android.Constants.AssetId.USDT_ASSET_ETH_ID import one.mixin.android.Constants.AssetId.XIN_ASSET_ID import one.mixin.android.R -import one.mixin.android.api.handleMixinResponse import one.mixin.android.databinding.FragmentTransactionsBinding import one.mixin.android.databinding.ViewWalletTransactionsBottomBinding import one.mixin.android.extension.buildAmountSymbol @@ -34,7 +33,6 @@ import one.mixin.android.extension.priceFormat import one.mixin.android.extension.screenHeight import one.mixin.android.extension.setQuoteText import one.mixin.android.extension.statusBarHeight -import one.mixin.android.extension.viewDestroyed import one.mixin.android.job.CheckBalanceJob import one.mixin.android.job.MixinJobManager import one.mixin.android.job.RefreshMarketJob @@ -44,6 +42,7 @@ import one.mixin.android.tip.Tip import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.common.NonMessengerUserBottomSheetDialogFragment import one.mixin.android.ui.common.UserBottomSheetDialogFragment +import one.mixin.android.ui.common.refresh.PendingDepositRefreshHelper import one.mixin.android.ui.home.market.Market import one.mixin.android.ui.home.web3.swap.SwapActivity import one.mixin.android.ui.wallet.AllTransactionsFragment.Companion.ARGS_TOKEN @@ -52,16 +51,13 @@ import one.mixin.android.ui.wallet.MarketDetailsFragment.Companion.ARGS_MARKET import one.mixin.android.ui.wallet.adapter.OnSnapshotListener import one.mixin.android.util.analytics.AnalyticsTracker import one.mixin.android.util.getChainName -import one.mixin.android.util.reportException import one.mixin.android.util.viewBinding import one.mixin.android.vo.Fiats import one.mixin.android.vo.SnapshotItem import one.mixin.android.vo.assetIdToAsset import one.mixin.android.vo.market.MarketItem import one.mixin.android.vo.notMessengerUser -import one.mixin.android.vo.safe.DepositEntry import one.mixin.android.vo.safe.TokenItem -import one.mixin.android.vo.safe.toSnapshot import one.mixin.android.widget.BottomSheet import one.mixin.android.widget.DebugClickListener import java.math.BigDecimal @@ -89,6 +85,8 @@ class TransactionsFragment : BaseFragment(R.layout.fragment_transactions), OnSna lateinit var asset: TokenItem + private var pendingDepositRefreshJob: kotlinx.coroutines.Job? = null + private val fromMarket by lazy { requireArguments().getBoolean(ARGS_FROM_MARKET, false) } @@ -100,9 +98,19 @@ class TransactionsFragment : BaseFragment(R.layout.fragment_transactions), OnSna private var scrollY = 0 + override fun onResume() { + super.onResume() + pendingDepositRefreshJob = PendingDepositRefreshHelper.startRefreshData( + fragment = this, + walletViewModel = walletViewModel, + refreshJob = pendingDepositRefreshJob + ) + } + override fun onPause() { super.onPause() scrollY = binding.scrollView.scrollY + pendingDepositRefreshJob = PendingDepositRefreshHelper.cancelRefreshData(pendingDepositRefreshJob) } override fun onViewCreated( @@ -258,12 +266,6 @@ class TransactionsFragment : BaseFragment(R.layout.fragment_transactions), OnSna } walletViewModel.refreshAsset(asset.assetId) - lifecycleScope.launch { - val depositEntry = walletViewModel.findAndSyncDepositEntry(asset.chainId, asset.assetId) - if (depositEntry != null && depositEntry.destination.isNotBlank()) { - refreshPendingDeposits(asset) - } - } } private var snapshotItems: List = emptyList() @@ -273,46 +275,6 @@ class TransactionsFragment : BaseFragment(R.layout.fragment_transactions), OnSna super.onDestroyView() } - private fun refreshPendingDeposits( - asset: TokenItem, - ) { - if (viewDestroyed()) return - lifecycleScope.launch { - handleMixinResponse( - invokeNetwork = { - walletViewModel.refreshPendingDeposits(asset.assetId) - }, - exceptionBlock = { e -> - reportException(e) - false - }, - successBlock = { list -> - withContext(Dispatchers.IO) { - val pendingDeposits = list.data ?: emptyList() - val destinationTags = walletViewModel.findDepositEntryDestinations() - pendingDeposits.filter { pd -> - destinationTags.any { dt -> - dt.destination == pd.destination && (dt.tag.isNullOrBlank() || dt.tag == pd.tag) - } - }.map { pd -> pd.toSnapshot() }.let { snapshots -> - // If there are no pending deposit snapshots belonging to the current user, clear token pending deposits - if (snapshots.isEmpty()) { - walletViewModel.clearPendingDepositsByAssetId(asset.assetId) - return@let - } - lifecycleScope.launch { - snapshots.map { it.assetId }.distinct().forEach { - walletViewModel.findOrSyncAsset(it) - } - walletViewModel.insertPendingDeposit(snapshots) - } - } - } - }, - ) - } - } - @SuppressLint("InflateParams") private fun showBottom() { val builder = BottomSheet.Builder(requireActivity()) diff --git a/app/src/main/java/one/mixin/android/ui/wallet/WalletFragment.kt b/app/src/main/java/one/mixin/android/ui/wallet/WalletFragment.kt index 9355381807..54f041a7f8 100644 --- a/app/src/main/java/one/mixin/android/ui/wallet/WalletFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/wallet/WalletFragment.kt @@ -23,6 +23,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.reactivex.android.schedulers.AndroidSchedulers import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext @@ -46,12 +47,14 @@ import one.mixin.android.extension.putString import one.mixin.android.extension.supportsS import one.mixin.android.extension.viewDestroyed import one.mixin.android.job.MixinJobManager -import one.mixin.android.job.RefreshSingleWalletJob import one.mixin.android.session.Session import one.mixin.android.ui.common.BaseFragment import one.mixin.android.ui.common.VerifyBottomSheetDialogFragment import one.mixin.android.ui.common.editDialog +import one.mixin.android.ui.common.refresh.PendingWeb3TransactionRefreshHelper +import one.mixin.android.ui.common.refresh.WalletRefreshHelper import one.mixin.android.ui.home.MainActivity +import one.mixin.android.ui.home.web3.Web3ViewModel import one.mixin.android.ui.wallet.components.AssetDashboardScreen import one.mixin.android.ui.wallet.components.WalletDestination import one.mixin.android.ui.wallet.components.WalletDestinationTypeAdapter @@ -120,6 +123,11 @@ class WalletFragment : BaseFragment(R.layout.fragment_wallet) { private var _binding: FragmentWalletBinding? = null private val binding get() = requireNotNull(_binding) private val walletViewModel by viewModels() + private val web3ViewModel by viewModels() + + private var walletRefreshJob: Job? = null + private var transactionRefreshJob: Job? = null + override fun onCreateView( inflater: LayoutInflater, @@ -237,6 +245,13 @@ class WalletFragment : BaseFragment(R.layout.fragment_wallet) { defaultSharedPreferences.putBoolean(Constants.Account.PREF_HAS_USED_WALLET_LIST, false) if (compose.isVisible.not()) { compose.visibility = VISIBLE + walletRefreshJob = WalletRefreshHelper.startRefreshData( + fragment = this@WalletFragment, + web3ViewModel = web3ViewModel, + walletId = null, + refreshJob = walletRefreshJob + ) + val centerX = titleTv.x.toInt() + titleTv.width / 2 val centerY = titleTv.y.toInt() + titleTv.height / 2 val startRadius = 0 @@ -301,6 +316,48 @@ class WalletFragment : BaseFragment(R.layout.fragment_wallet) { } } + private fun triggerJob(destination: WalletDestination) { + when (destination) { + is WalletDestination.Privacy -> { + walletRefreshJob = WalletRefreshHelper.cancelRefreshData(walletRefreshJob) + transactionRefreshJob = PendingWeb3TransactionRefreshHelper.cancelRefreshData(transactionRefreshJob) + } + is WalletDestination.Classic -> { + transactionRefreshJob = PendingWeb3TransactionRefreshHelper.startRefreshData( + fragment = this, + web3ViewModel = web3ViewModel, + jobManager = jobManager, + refreshJob = walletRefreshJob + ) + walletRefreshJob = WalletRefreshHelper.startRefreshData( + fragment = this, web3ViewModel = web3ViewModel, walletId = destination.walletId, refreshJob = walletRefreshJob + ) + } + is WalletDestination.Watch ->{ + transactionRefreshJob = PendingWeb3TransactionRefreshHelper.startRefreshData( + fragment = this, + web3ViewModel = web3ViewModel, + jobManager = jobManager, + refreshJob = walletRefreshJob + ) + walletRefreshJob = WalletRefreshHelper.startRefreshData( + fragment = this, web3ViewModel = web3ViewModel, walletId = destination.walletId, refreshJob = walletRefreshJob + ) + } + is WalletDestination.Import ->{ + transactionRefreshJob = PendingWeb3TransactionRefreshHelper.startRefreshData( + fragment = this, + web3ViewModel = web3ViewModel, + jobManager = jobManager, + refreshJob = walletRefreshJob + ) + walletRefreshJob = WalletRefreshHelper.startRefreshData( + fragment = this, web3ViewModel = web3ViewModel, walletId = destination.walletId, refreshJob = walletRefreshJob + ) + } + } + } + private fun updateUi(destination: WalletDestination) { Timber.e("updateUi called with destination: $destination") when (destination) { @@ -368,6 +425,7 @@ class WalletFragment : BaseFragment(R.layout.fragment_wallet) { } } } + triggerJob(destination) } private var migrateEnable = false @@ -420,8 +478,6 @@ class WalletFragment : BaseFragment(R.layout.fragment_wallet) { else -> { null } - }?.let { wallet -> - jobManager.addJobInBackground(RefreshSingleWalletJob(wallet)) } if (destination is WalletDestination.Classic || destination is WalletDestination.Import) { val walletId = if (destination is WalletDestination.Classic) { @@ -450,6 +506,7 @@ class WalletFragment : BaseFragment(R.layout.fragment_wallet) { } private fun closeMenu() { + triggerJob(selectedWalletDestination ?: WalletDestination.Privacy) val centerX = binding.titleTv.x.toInt() + binding.titleTv.width / 2 val centerY = binding.titleTv.y.toInt() + binding.titleTv.height / 2 val endRadius = hypot( @@ -713,6 +770,8 @@ class WalletFragment : BaseFragment(R.layout.fragment_wallet) { override fun onDestroyView() { super.onDestroyView() + walletRefreshJob = WalletRefreshHelper.cancelRefreshData(walletRefreshJob) + _binding = null _privacyBottomBinding = null _classicBottomBinding = null } diff --git a/app/src/main/java/one/mixin/android/ui/wallet/WalletViewModel.kt b/app/src/main/java/one/mixin/android/ui/wallet/WalletViewModel.kt index daab601a0c..de6e2e901e 100644 --- a/app/src/main/java/one/mixin/android/ui/wallet/WalletViewModel.kt +++ b/app/src/main/java/one/mixin/android/ui/wallet/WalletViewModel.kt @@ -57,7 +57,6 @@ import one.mixin.android.vo.User import one.mixin.android.vo.UtxoItem import one.mixin.android.vo.market.Market import one.mixin.android.vo.market.MarketItem -import one.mixin.android.vo.safe.DepositEntry import one.mixin.android.vo.safe.Output import one.mixin.android.vo.safe.SafeSnapshot import one.mixin.android.vo.safe.TokenItem @@ -179,16 +178,10 @@ internal constructor( suspend fun allPendingDeposit() = tokenRepository.allPendingDeposit() - suspend fun refreshPendingDeposits( - assetId: String, - ) = tokenRepository.pendingDeposits(assetId) - fun getPendingDisplays() = tokenRepository.getPendingDisplays() suspend fun clearAllPendingDeposits() = tokenRepository.clearAllPendingDeposits() - suspend fun clearPendingDepositsByAssetId(assetId: String) = tokenRepository.clearPendingDepositsByAssetId(assetId) - suspend fun insertPendingDeposit(snapshot: List) = tokenRepository.insertPendingDeposit(snapshot) suspend fun getAsset(assetId: String) = diff --git a/app/src/main/java/one/mixin/android/ui/wallet/transfer/TransferBalanceErrorBottomSheetDialogFragment.kt b/app/src/main/java/one/mixin/android/ui/wallet/transfer/TransferBalanceErrorBottomSheetDialogFragment.kt index b4d4d63606..79876948e0 100644 --- a/app/src/main/java/one/mixin/android/ui/wallet/transfer/TransferBalanceErrorBottomSheetDialogFragment.kt +++ b/app/src/main/java/one/mixin/android/ui/wallet/transfer/TransferBalanceErrorBottomSheetDialogFragment.kt @@ -13,7 +13,6 @@ import one.mixin.android.R import one.mixin.android.databinding.FragmentTransferBalanceErrorBottomSheetBinding import one.mixin.android.extension.dp import one.mixin.android.extension.getParcelableCompat -import one.mixin.android.extension.navTo import one.mixin.android.extension.roundTopOrBottom import one.mixin.android.extension.visibleDisplayHeight import one.mixin.android.extension.withArgs @@ -23,7 +22,6 @@ import one.mixin.android.ui.common.biometric.BiometricItem import one.mixin.android.ui.common.biometric.WithdrawBiometricItem import one.mixin.android.ui.home.web3.swap.SwapActivity import one.mixin.android.ui.wallet.AddFeeBottomSheetDialogFragment -import one.mixin.android.ui.wallet.DepositFragment import one.mixin.android.ui.wallet.WalletActivity import one.mixin.android.util.viewBinding import one.mixin.android.widget.BottomSheet diff --git a/app/src/main/java/one/mixin/android/web3/details/Web3TransactionFragment.kt b/app/src/main/java/one/mixin/android/web3/details/Web3TransactionFragment.kt index 654623e924..1ff750d1dd 100644 --- a/app/src/main/java/one/mixin/android/web3/details/Web3TransactionFragment.kt +++ b/app/src/main/java/one/mixin/android/web3/details/Web3TransactionFragment.kt @@ -32,7 +32,7 @@ import one.mixin.android.extension.withArgs import one.mixin.android.job.MixinJobManager import one.mixin.android.tip.wc.internal.WCEthereumTransaction import one.mixin.android.ui.common.BaseFragment -import one.mixin.android.ui.common.PendingTransactionRefreshHelper +import one.mixin.android.ui.common.refresh.PendingWeb3TransactionRefreshHelper import one.mixin.android.ui.home.web3.Web3ViewModel import one.mixin.android.ui.home.web3.showGasCheckAndBrowserBottomSheetDialogFragment import one.mixin.android.util.viewBinding @@ -405,7 +405,7 @@ class Web3TransactionFragment : BaseFragment(R.layout.fragment_web3_transaction) override fun onResume() { super.onResume() - refreshJob = PendingTransactionRefreshHelper.startRefreshData( + refreshJob = PendingWeb3TransactionRefreshHelper.startRefreshData( fragment = this, web3ViewModel = web3ViewModel, jobManager = jobManager, @@ -420,7 +420,7 @@ class Web3TransactionFragment : BaseFragment(R.layout.fragment_web3_transaction) override fun onPause() { super.onPause() - refreshJob = PendingTransactionRefreshHelper.cancelRefreshData(refreshJob) + refreshJob = PendingWeb3TransactionRefreshHelper.cancelRefreshData(refreshJob) } private fun updateTransactionStatus(newStatus: String) { diff --git a/app/src/main/java/one/mixin/android/web3/details/Web3TransactionsFragment.kt b/app/src/main/java/one/mixin/android/web3/details/Web3TransactionsFragment.kt index ed303cd05b..962c57ed3a 100644 --- a/app/src/main/java/one/mixin/android/web3/details/Web3TransactionsFragment.kt +++ b/app/src/main/java/one/mixin/android/web3/details/Web3TransactionsFragment.kt @@ -54,7 +54,7 @@ import one.mixin.android.job.RefreshWeb3TokenJob import one.mixin.android.tip.Tip import one.mixin.android.ui.address.TransferDestinationInputFragment import one.mixin.android.ui.common.BaseFragment -import one.mixin.android.ui.common.PendingTransactionRefreshHelper +import one.mixin.android.ui.common.refresh.PendingWeb3TransactionRefreshHelper import one.mixin.android.ui.home.market.Market import one.mixin.android.ui.home.web3.StakeAccountSummary import one.mixin.android.ui.home.web3.Web3ViewModel @@ -440,7 +440,7 @@ class Web3TransactionsFragment : BaseFragment(R.layout.fragment_web3_transaction override fun onResume() { super.onResume() - refreshJob = PendingTransactionRefreshHelper.startRefreshData( + refreshJob = PendingWeb3TransactionRefreshHelper.startRefreshData( fragment = this, web3ViewModel = web3ViewModel, jobManager = jobManager, @@ -450,7 +450,7 @@ class Web3TransactionsFragment : BaseFragment(R.layout.fragment_web3_transaction override fun onPause() { super.onPause() - refreshJob = PendingTransactionRefreshHelper.cancelRefreshData(refreshJob) + refreshJob = PendingWeb3TransactionRefreshHelper.cancelRefreshData(refreshJob) } private suspend fun getStakeAccounts(address: String) {