add tabbar theme extension to fix theme update failure after overlay

added

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2022-09-04 11:03:16 +08:00
parent a553334157
commit 62870e453c
7 changed files with 162 additions and 138 deletions

View File

@ -155,7 +155,7 @@ class MyTheme {
brightness: Brightness.light,
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
tabBarTheme: TabBarTheme(
tabBarTheme: const TabBarTheme(
labelColor: Colors.black87,
),
splashColor: Colors.transparent,
@ -163,13 +163,14 @@ class MyTheme {
).copyWith(
extensions: <ThemeExtension<dynamic>>[
ColorThemeExtension.light,
TabbarTheme.light,
],
);
static ThemeData darkTheme = ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
tabBarTheme: TabBarTheme(
tabBarTheme: const TabBarTheme(
labelColor: Colors.white70,
),
splashColor: Colors.transparent,
@ -177,12 +178,17 @@ class MyTheme {
).copyWith(
extensions: <ThemeExtension<dynamic>>[
ColorThemeExtension.dark,
TabbarTheme.dark,
],
);
static ColorThemeExtension color(BuildContext context) {
return Theme.of(context).extension<ColorThemeExtension>()!;
}
static TabbarTheme tabbar(BuildContext context) {
return Theme.of(context).extension<TabbarTheme>()!;
}
}
bool isDarkTheme() {

View File

@ -83,7 +83,6 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
@override
Widget build(BuildContext context) {
final theme = isDarkTheme() ? TarBarTheme.dark() : TarBarTheme.light();
final RxBool fullscreen = Get.find(tag: 'fullscreen');
return Obx(() => SubWindowDragToResizeArea(
resizeEdgeSize: fullscreen.value ? 1.0 : 8.0,
@ -95,14 +94,11 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
backgroundColor: MyTheme.color(context).bg,
body: Obx(() => DesktopTab(
controller: tabController,
theme: theme,
showTabBar: fullscreen.isFalse,
onClose: () {
tabController.clear();
},
tail: AddButton(
theme: theme,
).paddingOnly(left: 10),
tail: AddButton().paddingOnly(left: 10),
pageViewBuilder: (pageView) {
WindowController.fromWindowId(windowId())
.setFullscreen(fullscreen.isTrue);

View File

@ -48,17 +48,11 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
backgroundColor: MyTheme.color(context).bg,
body: DesktopTab(
controller: tabController,
theme: dark
? const TarBarTheme.dark()
: const TarBarTheme.light(),
tail: ActionIcon(
message: 'Settings',
icon: IconFont.menu,
theme: dark
? const TarBarTheme.dark()
: const TarBarTheme.light(),
onTap: onAddSetting,
is_close: false,
isClose: false,
),
));
})

View File

@ -62,8 +62,6 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
@override
Widget build(BuildContext context) {
final theme =
isDarkTheme() ? const TarBarTheme.dark() : const TarBarTheme.light();
return SubWindowDragToResizeArea(
windowId: windowId(),
child: Container(
@ -73,13 +71,10 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
backgroundColor: MyTheme.color(context).bg,
body: DesktopTab(
controller: tabController,
theme: theme,
onClose: () {
tabController.clear();
},
tail: AddButton(
theme: theme,
).paddingOnly(left: 10),
tail: AddButton().paddingOnly(left: 10),
)),
),
);

View File

@ -69,7 +69,6 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
@override
Widget build(BuildContext context) {
final theme = isDarkTheme() ? TarBarTheme.dark() : TarBarTheme.light();
return SubWindowDragToResizeArea(
windowId: windowId(),
child: Container(
@ -79,13 +78,10 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
backgroundColor: MyTheme.color(context).bg,
body: DesktopTab(
controller: tabController,
theme: theme,
onClose: () {
tabController.clear();
},
tail: AddButton(
theme: theme,
).paddingOnly(left: 10),
tail: AddButton().paddingOnly(left: 10),
)),
),
);

View File

@ -118,7 +118,6 @@ class ConnectionManagerState extends State<ConnectionManager> {
],
)
: DesktopTab(
theme: isDarkTheme() ? TarBarTheme.dark() : TarBarTheme.light(),
showTitle: false,
showMaximize: false,
showMinimize: true,

View File

@ -3,7 +3,7 @@ import 'dart:async';
import 'dart:math';
import 'package:desktop_multi_window/desktop_multi_window.dart';
import 'package:flutter/material.dart';
import 'package:flutter/material.dart' hide TabBarTheme;
import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:flutter_hbb/main.dart';
@ -158,8 +158,7 @@ class DesktopTabController {
class TabThemeConf {
double iconSize;
TarBarTheme theme;
TabThemeConf({required this.iconSize, required this.theme});
TabThemeConf({required this.iconSize});
}
typedef TabBuilder = Widget Function(
@ -168,7 +167,6 @@ typedef LabelGetter = Rx<String> Function(String key);
class DesktopTab extends StatelessWidget {
final Function(String)? onTabClose;
final TarBarTheme theme;
final bool showTabBar;
final bool showLogo;
final bool showTitle;
@ -189,7 +187,6 @@ class DesktopTab extends StatelessWidget {
DesktopTab({
Key? key,
required this.controller,
this.theme = const TarBarTheme.light(),
this.onTabClose,
this.showTabBar = true,
this.showLogo = true,
@ -213,15 +210,15 @@ class DesktopTab extends StatelessWidget {
return Column(children: [
Offstage(
offstage: !showTabBar,
child: Container(
child: SizedBox(
height: _kTabBarHeight,
child: Column(
children: [
Container(
SizedBox(
height: _kTabBarHeight - 1,
child: _buildBar(),
),
Divider(
const Divider(
height: 1,
thickness: 1,
),
@ -300,7 +297,7 @@ class DesktopTab extends StatelessWidget {
)),
Offstage(
offstage: !showTitle,
child: Text(
child: const Text(
"RustDesk",
style: TextStyle(fontSize: 13),
).marginOnly(left: 2))
@ -321,7 +318,6 @@ class DesktopTab extends StatelessWidget {
child: _ListView(
controller: controller,
onTabClose: onTabClose,
theme: theme,
tabBuilder: tabBuilder,
labelGetter: labelGetter,
)),
@ -334,7 +330,6 @@ class DesktopTab extends StatelessWidget {
mainTab: isMainWindow,
tabType: tabType,
state: state,
theme: theme,
showMinimize: showMinimize,
showMaximize: showMaximize,
showClose: showClose,
@ -349,7 +344,6 @@ class WindowActionPanel extends StatelessWidget {
final bool mainTab;
final DesktopTabType tabType;
final Rx<DesktopTabState> state;
final TarBarTheme theme;
final bool showMinimize;
final bool showMaximize;
@ -361,7 +355,6 @@ class WindowActionPanel extends StatelessWidget {
required this.mainTab,
required this.tabType,
required this.state,
required this.theme,
this.showMinimize = true,
this.showMaximize = true,
this.showClose = true,
@ -377,7 +370,6 @@ class WindowActionPanel extends StatelessWidget {
child: ActionIcon(
message: 'Minimize',
icon: IconFont.min,
theme: theme,
onTap: () {
if (mainTab) {
windowManager.minimize();
@ -385,31 +377,30 @@ class WindowActionPanel extends StatelessWidget {
WindowController.fromWindowId(windowId!).minimize();
}
},
is_close: false,
isClose: false,
)),
// TODO: drag makes window restore
Offstage(
offstage: !showMaximize,
child: FutureBuilder(builder: (context, snapshot) {
RxBool is_maximized = false.obs;
RxBool isMaximized = false.obs;
if (mainTab) {
windowManager.isMaximized().then((maximized) {
is_maximized.value = maximized;
isMaximized.value = maximized;
});
} else {
final wc = WindowController.fromWindowId(windowId!);
wc.isMaximized().then((maximized) {
is_maximized.value = maximized;
isMaximized.value = maximized;
});
}
return Obx(
() => ActionIcon(
message: is_maximized.value ? "Restore" : "Maximize",
icon: is_maximized.value ? IconFont.restore : IconFont.max,
theme: theme,
message: isMaximized.value ? "Restore" : "Maximize",
icon: isMaximized.value ? IconFont.restore : IconFont.max,
onTap: () {
if (mainTab) {
if (is_maximized.value) {
if (isMaximized.value) {
windowManager.unmaximize();
} else {
windowManager.maximize();
@ -417,15 +408,15 @@ class WindowActionPanel extends StatelessWidget {
} else {
// TODO: subwindow is maximized but first query result is not maximized.
final wc = WindowController.fromWindowId(windowId!);
if (is_maximized.value) {
if (isMaximized.value) {
wc.unmaximize();
} else {
wc.maximize();
}
}
is_maximized.value = !is_maximized.value;
isMaximized.value = !isMaximized.value;
},
is_close: false,
isClose: false,
),
);
})),
@ -434,7 +425,6 @@ class WindowActionPanel extends StatelessWidget {
child: ActionIcon(
message: 'Close',
icon: IconFont.close,
theme: theme,
onTap: () async {
action() {
if (mainTab) {
@ -455,7 +445,7 @@ class WindowActionPanel extends StatelessWidget {
action();
}
},
is_close: true,
isClose: true,
)),
],
);
@ -490,17 +480,15 @@ class WindowActionPanel extends StatelessWidget {
class _ListView extends StatelessWidget {
final DesktopTabController controller;
final Function(String key)? onTabClose;
final TarBarTheme theme;
final TabBuilder? tabBuilder;
final LabelGetter? labelGetter;
Rx<DesktopTabState> get state => controller.state;
_ListView(
const _ListView(
{required this.controller,
required this.onTabClose,
required this.theme,
this.tabBuilder,
this.labelGetter});
@ -510,7 +498,7 @@ class _ListView extends StatelessWidget {
controller: state.value.scrollController,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
physics: BouncingScrollPhysics(),
physics: const BouncingScrollPhysics(),
children: state.value.tabs.asMap().entries.map((e) {
final index = e.key;
final tab = e.value;
@ -525,7 +513,6 @@ class _ListView extends StatelessWidget {
selected: state.value.selected,
onClose: () => controller.remove(index),
onSelected: () => controller.jumpTo(index),
theme: theme,
tabBuilder: tabBuilder == null
? null
: (Widget icon, Widget labelWidget, TabThemeConf themeConf) {
@ -542,31 +529,29 @@ class _ListView extends StatelessWidget {
}
class _Tab extends StatefulWidget {
late final int index;
late final Rx<String> label;
late final IconData? selectedIcon;
late final IconData? unselectedIcon;
late final bool closable;
late final int selected;
late final Function() onClose;
late final Function() onSelected;
late final TarBarTheme theme;
final int index;
final Rx<String> label;
final IconData? selectedIcon;
final IconData? unselectedIcon;
final bool closable;
final int selected;
final Function() onClose;
final Function() onSelected;
final Widget Function(Widget icon, Widget label, TabThemeConf themeConf)?
tabBuilder;
_Tab(
{Key? key,
required this.index,
required this.label,
this.selectedIcon,
this.unselectedIcon,
this.tabBuilder,
required this.closable,
required this.selected,
required this.onClose,
required this.onSelected,
required this.theme})
: super(key: key);
const _Tab({
Key? key,
required this.index,
required this.label,
this.selectedIcon,
this.unselectedIcon,
this.tabBuilder,
required this.closable,
required this.selected,
required this.onClose,
required this.onSelected,
}) : super(key: key);
@override
State<_Tab> createState() => _TabState();
@ -586,8 +571,8 @@ class _TabState extends State<_Tab> with RestorationMixin {
isSelected ? widget.selectedIcon : widget.unselectedIcon,
size: _kIconSize,
color: isSelected
? widget.theme.selectedtabIconColor
: widget.theme.unSelectedtabIconColor,
? MyTheme.tabbar(context).selectedTabIconColor
: MyTheme.tabbar(context).unSelectedTabIconColor,
).paddingOnly(right: 5));
final labelWidget = Obx(() {
return Text(
@ -595,8 +580,8 @@ class _TabState extends State<_Tab> with RestorationMixin {
textAlign: TextAlign.center,
style: TextStyle(
color: isSelected
? widget.theme.selectedTextColor
: widget.theme.unSelectedTextColor),
? MyTheme.tabbar(context).selectedTextColor
: MyTheme.tabbar(context).unSelectedTextColor),
);
});
@ -609,8 +594,8 @@ class _TabState extends State<_Tab> with RestorationMixin {
],
);
} else {
return widget.tabBuilder!(icon, labelWidget,
TabThemeConf(iconSize: _kIconSize, theme: widget.theme));
return widget.tabBuilder!(
icon, labelWidget, TabThemeConf(iconSize: _kIconSize));
}
}
@ -639,7 +624,6 @@ class _TabState extends State<_Tab> with RestorationMixin {
visiable: hover.value && widget.closable,
tabSelected: isSelected,
onClose: () => widget.onClose(),
theme: widget.theme,
)))
])).paddingSymmetric(horizontal: 10),
Offstage(
@ -648,7 +632,7 @@ class _TabState extends State<_Tab> with RestorationMixin {
width: 1,
indent: _kDividerIndent,
endIndent: _kDividerIndent,
color: widget.theme.dividerColor,
color: MyTheme.tabbar(context).dividerColor,
thickness: 1,
),
)
@ -671,14 +655,12 @@ class _CloseButton extends StatelessWidget {
final bool visiable;
final bool tabSelected;
final Function onClose;
late final TarBarTheme theme;
_CloseButton({
const _CloseButton({
Key? key,
required this.visiable,
required this.tabSelected,
required this.onClose,
required this.theme,
}) : super(key: key);
@override
@ -694,8 +676,8 @@ class _CloseButton extends StatelessWidget {
Icons.close,
size: _kIconSize,
color: tabSelected
? theme.selectedIconColor
: theme.unSelectedIconColor,
? MyTheme.tabbar(context).selectedIconColor
: MyTheme.tabbar(context).unSelectedIconColor,
),
),
)).paddingOnly(left: 5);
@ -705,16 +687,14 @@ class _CloseButton extends StatelessWidget {
class ActionIcon extends StatelessWidget {
final String message;
final IconData icon;
final TarBarTheme theme;
final Function() onTap;
final bool is_close;
final bool isClose;
const ActionIcon({
Key? key,
required this.message,
required this.icon,
required this.theme,
required this.onTap,
required this.is_close,
required this.isClose,
}) : super(key: key);
@override
@ -722,34 +702,32 @@ class ActionIcon extends StatelessWidget {
RxBool hover = false.obs;
return Obx(() => Tooltip(
message: translate(message),
waitDuration: Duration(seconds: 1),
waitDuration: const Duration(seconds: 1),
child: InkWell(
hoverColor:
is_close ? Color.fromARGB(255, 196, 43, 28) : theme.hoverColor,
hoverColor: isClose
? const Color.fromARGB(255, 196, 43, 28)
: MyTheme.tabbar(context).hoverColor,
onHover: (value) => hover.value = value,
child: Container(
onTap: onTap,
child: SizedBox(
height: _kTabBarHeight - 1,
width: _kTabBarHeight - 1,
child: Icon(
icon,
color: hover.value && is_close
color: hover.value && isClose
? Colors.white
: theme.unSelectedIconColor,
: MyTheme.tabbar(context).unSelectedIconColor,
size: _kActionIconSize,
),
),
onTap: onTap,
),
));
}
}
class AddButton extends StatelessWidget {
late final TarBarTheme theme;
AddButton({
const AddButton({
Key? key,
required this.theme,
}) : super(key: key);
@override
@ -757,41 +735,101 @@ class AddButton extends StatelessWidget {
return ActionIcon(
message: 'New Connection',
icon: IconFont.add,
theme: theme,
onTap: () =>
rustDeskWinManager.call(WindowType.Main, "main_window_on_top", ""),
is_close: false);
isClose: false);
}
}
class TarBarTheme {
final Color unSelectedtabIconColor;
final Color selectedtabIconColor;
final Color selectedTextColor;
final Color unSelectedTextColor;
final Color selectedIconColor;
final Color unSelectedIconColor;
final Color dividerColor;
final Color hoverColor;
class TabbarTheme extends ThemeExtension<TabbarTheme> {
final Color? selectedTabIconColor;
final Color? unSelectedTabIconColor;
final Color? selectedTextColor;
final Color? unSelectedTextColor;
final Color? selectedIconColor;
final Color? unSelectedIconColor;
final Color? dividerColor;
final Color? hoverColor;
const TarBarTheme.light()
: unSelectedtabIconColor = const Color.fromARGB(255, 162, 203, 241),
selectedtabIconColor = MyTheme.accent,
selectedTextColor = const Color.fromARGB(255, 26, 26, 26),
unSelectedTextColor = const Color.fromARGB(255, 96, 96, 96),
selectedIconColor = const Color.fromARGB(255, 26, 26, 26),
unSelectedIconColor = const Color.fromARGB(255, 96, 96, 96),
dividerColor = const Color.fromARGB(255, 238, 238, 238),
hoverColor = const Color.fromARGB(
51, 158, 158, 158); // Colors.grey; //0xFF9E9E9E
const TabbarTheme(
{required this.selectedTabIconColor,
required this.unSelectedTabIconColor,
required this.selectedTextColor,
required this.unSelectedTextColor,
required this.selectedIconColor,
required this.unSelectedIconColor,
required this.dividerColor,
required this.hoverColor});
const TarBarTheme.dark()
: unSelectedtabIconColor = const Color.fromARGB(255, 30, 65, 98),
selectedtabIconColor = MyTheme.accent,
selectedTextColor = const Color.fromARGB(255, 255, 255, 255),
unSelectedTextColor = const Color.fromARGB(255, 207, 207, 207),
selectedIconColor = const Color.fromARGB(255, 215, 215, 215),
unSelectedIconColor = const Color.fromARGB(255, 255, 255, 255),
dividerColor = const Color.fromARGB(255, 64, 64, 64),
hoverColor = Colors.black26;
static const light = TabbarTheme(
selectedTabIconColor: MyTheme.accent,
unSelectedTabIconColor: Color.fromARGB(255, 162, 203, 241),
selectedTextColor: Color.fromARGB(255, 26, 26, 26),
unSelectedTextColor: Color.fromARGB(255, 96, 96, 96),
selectedIconColor: Color.fromARGB(255, 26, 26, 26),
unSelectedIconColor: Color.fromARGB(255, 96, 96, 96),
dividerColor: Color.fromARGB(255, 238, 238, 238),
hoverColor: Color.fromARGB(51, 158, 158, 158));
static const dark = TabbarTheme(
selectedTabIconColor: MyTheme.accent,
unSelectedTabIconColor: Color.fromARGB(255, 30, 65, 98),
selectedTextColor: Color.fromARGB(255, 255, 255, 255),
unSelectedTextColor: Color.fromARGB(255, 207, 207, 207),
selectedIconColor: Color.fromARGB(255, 215, 215, 215),
unSelectedIconColor: Color.fromARGB(255, 255, 255, 255),
dividerColor: Color.fromARGB(255, 64, 64, 64),
hoverColor: Colors.black26);
@override
ThemeExtension<TabbarTheme> copyWith({
Color? selectedTabIconColor,
Color? unSelectedTabIconColor,
Color? selectedTextColor,
Color? unSelectedTextColor,
Color? selectedIconColor,
Color? unSelectedIconColor,
Color? dividerColor,
Color? hoverColor,
}) {
return TabbarTheme(
selectedTabIconColor: selectedTabIconColor ?? this.selectedTabIconColor,
unSelectedTabIconColor:
unSelectedTabIconColor ?? this.unSelectedTabIconColor,
selectedTextColor: selectedTextColor ?? this.selectedTextColor,
unSelectedTextColor: unSelectedTextColor ?? this.unSelectedTextColor,
selectedIconColor: selectedIconColor ?? this.selectedIconColor,
unSelectedIconColor: unSelectedIconColor ?? this.unSelectedIconColor,
dividerColor: dividerColor ?? this.dividerColor,
hoverColor: hoverColor ?? this.hoverColor,
);
}
@override
ThemeExtension<TabbarTheme> lerp(
ThemeExtension<TabbarTheme>? other, double t) {
if (other is! TabbarTheme) {
return this;
}
return TabbarTheme(
selectedTabIconColor:
Color.lerp(selectedTabIconColor, other.selectedTabIconColor, t),
unSelectedTabIconColor:
Color.lerp(unSelectedTabIconColor, other.unSelectedTabIconColor, t),
selectedTextColor:
Color.lerp(selectedTextColor, other.selectedTextColor, t),
unSelectedTextColor:
Color.lerp(unSelectedTextColor, other.unSelectedTextColor, t),
selectedIconColor:
Color.lerp(selectedIconColor, other.selectedIconColor, t),
unSelectedIconColor:
Color.lerp(unSelectedIconColor, other.unSelectedIconColor, t),
dividerColor: Color.lerp(dividerColor, other.dividerColor, t),
hoverColor: Color.lerp(hoverColor, other.hoverColor, t),
);
}
static color(BuildContext context) {
return Theme.of(context).extension<ColorThemeExtension>()!;
}
}