diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt index 4bff981f..1aebace1 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt @@ -1200,9 +1200,18 @@ interface ITiebaApi { * @param postId PID */ fun checkReportPost( - postId: String + postId: String, ): Call + /** + * 获取举报贴子/回贴页面 URL + * + * @param postId PID + */ + fun checkReportPostAsync( + postId: String, + ): Deferred> + /** * 获得当前用户昵称(需登录) */ @@ -1213,7 +1222,7 @@ interface ITiebaApi { */ fun initNickNameFlow( bduss: String, - sToken: String + sToken: String, ): Flow /** diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt index 21b3ff7f..3765facc 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt @@ -910,6 +910,14 @@ object MixedTiebaApiImpl : ITiebaApi { ) ) + override fun checkReportPostAsync(postId: String): Deferred> = + RetrofitTiebaApi.OFFICIAL_TIEBA_API.checkReportAsync( + category = "1", + reportParam = mapOf( + "pid" to postId + ) + ) + override fun initNickNameFlow(): Flow = RetrofitTiebaApi.OFFICIAL_TIEBA_API.initNickNameFlow() diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/models/CheckReportBean.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/models/CheckReportBean.kt index 1589079c..d3256eec 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/models/CheckReportBean.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/models/CheckReportBean.kt @@ -1,15 +1,21 @@ package com.huanchengfly.tieba.post.api.models import com.google.gson.annotations.SerializedName +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +@Serializable data class CheckReportBean( + @SerialName("errno") @SerializedName("errno") var errorCode: Int?, + @SerialName("errmsg") @SerializedName("errmsg") var errorMsg: String?, - val data: CheckReportDataBean + val data: CheckReportDataBean, ) { + @Serializable data class CheckReportDataBean( - val url: String? + val url: String = "", ) } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/OfficialTiebaApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/OfficialTiebaApi.kt index 5826110c..fd913e78 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/OfficialTiebaApi.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/OfficialTiebaApi.kt @@ -492,9 +492,19 @@ interface OfficialTiebaApi { @Field("category") category: String, @FieldMap reportParam: Map, @Field("stoken") stoken: String? = AccountUtil.getLoginInfo() - ?.sToken + ?.sToken, ): Call + @Headers("${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}") + @POST("/c/f/ueg/checkjubao") + @FormUrlEncoded + fun checkReportAsync( + @Field("category") category: String, + @FieldMap reportParam: Map, + @Field("stoken") stoken: String? = AccountUtil.getLoginInfo() + ?.sToken, + ): Deferred> + @Headers("${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}") @POST("/c/c/bawu/delthread") @FormUrlEncoded diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/subposts/SubPostsPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/subposts/SubPostsPage.kt index 70c79df8..ebc5fb21 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/subposts/SubPostsPage.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/subposts/SubPostsPage.kt @@ -24,13 +24,14 @@ import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.ArrowBack +import androidx.compose.material.icons.automirrored.rounded.ArrowBack import androidx.compose.material.icons.rounded.Close import androidx.compose.material.icons.rounded.OpenInBrowser import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -88,6 +89,7 @@ import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.spec.DestinationStyleBottomSheet import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.delay +import kotlinx.coroutines.launch @Destination @Composable @@ -282,7 +284,7 @@ internal fun SubPostsContent( navigationIcon = { IconButton(onClick = { navigator.navigateUp() }) { Icon( - imageVector = if (isSheet) Icons.Rounded.Close else Icons.Rounded.ArrowBack, + imageVector = if (isSheet) Icons.Rounded.Close else Icons.AutoMirrored.Rounded.ArrowBack, contentDescription = stringResource(id = R.string.btn_close) ) } @@ -535,6 +537,8 @@ private fun SubPostItem( ) { val (subPost, contentRenders, blocked) = item val context = LocalContext.current + val navigator = LocalNavigator.current + val coroutineScope = rememberCoroutineScope() val author = remember(subPost) { subPost.get { author }?.wrapImmutable() } val hasAgreed = remember(subPost) { subPost.get { agree?.hasAgree == 1 } @@ -576,7 +580,9 @@ private fun SubPostItem( } DropdownMenuItem( onClick = { - TiebaUtil.reportPost(context, subPost.get { id }.toString()) + coroutineScope.launch { + TiebaUtil.reportPost(context, navigator, subPost.get { id }.toString()) + } menuState.expanded = false } ) { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt index c74a6239..bc9ecf09 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt @@ -122,6 +122,7 @@ import com.huanchengfly.tieba.post.ui.common.theme.compose.invertChipBackground import com.huanchengfly.tieba.post.ui.common.theme.compose.invertChipContent import com.huanchengfly.tieba.post.ui.common.theme.compose.pullRefreshIndicator import com.huanchengfly.tieba.post.ui.common.theme.compose.threadBottomBar +import com.huanchengfly.tieba.post.ui.page.LocalNavigator import com.huanchengfly.tieba.post.ui.page.ProvideNavigator import com.huanchengfly.tieba.post.ui.page.destinations.CopyTextDialogPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.ForumPageDestination @@ -1167,10 +1168,13 @@ fun ThreadPage( thread?.get { firstPostId }.takeIf { it != 0L } ?: firstPost?.get { id } ?: 0L - TiebaUtil.reportPost( - context, - firstPostId.toString() - ) + coroutineScope.launch { + TiebaUtil.reportPost( + context, + navigator, + firstPostId.toString() + ) + } }, onDeleteClick = { deletePost = null @@ -1634,6 +1638,8 @@ fun PostCard( onMenuDeleteClick: ((Post) -> Unit)? = null, ) { val context = LocalContext.current + val navigator = LocalNavigator.current + val coroutineScope = rememberCoroutineScope() val post = remember(postHolder) { postHolder.get() } val hasPadding = remember(key1 = postHolder, key2 = immersiveMode) { postHolder.get { floor > 1 } && !immersiveMode @@ -1693,7 +1699,9 @@ fun PostCard( } DropdownMenuItem( onClick = { - TiebaUtil.reportPost(context, post.id.toString()) + coroutineScope.launch { + TiebaUtil.reportPost(context, navigator, post.id.toString()) + } menuState.expanded = false } ) { @@ -1879,6 +1887,8 @@ private fun SubPostItem( onMenuCopyClick: ((SubPostList) -> Unit)?, ) { val context = LocalContext.current + val navigator = LocalNavigator.current + val coroutineScope = rememberCoroutineScope() val menuState = rememberMenuState() LongClickMenu( menuState = menuState, @@ -1905,7 +1915,9 @@ private fun SubPostItem( } DropdownMenuItem( onClick = { - TiebaUtil.reportPost(context, subPostList.get { id }.toString()) + coroutineScope.launch { + TiebaUtil.reportPost(context, navigator, subPostList.get { id }.toString()) + } menuState.expanded = false } ) { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/TiebaUtil.kt b/app/src/main/java/com/huanchengfly/tieba/post/utils/TiebaUtil.kt index b1c345fd..a681d0c6 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/TiebaUtil.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/TiebaUtil.kt @@ -14,11 +14,15 @@ import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.activities.WebViewActivity import com.huanchengfly.tieba.post.api.TiebaApi import com.huanchengfly.tieba.post.api.models.CheckReportBean +import com.huanchengfly.tieba.post.api.retrofit.doIfFailure +import com.huanchengfly.tieba.post.api.retrofit.doIfSuccess import com.huanchengfly.tieba.post.components.dialogs.LoadingDialog import com.huanchengfly.tieba.post.pendingIntentFlagMutable import com.huanchengfly.tieba.post.receivers.AutoSignAlarm import com.huanchengfly.tieba.post.services.OKSignService import com.huanchengfly.tieba.post.toastShort +import com.huanchengfly.tieba.post.ui.page.destinations.WebViewPageDestination +import com.ramcosta.composedestinations.navigation.DestinationsNavigator import retrofit2.Call import retrofit2.Callback import retrofit2.Response @@ -125,7 +129,7 @@ object TiebaUtil { .enqueue(object : Callback { override fun onResponse( call: Call, - response: Response + response: Response, ) { dialog.dismiss() WebViewActivity.launch(context, response.body()!!.data.url) @@ -137,4 +141,24 @@ object TiebaUtil { } }) } + + suspend fun reportPost( + context: Context, + navigator: DestinationsNavigator, + postId: String, + ) { + val dialog = LoadingDialog(context).apply { show() } + TiebaApi.getInstance() + .checkReportPostAsync(postId) + .doIfSuccess { + dialog.dismiss() + navigator.navigate( + WebViewPageDestination(it.data.url) + ) + } + .doIfFailure { + dialog.dismiss() + context.toastShort(R.string.toast_load_failed) + } + } } \ No newline at end of file