LinXunFeng / flutter_chat_packages

A collection of useful packages about chat.
https://www.fullstackaction.com/
55 stars 7 forks source link

feat(chat_bottom_container): add state persistence and recovery to ch… #10

Open pye52 opened 2 months ago

pye52 commented 2 months ago

在部分场景下用户可能希望打开一个Dialog或者BottomSheet进行输入,同时不会影响消息页面的ChatPanel区域

LinXunFeng commented 2 months ago

感谢你的 PR,不过我看你的调整,应该可以通过如下代码即可实现一样的效果

_buildFloatingBtn(
  icon: Icons.keyboard_arrow_up_sharp,
  onPressed: () async {
    // if (_keepPanel) {
    //   controller?.keepChatPanel();
    // }
    final panelType = controller!.currentPanelType;
    final data = controller!.data;

    await showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      builder: (context) {
        return const FractionallySizedBox(
          heightFactor: 0.8,
          child: ChatPage(),
        );
      },
    );

    controller?.updatePanelType(
      panelType,
      data: data,
      forceHandleFocus: data == PanelType.emoji
          ? ChatBottomHandleFocus.requestFocus
          : ChatBottomHandleFocus.none,
    );
    // if (_keepPanel) {
    //   controller?.restoreChatPanel();
    // }
  },
),

不知道我有没有理解错?

pye52 commented 2 months ago

嗯嗯,restoreChatPanel实际上就是做了这层封装。 主要是keepChatPanel提供了对isIgnoreFocusListener这个值的开关。 在setup中会对传入的focusnode添加一个监听

inputFocusNode.addListener(() {
    if (isIgnoreFocusListener) return;
    if (inputFocusNode.hasFocus) {
      updatePanelType(ChatBottomPanelType.keyboard);
    } else {
      updatePanelType(ChatBottomPanelType.none);
    }
  });

如果isIgnoreFocusListener没有设置为true,打开浮窗或者BottomSheet,会导致传入的focusNode失去焦点,onPanelTypeChange会被设置为ChatBottomPanelType.none。弹窗消失时,再重新恢复为对应的ChatBottomPanelType,导致对应组件的重建。

组件的重建会带来一些不必要的麻烦,例如底栏的实现可能是PageView或者TabView,这个时候原来的标签状态和滚动状态就不太好恢复了。而且用户在观感上,消息列表会出现两次滚动(弹窗弹出时,软键盘区收起导致列表向下滚动,恢复PanelType时列表又向上滚动)。

这里封装restoreChatPanel是希望提供成对的方法方便理解。或者看看是否有更好的实现方式。