unify tab logic

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2022-08-11 18:08:35 +08:00
parent c799fb1857
commit 94353cf90b
4 changed files with 103 additions and 132 deletions

View File

@ -1,5 +1,4 @@
import 'dart:convert';
import 'dart:math';
import 'package:desktop_multi_window/desktop_multi_window.dart';
import 'package:flutter/material.dart';
@ -25,24 +24,23 @@ class _ConnectionTabPageState extends State<ConnectionTabPage>
with TickerProviderStateMixin {
// refactor List<int> when using multi-tab
// this singleton is only for test
var connectionIds = RxList<String>.empty(growable: true);
var initialIndex = 0;
RxList<TabInfo> tabs = RxList<TabInfo>.empty(growable: true);
late Rx<TabController> tabController;
static final Rx<int> _selected = 0.obs;
IconData icon = Icons.desktop_windows_sharp;
var connectionMap = RxList<Widget>.empty(growable: true);
_ConnectionTabPageState(Map<String, dynamic> params) {
if (params['id'] != null) {
connectionIds.add(params['id']);
tabs.add(TabInfo(label: params['id'], icon: icon));
}
}
@override
void initState() {
super.initState();
tabController =
TabController(length: connectionIds.length, vsync: this).obs;
tabController = TabController(length: tabs.length, vsync: this).obs;
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
print(
"call ${call.method} with args ${call.arguments} from window ${fromWindowId}");
@ -51,23 +49,13 @@ class _ConnectionTabPageState extends State<ConnectionTabPage>
final args = jsonDecode(call.arguments);
final id = args['id'];
window_on_top(windowId());
final indexOf = connectionIds.indexOf(id);
if (indexOf >= 0) {
initialIndex = indexOf;
tabController.value.animateTo(initialIndex, duration: Duration.zero);
} else {
connectionIds.add(id);
initialIndex = connectionIds.length - 1;
tabController.value = TabController(
length: connectionIds.length,
vsync: this,
initialIndex: initialIndex);
}
_selected.value = initialIndex;
DesktopTabBar.onAdd(this, tabController, tabs, _selected,
TabInfo(label: id, icon: icon));
} else if (call.method == "onDestroy") {
print("executing onDestroy hook, closing ${connectionIds}");
connectionIds.forEach((id) {
final tag = '${id}';
print(
"executing onDestroy hook, closing ${tabs.map((tab) => tab.label).toList()}");
tabs.forEach((tab) {
final tag = '${tab.label}';
ffi(tag).close().then((_) {
Get.delete<FFI>(tag: tag);
});
@ -82,24 +70,21 @@ class _ConnectionTabPageState extends State<ConnectionTabPage>
return Scaffold(
body: Column(
children: [
Obx(() => DesktopTabBar(
controller: tabController,
tabs: connectionIds
.map((e) =>
TabInfo(label: e, icon: Icons.desktop_windows_sharp))
.toList(),
onTabClose: onRemoveId,
selected: _selected,
dark: isDarkTheme(),
mainTab: false,
)),
DesktopTabBar(
controller: tabController,
tabs: tabs,
onTabClose: onRemoveId,
selected: _selected,
dark: isDarkTheme(),
mainTab: false,
),
Expanded(
child: Obx(() => TabBarView(
controller: tabController.value,
children: connectionIds
.map((e) => RemotePage(
key: ValueKey(e),
id: e,
children: tabs
.map((tab) => RemotePage(
key: ValueKey(tab.label),
id: tab.label,
tabBarHeight: kDesktopRemoteTabBarHeight,
)) //RemotePage(key: ValueKey(e), id: e))
.toList()))),
@ -109,15 +94,8 @@ class _ConnectionTabPageState extends State<ConnectionTabPage>
}
void onRemoveId(String id) {
final indexOf = connectionIds.indexOf(id);
if (indexOf == -1) {
return;
}
connectionIds.removeAt(indexOf);
initialIndex = max(0, initialIndex - 1);
tabController.value = TabController(
length: connectionIds.length, vsync: this, initialIndex: initialIndex);
if (connectionIds.length == 0) {
DesktopTabBar.onClose(this, tabController, tabs, id);
if (tabs.length == 0) {
WindowController.fromWindowId(windowId()).close();
}
}

View File

@ -1,5 +1,3 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/consts.dart';
@ -36,15 +34,15 @@ class _DesktopTabPageState extends State<DesktopTabPage>
return Scaffold(
body: Column(
children: [
Obx((() => DesktopTabBar(
controller: tabController,
tabs: tabs.toList(),
onTabClose: onTabClose,
selected: _selected,
dark: isDarkTheme(),
mainTab: true,
onMenu: onTabbarMenu,
))),
DesktopTabBar(
controller: tabController,
tabs: tabs,
onTabClose: onTabClose,
selected: _selected,
dark: isDarkTheme(),
mainTab: true,
onAddSetting: onAddSetting,
),
Obx((() => Expanded(
child: TabBarView(
controller: tabController.value,
@ -65,24 +63,11 @@ class _DesktopTabPageState extends State<DesktopTabPage>
}
void onTabClose(String label) {
tabs.removeWhere((tab) => tab.label == label);
tabController.value = TabController(
length: tabs.length,
vsync: this,
initialIndex: max(0, tabs.length - 1));
DesktopTabBar.onClose(this, tabController, tabs, label);
}
void onTabbarMenu() {
int index = tabs.indexWhere((tab) => tab.label == kTabLabelSettingPage);
if (index >= 0) {
tabController.value.animateTo(index, duration: Duration.zero);
_selected.value = index;
} else {
tabs.add(TabInfo(label: kTabLabelSettingPage, icon: Icons.settings));
tabController.value = TabController(
length: tabs.length, vsync: this, initialIndex: tabs.length - 1);
tabController.value.animateTo(tabs.length - 1, duration: Duration.zero);
_selected.value = tabs.length - 1;
}
void onAddSetting() {
DesktopTabBar.onAdd(this, tabController, tabs, _selected,
TabInfo(label: kTabLabelSettingPage, icon: Icons.settings));
}
}

View File

@ -1,5 +1,4 @@
import 'dart:convert';
import 'dart:math';
import 'package:desktop_multi_window/desktop_multi_window.dart';
import 'package:flutter/material.dart';
@ -24,22 +23,21 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
with TickerProviderStateMixin {
// refactor List<int> when using multi-tab
// this singleton is only for test
var connectionIds = List<String>.empty(growable: true).obs;
var initialIndex = 0;
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;
_FileManagerTabPageState(Map<String, dynamic> params) {
if (params['id'] != null) {
connectionIds.add(params['id']);
tabs.add(TabInfo(label: params['id'], icon: icon));
}
}
@override
void initState() {
super.initState();
tabController =
TabController(length: connectionIds.length, vsync: this).obs;
tabController = TabController(length: tabs.length, vsync: this).obs;
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
print(
"call ${call.method} with args ${call.arguments} from window ${fromWindowId}");
@ -48,23 +46,13 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
final args = jsonDecode(call.arguments);
final id = args['id'];
window_on_top(windowId());
final indexOf = connectionIds.indexOf(id);
if (indexOf >= 0) {
initialIndex = indexOf;
tabController.value.animateTo(initialIndex, duration: Duration.zero);
} else {
connectionIds.add(id);
initialIndex = connectionIds.length - 1;
tabController.value = TabController(
length: connectionIds.length,
initialIndex: initialIndex,
vsync: this);
}
_selected.value = initialIndex;
DesktopTabBar.onAdd(this, tabController, tabs, _selected,
TabInfo(label: id, icon: icon));
} else if (call.method == "onDestroy") {
print("executing onDestroy hook, closing ${connectionIds}");
connectionIds.forEach((id) {
final tag = 'ft_${id}';
print(
"executing onDestroy hook, closing ${tabs.map((tab) => tab.label).toList()}");
tabs.forEach((tab) {
final tag = 'ft_${tab.label}';
ffi(tag).close().then((_) {
Get.delete<FFI>(tag: tag);
});
@ -79,26 +67,22 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
return Scaffold(
body: Column(
children: [
Obx(
() => DesktopTabBar(
controller: tabController,
tabs: connectionIds
.map((e) => TabInfo(label: e, icon: Icons.file_copy_sharp))
.toList(),
onTabClose: onRemoveId,
selected: _selected,
dark: isDarkTheme(),
mainTab: false,
),
DesktopTabBar(
controller: tabController,
tabs: tabs,
onTabClose: onRemoveId,
selected: _selected,
dark: isDarkTheme(),
mainTab: false,
),
Expanded(
child: Obx(
() => TabBarView(
controller: tabController.value,
children: connectionIds
.map((e) => FileManagerPage(
key: ValueKey(e),
id: e)) //RemotePage(key: ValueKey(e), id: e))
children: tabs
.map((tab) => FileManagerPage(
key: ValueKey(tab.label),
id: tab.label)) //RemotePage(key: ValueKey(e), id: e))
.toList()),
),
)
@ -108,15 +92,8 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
}
void onRemoveId(String id) {
final indexOf = connectionIds.indexOf(id);
if (indexOf == -1) {
return;
}
connectionIds.removeAt(indexOf);
initialIndex = max(0, initialIndex - 1);
tabController.value = TabController(
length: connectionIds.length, initialIndex: initialIndex, vsync: this);
if (connectionIds.length == 0) {
DesktopTabBar.onClose(this, tabController, tabs, id);
if (tabs.length == 0) {
WindowController.fromWindowId(windowId()).close();
}
}

View File

@ -22,13 +22,13 @@ class TabInfo {
class DesktopTabBar extends StatelessWidget {
late final Rx<TabController> controller;
late final List<TabInfo> tabs;
late final RxList<TabInfo> tabs;
late final Function(String) onTabClose;
late final Rx<int> selected;
late final bool dark;
late final _Theme _theme;
late final bool mainTab;
late final Function()? onMenu;
late final Function()? onAddSetting;
DesktopTabBar({
Key? key,
@ -38,7 +38,7 @@ class DesktopTabBar extends StatelessWidget {
required this.selected,
required this.dark,
required this.mainTab,
this.onMenu,
this.onAddSetting,
}) : _theme = dark ? _Theme.dark() : _Theme.light(),
super(key: key);
@ -105,19 +105,50 @@ class DesktopTabBar extends StatelessWidget {
),
),
Offstage(
offstage: onMenu == null,
child: InkWell(
child: Icon(
Icons.menu,
color: _theme.unSelectedIconColor,
),
onTap: () => onMenu?.call(),
).paddingOnly(right: 10),
offstage: onAddSetting == null,
child: Tooltip(
message: translate("Settings"),
child: InkWell(
child: Icon(
Icons.menu,
color: _theme.unSelectedIconColor,
),
onTap: () => onAddSetting?.call(),
).paddingOnly(right: 10),
),
)
],
),
);
}
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) {
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;
}
}
}
class _Tab extends StatelessWidget {
@ -169,7 +200,7 @@ class _Tab extends StatelessWidget {
).paddingSymmetric(horizontal: 5),
Expanded(
child: Text(
label,
translate(label),
style: TextStyle(
color: is_selected
? theme.selectedTextColor