diff --git a/flutter/lib/desktop/pages/connection_tab_page.dart b/flutter/lib/desktop/pages/connection_tab_page.dart
index eb8614dd4..5dd4a829a 100644
--- a/flutter/lib/desktop/pages/connection_tab_page.dart
+++ b/flutter/lib/desktop/pages/connection_tab_page.dart
@@ -20,28 +20,28 @@ class ConnectionTabPage extends StatefulWidget {
   State<ConnectionTabPage> createState() => _ConnectionTabPageState(params);
 }
 
-class _ConnectionTabPageState extends State<ConnectionTabPage>
-    with TickerProviderStateMixin {
+class _ConnectionTabPageState extends State<ConnectionTabPage> {
   // refactor List<int> when using multi-tab
   // this singleton is only for test
   RxList<TabInfo> tabs = RxList<TabInfo>.empty(growable: true);
-  late Rx<TabController> tabController;
-  static final Rx<int> _selected = 0.obs;
   static final Rx<String> _fullscreenID = "".obs;
-  IconData icon = Icons.desktop_windows_sharp;
+  final IconData selectedIcon = Icons.desktop_windows_sharp;
+  final IconData unselectedIcon = Icons.desktop_windows_outlined;
 
   var connectionMap = RxList<Widget>.empty(growable: true);
 
   _ConnectionTabPageState(Map<String, dynamic> params) {
     if (params['id'] != null) {
-      tabs.add(TabInfo(label: params['id'], icon: icon));
+      tabs.add(TabInfo(
+          label: params['id'],
+          selectedIcon: selectedIcon,
+          unselectedIcon: unselectedIcon));
     }
   }
 
   @override
   void initState() {
     super.initState();
-    tabController = TabController(length: tabs.length, vsync: this).obs;
     rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
       print(
           "call ${call.method} with args ${call.arguments} from window ${fromWindowId}");
@@ -50,8 +50,12 @@ class _ConnectionTabPageState extends State<ConnectionTabPage>
         final args = jsonDecode(call.arguments);
         final id = args['id'];
         window_on_top(windowId());
-        DesktopTabBar.onAdd(this, tabController, tabs, _selected,
-            TabInfo(label: id, icon: icon));
+        DesktopTabBar.onAdd(
+            tabs,
+            TabInfo(
+                label: id,
+                selectedIcon: selectedIcon,
+                unselectedIcon: unselectedIcon));
       } else if (call.method == "onDestroy") {
         print(
             "executing onDestroy hook, closing ${tabs.map((tab) => tab.label).toList()}");
@@ -74,18 +78,16 @@ class _ConnectionTabPageState extends State<ConnectionTabPage>
           Obx(() => Visibility(
               visible: _fullscreenID.value.isEmpty,
               child: DesktopTabBar(
-                controller: tabController,
                 tabs: tabs,
                 onTabClose: onRemoveId,
-                selected: _selected,
                 dark: isDarkTheme(),
                 mainTab: false,
               ))),
           Expanded(child: Obx(() {
             WindowController.fromWindowId(windowId())
                 .setFullscreen(_fullscreenID.value.isNotEmpty);
-            return TabBarView(
-                controller: tabController.value,
+            return PageView(
+                controller: DesktopTabBar.controller.value,
                 children: tabs
                     .map((tab) => RemotePage(
                           key: ValueKey(tab.label),
@@ -103,7 +105,6 @@ class _ConnectionTabPageState extends State<ConnectionTabPage>
   }
 
   void onRemoveId(String id) {
-    DesktopTabBar.onClose(this, tabController, tabs, id);
     ffi(id).close();
     if (tabs.length == 0) {
       WindowController.fromWindowId(windowId()).close();
diff --git a/flutter/lib/desktop/pages/desktop_tab_page.dart b/flutter/lib/desktop/pages/desktop_tab_page.dart
index 65ba37e45..5cbc7aece 100644
--- a/flutter/lib/desktop/pages/desktop_tab_page.dart
+++ b/flutter/lib/desktop/pages/desktop_tab_page.dart
@@ -13,20 +13,19 @@ class DesktopTabPage extends StatefulWidget {
   State<DesktopTabPage> createState() => _DesktopTabPageState();
 }
 
-class _DesktopTabPageState extends State<DesktopTabPage>
-    with TickerProviderStateMixin {
-  late Rx<TabController> tabController;
+class _DesktopTabPageState extends State<DesktopTabPage> {
   late RxList<TabInfo> tabs;
-  static final Rx<int> _selected = 0.obs;
 
   @override
   void initState() {
     super.initState();
     tabs = RxList.from([
-      TabInfo(label: kTabLabelHomePage, icon: Icons.home_sharp, closable: false)
+      TabInfo(
+          label: kTabLabelHomePage,
+          selectedIcon: Icons.home_sharp,
+          unselectedIcon: Icons.home_outlined,
+          closable: false)
     ], growable: true);
-    tabController =
-        TabController(length: tabs.length, vsync: this, initialIndex: 0).obs;
   }
 
   @override
@@ -35,17 +34,14 @@ class _DesktopTabPageState extends State<DesktopTabPage>
       body: Column(
         children: [
           DesktopTabBar(
-            controller: tabController,
             tabs: tabs,
-            onTabClose: onTabClose,
-            selected: _selected,
             dark: isDarkTheme(),
             mainTab: true,
             onAddSetting: onAddSetting,
           ),
           Obx((() => Expanded(
-                child: TabBarView(
-                    controller: tabController.value,
+                child: PageView(
+                    controller: DesktopTabBar.controller.value,
                     children: tabs.map((tab) {
                       switch (tab.label) {
                         case kTabLabelHomePage:
@@ -62,12 +58,12 @@ class _DesktopTabPageState extends State<DesktopTabPage>
     );
   }
 
-  void onTabClose(String label) {
-    DesktopTabBar.onClose(this, tabController, tabs, label);
-  }
-
   void onAddSetting() {
-    DesktopTabBar.onAdd(this, tabController, tabs, _selected,
-        TabInfo(label: kTabLabelSettingPage, icon: Icons.build));
+    DesktopTabBar.onAdd(
+        tabs,
+        TabInfo(
+            label: kTabLabelSettingPage,
+            selectedIcon: Icons.build_sharp,
+            unselectedIcon: Icons.build_outlined));
   }
 }
diff --git a/flutter/lib/desktop/pages/file_manager_tab_page.dart b/flutter/lib/desktop/pages/file_manager_tab_page.dart
index aa8c60afc..5f12c873a 100644
--- a/flutter/lib/desktop/pages/file_manager_tab_page.dart
+++ b/flutter/lib/desktop/pages/file_manager_tab_page.dart
@@ -19,25 +19,25 @@ class FileManagerTabPage extends StatefulWidget {
   State<FileManagerTabPage> createState() => _FileManagerTabPageState(params);
 }
 
-class _FileManagerTabPageState extends State<FileManagerTabPage>
-    with TickerProviderStateMixin {
+class _FileManagerTabPageState extends State<FileManagerTabPage> {
   // refactor List<int> when using multi-tab
   // this singleton is only for test
   RxList<TabInfo> tabs = List<TabInfo>.empty(growable: true).obs;
-  late Rx<TabController> tabController;
-  static final Rx<int> _selected = 0.obs;
-  IconData icon = Icons.file_copy_sharp;
+  final IconData selectedIcon = Icons.file_copy_sharp;
+  final IconData unselectedIcon = Icons.file_copy_outlined;
 
   _FileManagerTabPageState(Map<String, dynamic> params) {
     if (params['id'] != null) {
-      tabs.add(TabInfo(label: params['id'], icon: icon));
+      tabs.add(TabInfo(
+          label: params['id'],
+          selectedIcon: selectedIcon,
+          unselectedIcon: unselectedIcon));
     }
   }
 
   @override
   void initState() {
     super.initState();
-    tabController = TabController(length: tabs.length, vsync: this).obs;
     rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
       print(
           "call ${call.method} with args ${call.arguments} from window ${fromWindowId}");
@@ -46,8 +46,12 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
         final args = jsonDecode(call.arguments);
         final id = args['id'];
         window_on_top(windowId());
-        DesktopTabBar.onAdd(this, tabController, tabs, _selected,
-            TabInfo(label: id, icon: icon));
+        DesktopTabBar.onAdd(
+            tabs,
+            TabInfo(
+                label: id,
+                selectedIcon: selectedIcon,
+                unselectedIcon: unselectedIcon));
       } else if (call.method == "onDestroy") {
         print(
             "executing onDestroy hook, closing ${tabs.map((tab) => tab.label).toList()}");
@@ -68,17 +72,15 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
       body: Column(
         children: [
           DesktopTabBar(
-            controller: tabController,
             tabs: tabs,
             onTabClose: onRemoveId,
-            selected: _selected,
             dark: isDarkTheme(),
             mainTab: false,
           ),
           Expanded(
             child: Obx(
-              () => TabBarView(
-                  controller: tabController.value,
+              () => PageView(
+                  controller: DesktopTabBar.controller.value,
                   children: tabs
                       .map((tab) => FileManagerPage(
                           key: ValueKey(tab.label),
@@ -92,8 +94,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
   }
 
   void onRemoveId(String id) {
-    DesktopTabBar.onClose(this, tabController, tabs, id);
-    ffi(id).close();
+    ffi("ft_$id").close();
     if (tabs.length == 0) {
       WindowController.fromWindowId(windowId()).close();
     }
diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart
index 4a2581705..d2acb87ad 100644
--- a/flutter/lib/desktop/widgets/tabbar_widget.dart
+++ b/flutter/lib/desktop/widgets/tabbar_widget.dart
@@ -8,21 +8,22 @@ import 'package:flutter_hbb/main.dart';
 import 'package:flutter_hbb/utils/multi_window_manager.dart';
 import 'package:get/get.dart';
 import 'package:window_manager/window_manager.dart';
+import 'package:scroll_pos/scroll_pos.dart';
 
 const double _kTabBarHeight = kDesktopRemoteTabBarHeight;
 const double _kIconSize = 18;
 const double _kDividerIndent = 10;
 const double _kAddIconSize = _kTabBarHeight - 15;
-final tabBarKey = GlobalKey();
+final _tabBarKey = GlobalKey();
 
 void closeTab(String? id) {
-  final tabBar = tabBarKey.currentWidget as TabBar?;
+  final tabBar = _tabBarKey.currentWidget as _ListView?;
   if (tabBar == null) return;
-  final tabs = tabBar.tabs as List<_Tab>;
+  final tabs = tabBar.tabs;
   if (id == null) {
-    final current = tabBar.controller?.index;
-    if (current == null) return;
-    tabs[current].onClose();
+    if (tabBar.selected.value < tabs.length) {
+      tabs[tabBar.selected.value].onClose();
+    }
   } else {
     for (final tab in tabs) {
       if (tab.label == id) {
@@ -35,33 +36,45 @@ void closeTab(String? id) {
 
 class TabInfo {
   late final String label;
-  late final IconData icon;
+  late final IconData selectedIcon;
+  late final IconData unselectedIcon;
   late final bool closable;
 
-  TabInfo({required this.label, required this.icon, this.closable = true});
+  TabInfo(
+      {required this.label,
+      required this.selectedIcon,
+      required this.unselectedIcon,
+      this.closable = true});
 }
 
 class DesktopTabBar extends StatelessWidget {
-  late final Rx<TabController> controller;
   late final RxList<TabInfo> tabs;
-  late final Function(String) onTabClose;
-  late final Rx<int> selected;
+  late final Function(String)? onTabClose;
   late final bool dark;
   late final _Theme _theme;
   late final bool mainTab;
   late final Function()? onAddSetting;
+  final ScrollPosController scrollController =
+      ScrollPosController(itemCount: 0);
+  static final Rx<PageController> controller = PageController().obs;
+  static final Rx<int> selected = 0.obs;
 
   DesktopTabBar({
     Key? key,
-    required this.controller,
     required this.tabs,
-    required this.onTabClose,
-    required this.selected,
+    this.onTabClose,
     required this.dark,
     required this.mainTab,
     this.onAddSetting,
   })  : _theme = dark ? _Theme.dark() : _Theme.light(),
-        super(key: key);
+        super(key: key) {
+    scrollController.itemCount = tabs.length;
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      debugPrint("callback");
+      scrollController.scrollToItem(selected.value,
+          center: true, animate: true);
+    });
+  }
 
   @override
   Widget build(BuildContext context) {
@@ -81,57 +94,29 @@ class DesktopTabBar extends StatelessWidget {
                 ),
                 Expanded(
                   child: GestureDetector(
-                    onPanStart: (_) {
-                      if (mainTab) {
-                        windowManager.startDragging();
-                      } else {
-                        WindowController.fromWindowId(windowId!)
-                            .startDragging();
-                      }
-                    },
-                    child: Obx(() => TabBar(
-                        key: tabBarKey,
-                        indicatorColor: _theme.indicatorColor,
-                        labelPadding: const EdgeInsets.symmetric(
-                            vertical: 0, horizontal: 0),
-                        isScrollable: true,
-                        indicatorPadding: EdgeInsets.zero,
-                        physics: BouncingScrollPhysics(),
-                        controller: controller.value,
-                        tabs: tabs.asMap().entries.map((e) {
-                          int index = e.key;
-                          String label = e.value.label;
-
-                          return _Tab(
-                            index: index,
-                            label: label,
-                            icon: e.value.icon,
-                            closable: e.value.closable,
-                            selected: selected.value,
-                            onClose: () {
-                              onTabClose(label);
-                              if (index <= selected.value) {
-                                selected.value = max(0, selected.value - 1);
-                              }
-                              controller.value.animateTo(selected.value,
-                                  duration: Duration.zero);
-                            },
-                            onSelected: () {
-                              selected.value = index;
-                              controller.value
-                                  .animateTo(index, duration: Duration.zero);
-                            },
-                            theme: _theme,
-                          );
-                        }).toList())),
-                  ),
+                      onPanStart: (_) {
+                        if (mainTab) {
+                          windowManager.startDragging();
+                        } else {
+                          WindowController.fromWindowId(windowId!)
+                              .startDragging();
+                        }
+                      },
+                      child: _ListView(
+                          key: _tabBarKey,
+                          controller: controller,
+                          scrollController: scrollController,
+                          tabInfos: tabs,
+                          selected: selected,
+                          onTabClose: onTabClose,
+                          theme: _theme)),
                 ),
                 Offstage(
                   offstage: mainTab,
                   child: _AddButton(
                     theme: _theme,
                   ).paddingOnly(left: 10),
-                )
+                ),
               ],
             ),
           ),
@@ -157,32 +142,16 @@ class DesktopTabBar extends StatelessWidget {
     );
   }
 
-  static onClose(
-    TickerProvider vsync,
-    Rx<TabController> controller,
-    RxList<TabInfo> tabs,
-    String label,
-  ) {
-    tabs.removeWhere((tab) => tab.label == label);
-    controller.value = TabController(
-        length: tabs.length,
-        vsync: vsync,
-        initialIndex: max(0, tabs.length - 1));
-  }
-
-  static onAdd(TickerProvider vsync, Rx<TabController> controller,
-      RxList<TabInfo> tabs, Rx<int> selected, TabInfo tab) {
+  static onAdd(RxList<TabInfo> tabs, TabInfo tab) {
     int index = tabs.indexWhere((e) => e.label == tab.label);
     if (index >= 0) {
-      controller.value.animateTo(index, duration: Duration.zero);
       selected.value = index;
     } else {
       tabs.add(tab);
-      controller.value = TabController(
-          length: tabs.length, vsync: vsync, initialIndex: tabs.length - 1);
-      controller.value.animateTo(tabs.length - 1, duration: Duration.zero);
       selected.value = tabs.length - 1;
+      assert(selected.value >= 0);
     }
+    controller.value.jumpToPage(selected.value);
   }
 }
 
@@ -265,10 +234,76 @@ class WindowActionPanel extends StatelessWidget {
   }
 }
 
+class _ListView extends StatelessWidget {
+  late Rx<PageController> controller;
+  final ScrollPosController scrollController;
+  final RxList<TabInfo> tabInfos;
+  final Rx<int> selected;
+  final Function(String label)? onTabClose;
+  final _Theme _theme;
+  late List<_Tab> tabs;
+
+  _ListView({
+    Key? key,
+    required this.controller,
+    required this.scrollController,
+    required this.tabInfos,
+    required this.selected,
+    required this.onTabClose,
+    required _Theme theme,
+  })  : _theme = theme,
+        super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Obx(() {
+      tabs = tabInfos.asMap().entries.map((e) {
+        int index = e.key;
+        String label = e.value.label;
+        return _Tab(
+          index: index,
+          label: label,
+          selectedIcon: e.value.selectedIcon,
+          unselectedIcon: e.value.unselectedIcon,
+          closable: e.value.closable,
+          selected: selected.value,
+          onClose: () {
+            tabInfos.removeWhere((tab) => tab.label == label);
+            onTabClose?.call(label);
+            if (index <= selected.value) {
+              selected.value = max(0, selected.value - 1);
+            }
+            assert(tabInfos.length == 0 || selected.value < tabInfos.length);
+            scrollController.itemCount = tabInfos.length;
+            if (tabInfos.length > 0) {
+              scrollController.scrollToItem(selected.value,
+                  center: true, animate: true);
+              controller.value.jumpToPage(selected.value);
+            }
+          },
+          onSelected: () {
+            selected.value = index;
+            scrollController.scrollToItem(index, center: true, animate: true);
+            controller.value.jumpToPage(index);
+          },
+          theme: _theme,
+        );
+      }).toList();
+      return ListView(
+          controller: scrollController,
+          scrollDirection: Axis.horizontal,
+          shrinkWrap: true,
+          physics: BouncingScrollPhysics(),
+          children: tabs);
+    });
+  }
+}
+
 class _Tab extends StatelessWidget {
   late final int index;
   late final String label;
-  late final IconData icon;
+  late final IconData selectedIcon;
+  late final IconData unselectedIcon;
   late final bool closable;
   late final int selected;
   late final Function() onClose;
@@ -280,7 +315,8 @@ class _Tab extends StatelessWidget {
       {Key? key,
       required this.index,
       required this.label,
-      required this.icon,
+      required this.selectedIcon,
+      required this.unselectedIcon,
       required this.closable,
       required this.selected,
       required this.onClose,
@@ -292,59 +328,74 @@ class _Tab extends StatelessWidget {
   Widget build(BuildContext context) {
     bool is_selected = index == selected;
     bool show_divider = index != selected - 1 && index != selected;
-    return Ink(
-      child: InkWell(
-        onHover: (hover) => _hover.value = hover,
-        onTap: () => onSelected(),
-        child: Row(
-          children: [
-            Tab(
-                child: Row(
-                    crossAxisAlignment: CrossAxisAlignment.center,
-                    children: [
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.center,
-                    children: [
-                      Icon(
-                        icon,
-                        size: _kIconSize,
-                        color: is_selected
-                            ? theme.selectedtabIconColor
-                            : theme.unSelectedtabIconColor,
-                      ).paddingOnly(right: 5),
-                      Text(
-                        translate(label),
-                        textAlign: TextAlign.center,
-                        style: TextStyle(
-                            color: is_selected
-                                ? theme.selectedTextColor
-                                : theme.unSelectedTextColor),
-                      ),
-                    ],
+    return Stack(
+      children: [
+        Ink(
+          child: InkWell(
+            onHover: (hover) => _hover.value = hover,
+            onTap: () => onSelected(),
+            child: Row(
+              children: [
+                Container(
+                    height: _kTabBarHeight,
+                    child: Row(
+                        crossAxisAlignment: CrossAxisAlignment.center,
+                        children: [
+                          Row(
+                            mainAxisAlignment: MainAxisAlignment.center,
+                            children: [
+                              Icon(
+                                is_selected ? selectedIcon : unselectedIcon,
+                                size: _kIconSize,
+                                color: is_selected
+                                    ? theme.selectedtabIconColor
+                                    : theme.unSelectedtabIconColor,
+                              ).paddingOnly(right: 5),
+                              Text(
+                                translate(label),
+                                textAlign: TextAlign.center,
+                                style: TextStyle(
+                                    color: is_selected
+                                        ? theme.selectedTextColor
+                                        : theme.unSelectedTextColor),
+                              ),
+                            ],
+                          ),
+                          Offstage(
+                            offstage: !closable,
+                            child: Obx((() => _CloseButton(
+                                  visiable: _hover.value,
+                                  tabSelected: is_selected,
+                                  onClose: () => onClose(),
+                                  theme: theme,
+                                ))),
+                          )
+                        ])).paddingSymmetric(horizontal: 10),
+                Offstage(
+                  offstage: !show_divider,
+                  child: VerticalDivider(
+                    width: 1,
+                    indent: _kDividerIndent,
+                    endIndent: _kDividerIndent,
+                    color: theme.dividerColor,
+                    thickness: 1,
                   ),
-                  Offstage(
-                    offstage: !closable,
-                    child: Obx((() => _CloseButton(
-                          visiable: _hover.value,
-                          tabSelected: is_selected,
-                          onClose: () => onClose(),
-                          theme: theme,
-                        ))),
-                  )
-                ])).paddingSymmetric(horizontal: 10),
-            Offstage(
-              offstage: !show_divider,
-              child: VerticalDivider(
-                width: 1,
-                indent: _kDividerIndent,
-                endIndent: _kDividerIndent,
-                color: theme.dividerColor,
-                thickness: 1,
-              ),
-            )
-          ],
+                )
+              ],
+            ),
+          ),
         ),
-      ),
+        Positioned(
+            height: 2,
+            left: 0,
+            right: 0,
+            bottom: 0,
+            child: Center(
+              child: Container(
+                  color:
+                      is_selected ? theme.indicatorColor : Colors.transparent),
+            ))
+      ],
     );
   }
 }
diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock
index 679322df3..c27406913 100644
--- a/flutter/pubspec.lock
+++ b/flutter/pubspec.lock
@@ -49,7 +49,7 @@ packages:
       name: async
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.8.2"
+    version: "2.9.0"
   back_button_interceptor:
     dependency: "direct main"
     description:
@@ -147,7 +147,7 @@ packages:
       name: characters
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.2.0"
+    version: "1.2.1"
   charcode:
     dependency: transitive
     description:
@@ -168,7 +168,7 @@ packages:
       name: clock
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.1.0"
+    version: "1.1.1"
   code_builder:
     dependency: transitive
     description:
@@ -235,15 +235,17 @@ packages:
   dash_chat_2:
     dependency: "direct main"
     description:
-      name: dash_chat_2
-      url: "https://pub.flutter-io.cn"
-    source: hosted
+      path: "."
+      ref: feat_maxWidth
+      resolved-ref: "3946ecf86d3600b54632fd80d0eb0ef0e74f2d6a"
+      url: "https://github.com/fufesou/Dash-Chat-2"
+    source: git
     version: "0.0.12"
   desktop_drop:
     dependency: "direct main"
     description:
       name: desktop_drop
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "0.3.3"
   desktop_multi_window:
@@ -324,7 +326,7 @@ packages:
       name: fake_async
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.3.0"
+    version: "1.3.1"
   ffi:
     dependency: "direct main"
     description:
@@ -607,14 +609,14 @@ packages:
       name: matcher
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.12.11"
+    version: "0.12.12"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.1.4"
+    version: "0.1.5"
   menu_base:
     dependency: transitive
     description:
@@ -628,7 +630,7 @@ packages:
       name: meta
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.7.0"
+    version: "1.8.0"
   mime:
     dependency: transitive
     description:
@@ -705,7 +707,7 @@ packages:
       name: path
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.8.1"
+    version: "1.8.2"
   path_provider:
     dependency: "direct main"
     description:
@@ -846,6 +848,13 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "0.1.2"
+  scroll_pos:
+    dependency: "direct main"
+    description:
+      name: scroll_pos
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "0.3.0"
   settings_ui:
     dependency: "direct main"
     description:
@@ -948,7 +957,7 @@ packages:
       name: source_span
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.8.2"
+    version: "1.9.0"
   sqflite:
     dependency: transitive
     description:
@@ -990,7 +999,7 @@ packages:
       name: string_scanner
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.1.0"
+    version: "1.1.1"
   synchronized:
     dependency: transitive
     description:
@@ -1004,14 +1013,14 @@ packages:
       name: term_glyph
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.2.0"
+    version: "1.2.1"
   test_api:
     dependency: transitive
     description:
       name: test_api
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.4.9"
+    version: "0.4.12"
   timing:
     dependency: transitive
     description:
@@ -1029,10 +1038,12 @@ packages:
   tray_manager:
     dependency: "direct main"
     description:
-      name: tray_manager
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.1.7"
+      path: "."
+      ref: "3aa37c86e47ea748e7b5507cbe59f2c54ebdb23a"
+      resolved-ref: "3aa37c86e47ea748e7b5507cbe59f2c54ebdb23a"
+      url: "https://github.com/Kingtous/rustdesk_tray_manager"
+    source: git
+    version: "0.1.8"
   tuple:
     dependency: "direct main"
     description:
diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml
index f25d5e341..f616e887a 100644
--- a/flutter/pubspec.yaml
+++ b/flutter/pubspec.yaml
@@ -76,6 +76,7 @@ dependencies:
     visibility_detector: ^0.3.3
     contextmenu: ^3.0.0
     desktop_drop: ^0.3.3
+    scroll_pos: ^0.3.0
 
 dev_dependencies:
     flutter_launcher_icons: ^0.9.1