增加动态举报
This commit is contained in:
@@ -37,5 +37,7 @@ object ConstVars {
|
|||||||
const val DICT_KEY_GOOGLE_LOGIN_CLIENT_ID = "google_login_client_id"
|
const val DICT_KEY_GOOGLE_LOGIN_CLIENT_ID = "google_login_client_id"
|
||||||
// trtc功能开启
|
// trtc功能开启
|
||||||
const val DICT_KEY_ENABLE_TRTC = "enable_chat"
|
const val DICT_KEY_ENABLE_TRTC = "enable_chat"
|
||||||
|
// 举报选项
|
||||||
|
const val DICT_KEY_REPORT_OPTIONS = "report_reasons"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
50
app/src/main/java/com/aiosman/ravenow/data/CommonService.kt
Normal file
50
app/src/main/java/com/aiosman/ravenow/data/CommonService.kt
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package com.aiosman.ravenow.data
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.aiosman.ravenow.ConstVars
|
||||||
|
import com.aiosman.ravenow.data.api.ApiClient
|
||||||
|
import com.aiosman.ravenow.data.api.CreateReportRequestBody
|
||||||
|
import com.aiosman.ravenow.entity.ReportReasons
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class ReportReasonList(
|
||||||
|
@SerializedName("reasons") var reasons: ArrayList<ReportReasons>
|
||||||
|
)
|
||||||
|
|
||||||
|
interface CommonService {
|
||||||
|
suspend fun getReportReasons(): ReportReasonList
|
||||||
|
suspend fun createReport(
|
||||||
|
reportReasonId: Int,
|
||||||
|
reportType: String,
|
||||||
|
reportId: Int,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
class CommonServiceImpl : CommonService {
|
||||||
|
private val dictService: DictService = DictServiceImpl()
|
||||||
|
override suspend fun getReportReasons(): ReportReasonList {
|
||||||
|
val dictItem = dictService.getDictByKey(ConstVars.DICT_KEY_REPORT_OPTIONS)
|
||||||
|
val rawJson: String = dictItem.value as? String ?: throw Exception("parse report reasons error")
|
||||||
|
val gson = Gson()
|
||||||
|
val list = gson.fromJson(rawJson, ReportReasonList::class.java)
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun createReport(
|
||||||
|
reportReasonId: Int,
|
||||||
|
reportType: String,
|
||||||
|
reportId: Int,
|
||||||
|
) {
|
||||||
|
ApiClient.api.createReport(
|
||||||
|
CreateReportRequestBody(
|
||||||
|
reportType = reportType,
|
||||||
|
reportId = reportId,
|
||||||
|
reason = reportReasonId,
|
||||||
|
extra = "",
|
||||||
|
base64Images = emptyList()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -186,6 +186,21 @@ data class UpdateChatNotificationRequestBody(
|
|||||||
val strategy: String,
|
val strategy: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
data class CreateReportRequestBody(
|
||||||
|
@SerializedName("reportType")
|
||||||
|
val reportType: String,
|
||||||
|
@SerializedName("reportId")
|
||||||
|
val reportId: Int,
|
||||||
|
@SerializedName("reason")
|
||||||
|
val reason: Int,
|
||||||
|
@SerializedName("extra")
|
||||||
|
val extra: String,
|
||||||
|
@SerializedName("base64Images")
|
||||||
|
val base64Images: List<String>,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
interface RaveNowAPI {
|
interface RaveNowAPI {
|
||||||
@POST("register")
|
@POST("register")
|
||||||
suspend fun register(@Body body: RegisterRequestBody): Response<Unit>
|
suspend fun register(@Body body: RegisterRequestBody): Response<Unit>
|
||||||
@@ -429,5 +444,10 @@ interface RaveNowAPI {
|
|||||||
suspend fun updateChatNotification(
|
suspend fun updateChatNotification(
|
||||||
@Body body: UpdateChatNotificationRequestBody
|
@Body body: UpdateChatNotificationRequestBody
|
||||||
): Response<DataContainer<ChatNotification>>
|
): Response<DataContainer<ChatNotification>>
|
||||||
|
|
||||||
|
@POST("reports")
|
||||||
|
suspend fun createReport(
|
||||||
|
@Body body: CreateReportRequestBody
|
||||||
|
): Response<Unit>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
19
app/src/main/java/com/aiosman/ravenow/entity/Common.kt
Normal file
19
app/src/main/java/com/aiosman/ravenow/entity/Common.kt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package com.aiosman.ravenow.entity
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class ReportReasons(
|
||||||
|
@SerializedName("id") var id: Int,
|
||||||
|
@SerializedName("text") var text: Map<String, String>
|
||||||
|
) {
|
||||||
|
fun getReasonText(context:Context): String? {
|
||||||
|
val language = context.resources.configuration.locale.language
|
||||||
|
val langMapping = mapOf(
|
||||||
|
"zh" to "zh",
|
||||||
|
"en" to "en"
|
||||||
|
)
|
||||||
|
val useLang = langMapping[language] ?: "en"
|
||||||
|
return text[useLang] ?: text["en"]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,12 +11,11 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.aiosman.ravenow.data.MomentService
|
import com.aiosman.ravenow.data.MomentService
|
||||||
import com.aiosman.ravenow.entity.MomentServiceImpl
|
|
||||||
import com.aiosman.ravenow.data.UploadImage
|
import com.aiosman.ravenow.data.UploadImage
|
||||||
import com.aiosman.ravenow.entity.MomentEntity
|
import com.aiosman.ravenow.entity.MomentEntity
|
||||||
|
import com.aiosman.ravenow.entity.MomentServiceImpl
|
||||||
import com.aiosman.ravenow.event.MomentAddEvent
|
import com.aiosman.ravenow.event.MomentAddEvent
|
||||||
import com.aiosman.ravenow.exp.rotate
|
import com.aiosman.ravenow.exp.rotate
|
||||||
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.timeline.TimelineMomentViewModel
|
|
||||||
import com.aiosman.ravenow.ui.index.tabs.profile.MyProfileViewModel
|
import com.aiosman.ravenow.ui.index.tabs.profile.MyProfileViewModel
|
||||||
import com.aiosman.ravenow.ui.modification.Modification
|
import com.aiosman.ravenow.ui.modification.Modification
|
||||||
import com.aiosman.ravenow.utils.FileUtil
|
import com.aiosman.ravenow.utils.FileUtil
|
||||||
@@ -36,7 +35,7 @@ data class ImageItem(
|
|||||||
val file: File
|
val file: File
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
suspend fun fromUri(context: Context,uri: String): ImageItem? {
|
fun fromUri(context: Context,uri: String): ImageItem? {
|
||||||
// 保存图片文件到临时文件夹
|
// 保存图片文件到临时文件夹
|
||||||
context.contentResolver.openInputStream(Uri.parse(uri))?.use { inputStream ->
|
context.contentResolver.openInputStream(Uri.parse(uri))?.use { inputStream ->
|
||||||
val tempFileName = UUID.randomUUID().toString()
|
val tempFileName = UUID.randomUUID().toString()
|
||||||
@@ -65,10 +64,10 @@ data class ImageItem(
|
|||||||
// 清理临时文件
|
// 清理临时文件
|
||||||
tempFile.delete()
|
tempFile.delete()
|
||||||
return ImageItem(
|
return ImageItem(
|
||||||
Uri.fromFile(bitmapFile).toString(),
|
uri = Uri.fromFile(bitmapFile).toString(),
|
||||||
savedBitmapFilename,
|
id = savedBitmapFilename,
|
||||||
bitmap,
|
bitmap = bitmap,
|
||||||
bitmapFile
|
file = bitmapFile
|
||||||
)
|
)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
Log.e("NewPost", "Failed to save bitmap to file", e)
|
Log.e("NewPost", "Failed to save bitmap to file", e)
|
||||||
@@ -79,7 +78,21 @@ data class ImageItem(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
data class DraftImageItem(
|
||||||
|
val uri: String,
|
||||||
|
val id: String,
|
||||||
|
val filename: String
|
||||||
|
){
|
||||||
|
companion object {
|
||||||
|
fun fromImageItem(imageItem: ImageItem): DraftImageItem {
|
||||||
|
return DraftImageItem(imageItem.uri, imageItem.id, imageItem.file.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data class Draft(
|
||||||
|
val textContent: String,
|
||||||
|
val imageList: List<DraftImageItem>
|
||||||
|
)
|
||||||
object NewPostViewModel : ViewModel() {
|
object NewPostViewModel : ViewModel() {
|
||||||
var momentService: MomentService = MomentServiceImpl()
|
var momentService: MomentService = MomentServiceImpl()
|
||||||
var textContent by mutableStateOf("")
|
var textContent by mutableStateOf("")
|
||||||
@@ -89,6 +102,13 @@ object NewPostViewModel : ViewModel() {
|
|||||||
var relPostId by mutableStateOf<Int?>(null)
|
var relPostId by mutableStateOf<Int?>(null)
|
||||||
var relMoment by mutableStateOf<MomentEntity?>(null)
|
var relMoment by mutableStateOf<MomentEntity?>(null)
|
||||||
var currentPhotoUri: Uri? = null
|
var currentPhotoUri: Uri? = null
|
||||||
|
var draft: Draft? = null
|
||||||
|
// watch textContent change and save draft
|
||||||
|
// fun saveDraft() {
|
||||||
|
// draft = Draft(textContent, imageList.map {
|
||||||
|
// DraftImageItem(it.uri, it.id, it.bitmap)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
fun asNewPost() {
|
fun asNewPost() {
|
||||||
textContent = ""
|
textContent = ""
|
||||||
searchPlaceAddressResult = null
|
searchPlaceAddressResult = null
|
||||||
|
|||||||
@@ -36,8 +36,10 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.PagerDefaults
|
import androidx.compose.foundation.pager.PagerDefaults
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.CircularProgressIndicator
|
import androidx.compose.material.CircularProgressIndicator
|
||||||
import androidx.compose.material.LinearProgressIndicator
|
import androidx.compose.material.LinearProgressIndicator
|
||||||
import androidx.compose.material3.BasicAlertDialog
|
import androidx.compose.material3.BasicAlertDialog
|
||||||
@@ -75,6 +77,7 @@ import androidx.compose.ui.text.SpanStyle
|
|||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.text.withStyle
|
import androidx.compose.ui.text.withStyle
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -87,16 +90,24 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
|||||||
import androidx.paging.LoadState
|
import androidx.paging.LoadState
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import com.aiosman.ravenow.AppState
|
import com.aiosman.ravenow.AppState
|
||||||
|
import com.aiosman.ravenow.ConstVars
|
||||||
import com.aiosman.ravenow.LocalAppTheme
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
import com.aiosman.ravenow.LocalNavController
|
import com.aiosman.ravenow.LocalNavController
|
||||||
import com.aiosman.ravenow.R
|
import com.aiosman.ravenow.R
|
||||||
|
import com.aiosman.ravenow.data.CommonService
|
||||||
|
import com.aiosman.ravenow.data.CommonServiceImpl
|
||||||
|
import com.aiosman.ravenow.data.DictService
|
||||||
|
import com.aiosman.ravenow.data.DictServiceImpl
|
||||||
|
import com.aiosman.ravenow.data.ReportReasonList
|
||||||
import com.aiosman.ravenow.entity.CommentEntity
|
import com.aiosman.ravenow.entity.CommentEntity
|
||||||
import com.aiosman.ravenow.entity.MomentEntity
|
import com.aiosman.ravenow.entity.MomentEntity
|
||||||
import com.aiosman.ravenow.entity.MomentImageEntity
|
import com.aiosman.ravenow.entity.MomentImageEntity
|
||||||
|
import com.aiosman.ravenow.entity.ReportReasons
|
||||||
import com.aiosman.ravenow.exp.formatPostTime
|
import com.aiosman.ravenow.exp.formatPostTime
|
||||||
import com.aiosman.ravenow.exp.timeAgo
|
import com.aiosman.ravenow.exp.timeAgo
|
||||||
import com.aiosman.ravenow.ui.NavigationRoute
|
import com.aiosman.ravenow.ui.NavigationRoute
|
||||||
import com.aiosman.ravenow.ui.comment.NoticeScreenHeader
|
import com.aiosman.ravenow.ui.comment.NoticeScreenHeader
|
||||||
|
import com.aiosman.ravenow.ui.composables.ActionButton
|
||||||
import com.aiosman.ravenow.ui.composables.AnimatedFavouriteIcon
|
import com.aiosman.ravenow.ui.composables.AnimatedFavouriteIcon
|
||||||
import com.aiosman.ravenow.ui.composables.AnimatedLikeIcon
|
import com.aiosman.ravenow.ui.composables.AnimatedLikeIcon
|
||||||
import com.aiosman.ravenow.ui.composables.BottomNavigationPlaceholder
|
import com.aiosman.ravenow.ui.composables.BottomNavigationPlaceholder
|
||||||
@@ -107,6 +118,7 @@ import com.aiosman.ravenow.ui.composables.FollowButton
|
|||||||
import com.aiosman.ravenow.ui.composables.StatusBarSpacer
|
import com.aiosman.ravenow.ui.composables.StatusBarSpacer
|
||||||
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||||
import com.aiosman.ravenow.utils.FileUtil.saveImageToGallery
|
import com.aiosman.ravenow.utils.FileUtil.saveImageToGallery
|
||||||
|
import com.google.gson.Gson
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.engawapg.lib.zoomable.rememberZoomState
|
import net.engawapg.lib.zoomable.rememberZoomState
|
||||||
import net.engawapg.lib.zoomable.zoomable
|
import net.engawapg.lib.zoomable.zoomable
|
||||||
@@ -138,6 +150,7 @@ fun PostScreen(
|
|||||||
var editCommentModalState = rememberModalBottomSheetState(
|
var editCommentModalState = rememberModalBottomSheetState(
|
||||||
skipPartiallyExpanded = true
|
skipPartiallyExpanded = true
|
||||||
)
|
)
|
||||||
|
var showReportDialog by remember { mutableStateOf(false) }
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
@@ -250,6 +263,27 @@ fun PostScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (showReportDialog && viewModel.moment != null) {
|
||||||
|
ModalBottomSheet(
|
||||||
|
onDismissRequest = {
|
||||||
|
showReportDialog = false
|
||||||
|
},
|
||||||
|
containerColor = AppColors.background,
|
||||||
|
sheetState = rememberModalBottomSheetState(
|
||||||
|
skipPartiallyExpanded = true
|
||||||
|
),
|
||||||
|
dragHandle = {},
|
||||||
|
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
||||||
|
|
||||||
|
) {
|
||||||
|
ReportModal(
|
||||||
|
momentId = viewModel.moment!!.id,
|
||||||
|
onClose = {
|
||||||
|
showReportDialog = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
@@ -280,7 +314,6 @@ fun PostScreen(
|
|||||||
momentEntity = viewModel.moment
|
momentEntity = viewModel.moment
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
it
|
it
|
||||||
@@ -332,6 +365,9 @@ fun PostScreen(
|
|||||||
viewModel.deleteMoment {
|
viewModel.deleteMoment {
|
||||||
navController.navigateUp()
|
navController.navigateUp()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
onReportClick = {
|
||||||
|
showReportDialog = true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
@@ -643,7 +679,8 @@ fun Header(
|
|||||||
userId: Int?,
|
userId: Int?,
|
||||||
isFollowing: Boolean,
|
isFollowing: Boolean,
|
||||||
onFollowClick: () -> Unit,
|
onFollowClick: () -> Unit,
|
||||||
onDeleteClick: () -> Unit = {}
|
onDeleteClick: () -> Unit = {},
|
||||||
|
onReportClick: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
@@ -666,6 +703,10 @@ fun Header(
|
|||||||
onDeleteClick = {
|
onDeleteClick = {
|
||||||
onDeleteClick()
|
onDeleteClick()
|
||||||
expanded = false
|
expanded = false
|
||||||
|
},
|
||||||
|
onReportClick = {
|
||||||
|
onReportClick()
|
||||||
|
expanded = false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -729,21 +770,21 @@ fun Header(
|
|||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
}
|
}
|
||||||
if (AppState.UserId == userId) {
|
|
||||||
Box {
|
Box {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(20.dp)
|
.height(20.dp)
|
||||||
.padding(end = 8.dp)
|
.padding(end = 8.dp)
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
expanded = true
|
expanded = true
|
||||||
},
|
},
|
||||||
painter = painterResource(id = R.drawable.rider_pro_more_horizon),
|
painter = painterResource(id = R.drawable.rider_pro_more_horizon),
|
||||||
contentDescription = "",
|
contentDescription = "",
|
||||||
colorFilter = ColorFilter.tint(AppColors.text)
|
colorFilter = ColorFilter.tint(AppColors.text)
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1321,7 +1362,9 @@ fun PostBottomBar(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PostMenuModal(
|
fun PostMenuModal(
|
||||||
onDeleteClick: () -> Unit = {}
|
onDeleteClick: () -> Unit = {},
|
||||||
|
onReportClick: () -> Unit = {},
|
||||||
|
momentEntity: MomentEntity? = null
|
||||||
) {
|
) {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
@@ -1337,37 +1380,70 @@ fun PostMenuModal(
|
|||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Column(
|
momentEntity?.let {
|
||||||
modifier = Modifier,
|
Column(
|
||||||
verticalArrangement = Arrangement.Center,
|
modifier = Modifier.padding(end = 16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
verticalArrangement = Arrangement.Center,
|
||||||
) {
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.clip(CircleShape)
|
|
||||||
.noRippleClickable {
|
|
||||||
onDeleteClick()
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
Image(
|
Box(
|
||||||
painter = painterResource(id = R.drawable.rider_pro_moment_delete),
|
modifier = Modifier
|
||||||
contentDescription = "",
|
.clip(CircleShape)
|
||||||
modifier = Modifier.size(24.dp),
|
.noRippleClickable {
|
||||||
colorFilter = ColorFilter.tint(
|
onDeleteClick()
|
||||||
AppColors.text
|
}
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.rider_pro_moment_delete),
|
||||||
|
contentDescription = "",
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
colorFilter = ColorFilter.tint(
|
||||||
|
AppColors.text
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.delete),
|
||||||
|
fontSize = 11.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = AppColors.text
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.delete),
|
|
||||||
fontSize = 11.sp,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
color = AppColors.text
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(end = 16.dp),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(CircleShape)
|
||||||
|
.noRippleClickable {
|
||||||
|
onReportClick()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.rider_pro_moment_delete),
|
||||||
|
contentDescription = "",
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
colorFilter = ColorFilter.tint(
|
||||||
|
AppColors.text
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.report),
|
||||||
|
fontSize = 11.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = AppColors.text
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1597,4 +1673,183 @@ fun OrderSelectionComponent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReportModal(
|
||||||
|
momentId: Int,
|
||||||
|
onClose: () -> Unit = {}
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
val commonService : CommonService = CommonServiceImpl()
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val context = LocalContext.current
|
||||||
|
var reasonMapping by remember { mutableStateOf(mutableMapOf<Int,String>()) }
|
||||||
|
var result:Boolean? by remember { mutableStateOf(null) }
|
||||||
|
fun loadReportOptions() {
|
||||||
|
scope.launch {
|
||||||
|
val reportOptions = commonService.getReportReasons()
|
||||||
|
val newReasonMapping :MutableMap<Int,String> = mutableMapOf()
|
||||||
|
reportOptions.reasons.forEach { option ->
|
||||||
|
option.getReasonText(context)?.let {
|
||||||
|
newReasonMapping[option.id] = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reasonMapping = newReasonMapping
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun createReport(code:Int) {
|
||||||
|
scope.launch {
|
||||||
|
try {
|
||||||
|
commonService.createReport(
|
||||||
|
reportReasonId = code,
|
||||||
|
reportType = "post",
|
||||||
|
reportId = momentId
|
||||||
|
)
|
||||||
|
result = true
|
||||||
|
}catch (e:Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
loadReportOptions()
|
||||||
|
}
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(AppColors.background)
|
||||||
|
.padding(start = 24.dp, end = 24.dp, bottom = 64.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(top = 16.dp, bottom = 16.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.report),
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = AppColors.text
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// divider
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(1.dp)
|
||||||
|
.background(AppColors.divider)
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(top = 24.dp, bottom = 24.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.report_title),
|
||||||
|
fontSize = 20.sp,
|
||||||
|
color = AppColors.text,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.report_description),
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = AppColors.secondaryText,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// report options,scroll list
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
reasonMapping.forEach { (id, reason) ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.noRippleClickable {
|
||||||
|
createReport(id)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
// divider
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(1.dp)
|
||||||
|
.background(AppColors.divider)
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(vertical = 16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
text = reason,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = AppColors.text
|
||||||
|
)
|
||||||
|
// right icon
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.rider_pro_nav_next),
|
||||||
|
contentDescription = "",
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
tint = AppColors.text
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxWidth().weight(1f)
|
||||||
|
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(top = 24.dp, bottom = 24.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
if (result == true) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.report_success_desc),
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = AppColors.text
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (result == false) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.report_fail_desc),
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = AppColors.text
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
ActionButton(
|
||||||
|
text = stringResource(R.string.close),
|
||||||
|
click = {
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -94,4 +94,10 @@
|
|||||||
<string name="incorrect_captcha_please_try_again">验证码错误,请重试</string>
|
<string name="incorrect_captcha_please_try_again">验证码错误,请重试</string>
|
||||||
<string name="search_user_item_follower_count">%d 粉丝</string>
|
<string name="search_user_item_follower_count">%d 粉丝</string>
|
||||||
<string name="error_incorrect_old_password">旧密码不正确</string>
|
<string name="error_incorrect_old_password">旧密码不正确</string>
|
||||||
|
<string name="report">举报</string>
|
||||||
|
<string name="report_description">你的举报是匿名的,如果有人正面临危险,请立即联系当地应急服务,不要耽搁</string>
|
||||||
|
<string name="report_success_desc">举报成功</string>
|
||||||
|
<string name="report_fail_desc">举报失败,可以尝试重试</string>
|
||||||
|
<string name="report_title">举报这篇帖子的原因是?</string>
|
||||||
|
<string name="close">关闭</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -93,4 +93,10 @@
|
|||||||
<string name="incorrect_captcha_please_try_again">incorrect captcha,please try again</string>
|
<string name="incorrect_captcha_please_try_again">incorrect captcha,please try again</string>
|
||||||
<string name="search_user_item_follower_count">%d followers</string>
|
<string name="search_user_item_follower_count">%d followers</string>
|
||||||
<string name="error_incorrect_old_password">Incorrect old password</string>
|
<string name="error_incorrect_old_password">Incorrect old password</string>
|
||||||
|
<string name="report">Report</string>
|
||||||
|
<string name="report_description">Your report is anonymous, if anyone is in danger please contact local emergency services immediately without delay</string>
|
||||||
|
<string name="report_success_desc">Reported successfully</string>
|
||||||
|
<string name="report_fail_desc">Failed to report, please try again</string>
|
||||||
|
<string name="report_title">Reason for reporting this post?</string>
|
||||||
|
<string name="close">Close</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user