diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 38085ae8c..d5336e2e1 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -2140,3 +2140,20 @@ Widget buildRemoteBlock({required Widget child, WhetherUseRemoteBlock? use}) { ]), )); } + +Widget unreadMessageCountBuilder(RxInt? count) { + return Obx(() => Offstage( + offstage: !((count?.value ?? 0) > 0), + child: Container( + width: 16, + height: 16, + decoration: BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + child: Center( + child: Text("${count?.value ?? 0}", + maxLines: 1, style: TextStyle(color: Colors.white, fontSize: 10)), + ), + ).marginOnly(left: 4))); +} diff --git a/flutter/lib/common/shared_state.dart b/flutter/lib/common/shared_state.dart index e4711ddf8..d5ce29190 100644 --- a/flutter/lib/common/shared_state.dart +++ b/flutter/lib/common/shared_state.dart @@ -285,6 +285,29 @@ class PeerStringOption { Get.find(tag: tag(id, opt)); } +class UnreadChatCountState { + static String tag(id) => 'unread_chat_count_$id'; + + static void init(String id) { + final key = tag(id); + if (!Get.isRegistered(tag: key)) { + final RxInt state = RxInt(0); + Get.put(state, tag: key); + } else { + Get.find(tag: key).value = 0; + } + } + + static void delete(String id) { + final key = tag(id); + if (Get.isRegistered(tag: key)) { + Get.delete(tag: key); + } + } + + static RxInt find(String id) => Get.find(tag: tag(id)); +} + initSharedStates(String id) { PrivacyModeState.init(id); BlockInputState.init(id); @@ -294,6 +317,7 @@ initSharedStates(String id) { RemoteCursorMovedState.init(id); FingerprintState.init(id); PeerBoolOption.init(id, 'zoom-cursor', () => false); + UnreadChatCountState.init(id); } removeSharedStates(String id) { @@ -305,4 +329,5 @@ removeSharedStates(String id) { RemoteCursorMovedState.delete(id); FingerprintState.delete(id); PeerBoolOption.delete(id, 'zoom-cursor'); + UnreadChatCountState.delete(id); } diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 2333e343c..0b4f4094a 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -56,15 +56,14 @@ class _ConnectionTabPageState extends State { if (peerId != null) { ConnectionTypeState.init(peerId); tabController.onSelected = (id) { - final remotePage = tabController.state.value.tabs - .firstWhereOrNull((tab) => tab.key == id) - ?.page; + final remotePage = tabController.widget(id); if (remotePage is RemotePage) { final ffi = remotePage.ffi; bind.setCurSessionId(sessionId: ffi.sessionId); } WindowController.fromWindowId(windowId()) .setTitle(getWindowNameWithId(id)); + UnreadChatCountState.find(id).value = 0; }; tabController.add(TabInfo( key: peerId, @@ -206,6 +205,7 @@ class _ConnectionTabPageState extends State { ).paddingOnly(right: 5), ), label, + unreadMessageCountBuilder(UnreadChatCountState.find(key)), ], ); diff --git a/flutter/lib/desktop/pages/server_page.dart b/flutter/lib/desktop/pages/server_page.dart index e996de2db..51e736f7b 100644 --- a/flutter/lib/desktop/pages/server_page.dart +++ b/flutter/lib/desktop/pages/server_page.dart @@ -158,24 +158,7 @@ class ConnectionManagerState extends State { message: key, waitDuration: Duration(seconds: 1), child: label), - Obx(() => Offstage( - offstage: - !((client?.unreadChatMessageCount.value ?? 0) > 0), - child: Container( - width: 16, - height: 16, - decoration: BoxDecoration( - color: Colors.red, - shape: BoxShape.circle, - ), - child: Center( - child: Text( - "${client?.unreadChatMessageCount.value ?? 0}", - maxLines: 1, - style: TextStyle( - color: Colors.white, fontSize: 10)), - ), - ).marginOnly(left: 4))) + unreadMessageCountBuilder(client?.unreadChatMessageCount), ], ); }, diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index 975398c94..85cf12704 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -187,6 +187,10 @@ class DesktopTabController { state.value.tabs.clear(); state.refresh(); } + + Widget? widget(String key) { + return state.value.tabs.firstWhereOrNull((tab) => tab.key == key)?.page; + } } class TabThemeConf { diff --git a/flutter/lib/models/chat_model.dart b/flutter/lib/models/chat_model.dart index 81a240cba..d515d6706 100644 --- a/flutter/lib/models/chat_model.dart +++ b/flutter/lib/models/chat_model.dart @@ -1,10 +1,14 @@ import 'dart:async'; import 'package:dash_chat_2/dash_chat_2.dart'; +import 'package:desktop_multi_window/desktop_multi_window.dart'; import 'package:draggable_float_widget/draggable_float_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_hbb/common/shared_state.dart'; +import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; import 'package:flutter_hbb/models/platform_model.dart'; +import 'package:flutter_hbb/models/state_model.dart'; import 'package:get/get_rx/src/rx_types/rx_types.dart'; import 'package:get/get.dart'; import 'package:window_manager/window_manager.dart'; @@ -309,6 +313,29 @@ class ChatModel with ChangeNotifier { id: session.id, ); toId = id; + + if (isDesktop) { + if (Get.isRegistered()) { + DesktopTabController tabController = Get.find(); + var index = tabController.state.value.tabs + .indexWhere((e) => e.key == session.id); + final notSelected = + index >= 0 && tabController.state.value.selected != index; + // minisized: top and switch tab + // not minisized: add count + if (await WindowController.fromWindowId(stateGlobal.windowId) + .isMinimized()) { + window_on_top(stateGlobal.windowId); + if (notSelected) { + tabController.jumpTo(index); + } + } else { + if (notSelected) { + UnreadChatCountState.find(session.id).value += 1; + } + } + } + } } else { final client = session.serverModel.clients.firstWhere((client) => client.id == id); diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index a01a5a02b..e14ff5046 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -319,7 +319,7 @@ packages: description: path: "." ref: HEAD - resolved-ref: "30518303e28702bf6b8110465293c05d21bc4cd2" + resolved-ref: aee670819f5fe7e8b0f05e0239dafb5c62f7a84b url: "https://github.com/rustdesk-org/rustdesk_desktop_multi_window" source: git version: "0.1.0"