Browse Source

[feat]键盘插件,将声明式View操作,改成MVVM,通过数据驱动UI

hezihao 8 months ago
parent
commit
b11da4cb74
24 changed files with 458 additions and 147 deletions
  1. 5 0
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/base/BaseUIComponent.kt
  2. 11 0
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/base/IBusinessComponent.kt
  3. 1 1
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/base/IUIComponent.kt
  4. 21 3
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/base/RouteComponent.kt
  5. 0 10
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/IAiKeyboardComponent.kt
  6. 20 8
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/AiChatComponent.kt
  7. 60 49
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/AiKeyboardComponent.kt
  8. 30 5
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/KeyboardSelectComponent.kt
  9. 29 14
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/QuickSwitchComponent.kt
  10. 27 4
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/SettingComponent.kt
  11. 11 15
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/ToolBarComponent.kt
  12. 17 1
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/page/impl/LoginPageComponent.kt
  13. 19 4
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/page/impl/VipPageComponent.kt
  14. 4 4
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/enums/Mode.kt
  15. 52 0
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/enums/Tab.kt
  16. 2 2
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/model/ModeItem.kt
  17. 109 10
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/mvvm/viewmodel/KeyboardViewModel.kt
  18. 8 8
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/ui/popup/ModeSwitchPopupWindow.kt
  19. 1 1
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/ui/popup/item/ModeListItemViewBinder.kt
  20. 7 0
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/BridgeManager.kt
  21. 11 0
      plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/IBridgeApi.kt
  22. 6 6
      plugins/keyboard_android/android/src/main/res/layout/keyboard_layout.xml
  23. 3 2
      plugins/keyboard_android/android/src/main/res/layout/quick_switch_component.xml
  24. 4 0
      plugins/keyboard_android/android/src/main/res/values/string.xml

+ 5 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/base/BaseUIComponent.kt

@@ -43,6 +43,11 @@ abstract class BaseUIComponent<T : IUIComponent> @JvmOverloads constructor(
      */
     abstract fun bindView(view: View)
 
+    override fun isNeedLogin(): Boolean {
+        // 默认都不需要登录,就能打开
+        return false
+    }
+
     /**
      * 返回组件的接口
      */

+ 11 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/base/IBusinessComponent.kt

@@ -0,0 +1,11 @@
+package com.atmob.keyboard_android.component.base
+
+/**
+ * 业务组件,这里定义一些业务方法
+ */
+interface IBusinessComponent {
+    /**
+     * 打开该组件,是否需要登录才能打开
+     */
+    fun isNeedLogin(): Boolean
+}

+ 1 - 1
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/base/IUIComponent.kt

@@ -5,7 +5,7 @@ import android.view.ViewGroup
 /**
  * UI组件接口,用于定义基础功能API
  */
-interface IUIComponent {
+interface IUIComponent : IBusinessComponent {
     /**
      * 将组件转换为View实例
      */

+ 21 - 3
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/base/RouteComponent.kt

@@ -22,15 +22,33 @@ abstract class RouteComponent @JvmOverloads constructor(
     }
 
     override fun show(onStart: (() -> Unit)?, onFinish: (() -> Unit)?) {
-        mComponentAnimator.show(onStart, onFinish)
+        mComponentAnimator.show(onStart, onFinish = {
+            onComponentShow()
+            onFinish?.invoke()
+        })
     }
 
     override fun hide(onStart: (() -> Unit)?, onFinish: (() -> Unit)?) {
-        mComponentAnimator.hide(onStart, onFinish)
+        mComponentAnimator.hide(onStart, onFinish = {
+            onComponentHide()
+            onFinish?.invoke()
+        })
     }
 
     /**
      * 获取组件的动画执行器
      */
-    abstract fun getComponentAnimator(): Class<*>
+    protected abstract fun getComponentAnimator(): Class<*>
+
+    /**
+     * 组件打开时回调
+     */
+    protected fun onComponentShow() {
+    }
+
+    /**
+     * 组件关闭时回调
+     */
+    protected fun onComponentHide() {
+    }
 }

+ 0 - 10
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/IAiKeyboardComponent.kt

@@ -1,19 +1,9 @@
 package com.atmob.keyboard_android.component.child
 
 import com.atmob.keyboard_android.component.base.IUIComponent
-import com.atmob.keyboard_android.enums.Mode
 
 /**
  * Ai键盘组件接口
  */
 interface IAiKeyboardComponent : IUIComponent {
-    /**
-     * 更新模式,刷新布局
-     */
-    fun updateKeyboardMode(mode: Mode)
-
-    /**
-     * 重置布局
-     */
-    fun reset()
 }

+ 20 - 8
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/AiChatComponent.kt

@@ -7,15 +7,14 @@ import android.view.View
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.atmob.keyboard_android.R
-import com.atmob.keyboard_android.component.ComponentMediator
 import com.atmob.keyboard_android.component.base.BaseUIComponent
 import com.atmob.keyboard_android.component.child.IAiChatComponent
-import com.atmob.keyboard_android.component.child.IAiKeyboardComponent
 import com.atmob.keyboard_android.component.item.AiChatViewBinder
 import com.atmob.keyboard_android.component.item.EmptyPlaceholderViewBinder
 import com.atmob.keyboard_android.ext.click
 import com.atmob.keyboard_android.model.AiChatModel
 import com.atmob.keyboard_android.model.EmptyPlaceholderModel
+import com.atmob.keyboard_android.util.KeyboardHolder
 import com.atmob.keyboard_android.util.recyclerview.LinearDivider
 import com.blankj.utilcode.util.ConvertUtils
 import com.blankj.utilcode.util.ToastUtils
@@ -49,12 +48,8 @@ class AiChatComponent @JvmOverloads constructor(
     override fun bindView(view: View) {
         vBackBtn.click {
             // 关闭面板
-            hide(onFinish = {
-                // 重新显示键盘列表
-                val aiKeyboardComponent =
-                    ComponentMediator.findComponent(IAiKeyboardComponent::class.java)
-                aiKeyboardComponent?.reset()
-            })
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateAiChatPageShowing(false)
         }
         vReGenerateBtn.click {
             // 重新生成
@@ -88,6 +83,7 @@ class AiChatComponent @JvmOverloads constructor(
             addItemDecoration(LinearDivider(ConvertUtils.dp2px(8f), orientation, true))
         }
 
+        setupViewModel()
         setData()
     }
 
@@ -96,6 +92,22 @@ class AiChatComponent @JvmOverloads constructor(
     }
 
     /**
+     * 配置ViewModel
+     */
+    private fun setupViewModel() {
+        KeyboardHolder.getKeyboardService()?.run {
+            // 监听Ai生成页,显示或隐藏
+            getKeyboardViewModel().aiChatPageShowing.observe(getLifecycleOwner()) { isShowing ->
+                if (isShowing) {
+                    show()
+                } else {
+                    hide()
+                }
+            }
+        }
+    }
+
+    /**
      * 设置数据
      */
     @SuppressLint("NotifyDataSetChanged")

+ 60 - 49
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/AiKeyboardComponent.kt

@@ -7,16 +7,16 @@ import android.view.View
 import androidx.recyclerview.widget.GridLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.atmob.keyboard_android.R
-import com.atmob.keyboard_android.component.ComponentMediator
 import com.atmob.keyboard_android.component.base.BaseUIComponent
-import com.atmob.keyboard_android.component.child.IAiChatComponent
 import com.atmob.keyboard_android.component.child.IAiKeyboardComponent
 import com.atmob.keyboard_android.component.item.AiKeyboardKeyViewBinder
-import com.atmob.keyboard_android.enums.Mode
+import com.atmob.keyboard_android.enums.HelpMode
+import com.atmob.keyboard_android.enums.Tab
 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.util.KeyboardHolder
 import com.atmob.keyboard_android.util.recyclerview.GridDivider
 import com.atmob.keyboard_android.widget.indicator.TabPagerTitleView
 import com.blankj.utilcode.util.ConvertUtils
@@ -50,12 +50,7 @@ class AiKeyboardComponent @JvmOverloads constructor(
     /**
      * Tab列表
      */
-    private lateinit var mTabList: List<String>
-
-    /**
-     * 当前选中的Tab的索引
-     */
-    private var mCurrentTabIndex = 0
+    private lateinit var mTabList: List<Tab>
 
     override fun onInflateViewId(): Int {
         return R.layout.component_ai_keyboard
@@ -75,6 +70,7 @@ class AiKeyboardComponent @JvmOverloads constructor(
         setupTabBar()
         setupKeyList()
         setupActionBtn()
+        setupViewModel()
         setData()
     }
 
@@ -86,12 +82,7 @@ class AiKeyboardComponent @JvmOverloads constructor(
      * 配置Tab栏
      */
     private fun setupTabBar() {
-        mTabList = listOf(
-            "发起聊天",
-            "邀约话术",
-            "如何告白",
-            "关系升温"
-        )
+        mTabList = Tab.getAll()
 
         // 配置指示器
         vMagicIndicator.setNavigator(CommonNavigator(context).apply {
@@ -117,7 +108,7 @@ class AiKeyboardComponent @JvmOverloads constructor(
                         }
                     }
                     // Tab文字
-                    titleView.setText(mTabList[index])
+                    titleView.setText(mTabList[index].tabName)
                     // Tab未选中时的字体颜色
                     titleView.setTextColor(context.resources.getColor(R.color.text_color_secondary))
                     // Tab选中时的字体颜色
@@ -130,15 +121,16 @@ class AiKeyboardComponent @JvmOverloads constructor(
                     // 点击Tab,切换页面
                     titleView.setOnClickListener(object : OnClickListener {
                         override fun onClick(v: View?) {
-                            if (mCurrentTabIndex == index) {
+                            // Tab没有改变,不处理
+                            val currentTab = KeyboardHolder.getKeyboardService()
+                                ?.getKeyboardViewModel()?.tab?.value
+                            if (Tab.getTabByIndex(index) == currentTab) {
                                 return
                             }
-                            // 根据Tab类型,刷新内容
-                            val tab = mTabList[index]
-                            refreshContent(tab)
-                            // 切换Tab
-                            mCurrentTabIndex = index
-                            vMagicIndicator.onPageSelected(index)
+                            // 更新Tab
+                            val newTab = mTabList[index]
+                            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                                ?.updateTab(newTab)
                         }
                     })
                     return titleView
@@ -172,11 +164,8 @@ class AiKeyboardComponent @JvmOverloads constructor(
             mKeyListAdapter = MultiTypeAdapter(mKeyListItems).apply {
                 register(AiKeyboardKeyModel::class.java, AiKeyboardKeyViewBinder {
                     // 点击键盘按键,打开AI生成内容面板
-                    val aiChatComponent =
-                        ComponentMediator.findComponent(IAiChatComponent::class.java)
-                    aiChatComponent?.show()
-                    // 隐藏键盘列表
-                    vKeyList.setGone()
+                    KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                        ?.updateAiChatPageShowing(true)
                 })
             }
             layoutManager = GridLayoutManager(context, spanCount)
@@ -199,10 +188,48 @@ class AiKeyboardComponent @JvmOverloads constructor(
     }
 
     /**
+     * 配置ViewModel
+     */
+    private fun setupViewModel() {
+        KeyboardHolder.getKeyboardService()?.run {
+            // 监听模式更新,切换键盘
+            getKeyboardViewModel().helpMode.observe(getLifecycleOwner()) { newMode ->
+                updateKeyboardByHelpMode(newMode)
+            }
+            // 监听Tab切换,更新键盘列表
+            getKeyboardViewModel().tab.observe(getLifecycleOwner()) { newTab ->
+                // 切换Tab
+                vMagicIndicator.onPageSelected(newTab.getIndex())
+                // 关闭Ai内容生成面板
+                getKeyboardViewModel().updateAiChatPageShowing(false)
+                // 根据Tab,重新加载数据
+                loadKeyListByTab(newTab)
+            }
+            // 监听Ai内容生成页,是否显示
+            getKeyboardViewModel().aiChatPageShowing.observe(getLifecycleOwner()) { isShowing ->
+                // 显示Ai内容生成页,隐藏键盘列表
+                if (isShowing) {
+                    vKeyList.setGone()
+                } else {
+                    // Ai生成页关闭,则显示键盘列表
+                    vKeyList.setVisible()
+                }
+            }
+        }
+    }
+
+    /**
      * 填充数据
      */
     @SuppressLint("NotifyDataSetChanged")
     private fun setData() {
+    }
+
+    /**
+     * 根据Tab类型,加载键盘列表
+     */
+    @SuppressLint("NotifyDataSetChanged")
+    private fun loadKeyListByTab(tab: Tab) {
         val newList = mutableListOf<AiKeyboardKeyModel>().apply {
             add(AiKeyboardKeyModel("暧昧推拉"))
             add(AiKeyboardKeyModel("欲拒还迎"))
@@ -221,17 +248,11 @@ class AiKeyboardComponent @JvmOverloads constructor(
     }
 
     /**
-     * 刷新内容
-     *
-     * @param tab 选择了哪个Tab
+     * 根据帮助模式,切换键盘内容
      */
-    private fun refreshContent(tab: String) {
-        setData()
-    }
-
-    override fun updateKeyboardMode(mode: Mode) {
+    private fun updateKeyboardByHelpMode(helpMode: HelpMode) {
         // 根据不同的模式,切换不同的键盘
-        if (Mode.OPEN_REMARKS == mode) {
+        if (HelpMode.OPEN_REMARKS == helpMode) {
             // 开场白,显示Tab布局,隐藏粘贴栏
             vTabBarLayout.setVisible()
             vPasteBarLayout.setGone()
@@ -241,17 +262,7 @@ class AiKeyboardComponent @JvmOverloads constructor(
             vPasteBarLayout.setVisible()
         }
         // 隐藏AI生成内容面板
-        val aiChatComponent =
-            ComponentMediator.findComponent(IAiChatComponent::class.java)
-        aiChatComponent?.hide()
-        // 显示键盘列表
-        vKeyList.setVisible()
-    }
-
-    override fun reset() {
-        vKeyList.setVisible()
-        val aiChatComponent =
-            ComponentMediator.findComponent(IAiChatComponent::class.java)
-        aiChatComponent?.hide()
+        KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+            ?.updateAiChatPageShowing(false)
     }
 }

+ 30 - 5
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/KeyboardSelectComponent.kt

@@ -15,9 +15,9 @@ import com.atmob.keyboard_android.constant.Constants
 import com.atmob.keyboard_android.ext.click
 import com.atmob.keyboard_android.model.EmptyPlaceholderModel
 import com.atmob.keyboard_android.model.KeyboardSelectModel
+import com.atmob.keyboard_android.util.KeyboardHolder
 import com.atmob.keyboard_android.util.recyclerview.GridDivider
 import com.blankj.utilcode.util.ConvertUtils
-import com.blankj.utilcode.util.ToastUtils
 import me.drakeet.multitype.Items
 import me.drakeet.multitype.MultiTypeAdapter
 
@@ -49,12 +49,21 @@ class KeyboardSelectComponent @JvmOverloads constructor(
     override fun bindView(view: View) {
         vBackBtn.click {
             // 关闭选择页
-            hide()
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateKeyboardSelectPageShowing(false)
         }
         vSaveBtn.click {
-            // 保存设置
-            ToastUtils.showShort("保存设置")
-            hide()
+            val selectRole =
+                mListItems.filterIsInstance<KeyboardSelectModel>().find { it.isSelected }
+            if (selectRole == null) {
+                return@click
+            }
+            // 保存,用户选择的人设
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateRoleType(selectRole.name)
+            // 关闭选择器
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateKeyboardSelectPageShowing(false)
         }
 
         // 配置列表
@@ -88,6 +97,7 @@ class KeyboardSelectComponent @JvmOverloads constructor(
             )
         }
 
+        setupViewModel()
         setData()
     }
 
@@ -95,6 +105,21 @@ class KeyboardSelectComponent @JvmOverloads constructor(
         return IKeyboardSelectComponent::class.java
     }
 
+    /**
+     * 设置ViewModel
+     */
+    private fun setupViewModel() {
+        KeyboardHolder.getKeyboardService()?.run {
+            getKeyboardViewModel().keyboardSelectPageShowing.observe(getLifecycleOwner()) { isShowing ->
+                if (isShowing) {
+                    show()
+                } else {
+                    hide()
+                }
+            }
+        }
+    }
+
     @SuppressLint("NotifyDataSetChanged")
     private fun setData() {
         // TODO: 加载键盘列表

+ 29 - 14
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/QuickSwitchComponent.kt

@@ -5,14 +5,12 @@ import android.util.AttributeSet
 import android.view.View
 import android.widget.TextView
 import com.atmob.keyboard_android.R
-import com.atmob.keyboard_android.component.ComponentMediator
 import com.atmob.keyboard_android.component.base.BaseUIComponent
-import com.atmob.keyboard_android.component.child.IAiKeyboardComponent
-import com.atmob.keyboard_android.component.child.IKeyboardSelectComponent
 import com.atmob.keyboard_android.component.child.IQuickSwitchComponent
-import com.atmob.keyboard_android.enums.Mode
+import com.atmob.keyboard_android.enums.HelpMode
 import com.atmob.keyboard_android.ext.click
 import com.atmob.keyboard_android.ui.popup.ModeSwitchPopupWindow
+import com.atmob.keyboard_android.util.KeyboardHolder
 
 /**
  * 快速切换组件
@@ -23,6 +21,7 @@ class QuickSwitchComponent @JvmOverloads constructor(
     private lateinit var vModeSwitchLayout: View
     private lateinit var vModeText: TextView
     private lateinit var vKeyboardSelectLayout: View
+    private lateinit var vRoleType: TextView
 
     /**
      * 模式切换的弹窗
@@ -37,6 +36,7 @@ class QuickSwitchComponent @JvmOverloads constructor(
         vModeSwitchLayout = view.findViewById(R.id.mode_switch_layout)
         vModeText = view.findViewById(R.id.mode_text)
         vKeyboardSelectLayout = view.findViewById(R.id.keyboard_select_layout)
+        vRoleType = view.findViewById(R.id.role_type)
     }
 
     override fun bindView(view: View) {
@@ -45,23 +45,38 @@ class QuickSwitchComponent @JvmOverloads constructor(
             if (mModeSwitchPopupWindow.isShowing()) {
                 mModeSwitchPopupWindow.dismiss()
             } else {
-                mModeSwitchPopupWindow.show(vModeSwitchLayout, Mode.HELP_CHAT, object :
+                mModeSwitchPopupWindow.show(vModeSwitchLayout, HelpMode.HELP_CHAT, object :
                     ModeSwitchPopupWindow.OnModeSelectedListener {
-                    override fun onModeSelected(mode: Mode) {
-                        // 切换模式文字
-                        vModeText.text = mode.modeName
-                        // 切换键盘布局
-                        val aiKeyboardComponent = ComponentMediator.findComponent(IAiKeyboardComponent::class.java)
-                        aiKeyboardComponent?.updateKeyboardMode(mode)
+                    override fun onModeSelected(newMode: HelpMode) {
+                        // 切换模式
+                        KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                            ?.updateHelpMode(newMode)
                     }
                 })
             }
         }
         vKeyboardSelectLayout.click {
             // 显示键盘选择页
-            val keyboardSelectComponent =
-                ComponentMediator.findComponent(IKeyboardSelectComponent::class.java)
-            keyboardSelectComponent?.show()
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateKeyboardSelectPageShowing(true)
+        }
+
+        setupViewModel()
+    }
+
+    /**
+     * 配置ViewModel
+     */
+    private fun setupViewModel() {
+        KeyboardHolder.getKeyboardService()?.run {
+            // 监听帮助模式切换
+            getKeyboardViewModel().helpMode.observe(getLifecycleOwner()) { newMode ->
+                vModeText.text = newMode.modeName
+            }
+            // 监听人设切换
+            getKeyboardViewModel().roleType.observe(getLifecycleOwner()) { newRoleType ->
+                vRoleType.text = newRoleType
+            }
         }
     }
 

+ 27 - 4
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/SettingComponent.kt

@@ -34,10 +34,9 @@ class SettingComponent @JvmOverloads constructor(
 
     override fun bindView(view: View) {
         vBackBtn.click {
-            hide(onStart = {
-                KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
-                    ?.updateSettingPageShowing(false)
-            })
+            // 关闭
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateSettingPageShowing(false)
         }
         vSettingCustomPersonLayout.click {
             ToastUtils.showShort("跳转 => 定制人设")
@@ -48,6 +47,30 @@ class SettingComponent @JvmOverloads constructor(
         vSettingUnlockVipLayout.click {
             ToastUtils.showShort("跳转 => 解锁会员")
         }
+
+        setupViewModel()
+    }
+
+    /**
+     * 配置ViewModel
+     */
+    private fun setupViewModel() {
+        KeyboardHolder.getKeyboardService()?.run {
+            // 监听设置页的显示和隐藏
+            getKeyboardViewModel().settingPageShowing.observe(getLifecycleOwner()) { isShowing ->
+                if (isShowing) {
+                    show()
+                } else {
+                    hide()
+                }
+            }
+            // 如果键盘选择页打开,则关闭设置页
+            getKeyboardViewModel().keyboardSelectPageShowing.observe(getLifecycleOwner()) { isShowing ->
+                if (isShowing) {
+                    getKeyboardViewModel().updateSettingPageShowing(false)
+                }
+            }
+        }
     }
 
     override fun getComponentInterfaceClazz(): Class<ISettingComponent> {

+ 11 - 15
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/child/impl/ToolBarComponent.kt

@@ -4,12 +4,10 @@ import android.content.Context
 import android.util.AttributeSet
 import android.view.View
 import com.atmob.keyboard_android.R
-import com.atmob.keyboard_android.component.ComponentMediator
 import com.atmob.keyboard_android.component.base.BaseUIComponent
-import com.atmob.keyboard_android.component.child.ISettingComponent
 import com.atmob.keyboard_android.component.child.IToolBarComponent
-import com.atmob.keyboard_android.component.page.ILoginPageComponent
 import com.atmob.keyboard_android.ext.click
+import com.atmob.keyboard_android.ext.longClick
 import com.atmob.keyboard_android.keyboard.InputMethodPickerActivity
 import com.atmob.keyboard_android.util.KeyboardHolder
 
@@ -36,25 +34,23 @@ class ToolBarComponent @JvmOverloads constructor(
     override fun bindView(view: View) {
         vIcon.click {
             // 切换到设置页
-            val settingComponent = ComponentMediator.findComponent(ISettingComponent::class.java)
-            settingComponent?.show(onStart = {
-                KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
-                    ?.updateSettingPageShowing(true)
-            })
-
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateSettingPageShowing(true)
+        }
+        vIcon.longClick {
             // TODO: hezhiao,测试显示vip页
-//            val vipPageComponent = ComponentMediator.findComponent(IVipPageComponent::class.java)
-//            vipPageComponent?.show()
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateVipPageShowing(true)
+            true
         }
         vKeyboardSwitchBtn.click {
             // 打开系统输入法选择器
             InputMethodPickerActivity.start(context)
         }
         vIntimacyLayout.click {
-            // 点击亲密度布局
-            val loginPageComponent =
-                ComponentMediator.findComponent(ILoginPageComponent::class.java)
-            loginPageComponent?.show()
+            // 点击亲密度布局,跳转去登录页
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateLoginPageShowing(true)
         }
     }
 

+ 17 - 1
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/page/impl/LoginPageComponent.kt

@@ -7,6 +7,7 @@ import com.atmob.keyboard_android.R
 import com.atmob.keyboard_android.component.base.BaseUIComponent
 import com.atmob.keyboard_android.component.page.ILoginPageComponent
 import com.atmob.keyboard_android.ext.click
+import com.atmob.keyboard_android.util.KeyboardHolder
 import com.blankj.utilcode.util.ToastUtils
 
 /**
@@ -30,12 +31,27 @@ class LoginPageComponent @JvmOverloads constructor(
     override fun bindView(view: View) {
         vBackBtn.click {
             // 关闭
-            hide()
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateLoginPageShowing(false)
         }
         vLoginBtn.click {
             // 跳转到登录页
             ToastUtils.showShort("跳转到登录页")
         }
+        setData()
+    }
+
+    private fun setData() {
+        // 监听登录页,是否显示
+        KeyboardHolder.getKeyboardService()?.run {
+            getKeyboardViewModel().loginPageShowing.observe(getLifecycleOwner()) { isShowing ->
+                if (isShowing) {
+                    show()
+                } else {
+                    hide()
+                }
+            }
+        }
     }
 
     override fun getComponentInterfaceClazz(): Class<ILoginPageComponent> {

+ 19 - 4
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/component/page/impl/VipPageComponent.kt

@@ -7,7 +7,7 @@ import com.atmob.keyboard_android.R
 import com.atmob.keyboard_android.component.base.BaseUIComponent
 import com.atmob.keyboard_android.component.page.IVipPageComponent
 import com.atmob.keyboard_android.ext.click
-import com.blankj.utilcode.util.ToastUtils
+import com.atmob.keyboard_android.util.KeyboardHolder
 
 /**
  * Vip页组件
@@ -29,11 +29,26 @@ class VipPageComponent @JvmOverloads constructor(
 
     override fun bindView(view: View) {
         vBackBtn.click {
-            hide()
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateVipPageShowing(false)
         }
         vJoinVipBtn.click {
-            ToastUtils.showShort("购买VIP")
-            hide()
+            KeyboardHolder.getKeyboardService()?.getKeyboardViewModel()
+                ?.updateVipPageShowing(false)
+        }
+
+        setData()
+    }
+
+    private fun setData() {
+        KeyboardHolder.getKeyboardService()?.run {
+            getKeyboardViewModel().vipPageShowing.observe(getLifecycleOwner()) {
+                if (it) {
+                    show()
+                } else {
+                    hide()
+                }
+            }
         }
     }
 

+ 4 - 4
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/enums/Mode.kt

@@ -4,9 +4,9 @@ import com.atmob.keyboard_android.R
 import com.atmob.keyboard_android.ext.getResString
 
 /**
- * 模式枚举
+ * 帮助模式枚举
  */
-enum class Mode(val type: Int, val modeName: String) {
+enum class HelpMode(val type: Int, val modeName: String) {
     /**
      * 帮聊
      */
@@ -26,7 +26,7 @@ enum class Mode(val type: Int, val modeName: String) {
         /**
          * 通过类型,找到枚举实例
          */
-        fun fromType(type: Int): Mode {
+        fun fromType(type: Int): HelpMode {
             return values().firstOrNull {
                 it.type == type
             } ?: HELP_CHAT
@@ -35,7 +35,7 @@ enum class Mode(val type: Int, val modeName: String) {
         /**
          * 获取所有模式
          */
-        fun getAll(): List<Mode> {
+        fun getAll(): List<HelpMode> {
             return values().toList()
         }
     }

+ 52 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/enums/Tab.kt

@@ -0,0 +1,52 @@
+package com.atmob.keyboard_android.enums
+
+import com.atmob.keyboard_android.R
+import com.atmob.keyboard_android.ext.getResString
+
+/**
+ * 开场白的Tab类型
+ */
+enum class Tab(val type: Int, val tabName: String) {
+    /**
+     * 发起聊天
+     */
+    START_CHAT(1, getResString(R.string.start_chat)),
+
+    /**
+     * 邀约话术
+     */
+    INVITATION_SCRIPT(2, getResString(R.string.invitation_script)),
+
+    /**
+     * 如何告白
+     */
+    HOW_TO_CONFESS(3, getResString(R.string.how_to_confess)),
+
+    /**
+     * 关系升温
+     */
+    PROMOTION_RELATIONSHIP(4, getResString(R.string.promotion_relationship));
+
+    /**
+     * 获取Tab的索引
+     */
+    fun getIndex(): Int {
+        return Tab.getAll().indexOf(this)
+    }
+
+    companion object {
+        /**
+         * 获取全部
+         */
+        fun getAll(): List<Tab> {
+            return values().toList()
+        }
+
+        /**
+         * 根据索引,获取对应的Tab
+         */
+        fun getTabByIndex(index: Int): Tab {
+            return getAll()[index]
+        }
+    }
+}

+ 2 - 2
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/model/ModeItem.kt

@@ -1,6 +1,6 @@
 package com.atmob.keyboard_android.model
 
-import com.atmob.keyboard_android.enums.Mode
+import com.atmob.keyboard_android.enums.HelpMode
 import java.io.Serializable
 
 /**
@@ -8,7 +8,7 @@ import java.io.Serializable
  */
 data class ModeItem(
     // 模式
-    val mode: Mode,
+    val helpMode: HelpMode,
     /**
      * 是否选中
      */

+ 109 - 10
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/mvvm/viewmodel/KeyboardViewModel.kt

@@ -3,36 +3,135 @@ package com.atmob.keyboard_android.mvvm.viewmodel
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
+import com.atmob.keyboard_android.R
+import com.atmob.keyboard_android.enums.HelpMode
+import com.atmob.keyboard_android.enums.Tab
+import com.atmob.keyboard_android.util.ContextUtil
 
 /**
  * 键盘ViewModel
  */
 class KeyboardViewModel : ViewModel() {
+    // ----------------------------------- 响应式变量 -----------------------------------
+
     /**
-     * 用户的剪切板数据
+     * 登录页,是否展示
      */
-    private val _userClipboardData = MutableLiveData("")
-
-    val userClipboardData: LiveData<String> = _userClipboardData
+    private val _loginPageShowing = MutableLiveData(false)
+    val loginPageShowing: LiveData<Boolean> = _loginPageShowing
 
     /**
-     * 设置页是否展示
+     * 设置页是否展示
      */
     private val _settingPageShowing = MutableLiveData(false)
+    val settingPageShowing: LiveData<Boolean> = _settingPageShowing
 
-    val settingPageShowing = _settingPageShowing
+    /**
+     * VIP页,是否显示
+     */
+    private val _vipPageShowing = MutableLiveData(false)
+    val vipPageShowing: LiveData<Boolean> = _vipPageShowing
 
     /**
-     * 更新用户的剪切板数据
+     * 键盘选择页(人设列表),是否显示
      */
-    fun updateUserClipboardData(newText: String) {
-        _userClipboardData.value = newText
+    private val _keyboardSelectPageShowing = MutableLiveData(false)
+    val keyboardSelectPageShowing: LiveData<Boolean> = _keyboardSelectPageShowing
+
+    /**
+     * Ai生成内容页,是否显示
+     */
+    private val _aiChatPageShowing = MutableLiveData(false)
+    val aiChatPageShowing: LiveData<Boolean> = _aiChatPageShowing
+
+    /**
+     * 帮助模式,帮聊、教你说、开场白等
+     */
+    private val _helpMode = MutableLiveData(HelpMode.HELP_CHAT)
+    val helpMode: LiveData<HelpMode> = _helpMode
+
+    /**
+     * 人设类型
+     */
+    // TODO: hezihao,这里要改成具体的实体类,要到数据对接时,定义数据结构
+    private val _roleType =
+        MutableLiveData(ContextUtil.getContext().resources.getString(R.string.common_keyboard))
+    val roleType: LiveData<String> = _roleType
+
+    /**
+     * Tab类型
+     */
+    private val _tab = MutableLiveData(Tab.START_CHAT)
+    val tab: LiveData<Tab> = _tab
+
+    /**
+     * 用户的剪切板数据
+     */
+    private val _userClipboardData = MutableLiveData("")
+    val userClipboardData: LiveData<String> = _userClipboardData
+
+    // ----------------------------------- 更新方法 -----------------------------------
+
+    /**
+     * 更新,登录页,是否显示
+     */
+    fun updateLoginPageShowing(isShowing: Boolean) {
+        _loginPageShowing.value = isShowing
     }
 
     /**
-     * 更新设置页是否显示
+     * 更新设置页是否显示
      */
     fun updateSettingPageShowing(isShowing: Boolean) {
         _settingPageShowing.value = isShowing
     }
+
+    /**
+     * 更新,键盘选择页,是否显示
+     */
+    fun updateKeyboardSelectPageShowing(isShowing: Boolean) {
+        _keyboardSelectPageShowing.value = isShowing
+    }
+
+    /**
+     * 更新,VIP页,是否显示
+     */
+    fun updateVipPageShowing(isShowing: Boolean) {
+        _vipPageShowing.value = isShowing
+    }
+
+    /**
+     * 更新,Ai生成内容页,是否显示
+     */
+    fun updateAiChatPageShowing(isShowing: Boolean) {
+        _aiChatPageShowing.value = isShowing
+    }
+
+    /**
+     * 更新帮助模式
+     */
+    fun updateHelpMode(newMode: HelpMode) {
+        _helpMode.value = newMode
+    }
+
+    /**
+     * 更新人设类型
+     */
+    fun updateRoleType(roleType: String) {
+        _roleType.value = roleType
+    }
+
+    /**
+     * 更新键盘的Tab
+     */
+    fun updateTab(tab: Tab) {
+        _tab.value = tab
+    }
+
+    /**
+     * 更新,用户的剪切板数据
+     */
+    fun updateUserClipboardData(newText: String) {
+        _userClipboardData.value = newText
+    }
 }

+ 8 - 8
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/ui/popup/ModeSwitchPopupWindow.kt

@@ -10,7 +10,7 @@ import android.widget.TextView
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.atmob.keyboard_android.R
-import com.atmob.keyboard_android.enums.Mode
+import com.atmob.keyboard_android.enums.HelpMode
 import com.atmob.keyboard_android.ext.click
 import com.atmob.keyboard_android.model.ModeItem
 import com.atmob.keyboard_android.ui.popup.item.ModeListItemViewBinder
@@ -28,17 +28,17 @@ class ModeSwitchPopupWindow() {
      * 模式切换监听器
      */
     interface OnModeSelectedListener {
-        fun onModeSelected(mode: Mode)
+        fun onModeSelected(helpMode: HelpMode)
     }
 
     /**
      * 显示弹窗
      *
      * @param anchorView 锚点View
-     * @param currentMode 当前选中的模式
+     * @param currentHelpMode 当前选中的模式
      */
     @SuppressLint("InflateParams", "NotifyDataSetChanged")
-    fun show(anchorView: View, currentMode: Mode, listener: OnModeSelectedListener) {
+    fun show(anchorView: View, currentHelpMode: HelpMode, listener: OnModeSelectedListener) {
         if (isShowing()) {
             return
         }
@@ -59,8 +59,8 @@ class ModeSwitchPopupWindow() {
             }
 
             val listItems = Items().apply {
-                addAll(Mode.getAll().mapIndexed { index, item ->
-                    ModeItem(item, selected = item.modeName == currentMode.modeName)
+                addAll(HelpMode.getAll().mapIndexed { index, item ->
+                    ModeItem(item, selected = item.modeName == currentHelpMode.modeName)
                 })
             }
 
@@ -82,9 +82,9 @@ class ModeSwitchPopupWindow() {
                         notifyDataSetChanged()
 
                         // 更新当前选择的模式
-                        currentSelectMode.text = targetItem.mode.modeName
+                        currentSelectMode.text = targetItem.helpMode.modeName
                         // 通知外部更新模式
-                        listener.onModeSelected(targetItem.mode)
+                        listener.onModeSelected(targetItem.helpMode)
 
                         // 关闭弹窗
                         dismiss()

+ 1 - 1
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/ui/popup/item/ModeListItemViewBinder.kt

@@ -35,7 +35,7 @@ class ModeListItemViewBinder(
         item: ModeItem
     ) {
         holder.vMode.apply {
-            text = item.mode.modeName
+            text = item.helpMode.modeName
             // 选中
             if (item.selected) {
                 setTypeface(typeface, Typeface.BOLD)

+ 7 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/BridgeManager.kt

@@ -0,0 +1,7 @@
+package com.atmob.keyboard_android.util.bridge
+
+/**
+ * 交互管理器,封装原生端和Flutter端的交互方法
+ */
+class BridgeManager {
+}

+ 11 - 0
plugins/keyboard_android/android/src/main/kotlin/com/atmob/keyboard_android/util/bridge/IBridgeApi.kt

@@ -0,0 +1,11 @@
+package com.atmob.keyboard_android.util.bridge
+
+/**
+ * 定义桥接交互API
+ */
+interface IBridgeApi {
+    /**
+     * 用户是否已登录
+     */
+    fun isLogin(): Boolean
+}

+ 6 - 6
plugins/keyboard_android/android/src/main/res/layout/keyboard_layout.xml

@@ -9,20 +9,20 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
-    <!-- 登录组件 -->
-    <com.atmob.keyboard_android.component.page.impl.LoginPageComponent
+    <!-- 设置组件 -->
+    <com.atmob.keyboard_android.component.child.impl.SettingComponent
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:visibility="gone" />
 
-    <!-- VIP组件 -->
-    <com.atmob.keyboard_android.component.page.impl.VipPageComponent
+    <!-- 登录组件 -->
+    <com.atmob.keyboard_android.component.page.impl.LoginPageComponent
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:visibility="gone" />
 
-    <!-- 设置组件 -->
-    <com.atmob.keyboard_android.component.child.impl.SettingComponent
+    <!-- VIP组件 -->
+    <com.atmob.keyboard_android.component.page.impl.VipPageComponent
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:visibility="gone" />

+ 3 - 2
plugins/keyboard_android/android/src/main/res/layout/quick_switch_component.xml

@@ -28,7 +28,7 @@
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_vertical"
                 android:layout_marginStart="12dp"
-                android:text="@string/mode_teach_you_say"
+                android:text="@string/mode_help_chat"
                 android:textColor="@color/text_color_primary"
                 android:textSize="12sp"
                 android:textStyle="bold" />
@@ -51,11 +51,12 @@
             android:orientation="horizontal">
 
             <TextView
+                android:id="@+id/role_type"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_vertical"
                 android:layout_marginStart="9dp"
-                android:text="小蕊"
+                android:text="@string/common_keyboard"
                 android:textColor="@color/text_color_primary"
                 android:textSize="12sp" />
 

+ 4 - 0
plugins/keyboard_android/android/src/main/res/values/string.xml

@@ -23,4 +23,8 @@
     <string name="dialog_permission_tip_content">“追爱小键盘”想从“微信”粘贴\n你允许这样做吗?</string>
     <string name="reject">不允许</string>
     <string name="allow">允许</string>
+    <string name="start_chat">发起聊天</string>
+    <string name="invitation_script">邀约话术</string>
+    <string name="how_to_confess">如何告白</string>
+    <string name="promotion_relationship">关系升温</string>
 </resources>