自定义背景上传初步

This commit is contained in:
renhaoting 2025-11-07 11:46:22 +08:00
parent 3c9cdb3854
commit a6ccbfa2ba
10 changed files with 149 additions and 29 deletions

View File

@ -7,7 +7,6 @@ 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.HeartbeatBuy
import com.remax.visualnovel.entity.request.ParamBgUpload
import com.remax.visualnovel.entity.request.ParamLanguage
import com.remax.visualnovel.entity.request.ParamSoundList
import com.remax.visualnovel.entity.request.ParamUserid
@ -19,12 +18,12 @@ import com.remax.visualnovel.entity.response.Album
import com.remax.visualnovel.entity.response.Character
import com.remax.visualnovel.entity.response.ChatAiModule
import com.remax.visualnovel.entity.response.ChatBackgroundBase
import com.remax.visualnovel.entity.response.ChatModel
import com.remax.visualnovel.entity.response.ChatSet
import com.remax.visualnovel.entity.response.ChatSound
import com.remax.visualnovel.entity.response.Friends
import com.remax.visualnovel.entity.response.HeartbeatLevelOutput
import com.remax.visualnovel.entity.response.Pageable
import com.remax.visualnovel.entity.response.RespBgUpload
import com.remax.visualnovel.entity.response.Token
import com.remax.visualnovel.entity.response.VoiceASR
import com.remax.visualnovel.entity.response.base.Response
@ -32,11 +31,11 @@ import com.remax.visualnovel.entity.response.basenew.ResponseNew
import okhttp3.MultipartBody
import okhttp3.RequestBody
import retrofit2.http.Body
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.Part
import retrofit2.http.PartMap
interface ChatService {
@ -180,22 +179,17 @@ interface ChatService {
@POST(BuildConfig.API_BASE + "/model/config/list")
suspend fun requestAiModelList(@Body language: ParamLanguage): ResponseNew<List<ChatAiModule>>
@POST(BuildConfig.API_BASE + "/file/bgImage/upload")
suspend fun uploadCustomBgPic(@Body param: ParamBgUpload): ResponseNew<Any>
/*@Multipart
@POST(BuildConfig.API_BASE + "/file/bgImage/upload")
suspend fun uploadCustomBgPic(@Part("userId") title: RequestBody,
@Part file: MultipartBody.Part): ResponseNew<Any>*/
@POST(BuildConfig.API_BASE + "/file/bgImage/list")
suspend fun requestChatBgList(@Body userId: ParamUserid): ResponseNew<List<ChatBackgroundBase.ChatBackground>>
/*@FormUrlEncoded
@POST(BuildConfig.API_BASE + "/file/bgImage/list")
suspend fun requestChatBgList(@Field("userId") userId: Int): ResponseNew<List<ChatBackgroundBase.ChatBackground>>*/
@Multipart
@POST(BuildConfig.API_BASE + "/file/bgImage/upload")
fun uploadCustomBgPic(
@PartMap params: Map<String, RequestBody>,
@Part file: MultipartBody.Part
): ResponseNew<RespBgUpload>

View File

@ -3,5 +3,4 @@ package com.remax.visualnovel.entity.request
data class ParamBgUpload(
var userId: String,
var file: String,
)

View File

@ -0,0 +1,5 @@
package com.remax.visualnovel.entity.response
data class RespBgUpload (
val url: String,
)

View File

@ -1,5 +1,7 @@
package com.remax.visualnovel.repository.api
import android.net.Uri
import androidx.core.net.toFile
import com.remax.visualnovel.api.service.ChatService
import com.remax.visualnovel.entity.request.ChatSetting
import com.remax.visualnovel.entity.request.ParamBgUpload
@ -9,6 +11,10 @@ import com.remax.visualnovel.entity.request.ParamUserid
import com.remax.visualnovel.entity.request.SimpleDataDTO
import com.remax.visualnovel.repository.api.base.BaseRepositoryNew
import com.remax.visualnovel.ui.wallet.manager.WalletManager
import com.remax.visualnovel.utils.FileUtil
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import javax.inject.Inject
@ -31,6 +37,8 @@ class ChatRepository @Inject constructor(private val chatService: ChatService) :
// ------------------------ new ---------------------------------
suspend fun getSoundList(param: ParamSoundList) = executeHttp {
chatService.requestSoundList(param)
}
@ -39,14 +47,23 @@ class ChatRepository @Inject constructor(private val chatService: ChatService) :
chatService.requestAiModelList(language)
}
suspend fun getChatBgList(userId: Int) = executeHttp {
suspend fun getChatBgList(userId: ParamUserid) = executeHttp {
chatService.requestChatBgList(userId)
}
suspend fun uploadCustomBgPic(param: ParamBgUpload) = executeHttp {
chatService.uploadCustomBgPic(param)
suspend fun uploadCustomBgPic(
fileUri: Uri,
param: ParamBgUpload
) = executeHttp {
/*val file = fileUri.toFile()?:
return ApiFailedResponse(1, message = "File not exist")*/
val params = mutableMapOf<String, RequestBody>()
params["userId"] = param.userId.toRequestBody(("text/plain").toMediaType())
val filePart = FileUtil.createFilePart("file", fileUri.toFile())
chatService.uploadCustomBgPic(params, filePart)
}
}

View File

@ -2,6 +2,7 @@ package com.remax.visualnovel.ui.chat
import android.graphics.Point
import android.net.Uri
import android.view.View.GONE
import android.view.View.VISIBLE
import androidx.activity.viewModels
@ -97,7 +98,7 @@ class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
private fun loadChantBgDatas() {
launchAndCollect2({
mViewModel.loadChatBgList(1)
mViewModel.loadChatBgList(ParamUserid(1))
}) {
onSuccess = {
val dataList = it?: emptyList()
@ -129,6 +130,20 @@ class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
}
}
private fun uploadCustomBg(file: Uri) {
launchAndCollect2({
mViewModel.uploadCustomBgPic(1, file)
}) {
onSuccess = {
val dataList = it
}
onComplete = {
}
}
}
private val loginObserver = Observer<OnLoginEvent?> {
launchWithRequest({
//TODO - business handling for login events
@ -174,6 +189,10 @@ class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
override fun onSoundFiltersChanged(sexValue: Int) {
loadSoundDatas(sexValue)
}
override fun onUploadCustomBg(file: Uri) {
uploadCustomBg(file)
}
})
}
}

View File

@ -1,6 +1,7 @@
package com.remax.visualnovel.ui.chat
import android.net.Uri
import com.remax.visualnovel.app.viewmodel.base.OssViewModel
import com.remax.visualnovel.entity.imbean.raw.CustomRawData
import com.remax.visualnovel.entity.request.ChatSetting
@ -89,8 +90,9 @@ class ChatViewModel @Inject constructor(
//------------------------ new ------------------------
suspend fun loadSoundList(param: ParamSoundList) = chatRepository.getSoundList(param)
suspend fun loadAiModelList(language: ParamLanguage) = chatRepository.getAiModelList(language)
suspend fun loadChatBgList(userId: Int) = chatRepository.getChatBgList(userId)
suspend fun uploadCustomBgPic(param: ParamBgUpload) = chatRepository.uploadCustomBgPic(param)
suspend fun loadChatBgList(userId: ParamUserid) = chatRepository.getChatBgList(userId)
suspend fun uploadCustomBgPic(userId: Int, file: Uri) = chatRepository.uploadCustomBgPic(file, ParamBgUpload(userId.toString()))

View File

@ -3,6 +3,7 @@ package com.remax.visualnovel.ui.chat.setting.customui
import android.content.Context
import android.graphics.Color
import android.net.Uri
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
@ -18,6 +19,7 @@ import com.remax.visualnovel.entity.response.ChatMode
import com.remax.visualnovel.entity.response.ChatSound
import com.remax.visualnovel.extension.showConfirmDialog
import com.remax.visualnovel.ui.chat.setting.customui.expandableSelector.ExpandAiModelSelectView
import com.remax.visualnovel.ui.chat.setting.customui.expandableSelector.ExpandBackgroundSubView
import com.remax.visualnovel.ui.chat.setting.customui.expandableSelector.ExpandBubbleSelectView
import com.remax.visualnovel.ui.chat.setting.customui.expandableSelector.ExpandChatModeSelectView
import com.remax.visualnovel.ui.chat.setting.customui.expandableSelector.ExpandSoundSelectView
@ -34,6 +36,7 @@ class ChatSettingView @JvmOverloads constructor(
private lateinit var mEventListener: IEventListener
interface IEventListener {
fun onSoundFiltersChanged(sexValue: Int)
fun onUploadCustomBg(file: Uri)
}
fun setEventListener(listener: IEventListener) {
mEventListener = listener
@ -320,6 +323,11 @@ class ChatSettingView @JvmOverloads constructor(
)
mBinding.backgroundSelectorView.setItems(items)
mBinding.backgroundSelectorView.setOnEventListener(object: ExpandBackgroundSubView.IEventListener {
override fun onUploadCustomBg(file: Uri) {
mEventListener.onUploadCustomBg(file)
}
})
}

View File

@ -2,6 +2,7 @@ package com.remax.visualnovel.ui.chat.setting.customui.expandableSelector
import android.annotation.SuppressLint
import android.content.Context
import android.net.Uri
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.LinearLayout
@ -17,6 +18,7 @@ import com.remax.visualnovel.R
import com.remax.visualnovel.databinding.LayoutItemSettingBackgroundBinding
import com.remax.visualnovel.databinding.LayoutSettingBgSubViewBinding
import com.remax.visualnovel.entity.response.ChatBackgroundBase
import com.remax.visualnovel.entity.response.ChatBubble
import com.remax.visualnovel.extension.glide.load
import com.remax.visualnovel.extension.toast
import com.remax.visualnovel.utils.imagepick.EpalPickerPresenter
@ -39,6 +41,15 @@ class ExpandBackgroundSubView @JvmOverloads constructor(
private var items = mutableListOf<ChatBackgroundBase>()
private var mBinding: LayoutSettingBgSubViewBinding
private var mEventListener: IEventListener? = null
interface IEventListener {
fun onUploadCustomBg(file: Uri)
}
fun setOnEventListener(listener: IEventListener) {
this.mEventListener = listener
}
init {
mBinding = LayoutSettingBgSubViewBinding.inflate(LayoutInflater.from(context), this, true)
@ -132,7 +143,7 @@ class ExpandBackgroundSubView @JvmOverloads constructor(
activity?.toast(error?.message)
}
override fun onImagePickComplete(items: ArrayList<ImageItem>?) {
override fun onImagePickComplete(items: ArrayList<ImageItem>) {
appendCustomBg(items)
uploadImageAndRequest(items)
}
@ -160,7 +171,9 @@ class ExpandBackgroundSubView @JvmOverloads constructor(
}
private fun uploadImageAndRequest(items: ArrayList<ImageItem>?) {
// TODO
if (items != null && items.isNotEmpty()) {
mEventListener?.onUploadCustomBg(items.get(0)!!.uri)
}
}

View File

@ -25,7 +25,6 @@ class ExpandBubbleSelectView @JvmOverloads constructor(
private var isExpanded = false
private var animationDuration = 300
private var mEventListener: IEventListener? = null
interface IEventListener {
fun onItemSelected(position: Int, item: ChatBubble)
fun onExpanded(isExpanded: Boolean)

View File

@ -0,0 +1,64 @@
package com.remax.visualnovel.utils
import android.net.Uri
import com.remax.visualnovel.configs.NovelApplication
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
object FileUtil {
private val appContext = NovelApplication.appContext()
private fun getFileFromUri(uri: Uri): File? {
return try {
when (uri.scheme) {
"file" -> File(uri.path!!)
"content" -> {
val inputStream = appContext.contentResolver.openInputStream(uri)
val file = File.createTempFile("upload_", null, appContext.cacheDir)
inputStream?.use { input ->
file.outputStream().use { output ->
input.copyTo(output)
}
}
file
}
else -> null
}
} catch (e: Exception) {
null
}
}
fun createFilePart(partName: String, file: File): MultipartBody.Part {
val mediaType = getMimeType(file)
return MultipartBody.Part.createFormData(
partName,
file.name,
file.asRequestBody(mediaType.toMediaType())
)
}
private fun getMimeType(file: File): String {
return when (file.extension.lowercase()) {
"jpg", "jpeg" -> "image/jpeg"
"png" -> "image/png"
"pdf" -> "application/pdf"
"mp4" -> "video/mp4"
else -> "application/octet-stream"
}
}
//==================== 扩展函数 ====================
val Uri.toFile: File?
get() = FileUtil.getFileFromUri(this)
}