Files
rider-pro-android-app/app/src/main/java/com/aiosman/ravenow/AppState.kt
AllenTom ca16d54823 新增创建群聊的费用和人数上限功能
- **创建群聊费用:**
  - 创建群聊现在会根据后台配置的积分规则扣除相应费用(派币)。
  - 在创建页面会显示当前余额和所需费用。
  - 创建时会弹出确认弹窗,显示费用、当前余额和扣除后余额。
  - 如果余额不足,将无法创建。

- **群聊人数上限:**
  - 新增创建群聊时的初始成员人数上限,该上限从后台动态获取。
  - 在选择成员界面会显示当前已选人数和上限(例如 `5/10`)。
  - 如果选择的成员超过上限,会提示错误并且无法创建。

- **后台数据加载:**
  - 新增了从外部字典表 (`/outside/dict`) 获取配置的接口和逻辑,用于加载积分规则和群聊人数限制。
  - App启动时会预加载这些配置,以确保创建群聊时能正确显示费用和人数限制。
2025-11-12 17:23:20 +08:00

282 lines
10 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.aiosman.ravenow
import android.content.Context
import android.content.Intent
import android.icu.util.Calendar
import android.icu.util.TimeZone
import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import com.aiosman.ravenow.data.AccountService
import com.aiosman.ravenow.data.AccountServiceImpl
import com.aiosman.ravenow.data.DictService
import com.aiosman.ravenow.data.DictServiceImpl
import com.aiosman.ravenow.data.PointService
import com.aiosman.ravenow.entity.AccountProfileEntity
import com.aiosman.ravenow.ui.favourite.FavouriteListViewModel
import com.aiosman.ravenow.ui.favourite.FavouriteNoticeViewModel
import com.aiosman.ravenow.ui.follower.FollowerNoticeViewModel
import com.aiosman.ravenow.ui.index.IndexViewModel
import com.aiosman.ravenow.ui.index.tabs.message.MessageListViewModel
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.dynamic.DynamicViewModel
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.Explore
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.hot.HotMomentViewModel
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.account.AccountEditViewModel
import com.aiosman.ravenow.ui.index.tabs.search.DiscoverViewModel
import com.aiosman.ravenow.ui.index.tabs.search.SearchViewModel
import com.aiosman.ravenow.ui.index.tabs.ai.AgentViewModel
import com.aiosman.ravenow.ui.index.tabs.ai.tabs.mine.MineAgentViewModel
import com.aiosman.ravenow.ui.like.LikeNoticeViewModel
import com.aiosman.ravenow.utils.Utils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlin.coroutines.suspendCoroutine
import com.aiosman.ravenow.im.OpenIMManager
import io.openim.android.sdk.OpenIMClient
import io.openim.android.sdk.models.InitConfig
object AppState {
var UserId: Int? = null
var profile: AccountProfileEntity? = null
var darkMode by mutableStateOf(false)
var appTheme by mutableStateOf<AppThemeData>(LightThemeColors())
var googleClientId: String? = null
var enableGoogleLogin: Boolean = false
var enableChat = false
var agentCreatedSuccess by mutableStateOf(false)
var chatBackgroundUrl by mutableStateOf<String?>(null)
suspend fun initWithAccount(scope: CoroutineScope, context: Context) {
// 如果是游客模式,使用简化的初始化流程
if (AppStore.isGuest) {
initWithGuestAccount(scope)
return
}
val accountService: AccountService = AccountServiceImpl()
// 获取用户认证信息
val resp = accountService.getMyAccount()
// 更新必要的用户信息
val calendar: Calendar = Calendar.getInstance()
val tz: TimeZone = calendar.timeZone
val offsetInMillis: Int = tz.rawOffset
accountService.updateUserExtra(
Utils.getCurrentLanguage(),
// 时区偏移量单位是秒
offsetInMillis / 1000,
tz.displayName
)
// 设置当前登录用户 ID
UserId = resp.id
try {
var profileResult = accountService.getMyAccountProfile()
profile = profileResult
} catch (e:Exception) {
Log.e("AppState", "getMyAccountProfile Error:"+ e.message )
}
// 获取当前用户资料
// 注册 JPush
Messaging.registerDevice(scope, context)
initChat(context)
// 设置当前用户并刷新积分信息(完成登录态初始化后)
PointService.setCurrentUser(UserId)
try {
PointService.refreshMyPointsBalance()
} catch (e: Exception) {
Log.e("AppState", "刷新积分失败: ${e.message}")
}
// 并行加载积分规则和房间规则配置(不阻塞主流程)
scope.launch {
try {
PointService.refreshPointsRules()
} catch (e: Exception) {
Log.e("AppState", "加载积分规则失败: ${e.message}")
}
}
scope.launch {
try {
PointService.refreshRoomMaxMembers()
} catch (e: Exception) {
Log.e("AppState", "加载房间规则失败: ${e.message}")
}
}
}
/**
* 游客模式的简化初始化
*/
private fun initWithGuestAccount(scope: CoroutineScope) {
// 游客模式下不初始化推送和TRTC
// 设置默认的用户信息
UserId = 0
profile = null
enableChat = false
Log.d("AppState", "Guest mode initialized without push notifications and TRTC")
// 游客模式下也加载规则配置(用于查看费用信息)
scope.launch {
try {
PointService.refreshPointsRules()
} catch (e: Exception) {
Log.e("AppState", "加载积分规则失败: ${e.message}")
}
}
scope.launch {
try {
PointService.refreshRoomMaxMembers()
} catch (e: Exception) {
Log.e("AppState", "加载房间规则失败: ${e.message}")
}
}
}
private suspend fun initChat(context: Context){
val dictService :DictService = DictServiceImpl()
val enableItem = dictService.getDictByKey(ConstVars.DICT_KEY_ENABLE_TRTC)
val isEnableTrtc = enableItem.value as? Boolean
if (isEnableTrtc != true) {
enableChat = false
return
}
val accountService: AccountService = AccountServiceImpl()
val initConfig = InitConfig(
"https://im.ravenow.ai/api",//SDK api地址
"wss://im.ravenow.ai/msg_gateway",//SDK WebSocket地址
OpenIMManager.getStorageDir(context),//SDK数据库存储目录
)
// initConfig.isLogStandardOutput = true;
// initConfig.logLevel = 6
// 使用 OpenIMManager 初始化 SDK
OpenIMManager.initSDK(context, initConfig)
try {
if (profile?.chatToken != null && profile?.trtcUserId != null) {
loginToOpenIM(profile!!.trtcUserId, profile!!.chatToken!!)
}
context.startService(Intent(context, OpenIMService::class.java))
enableChat = true
} catch (e: Exception) {
e.printStackTrace()
enableChat = false
}
}
suspend fun loginToOpenIM(userId: String, imToken: String): Boolean {
return suspendCoroutine { continuation ->
OpenIMClient.getInstance().login(object : io.openim.android.sdk.listener.OnBase<String> {
override fun onError(code: Int, error: String?) {
Log.e("AppState", "OpenIM 登录失败: code=$code, error=$error")
continuation.resumeWith(Result.failure(Exception("OpenIM Login failed: $code, $error")))
}
override fun onSuccess(data: String?) {
Log.d("AppState", "OpenIM 登录成功: $data")
//其他api调用必须保证登录回调成功后操作
continuation.resumeWith(Result.success(true))
}
}, userId, imToken)
}
}
// suspend fun updateTrtcUserProfile() {
// val accountService: AccountService = AccountServiceImpl()
// val profile = accountService.getMyAccountProfile()
// val info = V2TIMUserFullInfo()
// info.setNickname(profile.nickName)
// info.faceUrl = profile.rawAvatar
// info.selfSignature = profile.bio
// return suspendCoroutine { continuation ->
// V2TIMManager.getInstance().setSelfInfo(info, object : V2TIMCallback {
// override fun onError(code: Int, desc: String?) {
// continuation.resumeWith(Result.failure(Exception("Update user profile failed: $code, $desc")))
// }
//
// override fun onSuccess() {
// continuation.resumeWith(Result.success(Unit))
// }
// })
// }
// }
fun switchTheme() {
darkMode = !darkMode
appTheme = if (darkMode) {
DarkThemeColors()
} else {
LightThemeColors()
}
AppStore.saveDarkMode(darkMode)
}
/**
* 检查是否是游客模式,并且是否需要登录
* @return true 如果是游客模式
*/
fun isGuestMode(): Boolean {
return AppStore.isGuest
}
/**
* 检查游客模式并提示登录
* @param onGuestMode 当是游客模式时的回调
* @return true 如果是游客模式
*/
fun checkGuestModeAndPromptLogin(onGuestMode: (() -> Unit)? = null): Boolean {
if (AppStore.isGuest) {
onGuestMode?.invoke()
return true
}
return false
}
fun ReloadAppState(context: Context) {
// 重置动态列表页面
TimelineMomentViewModel.ResetModel()
DynamicViewModel.ResetModel()
HotMomentViewModel.resetModel()
// 重置我的页面
MyProfileViewModel.ResetModel()
// 重置编辑资料页面 - 暂时注释掉看是否是这里导致的问题
// AccountEditViewModel.ResetModel()
// 重置发现页面
DiscoverViewModel.ResetModel()
// 重置搜索页面
SearchViewModel.ResetModel()
// 重置消息页面
MessageListViewModel.ResetModel()
// 重置点赞通知页面
LikeNoticeViewModel.ResetModel()
// 重置收藏页面
FavouriteListViewModel.ResetModel()
// 重置收藏通知页面
FavouriteNoticeViewModel.ResetModel()
// 重置粉丝通知页面
FollowerNoticeViewModel.ResetModel()
// 重置关注通知页面
IndexViewModel.ResetModel()
// 重置AI Agent相关页面
AgentViewModel.ResetModel()
MineAgentViewModel.ResetModel()
UserId = null
// 清空积分全局状态,避免用户切换串号
PointService.clear()
// 清除游客状态
AppStore.isGuest = false
context.stopService(Intent(context, OpenIMService::class.java))
}
}