diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart
index eac7fbf9b..4c298d917 100644
--- a/flutter/lib/common.dart
+++ b/flutter/lib/common.dart
@@ -215,18 +215,15 @@ class MyTheme {
   }
 
   static void changeDarkMode(ThemeMode mode) {
-    final preference = getThemeModePreference();
-    if (preference != mode) {
+    Get.changeThemeMode(mode);
+    if (desktopType == DesktopType.main) {
       if (mode == ThemeMode.system) {
         bind.mainSetLocalOption(key: kCommConfKeyTheme, value: '');
       } else {
         bind.mainSetLocalOption(
             key: kCommConfKeyTheme, value: mode.toShortString());
       }
-      Get.changeThemeMode(mode);
-      if (desktopType == DesktopType.main) {
-        bind.mainChangeTheme(dark: currentThemeMode().toShortString());
-      }
+      bind.mainChangeTheme(dark: currentThemeMode().toShortString());
     }
   }
 
diff --git a/flutter/lib/common/widgets/address_book.dart b/flutter/lib/common/widgets/address_book.dart
index c96dc115a..5b3527fa0 100644
--- a/flutter/lib/common/widgets/address_book.dart
+++ b/flutter/lib/common/widgets/address_book.dart
@@ -90,7 +90,7 @@ class _AddressBookState extends State<AddressBook> {
         Text(translate(error)),
         TextButton(
             onPressed: () {
-              setState(() {});
+              gFFI.abModel.pullAb();
             },
             child: Text(translate("Retry")))
       ],
diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart
index 523230810..01e3939ee 100644
--- a/flutter/lib/common/widgets/peer_tab_page.dart
+++ b/flutter/lib/common/widgets/peer_tab_page.dart
@@ -1,64 +1,107 @@
+import 'dart:convert';
+import 'dart:ui' as ui;
+
+import 'package:bot_toast/bot_toast.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_hbb/common/widgets/address_book.dart';
 import 'package:flutter_hbb/common/widgets/peers_view.dart';
 import 'package:flutter_hbb/common/widgets/peer_card.dart';
 import 'package:flutter_hbb/consts.dart';
+import 'package:flutter_hbb/desktop/widgets/popup_menu.dart';
+import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
+import 'package:flutter_hbb/desktop/widgets/material_mod_popup_menu.dart'
+    as mod_menu;
 import 'package:get/get.dart';
 
 import '../../common.dart';
 import '../../models/platform_model.dart';
 
 class PeerTabPage extends StatefulWidget {
-  final List<String> tabs;
-  final List<Widget> children;
-  const PeerTabPage({required this.tabs, required this.children, Key? key})
-      : super(key: key);
+  const PeerTabPage({Key? key}) : super(key: key);
   @override
   State<PeerTabPage> createState() => _PeerTabPageState();
 }
 
+class _TabEntry {
+  final String name;
+  final Widget widget;
+  final Function() load;
+  _TabEntry(this.name, this.widget, this.load);
+}
+
 class _PeerTabPageState extends State<PeerTabPage>
     with SingleTickerProviderStateMixin {
-  final RxInt _tabIndex = 0.obs;
+  late final RxInt tabHiddenFlag;
+  late final RxString currentTab;
+  late final RxList<String> visibleOrderedTabs;
+  final List<_TabEntry> entries = [
+    _TabEntry(
+        'Recent Sessions',
+        RecentPeersView(
+          menuPadding: kDesktopMenuPadding,
+        ),
+        bind.mainLoadRecentPeers),
+    _TabEntry(
+        'Favorites',
+        FavoritePeersView(
+          menuPadding: kDesktopMenuPadding,
+        ),
+        bind.mainLoadFavPeers),
+    _TabEntry(
+        'Discovered',
+        DiscoveredPeersView(
+          menuPadding: kDesktopMenuPadding,
+        ),
+        bind.mainDiscover),
+    _TabEntry(
+        'Address Book',
+        const AddressBook(
+          menuPadding: kDesktopMenuPadding,
+        ),
+        () => {}),
+  ];
 
   @override
   void initState() {
-    setPeer();
-    super.initState();
-  }
-
-  setPeer() {
-    final index = bind.getLocalFlutterConfig(k: 'peer-tab-index');
-    if (index != '') {
-      _tabIndex.value = int.parse(index);
+    tabHiddenFlag = (int.tryParse(
+                bind.getLocalFlutterConfig(k: 'hidden-peer-card'),
+                radix: 2) ??
+            0)
+        .obs;
+    currentTab = bind.getLocalFlutterConfig(k: 'current-peer-tab').obs;
+    visibleOrderedTabs = entries
+        .where((e) => !isTabHidden(e.name))
+        .map((e) => e.name)
+        .toList()
+        .obs;
+    try {
+      final json = jsonDecode(bind.getLocalFlutterConfig(k: 'peer-tab-order'));
+      if (json is List) {
+        final List<String> list = json.map((e) => e.toString()).toList();
+        if (list.length == visibleOrderedTabs.length &&
+            visibleOrderedTabs.every((e) => list.contains(e))) {
+          visibleOrderedTabs.value = list;
+        }
+      }
+    } catch (e) {
+      debugPrint('$e');
     }
 
+    adjustTab();
+
     final uiType = bind.getLocalFlutterConfig(k: 'peer-card-ui-type');
     if (uiType != '') {
       peerCardUiType.value = int.parse(uiType) == PeerUiType.list.index
           ? PeerUiType.list
           : PeerUiType.grid;
     }
+    super.initState();
   }
 
-  // hard code for now
-  Future<void> _handleTabSelection(int index) async {
-    _tabIndex.value = index;
-    await bind.setLocalFlutterConfig(k: 'peer-tab-index', v: index.toString());
-    switch (index) {
-      case 0:
-        bind.mainLoadRecentPeers();
-        break;
-      case 1:
-        bind.mainLoadFavPeers();
-        break;
-      case 2:
-        bind.mainDiscover();
-        break;
-      case 3:
-
-        /// AddressBook initState will refresh ab state
-        break;
-    }
+  Future<void> handleTabSelection(String tabName) async {
+    currentTab.value = tabName;
+    await bind.setLocalFlutterConfig(k: 'current-peer-tab', v: tabName);
+    entries.firstWhereOrNull((e) => e.name == tabName)?.load();
   }
 
   @override
@@ -80,8 +123,9 @@ class _PeerTabPageState extends State<PeerTabPage>
               child: Row(
                 crossAxisAlignment: CrossAxisAlignment.center,
                 children: [
-                  Expanded(child: _createSwitchBar(context)),
-                  const SizedBox(width: 10),
+                  Expanded(
+                      child: visibleContextMenuListener(
+                          _createSwitchBar(context))),
                   const PeerSearchBar(),
                   Offstage(
                       offstage: !isDesktop,
@@ -97,16 +141,34 @@ class _PeerTabPageState extends State<PeerTabPage>
 
   Widget _createSwitchBar(BuildContext context) {
     final textColor = Theme.of(context).textTheme.titleLarge?.color;
-    return ListView(
-        scrollDirection: Axis.horizontal,
-        shrinkWrap: true,
-        controller: ScrollController(),
-        children: super.widget.tabs.asMap().entries.map((t) {
-          return Obx(() => InkWell(
+    return Obx(() {
+      int indexCounter = -1;
+      return ReorderableListView(
+          buildDefaultDragHandles: false,
+          onReorder: (oldIndex, newIndex) {
+            var list = visibleOrderedTabs.toList();
+            if (oldIndex < newIndex) {
+              newIndex -= 1;
+            }
+            final String item = list.removeAt(oldIndex);
+            list.insert(newIndex, item);
+            bind.setLocalFlutterConfig(
+                k: 'peer-tab-order', v: jsonEncode(list));
+            visibleOrderedTabs.value = list;
+          },
+          scrollDirection: Axis.horizontal,
+          shrinkWrap: true,
+          scrollController: ScrollController(),
+          children: visibleOrderedTabs.map((t) {
+            indexCounter++;
+            return ReorderableDragStartListener(
+              key: ValueKey(t),
+              index: indexCounter,
+              child: InkWell(
                 child: Container(
                     padding: const EdgeInsets.symmetric(horizontal: 8),
                     decoration: BoxDecoration(
-                      color: _tabIndex.value == t.key
+                      color: currentTab.value == t
                           ? Theme.of(context).backgroundColor
                           : null,
                       borderRadius: BorderRadius.circular(isDesktop ? 2 : 6),
@@ -114,27 +176,30 @@ class _PeerTabPageState extends State<PeerTabPage>
                     child: Align(
                       alignment: Alignment.center,
                       child: Text(
-                        t.value,
+                        translate(t),
                         textAlign: TextAlign.center,
                         style: TextStyle(
                             height: 1,
                             fontSize: 14,
-                            color:
-                                _tabIndex.value == t.key ? textColor : textColor
-                                  ?..withOpacity(0.5)),
+                            color: currentTab.value == t ? textColor : textColor
+                              ?..withOpacity(0.5)),
                       ),
                     )),
-                onTap: () async => await _handleTabSelection(t.key),
-              ));
-        }).toList());
+                onTap: () async => await handleTabSelection(t),
+              ),
+            );
+          }).toList());
+    });
   }
 
   Widget _createPeersView() {
     final verticalMargin = isDesktop ? 12.0 : 6.0;
     return Expanded(
-      child: Obx(() => widget
-              .children[_tabIndex.value]) //: (to) => _tabIndex.value = to)
-          .marginSymmetric(vertical: verticalMargin),
+      child: Obx(() =>
+          entries.firstWhereOrNull((e) => e.name == currentTab.value)?.widget ??
+          visibleContextMenuListener(Center(
+            child: Text(translate('Right click to select tabs')),
+          ))).marginSymmetric(vertical: verticalMargin),
     );
   }
 
@@ -167,6 +232,87 @@ class _PeerTabPageState extends State<PeerTabPage>
           .toList(),
     );
   }
+
+  bool isTabHidden(String name) {
+    int index = entries.indexWhere((e) => e.name == name);
+    if (index >= 0) {
+      return tabHiddenFlag & (1 << index) != 0;
+    }
+    assert(false);
+    return false;
+  }
+
+  adjustTab() {
+    if (visibleOrderedTabs.isNotEmpty) {
+      if (!visibleOrderedTabs.contains(currentTab.value)) {
+        handleTabSelection(visibleOrderedTabs[0]);
+      }
+    } else {
+      currentTab.value = '';
+    }
+  }
+
+  Widget visibleContextMenuListener(Widget child) {
+    return Listener(
+        onPointerDown: (e) {
+          if (e.kind != ui.PointerDeviceKind.mouse) {
+            return;
+          }
+          if (e.buttons == 2) {
+            showRightMenu(
+              (CancelFunc cancelFunc) {
+                return visibleContextMenu(cancelFunc);
+              },
+              target: e.position,
+            );
+          }
+        },
+        child: child);
+  }
+
+  Widget visibleContextMenu(CancelFunc cancelFunc) {
+    final List<MenuEntryBase> menu = entries.asMap().entries.map((e) {
+      int bitMask = 1 << e.key;
+      return MenuEntrySwitch(
+          switchType: SwitchType.scheckbox,
+          text: translate(e.value.name),
+          getter: () async {
+            return tabHiddenFlag.value & bitMask == 0;
+          },
+          setter: (show) async {
+            if (show) {
+              tabHiddenFlag.value &= ~bitMask;
+            } else {
+              tabHiddenFlag.value |= bitMask;
+            }
+            await bind.setLocalFlutterConfig(
+                k: 'hidden-peer-card', v: tabHiddenFlag.value.toRadixString(2));
+            visibleOrderedTabs.removeWhere((e) => isTabHidden(e));
+            visibleOrderedTabs.addAll(entries
+                .where((e) =>
+                    !visibleOrderedTabs.contains(e.name) &&
+                    !isTabHidden(e.name))
+                .map((e) => e.name)
+                .toList());
+            await bind.setLocalFlutterConfig(
+                k: 'peer-tab-order', v: jsonEncode(visibleOrderedTabs));
+            cancelFunc();
+            adjustTab();
+          });
+    }).toList();
+    return mod_menu.PopupMenu(
+      items: menu
+          .map((entry) => entry.build(
+              context,
+              const MenuConfig(
+                commonColor: MyTheme.accent,
+                height: 20.0,
+                dividerHeight: 12.0,
+              )))
+          .expand((i) => i)
+          .toList(),
+    );
+  }
 }
 
 class PeerSearchBar extends StatefulWidget {
diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart
index a830d6399..7500fe99e 100644
--- a/flutter/lib/desktop/pages/connection_page.dart
+++ b/flutter/lib/desktop/pages/connection_page.dart
@@ -113,7 +113,7 @@ class _ConnectionPageState extends State<ConnectionPage>
                     delegate: SliverChildListDelegate([
                   Row(
                     children: [
-                      _buildRemoteIDTextField(context),
+                      Flexible(child: _buildRemoteIDTextField(context)),
                     ],
                   ).marginOnly(top: 22),
                   SizedBox(height: 12),
@@ -121,28 +121,7 @@ class _ConnectionPageState extends State<ConnectionPage>
                 ])),
                 SliverFillRemaining(
                   hasScrollBody: false,
-                  child: PeerTabPage(
-                    tabs: [
-                      translate('Recent Sessions'),
-                      translate('Favorites'),
-                      translate('Discovered'),
-                      translate('Address Book')
-                    ],
-                    children: [
-                      RecentPeersView(
-                        menuPadding: kDesktopMenuPadding,
-                      ),
-                      FavoritePeersView(
-                        menuPadding: kDesktopMenuPadding,
-                      ),
-                      DiscoveredPeersView(
-                        menuPadding: kDesktopMenuPadding,
-                      ),
-                      const AddressBook(
-                        menuPadding: kDesktopMenuPadding,
-                      ),
-                    ],
-                  ).paddingOnly(right: 12.0),
+                  child: PeerTabPage().paddingOnly(right: 12.0),
                 )
               ],
             ).paddingOnly(left: 12.0),
@@ -258,9 +237,8 @@ class _ConnectionPageState extends State<ConnectionPage>
         ),
       ),
     );
-    return Center(
-        child: Container(
-            constraints: const BoxConstraints(maxWidth: 600), child: w));
+    return Container(
+        constraints: const BoxConstraints(maxWidth: 600), child: w);
   }
 
   Widget buildStatus() {
diff --git a/flutter/lib/desktop/pages/server_page.dart b/flutter/lib/desktop/pages/server_page.dart
index 6c586994b..fa367f488 100644
--- a/flutter/lib/desktop/pages/server_page.dart
+++ b/flutter/lib/desktop/pages/server_page.dart
@@ -238,7 +238,7 @@ Widget buildConnectionCard(Client client) {
             key: ValueKey(client.id),
             children: [
               _CmHeader(client: client),
-              client.isFileTransfer || client.disconnected
+              client.type_() != ClientType.remote || client.disconnected
                   ? Offstage()
                   : _PrivilegeBoard(client: client),
               Expanded(
@@ -376,7 +376,7 @@ class _CmHeaderState extends State<_CmHeader>
           ),
         ),
         Offstage(
-          offstage: !client.authorized || client.isFileTransfer,
+          offstage: !client.authorized || client.type_() != ClientType.remote,
           child: IconButton(
               onPressed: () => checkClickTime(
                   client.id, () => gFFI.chatModel.toggleCMChatPage(client.id)),
@@ -510,7 +510,9 @@ class _CmControlPanel extends StatelessWidget {
   buildAuthorized(BuildContext context) {
     final bool canElevate = bind.cmCanElevate();
     final model = Provider.of<ServerModel>(context);
-    final showElevation = canElevate && model.showElevation;
+    final showElevation = canElevate &&
+        model.showElevation &&
+        client.type_() == ClientType.remote;
     return Column(
       mainAxisAlignment: MainAxisAlignment.end,
       children: [
@@ -560,7 +562,9 @@ class _CmControlPanel extends StatelessWidget {
   buildUnAuthorized(BuildContext context) {
     final bool canElevate = bind.cmCanElevate();
     final model = Provider.of<ServerModel>(context);
-    final showElevation = canElevate && model.showElevation;
+    final showElevation = canElevate &&
+        model.showElevation &&
+        client.type_() == ClientType.remote;
     final showAccept = model.approveMode != 'password';
     return Column(
       mainAxisAlignment: MainAxisAlignment.end,
diff --git a/flutter/lib/mobile/pages/connection_page.dart b/flutter/lib/mobile/pages/connection_page.dart
index e99226c4d..957910324 100644
--- a/flutter/lib/mobile/pages/connection_page.dart
+++ b/flutter/lib/mobile/pages/connection_page.dart
@@ -75,20 +75,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
         ])),
         SliverFillRemaining(
           hasScrollBody: false,
-          child: PeerTabPage(
-            tabs: [
-              translate('Recent Sessions'),
-              translate('Favorites'),
-              translate('Discovered'),
-              translate('Address Book')
-            ],
-            children: [
-              RecentPeersView(),
-              FavoritePeersView(),
-              DiscoveredPeersView(),
-              const AddressBook(),
-            ],
-          ),
+          child: PeerTabPage(),
         )
       ],
     ).marginOnly(top: 2, left: 10, right: 10);
diff --git a/flutter/lib/models/ab_model.dart b/flutter/lib/models/ab_model.dart
index 5a055fd14..afee97e75 100644
--- a/flutter/lib/models/ab_model.dart
+++ b/flutter/lib/models/ab_model.dart
@@ -34,13 +34,20 @@ class AbModel {
       if (resp.body.isNotEmpty && resp.body.toLowerCase() != "null") {
         Map<String, dynamic> json = jsonDecode(resp.body);
         if (json.containsKey('error')) {
-          abError = json['error'];
+          abError.value = json['error'];
         } else if (json.containsKey('data')) {
           final data = jsonDecode(json['data']);
-          tags.value = data['tags'];
-          peers.clear();
-          for (final peer in data['peers']) {
-            peers.add(Peer.fromJson(peer));
+          if (data != null) {
+            tags.clear();
+            peers.clear();
+            if (data['tags'] is List) {
+              tags.value = data['tags'];
+            }
+            if (data['peers'] is List) {
+              for (final peer in data['peers']) {
+                peers.add(Peer.fromJson(peer));
+              }
+            }
           }
         }
         return resp.body;
diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart
index 344733324..338da4ee3 100644
--- a/flutter/lib/models/server_model.dart
+++ b/flutter/lib/models/server_model.dart
@@ -581,10 +581,17 @@ class ServerModel with ChangeNotifier {
   }
 }
 
+enum ClientType {
+  remote,
+  file,
+  portForward,
+}
+
 class Client {
   int id = 0; // client connections inner count id
   bool authorized = false;
   bool isFileTransfer = false;
+  String portForward = "";
   String name = "";
   String peerId = ""; // peer user's id,show at app
   bool keyboard = false;
@@ -604,6 +611,7 @@ class Client {
     id = json['id'];
     authorized = json['authorized'];
     isFileTransfer = json['is_file_transfer'];
+    portForward = json['port_forward'];
     name = json['name'];
     peerId = json['peer_id'];
     keyboard = json['keyboard'];
@@ -620,6 +628,7 @@ class Client {
     data['id'] = id;
     data['is_start'] = authorized;
     data['is_file_transfer'] = isFileTransfer;
+    data['port_forward'] = portForward;
     data['name'] = name;
     data['peer_id'] = peerId;
     data['keyboard'] = keyboard;
@@ -631,6 +640,16 @@ class Client {
     data['disconnected'] = disconnected;
     return data;
   }
+
+  ClientType type_() {
+    if (isFileTransfer) {
+      return ClientType.file;
+    } else if (portForward.isNotEmpty) {
+      return ClientType.portForward;
+    } else {
+      return ClientType.remote;
+    }
+  }
 }
 
 String getLoginDialogTag(int id) {
diff --git a/src/lang/ca.rs b/src/lang/ca.rs
index e7794b989..6fc919b8d 100644
--- a/src/lang/ca.rs
+++ b/src/lang/ca.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/cn.rs b/src/lang/cn.rs
index 8af5229f2..1b49f6c4a 100644
--- a/src/lang/cn.rs
+++ b/src/lang/cn.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", "隐藏连接管理窗口"),
         ("hide_cm_tip", "在只允许密码连接并且只用固定密码的情况下才允许隐藏"),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", "右键选择选项卡"),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/cs.rs b/src/lang/cs.rs
index 547b233f4..6455023de 100644
--- a/src/lang/cs.rs
+++ b/src/lang/cs.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/da.rs b/src/lang/da.rs
index 5d815a90b..afd6476ee 100644
--- a/src/lang/da.rs
+++ b/src/lang/da.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/de.rs b/src/lang/de.rs
index e4306301b..273a607ed 100644
--- a/src/lang/de.rs
+++ b/src/lang/de.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", "Fenster zur Verwaltung der Verbindung verstecken"),
         ("hide_cm_tip", "Dies ist nur möglich, wenn der Zugriff nur über ein permanentes Passwort erfolgt."), // Sehr unklar. Muss noch angepasst werden. Original: Allow hiding only if accepting sessions via password and using pernament passw"),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/eo.rs b/src/lang/eo.rs
index f5a2f7e55..3a38b6601 100644
--- a/src/lang/eo.rs
+++ b/src/lang/eo.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/es.rs b/src/lang/es.rs
index d8362ff05..39d031c9d 100644
--- a/src/lang/es.rs
+++ b/src/lang/es.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", "Ocultar ventana de gestión de conexión"),
         ("hide_cm_tip", "Permitir ocultar solo si se aceptan sesiones a través de contraseña y usando contraseña permanente"),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/fa.rs b/src/lang/fa.rs
index ee3706e34..7513f84e8 100644
--- a/src/lang/fa.rs
+++ b/src/lang/fa.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", "پنهان کردن پنجره مدیریت اتصال"),
         ("hide_cm_tip", "فقط در صورت پذیرفتن جلسات از طریق رمز عبور و استفاده از رمز عبور دائمی، مخفی شدن مجاز است"),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/fr.rs b/src/lang/fr.rs
index 860f59518..a4eedfa2a 100644
--- a/src/lang/fr.rs
+++ b/src/lang/fr.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", "Masquer la fenêtre de gestion des connexions"),
         ("hide_cm_tip", "Autoriser le masquage uniquement si vous acceptez des sessions via un mot de passe et utilisez un mot de passe permanent"),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/gr.rs b/src/lang/gr.rs
index 20bb98200..986919a8b 100644
--- a/src/lang/gr.rs
+++ b/src/lang/gr.rs
@@ -397,6 +397,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Request access to your device", "Αίτημα πρόσβασης στη συσκευή σας"),
         ("Hide connection management window", "Απόκρυψη παραθύρου διαχείρισης σύνδεσης"),
         ("hide_cm_tip", "Να επιτρέπεται η απόκρυψη, μόνο εάν αποδέχεστε συνδέσεις μέσω κωδικού πρόσβασης και χρησιμοποιείτε μόνιμο κωδικό πρόσβασης"),
-        ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/hu.rs b/src/lang/hu.rs
index 51f072e16..941caeac1 100644
--- a/src/lang/hu.rs
+++ b/src/lang/hu.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/id.rs b/src/lang/id.rs
index b2492553d..7f4a50523 100644
--- a/src/lang/id.rs
+++ b/src/lang/id.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/it.rs b/src/lang/it.rs
index ec993ad04..98ea9366e 100644
--- a/src/lang/it.rs
+++ b/src/lang/it.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", "Nascondi la finestra di gestione delle connessioni"),
         ("hide_cm_tip", "Permetti di nascondere solo se si accettano sessioni con password permanente"),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/ja.rs b/src/lang/ja.rs
index 5cd6d8d6d..4121dd55c 100644
--- a/src/lang/ja.rs
+++ b/src/lang/ja.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/ko.rs b/src/lang/ko.rs
index 31d69841c..a1cd730e9 100644
--- a/src/lang/ko.rs
+++ b/src/lang/ko.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/kz.rs b/src/lang/kz.rs
index c32fa778d..1e623c0b6 100644
--- a/src/lang/kz.rs
+++ b/src/lang/kz.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/pl.rs b/src/lang/pl.rs
index edd9a4e45..ed14e3ca2 100644
--- a/src/lang/pl.rs
+++ b/src/lang/pl.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs
index 1c174af8d..65620e3e8 100644
--- a/src/lang/pt_PT.rs
+++ b/src/lang/pt_PT.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs
index 86bd1b77f..cf388a88c 100644
--- a/src/lang/ptbr.rs
+++ b/src/lang/ptbr.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/ru.rs b/src/lang/ru.rs
index bcb539498..76a8cca87 100644
--- a/src/lang/ru.rs
+++ b/src/lang/ru.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", "Скрывать окно управления соединениями"),
         ("hide_cm_tip", "Разрешать скрытие случае, если принимаются сеансы по паролю или используется постоянный пароль"),
         ("wayland_experiment_tip", "Поддержка Wayland находится на экспериментальной стадии, используйте X11, если вам требуется автоматический доступ."),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/sk.rs b/src/lang/sk.rs
index 194b3dc83..e7a9b12b5 100644
--- a/src/lang/sk.rs
+++ b/src/lang/sk.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/sq.rs b/src/lang/sq.rs
index a7cb45443..1926c849b 100644
--- a/src/lang/sq.rs
+++ b/src/lang/sq.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", "Fshih dritaren e menaxhimit të lidhjes"),
         ("hide_cm_tip", "Kjo është e mundur vetëm nëse aksesi bëhet nëpërmjet një fjalëkalimi të përhershëm"),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/sv.rs b/src/lang/sv.rs
index 79c9bbcc1..cfef903a7 100644
--- a/src/lang/sv.rs
+++ b/src/lang/sv.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", "Göm hanteringsfönster"),
         ("hide_cm_tip", "Tillåt att gömma endast om accepterande sessioner med lösenord och permanenta lösenord"),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/template.rs b/src/lang/template.rs
index acc92be20..ed7189ce6 100644
--- a/src/lang/template.rs
+++ b/src/lang/template.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/tr.rs b/src/lang/tr.rs
index bd2e9cd62..6c518da81 100644
--- a/src/lang/tr.rs
+++ b/src/lang/tr.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", "Bağlantı yönetimi penceresini gizle"),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/tw.rs b/src/lang/tw.rs
index 35b2cb2cf..e7c024420 100644
--- a/src/lang/tw.rs
+++ b/src/lang/tw.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", "隱藏連接管理窗口"),
         ("hide_cm_tip", "在只允許密碼連接並且只用固定密碼的情況下才允許隱藏"),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", "右鍵選擇選項卡"),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/ua.rs b/src/lang/ua.rs
index b1fdca17a..713d15c69 100644
--- a/src/lang/ua.rs
+++ b/src/lang/ua.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/lang/vn.rs b/src/lang/vn.rs
index acac782d1..c59de33fc 100644
--- a/src/lang/vn.rs
+++ b/src/lang/vn.rs
@@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
         ("Hide connection management window", ""),
         ("hide_cm_tip", ""),
         ("wayland_experiment_tip", ""),
+        ("Right click to select tabs", ""),
     ].iter().cloned().collect();
 }
diff --git a/src/ui/cm.tis b/src/ui/cm.tis
index 2cfc14bf1..74eb6c6d2 100644
--- a/src/ui/cm.tis
+++ b/src/ui/cm.tis
@@ -29,7 +29,7 @@ class Body: Reactor.Component
         };
         var right_style = show_chat ? "" : "display: none";
         var disconnected = c.disconnected;
-        var show_elevation_btn = handler.can_elevate() && show_elevation;
+        var show_elevation_btn = handler.can_elevate() && show_elevation && !c.is_file_transfer && c.port_forward.length == 0;
         var show_accept_btn = handler.get_option('approve-mode') != 'password';
        // below size:* is work around for Linux, it alreayd set in css, but not work, shit sciter
         return <div .content style="size:*">
diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs
index 6f8820e87..6b635436d 100644
--- a/src/ui_session_interface.rs
+++ b/src/ui_session_interface.rs
@@ -200,7 +200,7 @@ impl<T: InvokeUiSession> Session<T> {
             h265 = h265 && encoding_265;
             return (h264, h265);
         }
-        #[allow(dead_code)]
+        #[allow(unreachable_code)]
         (false, false)
     }
 
@@ -1211,7 +1211,13 @@ impl<T: InvokeUiSession> Interface for Session<T> {
                 input_os_password(p, true, self.clone());
             }
             let current = &pi.displays[pi.current_display as usize];
-            self.set_display(current.x, current.y, current.width, current.height, current.cursor_embeded);
+            self.set_display(
+                current.x,
+                current.y,
+                current.width,
+                current.height,
+                current.cursor_embeded,
+            );
         }
         self.update_privacy_mode();
         // Save recent peers, then push event to flutter. So flutter can refresh peer page.