Browse Source

[feat]键盘插件,帮聊模式,点击键盘按键,显示Lottie的爱心Loading,加载完毕后隐藏Loading

hezihao 9 months ago
parent
commit
4df3969d24

+ 3 - 0
plugins/keyboard_android/android/build.gradle

@@ -85,6 +85,9 @@ android {
         // 让Service支持Jetpack Lifecycle组件
         // 让Service支持Jetpack Lifecycle组件
         implementation "androidx.lifecycle:lifecycle-service:2.6.1"
         implementation "androidx.lifecycle:lifecycle-service:2.6.1"
 
 
+        // Lottie动画
+        implementation "com.airbnb.android:lottie:6.6.6"
+
         // Gson
         // Gson
         implementation "com.google.code.gson:gson:2.10"
         implementation "com.google.code.gson:gson:2.10"
         // CircleImageView
         // CircleImageView

File diff suppressed because it is too large
+ 1 - 0
plugins/keyboard_android/android/src/main/assets/lottie/anim_keyboard_love_fly.json


+ 36 - 6
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/AiKeyboardCommonPanelComponent.kt

@@ -98,6 +98,10 @@ class AiKeyboardCommonPanelComponent @JvmOverloads constructor(
             mKeyListAdapter = MultiTypeAdapter(mKeyListItems).apply {
             mKeyListAdapter = MultiTypeAdapter(mKeyListItems).apply {
                 // 键盘按键条目
                 // 键盘按键条目
                 register(AiKeyboardKeyModel::class.java, AiKeyboardKeyViewBinder {
                 register(AiKeyboardKeyModel::class.java, AiKeyboardKeyViewBinder {
+                    // 正在加载中,忽略点击
+                    if (it.isLoading) {
+                        return@AiKeyboardKeyViewBinder
+                    }
                     // 点击键盘按键,打开AI生成内容面板
                     // 点击键盘按键,打开AI生成内容面板
                     if (it.isVip) {
                     if (it.isVip) {
                         // 检查是否VIP
                         // 检查是否VIP
@@ -252,6 +256,7 @@ class AiKeyboardCommonPanelComponent @JvmOverloads constructor(
     /**
     /**
      * 加载按键列表
      * 加载按键列表
      */
      */
+    @SuppressLint("NotifyDataSetChanged")
     private fun loadKeyList() {
     private fun loadKeyList() {
         KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
         KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
             ?.getCharacterList(onSuccess = {
             ?.getCharacterList(onSuccess = {
@@ -291,8 +296,13 @@ class AiKeyboardCommonPanelComponent @JvmOverloads constructor(
 
 
     /**
     /**
      * 处理条目点击逻辑
      * 处理条目点击逻辑
+     *
+     * @param item 当前点击的条目的数据
      */
      */
-    private fun handleItemClickLogic(item: AiKeyboardKeyModel) {
+    @SuppressLint("NotifyDataSetChanged")
+    private fun handleItemClickLogic(
+        item: AiKeyboardKeyModel
+    ) {
         // 判断帮助模式
         // 判断帮助模式
         val helpMode = KeyboardHolder.getKeyboardService()
         val helpMode = KeyboardHolder.getKeyboardService()
             ?.getKeyboardViewModel()?.helpMode?.value
             ?.getKeyboardViewModel()?.helpMode?.value
@@ -301,7 +311,7 @@ class AiKeyboardCommonPanelComponent @JvmOverloads constructor(
         }
         }
 
 
         // 保存当前点击项的数据
         // 保存当前点击项的数据
-        mCurrentClickItem = item
+        this.mCurrentClickItem = item
 
 
         LogUtil.d("当前帮助模式 => $helpMode")
         LogUtil.d("当前帮助模式 => $helpMode")
 
 
@@ -316,7 +326,15 @@ class AiKeyboardCommonPanelComponent @JvmOverloads constructor(
 
 
         if (HelpMode.HELP_CHAT == helpMode) {
         if (HelpMode.HELP_CHAT == helpMode) {
             // 帮聊只会生成一条内容,直接添加到输入框
             // 帮聊只会生成一条内容,直接添加到输入框
-            doChatSuperReply(item.payload)
+            doChatSuperReply(item.payload, startCallback = {
+                // 生成开始,显示Loading
+                item.isLoading = true
+                mKeyListAdapter.notifyDataSetChanged()
+            }, finishCallback = {
+                // 生成结束,关闭Loading
+                item.isLoading = false
+                mKeyListAdapter.notifyDataSetChanged()
+            })
         } else {
         } else {
             // 教你说和开场白,有多条数据,需要添加到列表中展示
             // 教你说和开场白,有多条数据,需要添加到列表中展示
             if (HelpMode.TEACH_YOU_SAY == helpMode) {
             if (HelpMode.TEACH_YOU_SAY == helpMode) {
@@ -334,20 +352,31 @@ class AiKeyboardCommonPanelComponent @JvmOverloads constructor(
      *
      *
      * @param characterId 人设Id
      * @param characterId 人设Id
      */
      */
-    private fun doChatSuperReply(characterId: String) {
+    private fun doChatSuperReply(
+        characterId: String,
+        startCallback: (() -> Unit)? = null,
+        finishCallback: (() -> Unit)? = null
+    ) {
         val viewModel = KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
         val viewModel = KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+        startCallback?.invoke()
+        // 获取数据
         viewModel?.chatSuperReply(characterId, onSuccess = {
         viewModel?.chatSuperReply(characterId, onSuccess = {
+            // 获取成功
+            finishCallback?.invoke()
         }, onFail = {
         }, onFail = {
+            // 获取失败
             ToastUtils.showShort(it)
             ToastUtils.showShort(it)
+            finishCallback?.invoke()
         })
         })
     }
     }
 
 
     /**
     /**
      * 生成<教你说>的内容
      * 生成<教你说>的内容
      */
      */
-    private fun doChatSuperSpeak(characterId: String) {
+    private fun doChatSuperSpeak(characterId: String, finishCallback: (() -> Unit)? = null) {
         val viewModel = KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
         val viewModel = KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
         viewModel?.chatSuperSpeak(characterId, onSuccess = {
         viewModel?.chatSuperSpeak(characterId, onSuccess = {
+            finishCallback?.invoke()
         }, onFail = {
         }, onFail = {
             ToastUtils.showShort(it)
             ToastUtils.showShort(it)
         })
         })
@@ -356,9 +385,10 @@ class AiKeyboardCommonPanelComponent @JvmOverloads constructor(
     /**
     /**
      * 生成<开场白>的内容
      * 生成<开场白>的内容
      */
      */
-    private fun doChatPrologue(name: String) {
+    private fun doChatPrologue(name: String, finishCallback: (() -> Unit)? = null) {
         val viewModel = KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
         val viewModel = KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
         viewModel?.chatPrologue(name, onSuccess = {
         viewModel?.chatPrologue(name, onSuccess = {
+            finishCallback?.invoke()
         }, onFail = {
         }, onFail = {
             ToastUtils.showShort(it)
             ToastUtils.showShort(it)
         })
         })

+ 38 - 2
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/item/AiKeyboardKeyViewBinder.kt

@@ -5,8 +5,12 @@ import android.view.View
 import android.view.ViewGroup
 import android.view.ViewGroup
 import android.widget.TextView
 import android.widget.TextView
 import androidx.recyclerview.widget.RecyclerView
 import androidx.recyclerview.widget.RecyclerView
+import com.airbnb.lottie.LottieAnimationView
+import com.airbnb.lottie.LottieDrawable
 import com.atmob.keyboard_android.R
 import com.atmob.keyboard_android.R
 import com.atmob.keyboard_android.ext.click
 import com.atmob.keyboard_android.ext.click
+import com.atmob.keyboard_android.ext.setGone
+import com.atmob.keyboard_android.ext.setVisible
 import com.atmob.keyboard_android.model.AiKeyboardKeyModel
 import com.atmob.keyboard_android.model.AiKeyboardKeyModel
 import me.drakeet.multitype.ItemViewBinder
 import me.drakeet.multitype.ItemViewBinder
 
 
@@ -28,13 +32,45 @@ class AiKeyboardKeyViewBinder(
         holder: InnerViewHolder,
         holder: InnerViewHolder,
         item: AiKeyboardKeyModel
         item: AiKeyboardKeyModel
     ) {
     ) {
-        holder.vKeyText.text = item.text
-        holder.vKeyText.click {
+        // 加载中,显示Loading,隐藏文字
+        if (item.isLoading) {
+            holder.vLoadingLottieView.setVisible()
+            holder.vKeyText.setGone()
+            playLottieAnimation(holder.vLoadingLottieView)
+        } else {
+            // 隐藏Loading,显示文字
+            holder.vLoadingLottieView.setGone()
+            holder.vKeyText.setVisible()
+            // 文字
+            holder.vKeyText.apply {
+                text = item.text
+            }
+            stopLottieAnimation(holder.vLoadingLottieView)
+        }
+        holder.itemView.click {
             onItemClick.invoke(item)
             onItemClick.invoke(item)
         }
         }
     }
     }
 
 
+    /**
+     * 播放Lottie动画
+     */
+    private fun playLottieAnimation(animationView: LottieAnimationView) {
+        animationView.setAnimation("lottie/anim_keyboard_love_fly.json")
+        animationView.repeatCount = LottieDrawable.INFINITE
+        animationView.playAnimation()
+    }
+
+    /**
+     * 停止Lottie动画
+     */
+    private fun stopLottieAnimation(animationView: LottieAnimationView) {
+        animationView.cancelAnimation()
+    }
+
     inner class InnerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
     inner class InnerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
         val vKeyText: TextView = itemView.findViewById(R.id.key_text)
         val vKeyText: TextView = itemView.findViewById(R.id.key_text)
+        val vLoadingLottieView: LottieAnimationView =
+            itemView.findViewById(R.id.loading_lottie_view)
     }
     }
 }
 }

+ 5 - 1
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/model/AiKeyboardKeyModel.kt

@@ -17,5 +17,9 @@ data class AiKeyboardKeyModel(
     /**
     /**
      * 是否需要VIP
      * 是否需要VIP
      */
      */
-    val isVip: Boolean = false
+    val isVip: Boolean = false,
+    /**
+     * 是否正在加载中
+     */
+    var isLoading: Boolean = false
 ) : Serializable
 ) : Serializable

+ 13 - 2
plugins/keyboard_android/android/src/main/res/layout/item_ai_keyboard_key.xml

@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_height="wrap_content"
-    tools:background="@android:color/holo_blue_dark">
+    android:background="@drawable/bg_ai_keyboard_key">
 
 
     <TextView
     <TextView
         android:id="@+id/key_text"
         android:id="@+id/key_text"
         android:layout_width="match_parent"
         android:layout_width="match_parent"
         android:layout_height="46dp"
         android:layout_height="46dp"
         android:layout_gravity="center"
         android:layout_gravity="center"
-        android:background="@drawable/bg_ai_keyboard_key"
         android:ellipsize="end"
         android:ellipsize="end"
         android:gravity="center"
         android:gravity="center"
         android:maxLines="1"
         android:maxLines="1"
@@ -19,4 +19,15 @@
         android:textColor="@color/text_color_primary"
         android:textColor="@color/text_color_primary"
         android:textSize="14sp"
         android:textSize="14sp"
         tools:text="哄女友" />
         tools:text="哄女友" />
+
+    <com.airbnb.lottie.LottieAnimationView
+        android:id="@+id/loading_lottie_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:visibility="gone"
+        app:lottie_autoPlay="true"
+        app:lottie_fileName="lottie/anim_keyboard_love_fly.json"
+        app:lottie_loop="true"
+        tools:visibility="visible" />
 </FrameLayout>
 </FrameLayout>