diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubSettingActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubSettingActivity.kt index 2e963871..19b8d383 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubSettingActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubSettingActivity.kt @@ -1,7 +1,6 @@ package com.v2ray.ang.ui.subscription import android.content.Intent -import android.graphics.Bitmap import android.os.Bundle import androidx.activity.viewModels import androidx.annotation.StringRes @@ -53,7 +52,6 @@ import com.v2ray.ang.ui.compose.ReorderableListItem import com.v2ray.ang.ui.compose.SelectListDialog import com.v2ray.ang.ui.compose.SettingsSwitchItem import com.v2ray.ang.ui.compose.verticalScrollbar -import com.v2ray.ang.util.QRCodeDecoder import com.v2ray.ang.util.Utils import sh.calvin.reorderable.ReorderableItem import sh.calvin.reorderable.rememberReorderableLazyListState @@ -83,7 +81,7 @@ class SubSettingActivity : BaseComponentActivity() { startActivity(Intent(this, SubEditActivity::class.java).putExtra("subId", subId)) }, onRemoveSub = { subId -> removeSub(subId) }, - onShareQRCode = { url -> QRCodeDecoder.createQRCode(url) }, + onShareQRCode = viewModel::shareQRCode, onShareClipboard = { url -> Utils.setClipboard(this, url) toast(getString(R.string.toast_success)) @@ -110,7 +108,7 @@ fun SubSettingScreen( onSubUpdate: () -> Unit, onEditSub: (String) -> Unit, onRemoveSub: (String) -> Unit, - onShareQRCode: (String) -> Bitmap?, + onShareQRCode: (String) -> Unit, onShareClipboard: (String) -> Unit ) { val subscriptions by viewModel.subsFlow.collectAsStateWithLifecycle() @@ -119,7 +117,7 @@ fun SubSettingScreen( val confirmRemove = MmkvManager.decodeSettingsBool(AppConfig.PREF_CONFIRM_REMOVE, false) var shareTarget by remember { mutableStateOf?>(null) } - var showQRCodeBitmap by remember { mutableStateOf(null) } + val qrCodeBitmap by viewModel.qrCode.collectAsStateWithLifecycle() val lazyListState = rememberLazyListState() val reorderableState = rememberReorderableLazyListState(lazyListState) { from, to -> @@ -254,7 +252,7 @@ fun SubSettingScreen( onSelected = { action -> shareTarget = null when (action) { - SubscriptionShareAction.QRCode -> showQRCodeBitmap = onShareQRCode(url) + SubscriptionShareAction.QRCode -> onShareQRCode(url) SubscriptionShareAction.Clipboard -> onShareClipboard(url) } }, @@ -263,10 +261,10 @@ fun SubSettingScreen( } // QR Code Dialog - if (showQRCodeBitmap != null) { + if (qrCodeBitmap != null) { QRCodeDialog( - bitmap = showQRCodeBitmap, - onDismiss = { showQRCodeBitmap = null } + bitmap = qrCodeBitmap, + onDismiss = viewModel::dismissQRCode ) } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubscriptionsViewModel.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubscriptionsViewModel.kt index 889daf30..a13db679 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubscriptionsViewModel.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubscriptionsViewModel.kt @@ -1,6 +1,8 @@ package com.v2ray.ang.ui.subscription import android.app.Application +import android.graphics.Bitmap +import androidx.lifecycle.viewModelScope import com.v2ray.ang.AppConfig import com.v2ray.ang.R import com.v2ray.ang.dto.SubscriptionUpdateMessage @@ -14,14 +16,20 @@ import com.v2ray.ang.handler.SettingsManager import com.v2ray.ang.helper.MessageHelper import com.v2ray.ang.ui.base.BaseViewModel import com.v2ray.ang.util.LogUtil +import com.v2ray.ang.util.QRCodeDecoder import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch import kotlinx.coroutines.withContext class SubscriptionsViewModel(application: Application) : BaseViewModel(application) { + private var qrCodeJob: Job? = null + private val _qrCode = MutableStateFlow(null) + internal val qrCode = _qrCode.asStateFlow() private val subscriptions: MutableList = MmkvManager.decodeSubscriptions().toMutableList() @@ -55,6 +63,21 @@ class SubscriptionsViewModel(application: Application) : BaseViewModel(applicati _subsFlow.value = subscriptions.toList() } + internal fun shareQRCode(url: String) { + dismissQRCode() + qrCodeJob = viewModelScope.launch { + val bitmap = withContext(Dispatchers.Default) { QRCodeDecoder.createQRCode(url) } + if (bitmap == null) toastError(R.string.toast_failure) + _qrCode.value = bitmap + } + } + + internal fun dismissQRCode() { + qrCodeJob?.cancel() + qrCodeJob = null + _qrCode.value = null + } + fun move(fromPosition: Int, toPosition: Int) { if (subscriptions.moveItem(fromPosition, toPosition)) { MmkvManager.encodeSubsList(subscriptions.mapTo(mutableListOf()) { it.guid })