接入声优接口
This commit is contained in:
parent
2d967c52a0
commit
063a8bca04
|
|
@ -5,22 +5,17 @@ import com.remax.visualnovel.entity.response.basenew.ResponseNew
|
||||||
import com.remax.visualnovel.entity.request.ParamActorList
|
import com.remax.visualnovel.entity.request.ParamActorList
|
||||||
import com.remax.visualnovel.entity.request.ParamActorTag
|
import com.remax.visualnovel.entity.request.ParamActorTag
|
||||||
import com.remax.visualnovel.entity.response.ActorBean
|
import com.remax.visualnovel.entity.response.ActorBean
|
||||||
import com.remax.visualnovel.entity.response.ChatSound
|
|
||||||
import com.remax.visualnovel.widget.custom.ActorTag
|
import com.remax.visualnovel.widget.custom.ActorTag
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
|
||||||
|
|
||||||
interface ActorsService {
|
interface ActorsService {
|
||||||
@POST(BuildConfig.API_BASE + "/tag/selectByCondition")
|
@POST(BuildConfig.API_BASE + "/tag/list")
|
||||||
suspend fun requestActorTags(@Body param: ParamActorTag): ResponseNew<List<ActorTag>>
|
suspend fun requestActorTags(@Body param: ParamActorTag): ResponseNew<List<ActorTag>>
|
||||||
|
|
||||||
@POST(BuildConfig.API_BASE + "/character/select/list")
|
@POST(BuildConfig.API_BASE + "/character/list")
|
||||||
suspend fun requestActorList(@Body param: ParamActorList): ResponseNew<List<ActorBean>>
|
suspend fun requestActorList(@Body param: ParamActorList): ResponseNew<List<ActorBean>>
|
||||||
|
|
||||||
|
|
||||||
@GET(BuildConfig.API_BASE + "/tts/config/select/list")
|
|
||||||
suspend fun requestSoundList(): ResponseNew<List<ChatSound>>
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ import com.remax.visualnovel.entity.request.ChatAlbum
|
||||||
import com.remax.visualnovel.entity.request.ChatSetting
|
import com.remax.visualnovel.entity.request.ChatSetting
|
||||||
import com.remax.visualnovel.entity.request.HeartbeatBuy
|
import com.remax.visualnovel.entity.request.HeartbeatBuy
|
||||||
import com.remax.visualnovel.entity.request.ParamBgUpload
|
import com.remax.visualnovel.entity.request.ParamBgUpload
|
||||||
|
import com.remax.visualnovel.entity.request.ParamSoundList
|
||||||
import com.remax.visualnovel.entity.request.RTCRequest
|
import com.remax.visualnovel.entity.request.RTCRequest
|
||||||
import com.remax.visualnovel.entity.request.SearchPage
|
import com.remax.visualnovel.entity.request.SearchPage
|
||||||
import com.remax.visualnovel.entity.request.SimpleDataDTO
|
import com.remax.visualnovel.entity.request.SimpleDataDTO
|
||||||
|
|
@ -24,6 +25,7 @@ import com.remax.visualnovel.entity.response.Pageable
|
||||||
import com.remax.visualnovel.entity.response.Token
|
import com.remax.visualnovel.entity.response.Token
|
||||||
import com.remax.visualnovel.entity.response.VoiceASR
|
import com.remax.visualnovel.entity.response.VoiceASR
|
||||||
import com.remax.visualnovel.entity.response.base.Response
|
import com.remax.visualnovel.entity.response.base.Response
|
||||||
|
import com.remax.visualnovel.entity.response.basenew.ResponseNew
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
|
@ -93,7 +95,7 @@ interface ChatService {
|
||||||
* 获取聊天设置
|
* 获取聊天设置
|
||||||
*/
|
*/
|
||||||
@POST("/web/chat-set/get-my")
|
@POST("/web/chat-set/get-my")
|
||||||
suspend fun getChatSetting(@Body request: ChatSetting): Response<ChatSet>
|
suspend fun getChatSetting(@Body request: ChatSetting): ResponseNew<ChatSet>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改聊天设置
|
* 修改聊天设置
|
||||||
|
|
@ -111,7 +113,7 @@ interface ChatService {
|
||||||
* 修改聊天模型
|
* 修改聊天模型
|
||||||
*/
|
*/
|
||||||
@POST("/web/chat-set/set-chat-model")
|
@POST("/web/chat-set/set-chat-model")
|
||||||
suspend fun setChatModel(@Body request: ChatSetting): Response<Any>
|
suspend fun setChatModel(@Body request: ChatSetting): ResponseNew<Any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改是否自动播放语音
|
* 修改是否自动播放语音
|
||||||
|
|
@ -141,7 +143,7 @@ interface ChatService {
|
||||||
* 语音转文本
|
* 语音转文本
|
||||||
*/
|
*/
|
||||||
@POST(BuildConfig.API_COW + "/web/voice/asr-v2")
|
@POST(BuildConfig.API_COW + "/web/voice/asr-v2")
|
||||||
suspend fun voiceASR(@Body request: SimpleDataDTO): Response<VoiceASR>
|
suspend fun voiceASR(@Body request: SimpleDataDTO): ResponseNew<VoiceASR>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成语音
|
* 生成语音
|
||||||
|
|
@ -165,13 +167,16 @@ interface ChatService {
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
@GET(BuildConfig.API_BASE + "/tts/config/select/list")
|
@POST(BuildConfig.API_BASE + "/tts/config/list")
|
||||||
suspend fun loadSoundList(@Query("language") language: Int = 1): Response<List<ChatSound>>
|
suspend fun requestSoundList(@Body param: ParamSoundList): ResponseNew<List<ChatSound>>
|
||||||
|
|
||||||
@GET(BuildConfig.API_BASE + "/model/config/select/list")
|
@POST(BuildConfig.API_BASE + "/model/config/list")
|
||||||
suspend fun loadAiModelList(@Query("language") language: Int = 1): Response<List<ChatModel>>
|
suspend fun requestAiModelList(@Body language: Int = 1): ResponseNew<List<ChatModel>>
|
||||||
|
|
||||||
@POST(BuildConfig.API_BASE + "/bg_image/config/upload")
|
@POST(BuildConfig.API_BASE + "/bg_image/config/upload")
|
||||||
suspend fun uploadCustomBgPic(@Body param: ParamBgUpload): Response<Any>
|
suspend fun uploadCustomBgPic(@Body param: ParamBgUpload): ResponseNew<Any>
|
||||||
|
|
||||||
|
@POST(BuildConfig.API_BASE + "/bg_image/config/list")
|
||||||
|
suspend fun requestChatBgList(@Body userId: Int): ResponseNew<List<ChatBackgroundBase.ChatBackground>>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -9,6 +9,7 @@ import com.remax.visualnovel.entity.response.ChatBubble
|
||||||
import com.remax.visualnovel.entity.response.ChatModel
|
import com.remax.visualnovel.entity.response.ChatModel
|
||||||
import com.remax.visualnovel.entity.response.Pageable
|
import com.remax.visualnovel.entity.response.Pageable
|
||||||
import com.remax.visualnovel.entity.response.base.Response
|
import com.remax.visualnovel.entity.response.base.Response
|
||||||
|
import com.remax.visualnovel.entity.response.basenew.ResponseNew
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
|
||||||
|
|
@ -30,11 +31,11 @@ interface DictService {
|
||||||
* 礼物字典
|
* 礼物字典
|
||||||
*/
|
*/
|
||||||
@POST("/web/gift/dict-list")
|
@POST("/web/gift/dict-list")
|
||||||
suspend fun getGiftDict(@Body pageQuery: PageQuery = PageQuery(1).apply { page.ps = 100 }): Response<Pageable<Gift>>
|
suspend fun getGiftDict(@Body pageQuery: PageQuery = PageQuery(1).apply { page.ps = 100 }): ResponseNew<Pageable<Gift>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* chat模型
|
* chat模型
|
||||||
*/
|
*/
|
||||||
@POST("/web/chat-model/dict-list")
|
@POST("/web/chat-model/dict-list")
|
||||||
suspend fun getAIChatModel(): Response<List<ChatModel>>
|
suspend fun getAIChatModel(): ResponseNew<List<ChatModel>>
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.remax.visualnovel.entity.request
|
||||||
|
|
||||||
|
|
||||||
|
data class ParamSoundList(
|
||||||
|
var language: Int = 1,
|
||||||
|
var gender: Int? = null
|
||||||
|
)
|
||||||
|
|
@ -13,11 +13,12 @@ data class ChatSound(
|
||||||
val rules: Int = 0,
|
val rules: Int = 0,
|
||||||
val nameLanguage: String = "",
|
val nameLanguage: String = "",
|
||||||
val headPortrait: String = "",
|
val headPortrait: String = "",
|
||||||
|
|
||||||
|
// Other needed
|
||||||
|
var sampleUrl: String = "",
|
||||||
var isSelected: Boolean = false,
|
var isSelected: Boolean = false,
|
||||||
var isPlaying: Boolean = false,
|
var isPlaying: Boolean = false,
|
||||||
|
|
||||||
// Other needed
|
|
||||||
var sampleUrl: String = ""
|
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,5 @@ class ActorsRepository @Inject constructor(private val mActorsService: ActorsSer
|
||||||
mActorsService.requestActorList(param)
|
mActorsService.requestActorList(param)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,137 +1,50 @@
|
||||||
package com.remax.visualnovel.repository.api
|
package com.remax.visualnovel.repository.api
|
||||||
|
|
||||||
import com.pengxr.modular.eventbus.generated.events.EventDefineOfChatSettingEvents
|
|
||||||
import com.pengxr.modular.eventbus.generated.events.EventDefineOfUserAIEvents
|
|
||||||
import com.pengxr.modular.eventbus.generated.events.EventDefineOfUserEvents
|
|
||||||
import com.remax.visualnovel.api.service.ChatService
|
import com.remax.visualnovel.api.service.ChatService
|
||||||
import com.remax.visualnovel.entity.request.AIFeedback
|
|
||||||
import com.remax.visualnovel.entity.request.AIIDRequest
|
|
||||||
import com.remax.visualnovel.entity.request.AIIsShowDTO
|
|
||||||
import com.remax.visualnovel.entity.request.ChatAlbum
|
|
||||||
import com.remax.visualnovel.entity.request.ChatSetting
|
import com.remax.visualnovel.entity.request.ChatSetting
|
||||||
import com.remax.visualnovel.entity.request.HeartbeatBuy
|
import com.remax.visualnovel.entity.request.ParamBgUpload
|
||||||
import com.remax.visualnovel.entity.request.RTCRequest
|
import com.remax.visualnovel.entity.request.ParamSoundList
|
||||||
import com.remax.visualnovel.entity.request.SearchPage
|
|
||||||
import com.remax.visualnovel.entity.request.SimpleDataDTO
|
import com.remax.visualnovel.entity.request.SimpleDataDTO
|
||||||
import com.remax.visualnovel.entity.request.VoiceTTS
|
import com.remax.visualnovel.repository.api.base.BaseRepositoryNew
|
||||||
import com.remax.visualnovel.entity.response.Character
|
|
||||||
import com.remax.visualnovel.entity.response.ChatSet
|
|
||||||
import com.remax.visualnovel.repository.api.base.BaseRepository
|
|
||||||
import com.remax.visualnovel.ui.chat.message.events.model.ChatSetAutoPlayEvent
|
|
||||||
import com.remax.visualnovel.ui.chat.message.events.model.ChatSetBackgroundEvent
|
|
||||||
import com.remax.visualnovel.ui.wallet.manager.WalletManager
|
import com.remax.visualnovel.ui.wallet.manager.WalletManager
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by HJW on 2022/11/15
|
|
||||||
*/
|
|
||||||
class ChatRepository @Inject constructor(private val chatService: ChatService) : BaseRepository() {
|
|
||||||
|
|
||||||
suspend fun sendDialogueMsg(aiId: String) = executeHttp {
|
class ChatRepository @Inject constructor(private val chatService: ChatService) : BaseRepositoryNew() {
|
||||||
chatService.sendDialogueMsg(AIIDRequest(aiId))
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun viewAlbumImg(request: ChatAlbum) = executeHttp {
|
|
||||||
chatService.viewAlbumImg(request)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getIMAICharacterProfile(aiId: String) = executeHttp {
|
|
||||||
chatService.getIMAICharacterProfile(Character(aiId = aiId))
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getMyFriends(request: SearchPage) = executeHttp {
|
|
||||||
chatService.getMyFriends(request)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getMyFriendRank() = executeHttp {
|
|
||||||
chatService.getMyFriendRank()
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getPrompts(aiId: String) = executeHttp {
|
|
||||||
chatService.getPrompts(AIIDRequest(aiId))
|
|
||||||
}.transformResult({
|
|
||||||
WalletManager.refreshWallet()
|
|
||||||
})
|
|
||||||
|
|
||||||
suspend fun aiFeedback(request: AIFeedback) = executeHttp {
|
|
||||||
chatService.aiFeedback(request)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getRTCToken(roomId: String) = executeHttp {
|
|
||||||
chatService.getRTCToken(RTCRequest(roomId))
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun voiceChatOpt(request: RTCRequest) = executeHttp {
|
|
||||||
chatService.voiceChatOpt(request)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getChatBackgroundList(aiId: String) = executeHttp {
|
|
||||||
chatService.getChatBackgroundList(AIIDRequest(aiId))
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getChatSetting(aiId: String?) = executeHttp {
|
|
||||||
chatService.getChatSetting(ChatSetting(aiId))
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun setChatSetting(request: ChatSet) = executeHttp {
|
|
||||||
chatService.setChatSetting(request)
|
|
||||||
}.transformResult({
|
|
||||||
EventDefineOfUserEvents.onUserInfoChanged().post(null)
|
|
||||||
})
|
|
||||||
|
|
||||||
suspend fun setChatBubble(request: ChatSetting) = executeHttp {
|
|
||||||
chatService.setChatBubble(request)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun setChatModel(request: ChatSetting) = executeHttp {
|
suspend fun setChatModel(request: ChatSetting) = executeHttp {
|
||||||
chatService.setChatModel(request)
|
chatService.setChatModel(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun setChatAutoPlay(request: ChatSetting) = executeHttp {
|
suspend fun getChatSetting(aiId: String?) = executeHttp {
|
||||||
chatService.setChatAutoPlay(request)
|
chatService.getChatSetting(ChatSetting(aiId))
|
||||||
}.transformResult({
|
|
||||||
EventDefineOfChatSettingEvents.settingChanged()
|
|
||||||
.post(ChatSetAutoPlayEvent(request.aiId ?: "", if (request.isAutoPlayVoice == true) 1 else 0))
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
suspend fun setChatBackground(request: ChatSetting) = executeHttp {
|
|
||||||
chatService.setChatBackground(request)
|
|
||||||
}.transformResult({
|
|
||||||
EventDefineOfChatSettingEvents.settingChanged()
|
|
||||||
.post(ChatSetBackgroundEvent(request.aiId ?: "", request.backgroundImg))
|
|
||||||
})
|
|
||||||
|
|
||||||
suspend fun deleteChatBackground(request: ChatSetting) = executeHttp {
|
|
||||||
chatService.deleteChatBackground(request)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun relationSwitch(request: AIIsShowDTO) = executeHttp {
|
|
||||||
chatService.relationSwitch(request)
|
|
||||||
}.transformResult({
|
|
||||||
EventDefineOfUserAIEvents.onAIHeartIsOpenChanged().post(request)
|
|
||||||
})
|
|
||||||
|
|
||||||
suspend fun voiceASR(aiId: String, url: String?) = executeHttp {
|
suspend fun voiceASR(aiId: String, url: String?) = executeHttp {
|
||||||
chatService.voiceASR(SimpleDataDTO(aiId = aiId, url = url))
|
chatService.voiceASR(SimpleDataDTO(aiId = aiId, url = url))
|
||||||
}.transformResult({
|
}.transformResult({
|
||||||
WalletManager.refreshWallet()
|
WalletManager.refreshWallet()
|
||||||
})
|
})
|
||||||
|
|
||||||
suspend fun voiceTTS(request: VoiceTTS) = executeHttp {
|
|
||||||
chatService.voiceTTS(request)
|
|
||||||
|
// ------------------------ new ---------------------------------
|
||||||
|
suspend fun getSoundList(param: ParamSoundList) = executeHttp {
|
||||||
|
chatService.requestSoundList(param)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getHeartbeatLevel(aiId: String) = executeHttp {
|
suspend fun getAiModelList(language: Int = 1) = executeHttp {
|
||||||
chatService.getHeartbeatLevel(Character(aiId = aiId))
|
chatService.requestAiModelList(language)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun buyHeartbeatVal(request: HeartbeatBuy) = executeHttp {
|
suspend fun uploadCustomBgPic(param: ParamBgUpload) = executeHttp {
|
||||||
chatService.buyHeartbeatVal(request)
|
chatService.uploadCustomBgPic(param)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun loadSoundList(lang: Int) = executeHttp {
|
suspend fun getChatBgList(userId: Int) = executeHttp {
|
||||||
chatService.loadSoundList(lang)
|
chatService.requestChatBgList(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,22 +2,13 @@ package com.remax.visualnovel.repository.api
|
||||||
|
|
||||||
|
|
||||||
import com.remax.visualnovel.api.service.DictService
|
import com.remax.visualnovel.api.service.DictService
|
||||||
import com.remax.visualnovel.entity.request.AIIDRequest
|
import com.remax.visualnovel.repository.api.base.BaseRepositoryNew
|
||||||
import com.remax.visualnovel.repository.api.base.BaseRepository
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by HJW on 2022/11/15
|
|
||||||
*/
|
|
||||||
class DictRepository @Inject constructor(private val dictService: DictService) : BaseRepository() {
|
|
||||||
|
|
||||||
suspend fun getChatBubbleList(aiId: String) = executeHttp {
|
class DictRepository @Inject constructor(private val dictService: DictService) : BaseRepositoryNew() {
|
||||||
dictService.getChatBubbleList(AIIDRequest(aiId))
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getAIDict() = executeHttp {
|
|
||||||
dictService.getAIDict()
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getGiftDict() = executeHttp(false) { dictService.getGiftDict() }
|
suspend fun getGiftDict() = executeHttp(false) { dictService.getGiftDict() }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,12 @@ import com.pengxr.modular.eventbus.generated.events.EventDefineOfUserEvents
|
||||||
import com.remax.visualnovel.R
|
import com.remax.visualnovel.R
|
||||||
import com.remax.visualnovel.databinding.ActivityActorChatBinding
|
import com.remax.visualnovel.databinding.ActivityActorChatBinding
|
||||||
import com.remax.visualnovel.entity.request.ChatSetting
|
import com.remax.visualnovel.entity.request.ChatSetting
|
||||||
|
import com.remax.visualnovel.entity.request.ParamSoundList
|
||||||
import com.remax.visualnovel.event.model.OnLoginEvent
|
import com.remax.visualnovel.event.model.OnLoginEvent
|
||||||
import com.remax.visualnovel.extension.countDownCoroutines
|
import com.remax.visualnovel.extension.countDownCoroutines
|
||||||
import com.remax.visualnovel.extension.launchAndCollect
|
import com.remax.visualnovel.extension.launchAndCollect2
|
||||||
import com.remax.visualnovel.extension.launchAndLoadingCollect
|
import com.remax.visualnovel.extension.launchAndLoadingCollect
|
||||||
|
import com.remax.visualnovel.extension.launchAndLoadingCollect2
|
||||||
import com.remax.visualnovel.extension.launchWithRequest
|
import com.remax.visualnovel.extension.launchWithRequest
|
||||||
import com.remax.visualnovel.extension.setMargin
|
import com.remax.visualnovel.extension.setMargin
|
||||||
import com.remax.visualnovel.extension.toast
|
import com.remax.visualnovel.extension.toast
|
||||||
|
|
@ -71,12 +73,16 @@ class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initData() {
|
override fun initData() {
|
||||||
loadSoundDatas()
|
loadSoundDatas(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadSoundDatas() {
|
private fun loadSoundDatas(gender: Int?) {
|
||||||
launchAndCollect({
|
launchAndCollect2({
|
||||||
mViewModel.loadSoundList(LanguageUtil.instance().getCurrentLanguageCode())
|
val requestParam = ParamSoundList().apply {
|
||||||
|
this.gender = gender
|
||||||
|
this.language = LanguageUtil.instance().getCurrentLanguageCode()
|
||||||
|
}
|
||||||
|
mViewModel.loadSoundList(requestParam)
|
||||||
}) {
|
}) {
|
||||||
onSuccess = {
|
onSuccess = {
|
||||||
val dataList = it?: emptyList()
|
val dataList = it?: emptyList()
|
||||||
|
|
@ -87,7 +93,6 @@ class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val loginObserver = Observer<OnLoginEvent?> {
|
private val loginObserver = Observer<OnLoginEvent?> {
|
||||||
|
|
@ -227,7 +232,7 @@ class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
|
||||||
modelDialog.build(chatModels ?: emptyList(), chatSet?.modelCode, {
|
modelDialog.build(chatModels ?: emptyList(), chatSet?.modelCode, {
|
||||||
|
|
||||||
}) { model ->
|
}) { model ->
|
||||||
launchAndLoadingCollect({
|
launchAndLoadingCollect2({
|
||||||
setChatModel(
|
setChatModel(
|
||||||
ChatSetting(aiId, model.code)
|
ChatSetting(aiId, model.code)
|
||||||
)
|
)
|
||||||
|
|
@ -241,7 +246,7 @@ class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chatModels.isNullOrEmpty()) {
|
if (chatModels.isNullOrEmpty()) {
|
||||||
launchAndLoadingCollect({
|
launchAndLoadingCollect2({
|
||||||
mViewModel.getChatModels()
|
mViewModel.getChatModels()
|
||||||
}) {
|
}) {
|
||||||
onSuccess = {
|
onSuccess = {
|
||||||
|
|
|
||||||
|
|
@ -1,58 +1,25 @@
|
||||||
package com.remax.visualnovel.ui.chat
|
package com.remax.visualnovel.ui.chat
|
||||||
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.remax.visualnovel.app.viewmodel.base.OssViewModel
|
import com.remax.visualnovel.app.viewmodel.base.OssViewModel
|
||||||
import com.remax.visualnovel.entity.imbean.IMAIInMessage
|
|
||||||
import com.remax.visualnovel.entity.imbean.IMMessageWrapper
|
|
||||||
import com.remax.visualnovel.entity.imbean.raw.CustomRawData
|
import com.remax.visualnovel.entity.imbean.raw.CustomRawData
|
||||||
import com.remax.visualnovel.entity.imbean.raw.CustomScoreData
|
|
||||||
import com.remax.visualnovel.entity.request.AIFeedback
|
|
||||||
import com.remax.visualnovel.entity.request.AlbumDTO
|
|
||||||
import com.remax.visualnovel.entity.request.ChatAlbum
|
|
||||||
import com.remax.visualnovel.entity.request.ChatSetting
|
import com.remax.visualnovel.entity.request.ChatSetting
|
||||||
import com.remax.visualnovel.entity.request.Gift
|
|
||||||
import com.remax.visualnovel.entity.request.S3TypeDTO
|
import com.remax.visualnovel.entity.request.S3TypeDTO
|
||||||
import com.remax.visualnovel.entity.request.SendGift
|
|
||||||
import com.remax.visualnovel.entity.response.Album
|
|
||||||
import com.remax.visualnovel.entity.response.BucketBean
|
|
||||||
import com.remax.visualnovel.entity.response.Character
|
|
||||||
import com.remax.visualnovel.entity.response.ChatModel
|
import com.remax.visualnovel.entity.response.ChatModel
|
||||||
import com.remax.visualnovel.entity.response.ChatSet
|
import com.remax.visualnovel.entity.response.ChatSet
|
||||||
import com.remax.visualnovel.entity.response.HeartbeatLevelEnum
|
|
||||||
import com.remax.visualnovel.entity.response.VoiceASR
|
import com.remax.visualnovel.entity.response.VoiceASR
|
||||||
import com.remax.visualnovel.entity.response.base.ApiEmptyResponse
|
import com.remax.visualnovel.entity.response.base.ApiEmptyResponse
|
||||||
import com.remax.visualnovel.entity.response.base.ApiFailedResponse
|
|
||||||
import com.remax.visualnovel.entity.response.base.Response
|
import com.remax.visualnovel.entity.response.base.Response
|
||||||
import com.remax.visualnovel.extension.convertFromJson
|
|
||||||
import com.remax.visualnovel.manager.nim.FetchResult
|
|
||||||
import com.remax.visualnovel.manager.nim.LoadStatus
|
|
||||||
import com.remax.visualnovel.manager.nim.NimManager
|
|
||||||
import com.remax.visualnovel.repository.api.AIRepository
|
import com.remax.visualnovel.repository.api.AIRepository
|
||||||
import com.remax.visualnovel.repository.api.ChatRepository
|
import com.remax.visualnovel.repository.api.ChatRepository
|
||||||
import com.remax.visualnovel.repository.api.DictRepository
|
import com.remax.visualnovel.repository.api.DictRepository
|
||||||
import com.remax.visualnovel.repository.api.MessageRepository
|
import com.remax.visualnovel.repository.api.MessageRepository
|
||||||
import com.remax.visualnovel.repository.ext.convertMessage
|
|
||||||
import com.remax.visualnovel.ui.chat.message.call.manager.RTCManager
|
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum
|
|
||||||
import com.netease.nimlib.sdk.v2.message.V2NIMClearHistoryNotification
|
|
||||||
import com.netease.nimlib.sdk.v2.message.V2NIMMessage
|
|
||||||
import com.netease.nimlib.sdk.v2.message.V2NIMMessageCreator
|
import com.netease.nimlib.sdk.v2.message.V2NIMMessageCreator
|
||||||
import com.netease.nimlib.sdk.v2.message.V2NIMMessageDeletedNotification
|
import com.remax.visualnovel.entity.request.ParamSoundList
|
||||||
import com.netease.nimlib.sdk.v2.message.V2NIMMessageListener
|
import com.remax.visualnovel.entity.response.BucketBean
|
||||||
import com.netease.nimlib.sdk.v2.message.V2NIMMessagePinNotification
|
import com.remax.visualnovel.entity.response.Character
|
||||||
import com.netease.nimlib.sdk.v2.message.V2NIMMessageQuickCommentNotification
|
|
||||||
import com.netease.nimlib.sdk.v2.message.V2NIMMessageRevokeNotification
|
|
||||||
import com.netease.nimlib.sdk.v2.message.V2NIMP2PMessageReadReceipt
|
|
||||||
import com.netease.nimlib.sdk.v2.message.V2NIMTeamMessageReadReceipt
|
|
||||||
import com.netease.nimlib.sdk.v2.utils.V2NIMConversationIdUtil
|
|
||||||
import com.remax.visualnovel.manager.gift.GiftManager
|
|
||||||
import com.remax.visualnovel.ui.chat.message.detail.flirting.FlirtingLevelActivity
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -64,34 +31,11 @@ class ChatViewModel @Inject constructor(
|
||||||
private val aiRepository: AIRepository,
|
private val aiRepository: AIRepository,
|
||||||
) : OssViewModel() {
|
) : OssViewModel() {
|
||||||
|
|
||||||
var aiId: String = ""
|
private var bucketBean: BucketBean? = null
|
||||||
|
|
||||||
var character: Character? = null
|
var character: Character? = null
|
||||||
private set
|
private set
|
||||||
|
var aiId: String = ""
|
||||||
val conversationId: String
|
|
||||||
get() = V2NIMConversationIdUtil.conversationId(character?.nimAccountId, SessionTypeEnum.P2P) ?: ""
|
|
||||||
|
|
||||||
private val _aiBaseInfoFlow = MutableLiveData<Pair<Boolean, Character?>>()
|
|
||||||
val aiBaseInfoFlow = _aiBaseInfoFlow
|
|
||||||
|
|
||||||
fun checkHeartbeatLevel(targetLevel: HeartbeatLevelEnum, checkSuccess: () -> Unit) {
|
|
||||||
val currLevel = character?.aiUserHeartbeatRelation?.currHeartbeatEnum
|
|
||||||
if ((currLevel?.level ?: 0) >= targetLevel.level) {
|
|
||||||
checkSuccess()
|
|
||||||
} else {
|
|
||||||
FlirtingLevelActivity.start(aiId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun refreshAIBaseInfo(enterPage: Boolean) = chatRepository.getIMAICharacterProfile(aiId).transformResult({
|
|
||||||
character = it
|
|
||||||
NimManager.getUserList(listOf(character?.nimAccountId))
|
|
||||||
_aiBaseInfoFlow.value = Pair(enterPage, it)
|
|
||||||
getChatSetting()
|
|
||||||
getChatModels()
|
|
||||||
})
|
|
||||||
|
|
||||||
var chatModels: List<ChatModel>? = null
|
var chatModels: List<ChatModel>? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|
@ -111,9 +55,20 @@ class ChatViewModel @Inject constructor(
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 云信发送消息,raw代表是自定义消息
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun voiceASR(filePath: String): Response<VoiceASR> {
|
||||||
|
/*ossUploadFile(filePath, S3TypeDTO.SOUND, isImg = false, token = bucketBean).transformResult({
|
||||||
|
return chatRepository.voiceASR(aiId, it?.urlPath)
|
||||||
|
}) {
|
||||||
|
return Response.createZipFailResponse(it)
|
||||||
|
}*/
|
||||||
|
return ApiEmptyResponse()
|
||||||
|
}
|
||||||
|
|
||||||
fun sendMsg(msgContent: String, raw: CustomRawData? = null, errorCallback: (Int) -> Unit) {
|
fun sendMsg(msgContent: String, raw: CustomRawData? = null, errorCallback: (Int) -> Unit) {
|
||||||
|
|
||||||
val v2Message = if (raw != null)
|
val v2Message = if (raw != null)
|
||||||
|
|
@ -126,238 +81,11 @@ class ChatViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 消息发送LiveData,本地发送消息通过该LiveData通知UI
|
|
||||||
private val _sendScoreLiveData = MutableLiveData<Double?>()
|
|
||||||
val sendScoreLiveData: LiveData<Double?> = _sendScoreLiveData
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 接受方添加消息接收回调
|
|
||||||
*/
|
|
||||||
private val messageListener = object : V2NIMMessageListener {
|
|
||||||
/**
|
|
||||||
* 消息接收
|
|
||||||
*/
|
|
||||||
override fun onReceiveMessages(messages: List<V2NIMMessage>) {
|
|
||||||
NimManager.log("消息接收回调 onReceiveMessages")
|
|
||||||
NimManager.clearUnreadCountByIds(conversationId)
|
|
||||||
messages.firstOrNull()?.let { message ->
|
|
||||||
if (message.conversationId == conversationId) {
|
|
||||||
/**
|
|
||||||
* message中的分数
|
|
||||||
* 本地实时加减一下
|
|
||||||
* AI发送的文本消息和语音通话时,都会有serverExtension:{"score":0.1}的计算
|
|
||||||
*/
|
|
||||||
message.serverExtension?.convertFromJson<CustomScoreData>()?.let {
|
|
||||||
_sendScoreLiveData.value = it.score
|
|
||||||
RTCManager.sendIMScoreMessage(it.score)
|
|
||||||
}
|
|
||||||
|
|
||||||
val messageRecFetchResult = FetchResult<IMMessageWrapper>(LoadStatus.Success)
|
|
||||||
message.convertMessage()?.let { messageWrapper ->
|
|
||||||
if (messageWrapper.type == IMMessageWrapper.IN_TEXT_TYPE) {
|
|
||||||
/**
|
|
||||||
* 处理自动播放
|
|
||||||
*/
|
|
||||||
if (character?.isAutoPlayVoice == 1) {
|
|
||||||
(messageWrapper as? IMAIInMessage)?.imVoice?.autoPlay = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
messageRecFetchResult.data = messageWrapper
|
|
||||||
messageRecFetchResult.type = messageWrapper.fetchType
|
|
||||||
|
|
||||||
messageRecFetchResult.typeIndex = -1
|
|
||||||
_sendMessageLiveData.value = messageRecFetchResult
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onReceiveP2PMessageReadReceipts(readReceipts: List<V2NIMP2PMessageReadReceipt?>?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onReceiveTeamMessageReadReceipts(readReceipts: List<V2NIMTeamMessageReadReceipt?>?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMessageRevokeNotifications(revokeNotifications: List<V2NIMMessageRevokeNotification?>?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMessagePinNotification(pinNotification: V2NIMMessagePinNotification?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMessageQuickCommentNotification(quickCommentNotification: V2NIMMessageQuickCommentNotification?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMessageDeletedNotifications(messageDeletedNotifications: List<V2NIMMessageDeletedNotification?>?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onClearHistoryNotifications(clearHistoryNotifications: List<V2NIMClearHistoryNotification?>?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 本端发送消息状态回调
|
|
||||||
*/
|
|
||||||
override fun onSendMessage(message: V2NIMMessage) {
|
|
||||||
val sendingState = message.sendingState
|
|
||||||
NimManager.log("本端发送消息 $message")
|
|
||||||
NimManager.log("本端发送消息状态 $sendingState")
|
|
||||||
/**
|
|
||||||
* 发消息时需要刷新一下调用推荐回复接口
|
|
||||||
*/
|
|
||||||
refreshPrompts = true
|
|
||||||
if (message.conversationId == conversationId) {
|
|
||||||
postMessageSend(message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onReceiveMessagesModified(messages: List<V2NIMMessage>) {
|
|
||||||
NimManager.log("收到更新的消息 $messages")
|
|
||||||
messages.firstOrNull()?.let { message ->
|
|
||||||
NimManager.log("收到更新的消息 conversationId:${message.conversationId}")
|
|
||||||
if (message.conversationId == conversationId) {
|
|
||||||
val messageRecFetchResult = FetchResult<IMMessageWrapper>(LoadStatus.Success)
|
|
||||||
messageRecFetchResult.data = message.convertMessage()
|
|
||||||
messageRecFetchResult.type = FetchResult.FetchType.Update
|
|
||||||
messageRecFetchResult.typeIndex = -1
|
|
||||||
_sendMessageLiveData.value = messageRecFetchResult
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateMsg(message: V2NIMMessage) {
|
|
||||||
val messageRecFetchResult = FetchResult<IMMessageWrapper>(LoadStatus.Success)
|
|
||||||
messageRecFetchResult.data = message.convertMessage()
|
|
||||||
messageRecFetchResult.type = FetchResult.FetchType.Update
|
|
||||||
messageRecFetchResult.typeIndex = -1
|
|
||||||
_sendMessageLiveData.value = messageRecFetchResult
|
|
||||||
}
|
|
||||||
|
|
||||||
fun aiFeedback(request: AIFeedback) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
chatRepository.aiFeedback(request)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 消息发送LiveData,本地发送消息通过该LiveData通知UI
|
|
||||||
private val _sendMessageLiveData = MutableLiveData<FetchResult<IMMessageWrapper>?>()
|
|
||||||
val sendMessageLiveData: LiveData<FetchResult<IMMessageWrapper>?> = _sendMessageLiveData
|
|
||||||
|
|
||||||
private val sendMessageFetchResult by lazy {
|
|
||||||
FetchResult<IMMessageWrapper>(LoadStatus.Finish)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 同步发送消息
|
|
||||||
private fun postMessageSend(message: V2NIMMessage) {
|
|
||||||
message.convertMessage()?.let { messageWrapper ->
|
|
||||||
sendMessageFetchResult.loadStatus = LoadStatus.Success
|
|
||||||
sendMessageFetchResult.type = messageWrapper.fetchType
|
|
||||||
sendMessageFetchResult.data = messageWrapper
|
|
||||||
_sendMessageLiveData.value = sendMessageFetchResult
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addMessageListener() {
|
|
||||||
messageRepository.setMessageListener(true, messageListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var bucketBean: BucketBean? = null
|
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
viewModelScope.launch {
|
|
||||||
getBucketToken("mp3", S3TypeDTO.SOUND_PATH).transformResult({
|
|
||||||
bucketBean = it
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
messageRepository.setMessageListener(false, messageListener)
|
|
||||||
NimManager.clearUnreadCountByIds(conversationId)
|
|
||||||
GiftManager.initSelect()
|
|
||||||
}
|
|
||||||
|
|
||||||
private var anchorMessage: V2NIMMessage? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取历史消息
|
|
||||||
*/
|
|
||||||
suspend fun getMessageList(isRefresh: Boolean): FetchResult<List<IMMessageWrapper>> {
|
|
||||||
if (isRefresh) anchorMessage = null
|
|
||||||
val res = messageRepository.getMessageList(conversationId, anchorMessage, character)
|
|
||||||
// if (isRefresh && res.data?.size == 1) {
|
|
||||||
// sendDialogueMsg()
|
|
||||||
// }
|
|
||||||
anchorMessage = res.extraInfo as? V2NIMMessage
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun voiceASR(filePath: String): Response<VoiceASR> {
|
|
||||||
ossUploadFile(filePath, S3TypeDTO.SOUND, isImg = false, token = bucketBean).transformResult({
|
|
||||||
return chatRepository.voiceASR(aiId, it?.urlPath)
|
|
||||||
}) {
|
|
||||||
return Response.createZipFailResponse(it)
|
|
||||||
}
|
|
||||||
return ApiEmptyResponse()
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun sendGift(request: SendGift, gift: Gift): Response<Any> {
|
|
||||||
return messageRepository.sendGift(request, gift)
|
|
||||||
}
|
|
||||||
|
|
||||||
var refreshPrompts = true
|
|
||||||
private set
|
|
||||||
|
|
||||||
suspend fun getPrompts(): Response<List<String>> {
|
|
||||||
return if (refreshPrompts) {
|
|
||||||
refreshPrompts = false
|
|
||||||
chatRepository.getPrompts(aiId).transformResult {
|
|
||||||
// 失败的话需要重新拉
|
|
||||||
refreshPrompts = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ApiFailedResponse()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun viewAlbumImg(request: ChatAlbum) = chatRepository.viewAlbumImg(request)
|
|
||||||
|
|
||||||
suspend fun unlockAlbum(request: ChatAlbum) = aiRepository.unlockAlbum(request)
|
|
||||||
|
|
||||||
fun sendDialogueMsg() {
|
|
||||||
viewModelScope.launch {
|
|
||||||
chatRepository.sendDialogueMsg(aiId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun changeLiked(): Response<Any> {
|
|
||||||
val isLiked = character?.liked == true
|
|
||||||
val request = AlbumDTO(
|
|
||||||
aiId = aiId,
|
|
||||||
likedStatus = if (isLiked) Album.LIKED else Album.CANCELED,
|
|
||||||
liked = isLiked
|
|
||||||
)
|
|
||||||
return aiRepository.setAILikeOrCancel(request).transformResult({
|
|
||||||
changeCharacterLiked(isLiked)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun changeCharacterLiked(isLiked: Boolean) {
|
|
||||||
character?.apply {
|
|
||||||
liked = isLiked
|
|
||||||
likedNum = if (isLiked) {
|
|
||||||
likedNum?.plus(1)
|
|
||||||
} else {
|
|
||||||
likedNum?.minus(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------ new ------------------------
|
//------------------------ new ------------------------
|
||||||
suspend fun loadSoundList(lang: Int) = chatRepository.loadSoundList(lang)
|
suspend fun loadSoundList(param: ParamSoundList) = chatRepository.getSoundList(param)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,248 +0,0 @@
|
||||||
package com.remax.visualnovel.ui.chat.message.detail.flirting
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by HJW on 2025/8/16
|
|
||||||
*/
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.view.View
|
|
||||||
import androidx.activity.viewModels
|
|
||||||
import androidx.core.view.isGone
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import com.airbnb.lottie.LottieAnimationView
|
|
||||||
import com.alibaba.android.arouter.facade.annotation.Autowired
|
|
||||||
import com.alibaba.android.arouter.facade.annotation.Route
|
|
||||||
import com.alibaba.android.arouter.launcher.ARouter
|
|
||||||
import com.remax.visualnovel.R
|
|
||||||
import com.remax.visualnovel.app.base.BaseBindingActivity
|
|
||||||
import com.remax.visualnovel.app.delegate.isFull
|
|
||||||
import com.remax.visualnovel.app.delegate.titleTextAlpha
|
|
||||||
import com.remax.visualnovel.app.widget.tips.TipsSwitchWindow
|
|
||||||
import com.remax.visualnovel.entity.request.AIIsShowDTO
|
|
||||||
import com.remax.visualnovel.entity.response.HeartbeatLevel
|
|
||||||
import com.remax.visualnovel.extension.addScrollerAlpha
|
|
||||||
import com.remax.visualnovel.extension.getTemperatureTxt
|
|
||||||
import com.remax.visualnovel.extension.glide.loadAndRoundCorner
|
|
||||||
import com.remax.visualnovel.extension.launchAndLoadingCollect
|
|
||||||
import com.remax.visualnovel.extension.setMargin
|
|
||||||
import com.remax.visualnovel.extension.setOnClick
|
|
||||||
import com.remax.visualnovel.extension.setSize
|
|
||||||
import com.remax.visualnovel.extension.setSpanTypeFace
|
|
||||||
import com.remax.visualnovel.extension.showMoreTxtDialog
|
|
||||||
import com.remax.visualnovel.extension.translationYObjectAnimator
|
|
||||||
import com.remax.visualnovel.utils.Routers
|
|
||||||
import com.remax.visualnovel.utils.spannablex.spannable
|
|
||||||
import com.remax.visualnovel.utils.spannablex.utils.dp
|
|
||||||
import com.remax.visualnovel.widget.ui.UserAvatarView
|
|
||||||
import com.remax.visualnovel.widget.uitoken.changeTextFont
|
|
||||||
import com.remax.visualnovel.widget.uitoken.handleUIToken
|
|
||||||
import com.drake.brv.annotaion.DividerOrientation
|
|
||||||
import com.drake.brv.utils.divider
|
|
||||||
import com.drake.brv.utils.grid
|
|
||||||
import com.drake.brv.utils.models
|
|
||||||
import com.drake.brv.utils.setup
|
|
||||||
import com.remax.visualnovel.databinding.ActivityFlirtingLevelBinding
|
|
||||||
import com.remax.visualnovel.databinding.ItemFlirtingLevelBinding
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
|
||||||
import timber.log.Timber
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
|
||||||
@Route(path = Routers.CHAT_FLIRTING_LEVEL)
|
|
||||||
class FlirtingLevelActivity : BaseBindingActivity<ActivityFlirtingLevelBinding>() {
|
|
||||||
|
|
||||||
private val flirtingLevelViewModel by viewModels<FlirtingLevelViewModel>()
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
@Autowired
|
|
||||||
var aiId = ""
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
override fun initView() {
|
|
||||||
ARouter.getInstance().inject(this)
|
|
||||||
setToolbar(R.string.app_name) {
|
|
||||||
isFull = true
|
|
||||||
titleTextAlpha = 1f
|
|
||||||
setRightIconBtn1(R.string.icon_more) {
|
|
||||||
val switchWindow = TipsSwitchWindow()
|
|
||||||
switchWindow.build(
|
|
||||||
this@FlirtingLevelActivity,
|
|
||||||
R.string.hide_relations,
|
|
||||||
flirtingLevelViewModel.levelOutput?.aiUserHeartbeatRelation?.isShow != true
|
|
||||||
) { switchView, isChecked ->
|
|
||||||
launchAndLoadingCollect({
|
|
||||||
flirtingLevelViewModel.relationSwitch(AIIsShowDTO(aiId, if (isChecked) 0 else 1))
|
|
||||||
}) {
|
|
||||||
onSuccess = {
|
|
||||||
with(binding) {
|
|
||||||
listOf(tvMeet, dividerMeet1, dividerMeet2).forEach { view ->
|
|
||||||
view.isGone =
|
|
||||||
flirtingLevelViewModel.levelOutput?.aiUserHeartbeatRelation?.isShow != true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onFailed = { _, _ ->
|
|
||||||
switchView.isChecked = !isChecked
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switchWindow.showAsDropDown(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
setRightIconBtn2(R.string.icon_faq) {
|
|
||||||
showMoreTxtDialog(
|
|
||||||
texts = listOf(
|
|
||||||
R.string.flirting_tips_txt_1,
|
|
||||||
R.string.flirting_tips_txt_2,
|
|
||||||
R.string.flirting_tips_txt_3
|
|
||||||
).map { getString(it) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
with(binding) {
|
|
||||||
scrollView.addScrollerAlpha(aiAvatarView, includeBgAlpha = true, textAlpha = false)
|
|
||||||
|
|
||||||
tvMeet.text = "· ${getString(R.string.meet)} ·"
|
|
||||||
|
|
||||||
setOnClick(retrieveGroup) {
|
|
||||||
flirtingLevelViewModel.levelOutput?.aiUserHeartbeatRelation?.let {
|
|
||||||
val retrieveDialog = FlirtingRetrieveDialog(this@FlirtingLevelActivity)
|
|
||||||
retrieveDialog.build(it) {
|
|
||||||
launchAndLoadingCollect({
|
|
||||||
flirtingLevelViewModel.buyHeartbeatVal(aiId)
|
|
||||||
}) {
|
|
||||||
onSuccess = {
|
|
||||||
initData()
|
|
||||||
retrieveDialog.dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
retrieveDialog.binding.run {
|
|
||||||
showHeartAnim(levelBg, levelBgTop, lottieView, 84f)
|
|
||||||
}
|
|
||||||
retrieveDialog.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rv.grid(2)
|
|
||||||
.divider {
|
|
||||||
setDivider(16, true)
|
|
||||||
orientation = DividerOrientation.VERTICAL
|
|
||||||
}.setup {
|
|
||||||
addType<HeartbeatLevel>(R.layout.item_flirting_level)
|
|
||||||
onBind {
|
|
||||||
val item = getModel<HeartbeatLevel>()
|
|
||||||
with(getBinding<ItemFlirtingLevelBinding>()) {
|
|
||||||
tvName.text = item.name
|
|
||||||
tvName.isEnabled = item.isUnlock
|
|
||||||
lockView.isVisible = !item.isUnlock
|
|
||||||
imageView.loadAndRoundCorner(item.imgUrl, 16)
|
|
||||||
tvTemperature.text = item.startVal.getTemperatureTxt()
|
|
||||||
tvTemperature.isEnabled = item.isUnlock
|
|
||||||
imageStroke.isVisible = item.isUnlock
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n", "DefaultLocale")
|
|
||||||
override fun initData() {
|
|
||||||
launchAndLoadingCollect({
|
|
||||||
flirtingLevelViewModel.getHeartbeatLevel(aiId)
|
|
||||||
}) {
|
|
||||||
onSuccess = {
|
|
||||||
val relation = it?.aiUserHeartbeatRelation
|
|
||||||
with(binding) {
|
|
||||||
listOf(tvMeet, dividerMeet1, dividerMeet2).forEach { view ->
|
|
||||||
view.isGone = relation?.isShow != true
|
|
||||||
}
|
|
||||||
|
|
||||||
showHeartAnim(levelBg, levelBgTop, lottieView, avatarView = aiAvatarView)
|
|
||||||
|
|
||||||
aiAvatarView.loadAvatar(relation?.aiHeadImg)
|
|
||||||
myAvatarView.loadAvatar(relation?.userHeadImg)
|
|
||||||
val currHeartbeat = relation?.currHeartbeatEnum
|
|
||||||
if (currHeartbeat == null) {
|
|
||||||
tvMeet.changeTextFont {
|
|
||||||
textUITextToken = getString(R.string.txt_title_s)
|
|
||||||
}
|
|
||||||
tvMeet.setText(R.string.no_intention_yet)
|
|
||||||
} else {
|
|
||||||
tvMeet.changeTextFont {
|
|
||||||
textUITextToken = getString(R.string.txt_display_s)
|
|
||||||
}
|
|
||||||
tvMeet.setText(currHeartbeat.tagName)
|
|
||||||
}
|
|
||||||
val heartbeatScore = String.format("%.2f", (relation?.heartbeatScore ?: 0.0f) * 100)
|
|
||||||
|
|
||||||
tvMeetDesc.text =
|
|
||||||
getString(R.string.flirting_desc, relation?.dayCount ?: 0, heartbeatScore)
|
|
||||||
tvLevel.text = spannable {
|
|
||||||
if (currHeartbeat != null) {
|
|
||||||
currHeartbeat.levelContent.text()
|
|
||||||
" 丨 ".color(handleUIToken(R.string.color_outline_normal)?.color ?: 0)
|
|
||||||
}
|
|
||||||
(relation?.heartbeatVal ?: 0.0).toString().text()
|
|
||||||
getString(R.string.temperature).span {
|
|
||||||
setSpanTypeFace(this@FlirtingLevelActivity, R.string.txt_numMonotype_s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 已经扣减的心动分
|
|
||||||
*/
|
|
||||||
retrieveGroup.isVisible = (relation?.subtractHeartbeatVal ?: 0.0) != 0.0
|
|
||||||
retrieveTitle.text =
|
|
||||||
getString(R.string.flirting_deducted_desc, (relation?.subtractHeartbeatVal ?: 0.0).toString())
|
|
||||||
|
|
||||||
rv.models = it?.heartbeatLeveLDictList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showHeartAnim(
|
|
||||||
levelBg: View,
|
|
||||||
levelBgTop: View,
|
|
||||||
heartLottie: LottieAnimationView,
|
|
||||||
bgBottomMargin: Float = 0f,
|
|
||||||
avatarView: UserAvatarView? = null,
|
|
||||||
) {
|
|
||||||
levelBg.post {
|
|
||||||
val currProgress =
|
|
||||||
flirtingLevelViewModel.levelOutput?.aiUserHeartbeatRelation?.currHeartbeatEnum?.level ?: 0
|
|
||||||
val progress = currProgress / 10f
|
|
||||||
|
|
||||||
// 弹窗中的切图需要往上移动
|
|
||||||
levelBg.setMargin(bottomMargin = -((bgBottomMargin / 400f) * levelBgTop.measuredHeight).toInt())
|
|
||||||
|
|
||||||
// 根据切图比例调整宽高
|
|
||||||
val heartSize = ((98f / 214f) * levelBgTop.measuredHeight).toInt()
|
|
||||||
heartLottie.setSize(heartSize, heartSize)
|
|
||||||
|
|
||||||
// 头像框距离顶部的边距
|
|
||||||
val marginTop = ((120f / 214f) * levelBgTop.measuredHeight) + (heartSize - 64.dp) / 2f
|
|
||||||
avatarView?.setMargin(topMargin = marginTop.toInt())
|
|
||||||
avatarView?.isVisible = true
|
|
||||||
binding.myAvatarView.isVisible = true
|
|
||||||
|
|
||||||
// 动画持续时间
|
|
||||||
val totalTime = 1000L
|
|
||||||
// 总高度进度算
|
|
||||||
val totalHeight = progress * heartSize
|
|
||||||
Timber.i("showHeartAnim heartSize:$heartSize totalHeight:$totalHeight")
|
|
||||||
heartLottie.translationYObjectAnimator(-totalHeight, totalTime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun start(aiId: String?) {
|
|
||||||
if (aiId != null) {
|
|
||||||
ARouter.getInstance()
|
|
||||||
.build(Routers.CHAT_FLIRTING_LEVEL)
|
|
||||||
.withString("aiId", aiId)
|
|
||||||
.navigation()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -17,7 +17,7 @@ class FlirtingLevelViewModel @Inject constructor(private val chatRepository: Cha
|
||||||
var levelOutput: HeartbeatLevelOutput? = null
|
var levelOutput: HeartbeatLevelOutput? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
suspend fun getHeartbeatLevel(aiId: String) = chatRepository.getHeartbeatLevel(aiId).transformResult({
|
/*suspend fun getHeartbeatLevel(aiId: String) = chatRepository.getHeartbeatLevel(aiId).transformResult({
|
||||||
levelOutput = it
|
levelOutput = it
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -28,5 +28,17 @@ class FlirtingLevelViewModel @Inject constructor(private val chatRepository: Cha
|
||||||
suspend fun buyHeartbeatVal(aiId: String) = chatRepository.buyHeartbeatVal(HeartbeatBuy(
|
suspend fun buyHeartbeatVal(aiId: String) = chatRepository.buyHeartbeatVal(HeartbeatBuy(
|
||||||
aiId,
|
aiId,
|
||||||
levelOutput?.aiUserHeartbeatRelation?.subtractHeartbeatVal
|
levelOutput?.aiUserHeartbeatRelation?.subtractHeartbeatVal
|
||||||
))
|
))*/
|
||||||
|
|
||||||
|
suspend fun getHeartbeatLevel(aiId: String) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun relationSwitch(request: AIIsShowDTO) {
|
||||||
|
|
||||||
|
}
|
||||||
|
suspend fun buyHeartbeatVal(aiId: String) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -199,47 +199,7 @@ class ChatSettingView @JvmOverloads constructor(
|
||||||
nameLanguage = "名称-5"
|
nameLanguage = "名称-5"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
/*val items = listOf(
|
|
||||||
ChatSound(
|
|
||||||
id = 1L,
|
|
||||||
name = "Sound-1",
|
|
||||||
description = "This is description for sound-1",
|
|
||||||
isMale = true,
|
|
||||||
imgUrl = ""
|
|
||||||
),
|
|
||||||
ChatSound(
|
|
||||||
id = 2L,
|
|
||||||
name = "Sound-2",
|
|
||||||
description = "This is description for sound-2",
|
|
||||||
isMale = false,
|
|
||||||
imgUrl = ""
|
|
||||||
),
|
|
||||||
|
|
||||||
ChatSound(
|
|
||||||
id = 3L,
|
|
||||||
name = "Sound-3",
|
|
||||||
description = "This is description for sound-3",
|
|
||||||
isMale = true,
|
|
||||||
imgUrl = ""
|
|
||||||
),
|
|
||||||
|
|
||||||
ChatSound(
|
|
||||||
id = 4L,
|
|
||||||
name = "Sound-4",
|
|
||||||
description = "This is description for sound-4",
|
|
||||||
isMale = false,
|
|
||||||
imgUrl = ""
|
|
||||||
),
|
|
||||||
|
|
||||||
ChatSound(
|
|
||||||
id = 5L,
|
|
||||||
name = "Sound-5",
|
|
||||||
description = "This is description for sound-5",
|
|
||||||
isMale = true,
|
|
||||||
imgUrl = ""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
with(mBinding.soundActorSelector) {
|
with(mBinding.soundActorSelector) {
|
||||||
setItems(items)
|
setItems(items)
|
||||||
setEventListener(
|
setEventListener(
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import android.widget.LinearLayout
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.drake.brv.annotaion.DividerOrientation
|
import com.drake.brv.annotaion.DividerOrientation
|
||||||
import com.drake.brv.utils.addModels
|
|
||||||
import com.drake.brv.utils.bindingAdapter
|
import com.drake.brv.utils.bindingAdapter
|
||||||
import com.drake.brv.utils.divider
|
import com.drake.brv.utils.divider
|
||||||
import com.drake.brv.utils.grid
|
import com.drake.brv.utils.grid
|
||||||
|
|
@ -59,21 +58,6 @@ class ExpandBackgroundSubView @JvmOverloads constructor(
|
||||||
addType<ChatBackgroundBase.ChatBackgroundUpload>(R.layout.layout_item_setting_background_upload)
|
addType<ChatBackgroundBase.ChatBackgroundUpload>(R.layout.layout_item_setting_background_upload)
|
||||||
|
|
||||||
onClick(R.id.root) {
|
onClick(R.id.root) {
|
||||||
/*when (val item = getModel<Any>(it)) {
|
|
||||||
is ChatBackgroundBase.ChatBackground -> {
|
|
||||||
val chatBackground = getModel<ChatBackgroundBase.ChatBackground>()
|
|
||||||
if (!chatBackground.isSelected) {
|
|
||||||
itemsRv.bindingAdapter.models?.filterIsInstance<ChatBackgroundBase.ChatBackground>()?.forEach { item ->
|
|
||||||
item.isSelected = item == chatBackground
|
|
||||||
}
|
|
||||||
itemsRv.bindingAdapter.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is ChatBackgroundBase.ChatBackgroundUpload -> {
|
|
||||||
selectCustomBg()
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
when (itemViewType) {
|
when (itemViewType) {
|
||||||
R.layout.layout_item_setting_background -> {
|
R.layout.layout_item_setting_background -> {
|
||||||
val chatBackground = getModel<ChatBackgroundBase.ChatBackground>()
|
val chatBackground = getModel<ChatBackgroundBase.ChatBackground>()
|
||||||
|
|
@ -91,6 +75,12 @@ class ExpandBackgroundSubView @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClick(R.id.iv_del) {
|
||||||
|
// TODO - request delete method
|
||||||
|
val chatBackground = getModel<ChatBackgroundBase.ChatBackground>()
|
||||||
|
//itemsRv.bindingAdapter.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
onBind {
|
onBind {
|
||||||
when (itemViewType) {
|
when (itemViewType) {
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,10 @@ import com.remax.visualnovel.configs.NovelApplication
|
||||||
import com.remax.visualnovel.databinding.FragmentMainActorBinding
|
import com.remax.visualnovel.databinding.FragmentMainActorBinding
|
||||||
import com.remax.visualnovel.entity.request.ParamActorList
|
import com.remax.visualnovel.entity.request.ParamActorList
|
||||||
import com.remax.visualnovel.entity.request.ParamActorTag
|
import com.remax.visualnovel.entity.request.ParamActorTag
|
||||||
|
import com.remax.visualnovel.entity.request.ParamSoundList
|
||||||
import com.remax.visualnovel.entity.response.ActorBean
|
import com.remax.visualnovel.entity.response.ActorBean
|
||||||
import com.remax.visualnovel.extension.launchAndCollect2
|
import com.remax.visualnovel.extension.launchAndCollect2
|
||||||
|
import com.remax.visualnovel.utils.LanguageUtil
|
||||||
import com.remax.visualnovel.utils.Routers
|
import com.remax.visualnovel.utils.Routers
|
||||||
import com.remax.visualnovel.utils.StatusBarUtil3
|
import com.remax.visualnovel.utils.StatusBarUtil3
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
@ -32,7 +34,7 @@ class ActorListFragment : BaseBindingFragment<FragmentMainActorBinding>() {
|
||||||
private val mActorsModel by viewModels<ActorsViewModel>()
|
private val mActorsModel by viewModels<ActorsViewModel>()
|
||||||
private var mLoadedPageIndex = 0
|
private var mLoadedPageIndex = 0
|
||||||
private val mRequestParam by lazy { ParamActorList() }
|
private val mRequestParam by lazy { ParamActorList() }
|
||||||
private val mRequestTagsParam by lazy { ParamActorTag() }
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreated(bundle: Bundle?) {
|
override fun onCreated(bundle: Bundle?) {
|
||||||
|
|
@ -151,20 +153,22 @@ class ActorListFragment : BaseBindingFragment<FragmentMainActorBinding>() {
|
||||||
|
|
||||||
|
|
||||||
private fun getActorTags() {
|
private fun getActorTags() {
|
||||||
mRequestTagsParam.limit = Int.MAX_VALUE
|
val tagsParam = ParamActorTag().apply {
|
||||||
|
limit = Int.MAX_VALUE
|
||||||
|
}
|
||||||
|
|
||||||
launchAndCollect2({
|
launchAndCollect2({
|
||||||
mActorsModel.getActorTags(mRequestTagsParam)
|
mActorsModel.getActorTags(tagsParam)
|
||||||
}, showLoading = false) {
|
}, showLoading = false) {
|
||||||
onSuccess = {
|
onSuccess = {
|
||||||
val data = it ?: emptyList()
|
val data = it ?: emptyList()
|
||||||
binding.tagFlowLayout.setTagDataList(data)
|
binding.tagFlowLayout.setTagDataList(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun createSampleData(): List<ActorBean> {
|
private fun createSampleData(): List<ActorBean> {
|
||||||
return listOf(
|
return listOf(
|
||||||
ActorBean(characterName = "testName-1", description = "Des-xxxxxxxxxxxxx"),
|
ActorBean(characterName = "testName-1", description = "Des-xxxxxxxxxxxxx"),
|
||||||
|
|
|
||||||
|
|
@ -24,4 +24,5 @@ class ActorsViewModel @Inject constructor(private val mActorsRepository: ActorsR
|
||||||
|
|
||||||
suspend fun getActorTags(param: ParamActorTag) = mActorsRepository.getActorTags(param)
|
suspend fun getActorTags(param: ParamActorTag) = mActorsRepository.getActorTags(param)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,12 +42,12 @@
|
||||||
|
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenImageView
|
<com.remax.visualnovel.widget.uitoken.view.UITokenImageView
|
||||||
android:id="@+id/iv_del"
|
android:id="@+id/iv_del"
|
||||||
android:layout_width="@dimen/dp_15"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/dp_15"
|
android:layout_height="wrap_content"
|
||||||
android:src="@mipmap/setting_delete"
|
android:src="@mipmap/setting_delete"
|
||||||
app:radiusToken="@string/radius_l"
|
app:radiusToken="@string/radius_l"
|
||||||
android:tint="@color/white"
|
android:tint="@color/white"
|
||||||
android:layout_marginBottom="@dimen/dp_9"
|
android:paddingVertical="@dimen/dp_12"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue