feat:初步完成特权卡发布新增视频功能

This commit is contained in:
Max
2023-11-02 19:13:32 +08:00
parent 60d60d3578
commit 3de4273531
5 changed files with 283 additions and 93 deletions

View File

@@ -35,7 +35,10 @@ class PrivilegeViewModel : BaseViewModel() {
description: String,
effectDay: Int,
erbanNoStr: String,
cardUrl: String
cardUrl: String,
duration: Long?,
cardType: Int,
effectUrl: String?,
) {
safeLaunch(
block = {
@@ -46,6 +49,9 @@ class PrivilegeViewModel : BaseViewModel() {
effectDay,
erbanNoStr,
cardUrl,
duration,
cardType,
effectUrl,
AvRoomDataManager.get().roomUid.toString()
)
}
@@ -59,5 +65,4 @@ class PrivilegeViewModel : BaseViewModel() {
}
)
}
}

View File

@@ -4,15 +4,22 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.Gravity
import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.chuhai.utils.PathUtils
import com.hjq.toast.ToastUtils
import com.netease.nim.uikit.common.util.sys.ScreenUtil
import com.netease.nim.uikit.support.glide.GlideApp
import com.nnbc123.app.ErbanTakePhotoActivity.TakePhotoCallBack
import com.nnbc123.app.R
import com.nnbc123.app.application.XChatApplication
@@ -24,21 +31,25 @@ import com.nnbc123.app.common.util.BitmapUtil
import com.nnbc123.app.databinding.DialogCreatePrivilegeCardBinding
import com.nnbc123.app.takephoto.model.TResult
import com.nnbc123.app.ui.utils.ImageLoadUtils
import com.nnbc123.app.ui.utils.ImageLoadUtilsV2
import com.nnbc123.app.ui.widget.dialog.CommonTipDialog
import com.nnbc123.core.file.FileModel
import com.nnbc123.core.privilege.bean.PrivilegeCardInfo
import com.nnbc123.core.utils.Logger
import com.nnbc123.core.utils.TextUtils
import com.nnbc123.library.common.file.FileHelper
import com.nnbc123.library.common.glide.GlideUtils
import com.nnbc123.library.common.photo.PhotoProviderNew
import com.nnbc123.library.common.support.PathHelper
import com.nnbc123.library.common.util.PhotoCompressCallback
import com.nnbc123.library.common.util.PhotoCompressUtil
import com.nnbc123.library.easyphoto.constant.Type
import com.nnbc123.library.easyphoto.models.album.entity.Photo
import com.nnbc123.library.utils.SingleToastUtil
import com.nnbc123.library.utils.codec.MD5Utils
import com.yalantis.ucrop.UCrop
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.EventBus
import java.text.SimpleDateFormat
import java.util.*
@@ -82,6 +93,9 @@ class CreatePrivilegeCardDialog : BaseDialog<DialogCreatePrivilegeCardBinding>()
private var saveTipDialog: CommonTipDialog? = null
private var mUrl = ""
private var effectUrl: String? = null
private var cardType = 0
private var duration: Long? = null
private var mUri: Uri? = null
private var mJob: Job? = null
@@ -103,8 +117,11 @@ class CreatePrivilegeCardDialog : BaseDialog<DialogCreatePrivilegeCardBinding>()
binding.edExplain.setText(it.description)
binding.edValid.setText(it.effectDay.toString())
binding.edId.setText(it.erbanNoStr)
ImageLoadUtilsV2.loadImage(binding.ivPic, it.cardUrl)
loadImage(it.cardUrl)
this.mUrl = it.cardUrl
this.duration = it.duration
this.cardType = it.cardType
this.effectUrl = it.effectUrl
}
binding.edName.addTextChangedListener(object : TextWatcher {
@@ -184,10 +201,12 @@ class CreatePrivilegeCardDialog : BaseDialog<DialogCreatePrivilegeCardBinding>()
binding.ivPic.setOnClickListener {
mUri = Uri.parse("file://${FileHelper.getRootCacheDir()?.path}/${getNowTime()}.jpg")
PhotoProviderNew.photoProvider(
PhotoProviderNew.photoVideoProvider(
this,
canChooseGif = true,
resultCode = REQUEST_CODE_OPEN_PHOTO_PROVIDER
resultCode = REQUEST_CODE_OPEN_PHOTO_PROVIDER,
maxFileSize = 1024 * 1024 * 100,
videoMaxSecond = 15,
)
}
binding.tvCancel.setOnClickListener {
@@ -228,7 +247,10 @@ class CreatePrivilegeCardDialog : BaseDialog<DialogCreatePrivilegeCardBinding>()
binding.edExplain.text.toString(),
binding.edValid.text.toString().toInt(),
binding.edId.text.toString(),
mUrl
mUrl,
duration,
cardType,
effectUrl
)
saveTipDialog?.dismiss()
}
@@ -266,31 +288,10 @@ class CreatePrivilegeCardDialog : BaseDialog<DialogCreatePrivilegeCardBinding>()
if (resultCode == BaseActivity.RESULT_OK) {
when (requestCode) {
REQUEST_CODE_OPEN_PHOTO_PROVIDER -> data?.let {
val photos = PhotoProviderNew.getResultPhotoList(it) ?: return
if (photos.isNotEmpty()) {
val photo = photos[0]
if(photo.path.endsWith(Type.GIF) || photo.type.endsWith(Type.GIF)){
FileModel.get()
.uploadFile(photo.path)
.compose(bindToLifecycle())
.subscribe { url: String?, throwable: Throwable? ->
if (throwable != null) {
SingleToastUtil.showToast("上传失败")
} else {
url?.let { it1 ->
GlideUtils.instance().loadUriGiftAndCrossFadeRound(
it1, binding.ivPic, 10f)
}
if (url != null) {
mUrl = url
}
}
}
} else {
crop(photo.uri, photo.size, mUri)
}
}
val photo = PhotoProviderNew.getResultPhotoList(it)?.firstOrNull() ?: return
onPhotoResult(photo)
}
UCrop.REQUEST_CROP -> {
mUri?.path?.let {
mJob = PhotoCompressUtil.compress(
@@ -300,25 +301,7 @@ class CreatePrivilegeCardDialog : BaseDialog<DialogCreatePrivilegeCardBinding>()
object : PhotoCompressCallback {
@SuppressLint("CheckResult")
override fun onSuccess(compressedImg: String) {
FileModel.get()
.uploadFile(compressedImg)
.compose(bindToLifecycle())
.subscribe { url: String?, throwable: Throwable? ->
if (throwable != null) {
SingleToastUtil.showToast("上传失败")
} else {
ImageLoadUtils.loadRectImage(
context,
url,
binding.ivPic,
R.drawable.default_cover,
ScreenUtil.dip2px(10f)
)
if (url != null) {
mUrl = url
}
}
}
uploadImage(compressedImg)
}
override fun onFail(e: Throwable) {
@@ -386,25 +369,12 @@ class CreatePrivilegeCardDialog : BaseDialog<DialogCreatePrivilegeCardBinding>()
@SuppressLint("CheckResult")
override fun takeSuccess(result: TResult?) {
FileModel.get()
.uploadFile(result?.image?.compressPath)
.compose(bindToLifecycle())
.subscribe { url: String?, throwable: Throwable? ->
if (throwable != null) {
SingleToastUtil.showToast("上传失败")
} else {
ImageLoadUtils.loadRectImage(
context,
url,
binding.ivPic,
R.drawable.default_cover,
ScreenUtil.dip2px(10f)
)
if (url != null) {
mUrl = url
}
}
val path = result?.image?.compressPath
if (path == null) {
SingleToastUtil.showToast("文件不存在")
return
}
uploadImage(path)
}
override fun takeFail(result: TResult?, msg: String?) {
@@ -420,4 +390,111 @@ class CreatePrivilegeCardDialog : BaseDialog<DialogCreatePrivilegeCardBinding>()
mJob?.cancel()
}
private fun uploadFile(path: String, onSuccess: (String) -> Unit) {
val d = FileModel.get()
.uploadFile(path)
.compose(bindToLifecycle())
.subscribe { url: String?, throwable: Throwable? ->
if (throwable != null || url.isNullOrEmpty()) {
SingleToastUtil.showToast("上传失败")
} else {
onSuccess.invoke(url)
}
}
}
private fun uploadImage(path: String) {
Log.d(TAG, "uploadImage path:${path}")
uploadFile(path) {
loadImage(path)
mUrl = it
cardType = 0
effectUrl = null
duration = null
}
}
private fun uploadGif(path: String) {
Log.d(TAG, "uploadGif path:${path}")
uploadFile(path) {
loadImage(path)
mUrl = it
cardType = 1
effectUrl = null
duration = null
}
}
private fun uploadVideo(photo: Photo) {
val path = photo.path
Log.d(TAG, "uploadVideo path:${path}")
GlideApp.with(this).asBitmap().dontTransform().load(path)
.into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?
) {
val outPath = getImageTempPath(path)
lifecycleScope.launch {
Log.d(TAG, "uploadVideo 开始保存封面 outPath:${outPath}")
val saveResult = com.chuhai.utils.ImageUtils.save(
resource,
outPath,
Bitmap.CompressFormat.JPEG, true
)
if (saveResult) {
Log.d(TAG, "uploadVideo 封面保存成功")
withContext(Dispatchers.Main) {
uploadFile(outPath) { cover ->
uploadFile(path) { video ->
loadImage(cover)
this@CreatePrivilegeCardDialog.cardType = 2
this@CreatePrivilegeCardDialog.duration = photo.duration
this@CreatePrivilegeCardDialog.effectUrl = video
this@CreatePrivilegeCardDialog.mUrl = cover
}
}
}
} else {
Log.d(TAG, "uploadVideo 保存失败")
SingleToastUtil.showToast("文件解析失败")
}
}
}
override fun onLoadCleared(placeholder: Drawable?) {
Log.d(TAG, "uploadVideo 封面解析失败")
SingleToastUtil.showToast("视频解析失败")
}
})
}
private fun loadImage(path: String) {
ImageLoadUtils.loadRectImage(
context,
path,
binding.ivPic,
R.drawable.default_cover,
ScreenUtil.dip2px(10f)
)
}
private fun onPhotoResult(photo: Photo) {
val path = photo.path
Log.d(TAG, "onPhotoResult path:$path")
if (path.endsWith("mp4") || photo.type.endsWith(Type.VIDEO)) {
uploadVideo(photo)
} else if (photo.path.endsWith(Type.GIF) || photo.type.endsWith(Type.GIF)) {
uploadGif(path)
} else {
crop(photo.uri, photo.size, mUri)
}
}
private fun getImageTempPath(path: String): String {
return PathUtils.plusPathNotNull(
PathHelper.getExternalDownloadCachePath(),
"${MD5Utils.getMD5String(path)}.jpeg"
)
}
}

View File

@@ -25,5 +25,11 @@ data class PrivilegeCardInfo(
val updateTime: String = "",
val sendNick: String = "",
val sendUid: Long = 0L,
val cardNum: Int = 0
val cardNum: Int = 0,
//卡片类型 0 图片 1 gif 2 mp4
val cardType: Int = 0,
// 时长毫秒
val duration: Long? = null,
// 视频特效url
val effectUrl: String? = null
) : Serializable

View File

@@ -19,9 +19,31 @@ object PrivilegeModel : BaseModel() {
api.getPrivilegeCardList(cardStatus, roomUid)
}
suspend fun savePrivilegeCard(cardName: String, dailyNum: Int, description: String, effectDay: Int, erbanNoStr: String, cardUrl: String, roomUid: String): String? =
suspend fun savePrivilegeCard(
cardName: String,
dailyNum: Int,
description: String,
effectDay: Int,
erbanNoStr: String,
cardUrl: String,
duration: Long?,
cardType: Int,
effectUrl: String?,
roomUid: String
): String? =
launchRequest {
api.savePrivilegeCard(cardName, dailyNum, description, effectDay, erbanNoStr, cardUrl, roomUid)
api.savePrivilegeCard(
cardName,
dailyNum,
description,
effectDay,
erbanNoStr,
cardUrl,
cardType,
duration,
effectUrl,
roomUid
)
}
suspend fun deletePrivilegeCard(id: Int): String? =
@@ -55,6 +77,9 @@ object PrivilegeModel : BaseModel() {
@Query("effectDay") effectDay: Int,
@Query("erbanNoStr") erbanNoStr: String,
@Query("cardUrl") cardUrl: String,
@Query("cardType") cardType: Int,
@Query("duration") duration: Long?,
@Query("effectUrl") effectUrl: String?,
@Query("roomUid") roomUid: String
): ServiceResult<String>

View File

@@ -55,13 +55,24 @@ object PhotoProviderNew {
*/
@JvmStatic
@JvmOverloads
fun photoProviderPublish(activity: Activity, maxSelect: Int = 1, canChooseGif: Boolean = false, resultCode: Int, isClearCache: Boolean = true) {
fun photoProviderPublish(
activity: Activity,
maxSelect: Int = 1,
canChooseGif: Boolean = false,
resultCode: Int,
isClearCache: Boolean = true
) {
cancelJop()
mPhotoJob = MainScope().launch {
if (isClearCache && isClearByTime()) {
withContext(Dispatchers.IO) { clearCache() }
}
EasyPhotos.createAlbum(activity, false, false, GlideEngine())//参数说明上下文是否显示相机按钮是否使用宽高数据false时宽高数据为0扫描速度更快[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93)
EasyPhotos.createAlbum(
activity,
false,
false,
GlideEngine()
)//参数说明上下文是否显示相机按钮是否使用宽高数据false时宽高数据为0扫描速度更快[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93)
.setCount(maxSelect)//参数说明最大可选数默认1
.setGif(canChooseGif)
.filter(JPEG, JPG, PNG, WEBP)
@@ -73,7 +84,12 @@ object PhotoProviderNew {
@JvmStatic
@JvmOverloads
fun videoProvider(activity: Activity, maxSelect: Int = 1, resultCode: Int, isClearCache: Boolean = true) {
fun videoProvider(
activity: Activity,
maxSelect: Int = 1,
resultCode: Int,
isClearCache: Boolean = true
) {
cancelJop()
mPhotoJob = MainScope().launch {
if (isClearCache && isClearByTime()) {
@@ -90,13 +106,24 @@ object PhotoProviderNew {
@JvmStatic
@JvmOverloads
fun photoProvider(activity: Activity, maxSelect: Int = 1, canChooseGif: Boolean = false, resultCode: Int, isClearCache: Boolean = true) {
fun photoProvider(
activity: Activity,
maxSelect: Int = 1,
canChooseGif: Boolean = false,
resultCode: Int,
isClearCache: Boolean = true
) {
cancelJop()
mPhotoJob = MainScope().launch {
if (isClearCache && isClearByTime()) {
withContext(Dispatchers.IO) { clearCache() }
}
EasyPhotos.createAlbum(activity, false, false, GlideEngine())//参数说明上下文是否显示相机按钮是否使用宽高数据false时宽高数据为0扫描速度更快[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93)
EasyPhotos.createAlbum(
activity,
false,
false,
GlideEngine()
)//参数说明上下文是否显示相机按钮是否使用宽高数据false时宽高数据为0扫描速度更快[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93)
.setCount(maxSelect)//参数说明最大可选数默认1
.setGif(canChooseGif)
.setPuzzleMenu(false)
@@ -107,13 +134,24 @@ object PhotoProviderNew {
@JvmStatic
@JvmOverloads
fun photoProvider(activity: FragmentActivity, maxSelect: Int = 1, canChooseGif: Boolean = false, resultCode: Int, isClearCache: Boolean = true) {
fun photoProvider(
activity: FragmentActivity,
maxSelect: Int = 1,
canChooseGif: Boolean = false,
resultCode: Int,
isClearCache: Boolean = true
) {
cancelJop()
mPhotoJob = MainScope().launch {
if (isClearCache && isClearByTime()) {
withContext(Dispatchers.IO) { clearCache() }
}
EasyPhotos.createAlbum(activity, false, false, GlideEngine())//参数说明上下文是否显示相机按钮是否使用宽高数据false时宽高数据为0扫描速度更快[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93)
EasyPhotos.createAlbum(
activity,
false,
false,
GlideEngine()
)//参数说明上下文是否显示相机按钮是否使用宽高数据false时宽高数据为0扫描速度更快[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93)
.setCount(maxSelect)//参数说明最大可选数默认1
.setGif(canChooseGif)
.setPuzzleMenu(false)
@@ -124,13 +162,25 @@ object PhotoProviderNew {
@JvmStatic
@JvmOverloads
fun photoProvider(fragment: Fragment, maxSelect: Int = 1, canChooseGif: Boolean = false, resultCode: Int, isClearCache: Boolean = true, minFileSize: Long = 0L) {
fun photoProvider(
fragment: Fragment,
maxSelect: Int = 1,
canChooseGif: Boolean = false,
resultCode: Int,
isClearCache: Boolean = true,
minFileSize: Long = 0L
) {
cancelJop()
mPhotoJob = MainScope().launch {
if (isClearCache && isClearByTime()) {
withContext(Dispatchers.IO) { clearCache() }
}
EasyPhotos.createAlbum(fragment, false, false, GlideEngine())//参数说明上下文是否显示相机按钮是否使用宽高数据false时宽高数据为0扫描速度更快[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93)
EasyPhotos.createAlbum(
fragment,
false,
false,
GlideEngine()
)//参数说明上下文是否显示相机按钮是否使用宽高数据false时宽高数据为0扫描速度更快[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93)
.setCount(maxSelect)//参数说明最大可选数默认1
.setGif(canChooseGif)
.setMinFileSize(minFileSize)
@@ -142,19 +192,39 @@ object PhotoProviderNew {
@JvmStatic
@JvmOverloads
fun photoVideoProvider(fragment: Fragment, maxSelect: Int = 1, canChooseGif: Boolean = false, resultCode: Int, isClearCache: Boolean = true, minFileSize: Long = 0L) {
fun photoVideoProvider(
fragment: Fragment,
maxSelect: Int = 1,
canChooseGif: Boolean = false,
resultCode: Int,
isClearCache: Boolean = true,
minFileSize: Long = 0L,
maxFileSize: Long = Long.MAX_VALUE,
videoMaxSecond: Int = -1
) {
cancelJop()
mPhotoJob = MainScope().launch {
if (isClearCache && isClearByTime()) {
withContext(Dispatchers.IO) { clearCache() }
}
EasyPhotos.createAlbum(fragment, false, false, GlideEngine())//参数说明上下文是否显示相机按钮是否使用宽高数据false时宽高数据为0扫描速度更快[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93)
EasyPhotos.createAlbum(
fragment,
false,
false,
GlideEngine()
)//参数说明上下文是否显示相机按钮是否使用宽高数据false时宽高数据为0扫描速度更快[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93)
.setCount(maxSelect)//参数说明最大可选数默认1
.setGif(canChooseGif)
.setVideo(true)
.setMinFileSize(minFileSize)
.setMaxFileSize(maxFileSize)
.setPuzzleMenu(false)
.setCleanMenu(false)
.apply {
if (videoMaxSecond > 0) {
setVideoMaxSecond(videoMaxSecond)
}
}
.start(resultCode)
}
}
@@ -200,7 +270,10 @@ object PhotoProviderNew {
val path = "$foldPath${it.name}"
if (FileHelper.copyFileFromUri(it.uri, path, true)) {
newPaths.add(path)
Logger.debug(TAG, "path: ${it.path} , displayName: ${it.name} , newPath: $path ")
Logger.debug(
TAG,
"path: ${it.path} , displayName: ${it.name} , newPath: $path "
)
}
}
}
@@ -215,8 +288,12 @@ object PhotoProviderNew {
*/
fun clearCache() {
Logger.debug(
TAG, "clearCache => mLastSelectTime: ${TimeUtils.getDateTimeString(
mLastSelectTime, TIME_FORMAT)}")
TAG, "clearCache => mLastSelectTime: ${
TimeUtils.getDateTimeString(
mLastSelectTime, TIME_FORMAT
)
}"
)
FileHelper.removeAllFile(getInternalPath() + File.separator)
}