新增聊天消息提醒

This commit is contained in:
2024-10-11 16:51:51 +08:00
parent 36739b1615
commit 81f90db1b1
15 changed files with 414 additions and 105 deletions

View File

@@ -37,9 +37,9 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"
android:windowSoftInputMode="adjustResize"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/Theme.RiderPro"> android:theme="@style/Theme.RiderPro"
android:windowSoftInputMode="adjustResize">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
@@ -69,6 +69,9 @@
<action android:name="cn.jiguang.user.service.action" /> <action android:name="cn.jiguang.user.service.action" />
</intent-filter> </intent-filter>
</service> </service>
<service
android:name=".TrtcService"
android:exported="false" />
<receiver <receiver
android:name=".JpushReciver" android:name=".JpushReciver"

View File

@@ -1,6 +1,7 @@
package com.aiosman.riderpro package com.aiosman.riderpro
import android.content.Context import android.content.Context
import android.content.Intent
import android.icu.util.Calendar import android.icu.util.Calendar
import android.icu.util.TimeZone import android.icu.util.TimeZone
import android.util.Log import android.util.Log
@@ -23,7 +24,6 @@ import com.tencent.imsdk.v2.V2TIMLogListener
import com.tencent.imsdk.v2.V2TIMManager import com.tencent.imsdk.v2.V2TIMManager
import com.tencent.imsdk.v2.V2TIMSDKConfig import com.tencent.imsdk.v2.V2TIMSDKConfig
import com.tencent.imsdk.v2.V2TIMUserFullInfo import com.tencent.imsdk.v2.V2TIMUserFullInfo
import com.tencent.imsdk.v2.V2TIMValueCallback
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.suspendCoroutine
@@ -66,8 +66,12 @@ object AppState {
val sign = accountService.getMyTrtcSign() val sign = accountService.getMyTrtcSign()
loginToTrtc(sign.userId, sign.sig) loginToTrtc(sign.userId, sign.sig)
updateTrtcUserProfile() updateTrtcUserProfile()
// 登录成功后启动TrtcService
context.startService(
Intent(context, TrtcService::class.java)
)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace()
} }
} }
@@ -105,7 +109,7 @@ object AppState {
} }
} }
fun ReloadAppState() { fun ReloadAppState(context: Context) {
// 重置动态列表页面 // 重置动态列表页面
MomentViewModel.ResetModel() MomentViewModel.ResetModel()
// 重置我的页面 // 重置我的页面
@@ -129,5 +133,13 @@ object AppState {
// 重置关注通知页面 // 重置关注通知页面
IndexViewModel.ResetModel() IndexViewModel.ResetModel()
UserId = null UserId = null
// 关闭 TrtcService
val trtcService = Intent(
context,
TrtcService::class.java
)
context.stopService(trtcService)
} }
} }

View File

@@ -0,0 +1,40 @@
package com.aiosman.riderpro
import com.aiosman.riderpro.data.ChatService
import com.aiosman.riderpro.data.ChatServiceImpl
import com.aiosman.riderpro.entity.ChatNotification
/**
* 保存一些关于聊天的状态
*/
object ChatState {
val chatService: ChatService = ChatServiceImpl()
var chatNotificationList = mutableListOf<ChatNotification>()
suspend fun getStrategyByTargetTrtcId(targetTrtcId: String): ChatNotification? {
// 先从缓存中查找
if (chatNotificationList.isNotEmpty()) {
chatNotificationList.forEach {
if (it.targetTrtcId == targetTrtcId) {
return it
}
}
}
// 缓存中没有再从网络获取
chatService.getChatNotifications(targetTrtcId)?.let {
chatNotificationList.add(it)
return it
}
// 存在未设置策略的情况
return null
}
suspend fun updateChatNotification(targetUserId: Int, strategy: String): ChatNotification {
val updatedData = chatService.updateChatNotification(targetUserId, strategy)
chatNotificationList = chatNotificationList.filter {
it.targetUserId != targetUserId
}.toMutableList().apply {
add(updatedData)
}
return updatedData
}
}

View File

@@ -26,6 +26,8 @@ import cn.jiguang.api.utils.JCollectionAuth
import cn.jpush.android.api.JPushInterface import cn.jpush.android.api.JPushInterface
import com.aiosman.riderpro.data.AccountService import com.aiosman.riderpro.data.AccountService
import com.aiosman.riderpro.data.AccountServiceImpl import com.aiosman.riderpro.data.AccountServiceImpl
import com.aiosman.riderpro.data.UserService
import com.aiosman.riderpro.data.UserServiceImpl
import com.aiosman.riderpro.ui.Navigation import com.aiosman.riderpro.ui.Navigation
import com.aiosman.riderpro.ui.NavigationRoute import com.aiosman.riderpro.ui.NavigationRoute
import com.aiosman.riderpro.ui.navigateToPost import com.aiosman.riderpro.ui.navigateToPost
@@ -109,7 +111,7 @@ class MainActivity : ComponentActivity() {
// 处理带有 postId 的通知点击 // 处理带有 postId 的通知点击
val postId = intent.getStringExtra("POST_ID") val postId = intent.getStringExtra("POST_ID")
var commentId = intent.getStringExtra("COMMENT_ID") var commentId = intent.getStringExtra("COMMENT_ID")
var action = intent.getStringExtra("ACTION") val action = intent.getStringExtra("ACTION")
if (action == "newFollow") { if (action == "newFollow") {
navController.navigate(NavigationRoute.Followers.route) navController.navigate(NavigationRoute.Followers.route)
return@Navigation return@Navigation
@@ -118,6 +120,25 @@ class MainActivity : ComponentActivity() {
navController.navigate(NavigationRoute.Followers.route) navController.navigate(NavigationRoute.Followers.route)
return@Navigation return@Navigation
} }
if (action == "TRTC_NEW_MESSAGE") {
val userService:UserService = UserServiceImpl()
val sender = intent.getStringExtra("SENDER")
sender?.let {
scope.launch {
try {
val profile = userService.getUserProfileByTrtcUserId(it)
navController.navigate(NavigationRoute.Chat.route.replace(
"{id}",
profile.id.toString()
))
}catch (e:Exception){
e.printStackTrace()
}
}
}
return@Navigation
}
if (commentId == null) { if (commentId == null) {
commentId = "0" commentId = "0"
} }

View File

@@ -0,0 +1,129 @@
package com.aiosman.riderpro
import android.Manifest
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.IBinder
import android.util.Log
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.aiosman.riderpro.entity.ChatItem
import com.tencent.imsdk.v2.V2TIMAdvancedMsgListener
import com.tencent.imsdk.v2.V2TIMManager
import com.tencent.imsdk.v2.V2TIMMessage
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class TrtcService : Service() {
private var trtcMessageListener: V2TIMAdvancedMsgListener? = null
private val channelId = "chat_notification"
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d("TrtcService", "onStartCommand")
createNotificationChannel()
CoroutineScope(Dispatchers.IO).launch {
registerMessageListener(applicationContext)
}
return START_STICKY;
}
override fun onDestroy() {
super.onDestroy()
Log.d("TrtcService", "onDestroy")
CoroutineScope(Dispatchers.IO).launch {
unRegisterMessageListener()
}
}
private fun registerMessageListener(context: Context) {
val scope = CoroutineScope(Dispatchers.IO)
trtcMessageListener = object : V2TIMAdvancedMsgListener() {
override fun onRecvNewMessage(msg: V2TIMMessage?) {
super.onRecvNewMessage(msg)
msg?.let {
if (MainActivityLifecycle.isForeground) {
return
}
scope.launch {
// 先获取通知策略
val notiStrategy = ChatState.getStrategyByTargetTrtcId(it.sender)
if (notiStrategy == null) {
// 未设置策略, 默认通知
sendNotification(context, it)
return@launch
}
if (notiStrategy.strategy != "mute") {
sendNotification(context, it)
}
}
}
}
}
V2TIMManager.getMessageManager().addAdvancedMsgListener(trtcMessageListener)
}
private fun unRegisterMessageListener() {
V2TIMManager.getMessageManager().removeAdvancedMsgListener(trtcMessageListener)
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "Chat Notification"
val descriptionText = "Notification for chat message"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(channelId, name, importance).apply {
description = descriptionText
}
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
private fun sendNotification(context: Context, message: V2TIMMessage) {
val intent = Intent(context, MainActivity::class.java).apply {
putExtra("ACTION", "TRTC_NEW_MESSAGE")
putExtra("SENDER", message.sender)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val chatItem = ChatItem.convertToChatItem(message, context) ?: return
val builder = NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.mipmap.rider_pro_log_round)
.setContentTitle(chatItem.nickname)
.setContentText(chatItem.textDisplay)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
with(NotificationManagerCompat.from(context)) {
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
return
}
notify(message.msgID.hashCode(), builder.build())
}
}
}

View File

@@ -0,0 +1,42 @@
package com.aiosman.riderpro.data
import com.aiosman.riderpro.data.api.ApiClient
import com.aiosman.riderpro.data.api.UpdateChatNotificationRequestBody
import com.aiosman.riderpro.entity.ChatNotification
interface ChatService {
suspend fun getChatNotifications(
targetTrtcId: String
): ChatNotification?
suspend fun updateChatNotification(
targetUserId: Int,
strategy: String
): ChatNotification
}
class ChatServiceImpl : ChatService {
override suspend fun getChatNotifications(
targetTrtcId: String
): ChatNotification? {
val resp = ApiClient.api.getChatNotification(targetTrtcId)
if (resp.isSuccessful) {
return resp.body()?.data
}
return null
}
override suspend fun updateChatNotification(
targetUserId: Int,
strategy: String
): ChatNotification {
val resp = ApiClient.api.updateChatNotification(UpdateChatNotificationRequestBody(
targetUserId = targetUserId,
strategy = strategy
))
if (resp.isSuccessful) {
return resp.body()?.data!!
}
throw Exception("update chat notification failed")
}
}

View File

@@ -9,6 +9,7 @@ import com.aiosman.riderpro.data.Comment
import com.aiosman.riderpro.data.DataContainer import com.aiosman.riderpro.data.DataContainer
import com.aiosman.riderpro.data.ListContainer import com.aiosman.riderpro.data.ListContainer
import com.aiosman.riderpro.data.Moment import com.aiosman.riderpro.data.Moment
import com.aiosman.riderpro.entity.ChatNotification
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.RequestBody import okhttp3.RequestBody
@@ -154,31 +155,6 @@ data class GenerateLoginCaptchaRequestBody(
@SerializedName("username") @SerializedName("username")
val username: String, val username: String,
) )
//{
// "id":48,
// "dot": [
// {
// "index": 0,
// "x": 76,
// "y": 165
// },
// {
// "index": 1,
// "x": 144,
// "y": 21
// },
// {
// "index": 2,
// "x": 220,
// "y": 42
// },
// {
// "index": 3,
// "x": 10,
// "y": 10
// }
// ]
//}
data class DotPosition( data class DotPosition(
@SerializedName("index") @SerializedName("index")
val index: Int, val index: Int,
@@ -193,6 +169,15 @@ data class CaptchaInfo(
@SerializedName("dot") @SerializedName("dot")
val dot: List<DotPosition> val dot: List<DotPosition>
) )
data class UpdateChatNotificationRequestBody(
@SerializedName("targetUserId")
val targetUserId: Int,
@SerializedName("strategy")
val strategy: String,
)
interface RiderProAPI { interface RiderProAPI {
@POST("register") @POST("register")
suspend fun register(@Body body: RegisterRequestBody): Response<Unit> suspend fun register(@Body body: RegisterRequestBody): Response<Unit>
@@ -417,4 +402,14 @@ interface RiderProAPI {
@Body body: GenerateLoginCaptchaRequestBody @Body body: GenerateLoginCaptchaRequestBody
): Response<DataContainer<CaptchaResponseBody>> ): Response<DataContainer<CaptchaResponseBody>>
} @GET("chat/notification")
suspend fun getChatNotification(
@Query("targetTrtcId") targetTrtcId: String
): Response<DataContainer<ChatNotification>>
@POST("chat/notification")
suspend fun updateChatNotification(
@Body body: UpdateChatNotificationRequestBody
): Response<DataContainer<ChatNotification>>
}

View File

@@ -3,6 +3,7 @@ package com.aiosman.riderpro.entity
import android.content.Context import android.content.Context
import android.icu.util.Calendar import android.icu.util.Calendar
import com.aiosman.riderpro.exp.formatChatTime import com.aiosman.riderpro.exp.formatChatTime
import com.google.gson.annotations.SerializedName
import com.tencent.imsdk.v2.V2TIMImageElem import com.tencent.imsdk.v2.V2TIMImageElem
import com.tencent.imsdk.v2.V2TIMMessage import com.tencent.imsdk.v2.V2TIMMessage
@@ -15,11 +16,11 @@ data class ChatItem(
val timeCategory: String = "", val timeCategory: String = "",
val timestamp: Long = 0, val timestamp: Long = 0,
val imageList: MutableList<V2TIMImageElem.V2TIMImage> = emptyList<V2TIMImageElem.V2TIMImage>().toMutableList(), val imageList: MutableList<V2TIMImageElem.V2TIMImage> = emptyList<V2TIMImageElem.V2TIMImage>().toMutableList(),
val messageType : Int = 0, val messageType: Int = 0,
val textDisplay : String = "", val textDisplay: String = "",
val msgId: String, // Add this property val msgId: String, // Add this property
var showTimestamp: Boolean = false, var showTimestamp: Boolean = false,
var showTimeDivider:Boolean = false var showTimeDivider: Boolean = false
) { ) {
companion object { companion object {
fun convertToChatItem(message: V2TIMMessage, context: Context): ChatItem? { fun convertToChatItem(message: V2TIMMessage, context: Context): ChatItem? {
@@ -36,7 +37,7 @@ data class ChatItem(
val timestamp = message.timestamp val timestamp = message.timestamp
val calendar = Calendar.getInstance() val calendar = Calendar.getInstance()
calendar.timeInMillis = timestamp * 1000 calendar.timeInMillis = timestamp * 1000
val imageElm = message.imageElem?.imageList val imageElm = message.imageElem?.imageList
when (message.elemType) { when (message.elemType) {
V2TIMMessage.V2TIM_ELEM_TYPE_IMAGE -> { V2TIMMessage.V2TIM_ELEM_TYPE_IMAGE -> {
val imageElm = message.imageElem?.imageList?.all { val imageElm = message.imageElem?.imageList?.all {
@@ -74,8 +75,8 @@ data class ChatItem(
textDisplay = message.textElem?.text ?: "Unsupported message type", textDisplay = message.textElem?.text ?: "Unsupported message type",
msgId = message.msgID // Add this line to include msgId msgId = message.msgID // Add this line to include msgId
) )
} }
else -> { else -> {
return null return null
} }
@@ -85,3 +86,16 @@ data class ChatItem(
} }
} }
data class ChatNotification(
@SerializedName("userId")
val userId: Int,
@SerializedName("userTrtcId")
val userTrtcId: String,
@SerializedName("targetUserId")
val targetUserId: Int,
@SerializedName("targetTrtcId")
val targetTrtcId: String,
@SerializedName("strategy")
val strategy: String
)

View File

@@ -66,12 +66,15 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.aiosman.riderpro.LocalNavController import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.R import com.aiosman.riderpro.R
import com.aiosman.riderpro.entity.ChatItem import com.aiosman.riderpro.entity.ChatItem
import com.aiosman.riderpro.exp.formatChatTime import com.aiosman.riderpro.exp.formatChatTime
import com.aiosman.riderpro.ui.composables.CustomAsyncImage import com.aiosman.riderpro.ui.composables.CustomAsyncImage
import com.aiosman.riderpro.ui.composables.DropdownMenu
import com.aiosman.riderpro.ui.composables.MenuItem
import com.aiosman.riderpro.ui.composables.StatusBarSpacer import com.aiosman.riderpro.ui.composables.StatusBarSpacer
import com.aiosman.riderpro.ui.modifiers.noRippleClickable import com.aiosman.riderpro.ui.modifiers.noRippleClickable
import com.tencent.imsdk.v2.V2TIMMessage import com.tencent.imsdk.v2.V2TIMMessage
@@ -80,6 +83,7 @@ import kotlinx.coroutines.launch
@Composable @Composable
fun ChatScreen(userId: String) { fun ChatScreen(userId: String) {
var isMenuExpanded by remember { mutableStateOf(false) }
val navController = LocalNavController.current val navController = LocalNavController.current
val context = LocalNavController.current.context val context = LocalNavController.current.context
val viewModel = viewModel<ChatViewModel>( val viewModel = viewModel<ChatViewModel>(
@@ -131,7 +135,7 @@ fun ChatScreen(userId: String) {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp, horizontal = 16.dp), .padding(vertical = 16.dp, horizontal = 16.dp),
horizontalArrangement = Arrangement.Start, horizontalArrangement = Arrangement.Start,
verticalAlignment = androidx.compose.ui.Alignment.CenterVertically verticalAlignment = androidx.compose.ui.Alignment.CenterVertically
) { ) {
@@ -154,6 +158,41 @@ fun ChatScreen(userId: String) {
fontWeight = androidx.compose.ui.text.font.FontWeight.Bold fontWeight = androidx.compose.ui.text.font.FontWeight.Bold
) )
) )
Spacer(modifier = Modifier.weight(1f))
Box {
Image(
painter = painterResource(R.drawable.rider_pro_more_horizon),
modifier = Modifier
.size(28.dp)
.noRippleClickable {
isMenuExpanded = true
},
contentDescription = null
)
DropdownMenu(
expanded = isMenuExpanded,
onDismissRequest = {
isMenuExpanded = false
},
menuItems = listOf(
MenuItem(
title = if (viewModel.notificationStrategy == "mute") "Unmute" else "Mute",
icon = if (viewModel.notificationStrategy == "mute") R.drawable.rider_pro_notice_mute else R.drawable.rider_pro_notice_active,
){
isMenuExpanded = false
viewModel.viewModelScope.launch {
if (viewModel.notificationStrategy == "mute") {
viewModel.updateNotificationStrategy("active")
} else {
viewModel.updateNotificationStrategy("mute")
}
}
}
),
)
}
} }
} }
}, },

View File

@@ -1,7 +1,6 @@
package com.aiosman.riderpro.ui.chat package com.aiosman.riderpro.ui.chat
import android.content.Context import android.content.Context
import android.icu.util.Calendar
import android.net.Uri import android.net.Uri
import android.provider.MediaStore import android.provider.MediaStore
import android.util.Log import android.util.Log
@@ -11,16 +10,16 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.aiosman.riderpro.ChatState
import com.aiosman.riderpro.data.AccountService import com.aiosman.riderpro.data.AccountService
import com.aiosman.riderpro.data.AccountServiceImpl import com.aiosman.riderpro.data.AccountServiceImpl
import com.aiosman.riderpro.data.UserService import com.aiosman.riderpro.data.UserService
import com.aiosman.riderpro.data.UserServiceImpl import com.aiosman.riderpro.data.UserServiceImpl
import com.aiosman.riderpro.entity.AccountProfileEntity import com.aiosman.riderpro.entity.AccountProfileEntity
import com.aiosman.riderpro.entity.ChatItem import com.aiosman.riderpro.entity.ChatItem
import com.aiosman.riderpro.exp.formatChatTime import com.aiosman.riderpro.entity.ChatNotification
import com.tencent.imsdk.v2.V2TIMAdvancedMsgListener import com.tencent.imsdk.v2.V2TIMAdvancedMsgListener
import com.tencent.imsdk.v2.V2TIMCallback import com.tencent.imsdk.v2.V2TIMCallback
import com.tencent.imsdk.v2.V2TIMImageElem
import com.tencent.imsdk.v2.V2TIMManager import com.tencent.imsdk.v2.V2TIMManager
import com.tencent.imsdk.v2.V2TIMMessage import com.tencent.imsdk.v2.V2TIMMessage
import com.tencent.imsdk.v2.V2TIMSendCallback import com.tencent.imsdk.v2.V2TIMSendCallback
@@ -44,6 +43,7 @@ class ChatViewModel(
var isLoading by mutableStateOf(false) var isLoading by mutableStateOf(false)
var lastMessage: V2TIMMessage? = null var lastMessage: V2TIMMessage? = null
val showTimestampMap = mutableMapOf<String, Boolean>() // Add this map val showTimestampMap = mutableMapOf<String, Boolean>() // Add this map
var chatNotification by mutableStateOf<ChatNotification?>(null)
fun init(context: Context) { fun init(context: Context) {
// 获取用户信息 // 获取用户信息
viewModelScope.launch { viewModelScope.launch {
@@ -53,6 +53,9 @@ class ChatViewModel(
RegistListener(context) RegistListener(context)
fetchHistoryMessage(context) fetchHistoryMessage(context)
// 获取通知信息
val notiStrategy = ChatState.getStrategyByTargetTrtcId(resp.trtcUserId)
chatNotification = notiStrategy
} }
} }
@@ -243,4 +246,13 @@ class ChatViewModel(
} }
return list return list
} }
suspend fun updateNotificationStrategy(strategy: String) {
userProfile?.let {
val result = ChatState.updateChatNotification(it.id, strategy)
chatNotification = result
}
}
val notificationStrategy get() = chatNotification?.strategy ?: "default"
} }

View File

@@ -73,13 +73,13 @@ object MyProfileViewModel : ViewModel() {
} }
} }
suspend fun logout() { suspend fun logout(context: Context) {
AppStore.apply { AppStore.apply {
token = null token = null
rememberMe = false rememberMe = false
saveData() saveData()
} }
AppState.ReloadAppState() AppState.ReloadAppState(context)
} }
fun updateUserProfileBanner(bannerImageUrl: Uri?,file:File, context: Context) { fun updateUserProfileBanner(bannerImageUrl: Uri?,file:File, context: Context) {

View File

@@ -378,62 +378,65 @@ fun ProfileV3(
color = Color.Black color = Color.Black
) )
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
Box( if (isSelf) {
modifier = Modifier
) {
Box( Box(
modifier = Modifier modifier = Modifier
.padding(16.dp)
) { ) {
Icon( Box(
painter = painterResource(id = R.drawable.rider_pro_more_horizon), modifier = Modifier
contentDescription = "", .padding(16.dp)
modifier = Modifier.noRippleClickable { ) {
minibarExpanded = true Icon(
}, painter = painterResource(id = R.drawable.rider_pro_more_horizon),
tint = Color.Black contentDescription = "",
) modifier = Modifier.noRippleClickable {
} minibarExpanded = true
DropdownMenu( },
expanded = minibarExpanded, tint = Color.Black
onDismissRequest = { minibarExpanded = false }, )
width = 250, }
menuItems = listOf( DropdownMenu(
MenuItem( expanded = minibarExpanded,
stringResource(R.string.logout), onDismissRequest = { minibarExpanded = false },
R.mipmap.rider_pro_logout width = 250,
) { menuItems = listOf(
minibarExpanded = false MenuItem(
scope.launch { stringResource(R.string.logout),
onLogout() R.mipmap.rider_pro_logout
navController.navigate(NavigationRoute.Login.route) { ) {
popUpTo(NavigationRoute.Index.route) { minibarExpanded = false
inclusive = true scope.launch {
onLogout()
navController.navigate(NavigationRoute.Login.route) {
popUpTo(NavigationRoute.Index.route) {
inclusive = true
}
} }
} }
},
MenuItem(
stringResource(R.string.change_password),
R.mipmap.rider_pro_change_password
) {
minibarExpanded = false
scope.launch {
navController.navigate(NavigationRoute.ChangePasswordScreen.route)
}
},
MenuItem(
stringResource(R.string.favourites),
R.drawable.rider_pro_favourite
) {
minibarExpanded = false
scope.launch {
navController.navigate(NavigationRoute.FavouriteList.route)
}
} }
}, )
MenuItem(
stringResource(R.string.change_password),
R.mipmap.rider_pro_change_password
) {
minibarExpanded = false
scope.launch {
navController.navigate(NavigationRoute.ChangePasswordScreen.route)
}
},
MenuItem(
stringResource(R.string.favourites),
R.drawable.rider_pro_favourite
) {
minibarExpanded = false
scope.launch {
navController.navigate(NavigationRoute.FavouriteList.route)
}
}
) )
) }
} }
} }
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
} }

View File

@@ -2,6 +2,7 @@ package com.aiosman.riderpro.ui.index.tabs.profile
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -9,29 +10,17 @@ import kotlinx.coroutines.launch
fun ProfileWrap( fun ProfileWrap(
) { ) {
val context = LocalContext.current
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
MyProfileViewModel.loadProfile() MyProfileViewModel.loadProfile()
} }
// ProfileV2(
// onUpdateBanner = { uri, context ->
// MyProfileViewModel.updateUserProfileBanner(uri, context)
// },
// onLogout = {
// MyProfileViewModel.viewModelScope.launch {
// MyProfileViewModel.logout()
// }
//
// },
// profile = MyProfileViewModel.profile,
// sharedFlow = MyProfileViewModel.sharedFlow
// )
ProfileV3( ProfileV3(
onUpdateBanner = { uri, file, context -> onUpdateBanner = { uri, file, context ->
MyProfileViewModel.updateUserProfileBanner(uri, file, context) MyProfileViewModel.updateUserProfileBanner(uri, file, context)
}, },
onLogout = { onLogout = {
MyProfileViewModel.viewModelScope.launch { MyProfileViewModel.viewModelScope.launch {
MyProfileViewModel.logout() MyProfileViewModel.logout(context)
} }
}, },

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:alpha="0.77" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zM18,16v-5c0,-3.07 -1.63,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.64,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2zM16,17L8,17v-6c0,-2.48 1.51,-4.5 4,-4.5s4,2.02 4,4.5v6z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:alpha="0.77" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zM12,6.5c2.49,0 4,2.02 4,4.5v0.1l2,2L18,11c0,-3.07 -1.63,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68c-0.24,0.06 -0.47,0.15 -0.69,0.23l1.64,1.64c0.18,-0.02 0.36,-0.05 0.55,-0.05zM5.41,3.35L4,4.76l2.81,2.81C6.29,8.57 6,9.74 6,11v5l-2,2v1h14.24l1.74,1.74 1.41,-1.41L5.41,3.35zM16,17L8,17v-6c0,-0.68 0.12,-1.32 0.34,-1.9L16,16.76L16,17z"/>
</vector>