From d63d7a5a134cee5edadcbff03bb18f4040e7e3a0 Mon Sep 17 00:00:00 2001 From: HuanCheng65 <22636177+HuanCheng65@users.noreply.github.com> Date: Thu, 20 Jul 2023 22:58:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=80=89=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../huanchengfly/tieba/post/MainActivityV2.kt | 15 +++++ .../tieba/post/activities/ReplyActivity.kt | 4 +- .../activities/TranslucentThemeActivity.kt | 6 +- .../tieba/post/adapters/InsertPhotoAdapter.kt | 12 ++-- .../tieba/post/arch/GlobalEvent.kt | 55 ++++++++++++++----- .../editprofile/view/EditProfileActivity.kt | 6 +- .../tieba/post/utils/ImagePicker.kt | 38 +++++++++---- 7 files changed, 98 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/MainActivityV2.kt b/app/src/main/java/com/huanchengfly/tieba/post/MainActivityV2.kt index 9aee2806..c65fd765 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/MainActivityV2.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/MainActivityV2.kt @@ -54,6 +54,9 @@ import com.google.accompanist.navigation.material.ModalBottomSheetLayout import com.google.accompanist.systemuicontroller.SystemUiController import com.huanchengfly.tieba.post.api.retrofit.exception.getErrorMessage import com.huanchengfly.tieba.post.arch.BaseComposeActivity +import com.huanchengfly.tieba.post.arch.GlobalEvent +import com.huanchengfly.tieba.post.arch.emitGlobalEvent +import com.huanchengfly.tieba.post.arch.onGlobalEvent import com.huanchengfly.tieba.post.services.NotifyJobService import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme import com.huanchengfly.tieba.post.ui.page.NavGraphs @@ -69,9 +72,11 @@ import com.huanchengfly.tieba.post.utils.AccountUtil import com.huanchengfly.tieba.post.utils.ClientUtils import com.huanchengfly.tieba.post.utils.JobServiceUtil import com.huanchengfly.tieba.post.utils.PermissionUtils +import com.huanchengfly.tieba.post.utils.PickMediasRequest import com.huanchengfly.tieba.post.utils.TiebaUtil import com.huanchengfly.tieba.post.utils.isIgnoringBatteryOptimizations import com.huanchengfly.tieba.post.utils.newIntentFilter +import com.huanchengfly.tieba.post.utils.registerPickMediasLauncher import com.huanchengfly.tieba.post.utils.requestIgnoreBatteryOptimizations import com.huanchengfly.tieba.post.utils.requestPermission import com.ramcosta.composedestinations.DestinationsNavHost @@ -124,6 +129,11 @@ class MainActivityV2 : BaseComposeActivity() { private val notificationCountFlow: MutableSharedFlow = MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) + private val pickMediasLauncher = + registerPickMediasLauncher { + emitGlobalEvent(GlobalEvent.SelectedImages(it.id, it.uris)) + } + private val devicePostureFlow: StateFlow by lazy { WindowInfoTracker.getOrCreate(this) .windowLayoutInfo(this) @@ -251,6 +261,11 @@ class MainActivityV2 : BaseComposeActivity() { okSignAlertDialogState.show() } } + onGlobalEvent { + pickMediasLauncher.launch( + PickMediasRequest(it.id, it.maxCount, it.mediaType) + ) + } CompositionLocalProvider( LocalNotificationCountFlow provides notificationCountFlow, LocalDevicePosture provides devicePostureFlow.collectAsState(), diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/ReplyActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/ReplyActivity.kt index e60dd40b..db4c2d01 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/activities/ReplyActivity.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/ReplyActivity.kt @@ -99,9 +99,9 @@ class ReplyActivity : BaseActivity(), View.OnClickListener, get() = false @JvmField - val pickMediasLauncher = registerPickMediasLauncher { + val pickMediasLauncher = registerPickMediasLauncher { (_, uris) -> val photoInfoBeans = insertPhotoAdapter.getFileList().toMutableList() - for (uri in it) { + for (uri in uris) { photoInfoBeans.add(PhotoInfoBean(this, uri)) } insertPhotoAdapter.setFileList(photoInfoBeans) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/TranslucentThemeActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/TranslucentThemeActivity.kt index be67c4ee..51f27f94 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/activities/TranslucentThemeActivity.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/TranslucentThemeActivity.kt @@ -97,9 +97,9 @@ class TranslucentThemeActivity : BaseActivity(), View.OnClickListener, OnSeekBar @BindView(R.id.color_theme) lateinit var colorTheme: ViewGroup - private val selectImageLauncher = registerPickMediasLauncher { - if (it.isNotEmpty()) { - val sourceUri = it[0] + private val selectImageLauncher = registerPickMediasLauncher { (_, uris) -> + if (uris.isNotEmpty()) { + val sourceUri = uris[0] launchUCrop(sourceUri) } } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/InsertPhotoAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/InsertPhotoAdapter.kt index a2aeeffa..f2a39703 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/InsertPhotoAdapter.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/InsertPhotoAdapter.kt @@ -70,10 +70,14 @@ class InsertPhotoAdapter(private val mContext: Context) : RecyclerView.Adapter + ) : GlobalEvent } -private val mutableGlobalEventFlow by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { MutableSharedFlow() } +private val globalEventChannel: Channel = Channel() -val GlobalEventFlow by lazy { mutableGlobalEventFlow } +val GlobalEventFlow: Flow + get() = globalEventChannel.receiveAsFlow() fun emitGlobalEvent(event: GlobalEvent) { - mutableGlobalEventFlow.tryEmit(event) + globalEventChannel.trySend(event) } -inline fun CoroutineScope.onGlobalEvent( +@Composable +inline fun onGlobalEvent( + coroutineScope: CoroutineScope = rememberCoroutineScope(), noinline listener: suspend (Event) -> Unit -): Job { - return launch { - GlobalEventFlow - .filterIsInstance() - .cancellable() - .collect { - launch { - listener(it) +) { + DisposableEffect(listener) { + val job = coroutineScope.launch { + GlobalEventFlow + .filterIsInstance() + .cancellable() + .collect { + launch { + listener(it) + } } - } + } + onDispose { + job.cancel() + } } } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/editprofile/view/EditProfileActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/editprofile/view/EditProfileActivity.kt index c02e2f2c..306568e9 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/editprofile/view/EditProfileActivity.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/editprofile/view/EditProfileActivity.kt @@ -69,9 +69,9 @@ class EditProfileActivity : BaseActivity() { } private val pickMediasLauncher = - registerPickMediasLauncher { - if (it.isNotEmpty()) { - val sourceUri = it[0] + registerPickMediasLauncher { (_, uris) -> + if (uris.isNotEmpty()) { + val sourceUri = uris[0] Glide.with(this) .asFile() .load(sourceUri) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/ImagePicker.kt b/app/src/main/java/com/huanchengfly/tieba/post/utils/ImagePicker.kt index 543515da..82a366f9 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/ImagePicker.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/ImagePicker.kt @@ -1,5 +1,6 @@ package com.huanchengfly.tieba.post.utils +import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.content.Intent @@ -16,9 +17,9 @@ import com.zhihu.matisse.MimeType import com.zhihu.matisse.engine.impl.GlideEngine import com.zhihu.matisse.ui.MatisseActivity -fun AppCompatActivity.registerPickMediasLauncher(callback: (List) -> Unit): ActivityResultLauncher { +fun AppCompatActivity.registerPickMediasLauncher(callback: (PickMediasResult) -> Unit): ActivityResultLauncher { return registerForActivityResult( - PickMediasContract() + PickMediasContract ) { callback(it) } @@ -55,15 +56,17 @@ private fun Intent.getClipDataUris(): List { return ArrayList(resultSet) } +@SuppressLint("NewApi") private fun getMaxItems() = if (isPhotoPickerAvailable()) { MediaStore.getPickImagesMaxLimit() } else { Integer.MAX_VALUE } -class PickMediasRequest( - var maxItems: Int = 1, - var mediaType: MediaType = ImageAndVideo +data class PickMediasRequest( + val id: String = "", + val maxItems: Int = 1, + val mediaType: MediaType = ImageAndVideo ) { sealed interface MediaType @@ -73,7 +76,7 @@ class PickMediasRequest( object ImageAndVideo : MediaType - class SingleMimeType(val mimeType: String) : MediaType + data class SingleMimeType(val mimeType: String) : MediaType companion object { internal fun getMimeType(input: MediaType): String? { @@ -87,8 +90,19 @@ class PickMediasRequest( } } -class PickMediasContract : ActivityResultContract>() { +data class PickMediasResult( + val id: String, + val uris: List +) + +object PickMediasContract : ActivityResultContract() { + private var curRequestId: String? = null + + val hasCurrentRequest: Boolean + get() = curRequestId != null + override fun createIntent(context: Context, input: PickMediasRequest): Intent { + curRequestId = input.id if (isPhotoPickerAvailable()) { return Intent(MediaStore.ACTION_PICK_IMAGES).apply { type = PickMediasRequest.getMimeType(input.mediaType) @@ -112,13 +126,15 @@ class PickMediasContract : ActivityResultContract>( return Intent(context, MatisseActivity::class.java) } - override fun parseResult(resultCode: Int, intent: Intent?): List { + override fun parseResult(resultCode: Int, intent: Intent?): PickMediasResult { + val id = curRequestId + "" + curRequestId = null if (resultCode != Activity.RESULT_OK || intent == null) { - return emptyList() + return PickMediasResult(id, emptyList()) } if (isPhotoPickerAvailable()) { - return intent.getClipDataUris() + return PickMediasResult(id, intent.getClipDataUris()) } - return Matisse.obtainResult(intent) + return PickMediasResult(id, Matisse.obtainResult(intent)) } } \ No newline at end of file