diff --git a/flutter/assets/actions.svg b/flutter/assets/actions.svg
new file mode 100644
index 000000000..5403853db
--- /dev/null
+++ b/flutter/assets/actions.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/call_end.svg b/flutter/assets/call_end.svg
new file mode 100644
index 000000000..39367c3c5
--- /dev/null
+++ b/flutter/assets/call_end.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/call_wait.svg b/flutter/assets/call_wait.svg
new file mode 100644
index 000000000..42a11fe56
--- /dev/null
+++ b/flutter/assets/call_wait.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/chat.svg b/flutter/assets/chat.svg
index 03491be6e..7088107b0 100644
--- a/flutter/assets/chat.svg
+++ b/flutter/assets/chat.svg
@@ -1 +1,2 @@
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/flutter/assets/close.svg b/flutter/assets/close.svg
new file mode 100644
index 000000000..7488acc9f
--- /dev/null
+++ b/flutter/assets/close.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/display.svg b/flutter/assets/display.svg
new file mode 100644
index 000000000..b5a88106e
--- /dev/null
+++ b/flutter/assets/display.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/fullscreen.svg b/flutter/assets/fullscreen.svg
new file mode 100644
index 000000000..cd01f93f9
--- /dev/null
+++ b/flutter/assets/fullscreen.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/fullscreen_exit.svg b/flutter/assets/fullscreen_exit.svg
new file mode 100644
index 000000000..8d4414897
--- /dev/null
+++ b/flutter/assets/fullscreen_exit.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/keyboard.svg b/flutter/assets/keyboard.svg
new file mode 100644
index 000000000..d5481d7a1
--- /dev/null
+++ b/flutter/assets/keyboard.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/pinned.svg b/flutter/assets/pinned.svg
new file mode 100644
index 000000000..dd718b96a
--- /dev/null
+++ b/flutter/assets/pinned.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/rec.svg b/flutter/assets/rec.svg
new file mode 100644
index 000000000..33a57e9d0
--- /dev/null
+++ b/flutter/assets/rec.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/unpinned.svg b/flutter/assets/unpinned.svg
new file mode 100644
index 000000000..9e9e3de8b
--- /dev/null
+++ b/flutter/assets/unpinned.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart
index 9b00b481f..7bd2a4126 100644
--- a/flutter/lib/desktop/pages/remote_tab_page.dart
+++ b/flutter/lib/desktop/pages/remote_tab_page.dart
@@ -22,7 +22,10 @@ import 'package:bot_toast/bot_toast.dart';
import '../../models/platform_model.dart';
class _MenuTheme {
- static const Color commonColor = MyTheme.accent;
+ static const Color blueColor = MyTheme.button;
+ static const Color hoverBlueColor = MyTheme.accent;
+ static const Color redColor = Colors.redAccent;
+ static const Color hoverRedColor = Colors.red;
// kMinInteractiveDimension
static const double height = 20.0;
static const double dividerHeight = 12.0;
@@ -280,7 +283,7 @@ class _ConnectionTabPageState extends State {
.map((entry) => entry.build(
context,
const MenuConfig(
- commonColor: _MenuTheme.commonColor,
+ commonColor: _MenuTheme.blueColor,
height: _MenuTheme.height,
dividerHeight: _MenuTheme.dividerHeight,
)))
diff --git a/flutter/lib/desktop/widgets/material_mod_popup_menu.dart b/flutter/lib/desktop/widgets/material_mod_popup_menu.dart
index 666c9a6e2..47de1be20 100644
--- a/flutter/lib/desktop/widgets/material_mod_popup_menu.dart
+++ b/flutter/lib/desktop/widgets/material_mod_popup_menu.dart
@@ -5,6 +5,8 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_hbb/common.dart';
+import 'package:flutter_hbb/desktop/widgets/menu_button.dart';
// Examples can assume:
// enum Commands { heroAndScholar, hurricaneCame }
@@ -1391,22 +1393,20 @@ class PopupMenuButtonState extends State> {
onTap: widget.enabled ? showButtonMenu : null,
onHover: widget.onHover,
canRequestFocus: _canRequestFocus,
- radius: widget.splashRadius,
enableFeedback: enableFeedback,
child: widget.child,
),
);
}
- return IconButton(
+ return MenuButton(
icon: widget.icon ?? Icon(Icons.adaptive.more),
- padding: widget.padding,
- splashRadius: widget.splashRadius,
- iconSize: widget.iconSize ?? iconTheme.size ?? _kDefaultIconSize,
tooltip:
widget.tooltip ?? MaterialLocalizations.of(context).showMenuTooltip,
onPressed: widget.enabled ? showButtonMenu : null,
enableFeedback: enableFeedback,
+ color: MyTheme.button,
+ hoverColor: MyTheme.accent,
);
}
}
diff --git a/flutter/lib/desktop/widgets/menu_button.dart b/flutter/lib/desktop/widgets/menu_button.dart
new file mode 100644
index 000000000..7c9fe67eb
--- /dev/null
+++ b/flutter/lib/desktop/widgets/menu_button.dart
@@ -0,0 +1,61 @@
+import 'package:flutter/material.dart';
+
+class MenuButton extends StatefulWidget {
+ final GestureTapCallback? onPressed;
+ final Color color;
+ final Color hoverColor;
+ final Color? splashColor;
+ final Widget icon;
+ final String? tooltip;
+ final EdgeInsetsGeometry padding;
+ final bool enableFeedback;
+ const MenuButton({
+ super.key,
+ required this.onPressed,
+ required this.color,
+ required this.hoverColor,
+ required this.icon,
+ this.splashColor,
+ this.tooltip = "",
+ this.padding = const EdgeInsets.symmetric(horizontal: 3, vertical: 6),
+ this.enableFeedback = true,
+ });
+
+ @override
+ State createState() => _MenuButtonState();
+}
+
+class _MenuButtonState extends State {
+ bool _isHover = false;
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: widget.padding,
+ child: Tooltip(
+ message: widget.tooltip,
+ child: Material(
+ type: MaterialType.transparency,
+ child: Ink(
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(5),
+ color: _isHover ? widget.hoverColor : widget.color,
+ ),
+ child: InkWell(
+ onHover: (val) {
+ setState(() {
+ _isHover = val;
+ });
+ },
+ borderRadius: BorderRadius.circular(5),
+ splashColor: widget.splashColor,
+ enableFeedback: widget.enableFeedback,
+ onTap: widget.onPressed,
+ child: widget.icon,
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart
index c68b394e4..933850c99 100644
--- a/flutter/lib/desktop/widgets/remote_menubar.dart
+++ b/flutter/lib/desktop/widgets/remote_menubar.dart
@@ -5,6 +5,7 @@ import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:flutter_hbb/desktop/widgets/menu_button.dart';
import 'package:flutter_hbb/models/chat_model.dart';
import 'package:flutter_hbb/models/state_model.dart';
import 'package:flutter_hbb/consts.dart';
@@ -94,7 +95,10 @@ class MenubarState {
}
class _MenubarTheme {
- static const Color commonColor = MyTheme.accent;
+ static const Color blueColor = MyTheme.button;
+ static const Color hoverBlueColor = MyTheme.accent;
+ static const Color redColor = Colors.redAccent;
+ static const Color hoverRedColor = Colors.red;
// kMinInteractiveDimension
static const double height = 20.0;
static const double dividerHeight = 12.0;
@@ -411,7 +415,7 @@ class _RemoteMenubarState extends State {
if (widget.ffi.ffiModel.isPeerAndroid) {
menubarItems.add(IconButton(
tooltip: translate('Mobile Actions'),
- color: _MenubarTheme.commonColor,
+ color: _MenubarTheme.blueColor,
icon: const Icon(Icons.build),
onPressed: () {
widget.ffi.dialogManager
@@ -431,55 +435,65 @@ class _RemoteMenubarState extends State {
menubarItems.add(_buildRecording(context));
menubarItems.add(_buildClose(context));
return PopupMenuTheme(
- data: const PopupMenuThemeData(
- textStyle: TextStyle(color: _MenubarTheme.commonColor)),
- child: Column(mainAxisSize: MainAxisSize.min, children: [
+ data: const PopupMenuThemeData(
+ textStyle: TextStyle(color: _MenubarTheme.blueColor)),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
Container(
- decoration: BoxDecoration(
- color: Colors.white,
- border: Border.all(color: MyTheme.border),
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.vertical(
+ bottom: Radius.circular(10),
),
- child: SingleChildScrollView(
- scrollDirection: Axis.horizontal,
- child: Row(
- mainAxisSize: MainAxisSize.min,
- children: menubarItems,
- ),
- )),
+ ),
+ child: SingleChildScrollView(
+ scrollDirection: Axis.horizontal,
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ SizedBox(width: 3),
+ ...menubarItems,
+ SizedBox(width: 3)
+ ],
+ ),
+ ),
+ ),
_buildDraggableShowHide(context),
- ]));
+ ],
+ ),
+ );
}
Widget _buildPinMenubar(BuildContext context) {
- return Obx(() => IconButton(
- tooltip: translate(pin ? 'Unpin menubar' : 'Pin menubar'),
- onPressed: () {
- widget.state.switchPin();
- },
- icon: Obx(() => Transform.rotate(
- angle: pin ? math.pi / 4 : 0,
- child: Icon(
- Icons.push_pin,
- color: pin ? _MenubarTheme.commonColor : Colors.grey,
- ))),
- ));
+ return Obx(
+ () => MenuButton(
+ tooltip: translate(pin ? 'Unpin menubar' : 'Pin menubar'),
+ onPressed: () {
+ widget.state.switchPin();
+ },
+ icon: SvgPicture.asset(
+ pin ? "assets/pinned.svg" : "assets/unpinned.svg",
+ color: Colors.white,
+ ),
+ color: pin ? _MenubarTheme.blueColor : Colors.grey[800]!,
+ hoverColor: pin ? _MenubarTheme.hoverBlueColor : Colors.grey[850]!,
+ ),
+ );
}
Widget _buildFullscreen(BuildContext context) {
- return IconButton(
+ return MenuButton(
tooltip: translate(isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'),
onPressed: () {
_setFullscreen(!isFullscreen);
},
- icon: isFullscreen
- ? const Icon(
- Icons.fullscreen_exit,
- color: _MenubarTheme.commonColor,
- )
- : const Icon(
- Icons.fullscreen,
- color: _MenubarTheme.commonColor,
- ),
+ icon: SvgPicture.asset(
+ isFullscreen ? "assets/fullscreen_exit.svg" : "assets/fullscreen.svg",
+ color: Colors.white,
+ ),
+ color: _MenubarTheme.blueColor,
+ hoverColor: _MenubarTheme.hoverBlueColor,
);
}
@@ -487,14 +501,13 @@ class _RemoteMenubarState extends State {
final pi = widget.ffi.ffiModel.pi;
return mod_menu.PopupMenuButton(
tooltip: translate('Select Monitor'),
- padding: EdgeInsets.zero,
position: mod_menu.PopupMenuPosition.under,
icon: Stack(
alignment: Alignment.center,
children: [
- const Icon(
- Icons.personal_video,
- color: _MenubarTheme.commonColor,
+ SvgPicture.asset(
+ "assets/display.svg",
+ color: Colors.white,
),
Padding(
padding: const EdgeInsets.only(bottom: 3.9),
@@ -502,8 +515,7 @@ class _RemoteMenubarState extends State {
RxInt display = CurrentDisplayState.find(widget.id);
return Text(
'${display.value + 1}/${pi.displays.length}',
- style: const TextStyle(
- color: _MenubarTheme.commonColor, fontSize: 8),
+ style: const TextStyle(color: Colors.white, fontSize: 8),
);
}),
)
@@ -516,23 +528,25 @@ class _RemoteMenubarState extends State {
Stack(
alignment: Alignment.center,
children: [
- const Icon(
- Icons.personal_video,
- color: _MenubarTheme.commonColor,
+ SvgPicture.asset(
+ "assets/display.svg",
+ color: Colors.white,
),
TextButton(
child: Container(
- alignment: AlignmentDirectional.center,
- constraints:
- const BoxConstraints(minHeight: _MenubarTheme.height),
- child: Padding(
- padding: const EdgeInsets.only(bottom: 2.5),
- child: Text(
- (i + 1).toString(),
- style:
- const TextStyle(color: _MenubarTheme.commonColor),
+ alignment: AlignmentDirectional.center,
+ constraints:
+ const BoxConstraints(minHeight: _MenubarTheme.height),
+ child: Padding(
+ padding: const EdgeInsets.only(bottom: 2.5),
+ child: Text(
+ (i + 1).toString(),
+ style: TextStyle(
+ color: Colors.white,
),
- )),
+ ),
+ ),
+ ),
onPressed: () {
if (Navigator.canPop(context)) {
Navigator.pop(context);
@@ -567,9 +581,9 @@ class _RemoteMenubarState extends State {
Widget _buildControl(BuildContext context) {
return mod_menu.PopupMenuButton(
padding: EdgeInsets.zero,
- icon: const Icon(
- Icons.bolt,
- color: _MenubarTheme.commonColor,
+ icon: SvgPicture.asset(
+ "assets/actions.svg",
+ color: Colors.white,
),
tooltip: translate('Control Actions'),
position: mod_menu.PopupMenuPosition.under,
@@ -577,7 +591,7 @@ class _RemoteMenubarState extends State {
.map((entry) => entry.build(
context,
const MenuConfig(
- commonColor: _MenubarTheme.commonColor,
+ commonColor: _MenubarTheme.blueColor,
height: _MenubarTheme.height,
dividerHeight: _MenubarTheme.dividerHeight,
)))
@@ -599,9 +613,9 @@ class _RemoteMenubarState extends State {
final remoteCount = RemoteCountState.find().value;
return mod_menu.PopupMenuButton(
padding: EdgeInsets.zero,
- icon: const Icon(
- Icons.tv,
- color: _MenubarTheme.commonColor,
+ icon: SvgPicture.asset(
+ "assets/display.svg",
+ color: Colors.white,
),
tooltip: translate('Display Settings'),
position: mod_menu.PopupMenuPosition.under,
@@ -611,7 +625,7 @@ class _RemoteMenubarState extends State {
.map((entry) => entry.build(
context,
const MenuConfig(
- commonColor: _MenubarTheme.commonColor,
+ commonColor: _MenubarTheme.blueColor,
height: _MenubarTheme.height,
dividerHeight: _MenubarTheme.dividerHeight,
)))
@@ -632,9 +646,9 @@ class _RemoteMenubarState extends State {
}
return mod_menu.PopupMenuButton(
padding: EdgeInsets.zero,
- icon: const Icon(
- Icons.keyboard,
- color: _MenubarTheme.commonColor,
+ icon: SvgPicture.asset(
+ "assets/keyboard.svg",
+ color: Colors.white,
),
tooltip: translate('Keyboard Settings'),
position: mod_menu.PopupMenuPosition.under,
@@ -642,7 +656,7 @@ class _RemoteMenubarState extends State {
.map((entry) => entry.build(
context,
const MenuConfig(
- commonColor: _MenubarTheme.commonColor,
+ commonColor: _MenubarTheme.blueColor,
height: _MenubarTheme.height,
dividerHeight: _MenubarTheme.dividerHeight,
)))
@@ -655,23 +669,22 @@ class _RemoteMenubarState extends State {
return Consumer(builder: ((context, value, child) {
if (value.permissions['recording'] != false) {
return Consumer(
- builder: (context, value, child) => IconButton(
- tooltip: value.start
- ? translate('Stop session recording')
- : translate('Start session recording'),
- onPressed: () => value.toggle(),
- icon: value.start
- ? Icon(
- Icons.pause_circle_filled,
- color: _MenubarTheme.commonColor,
- )
- : SvgPicture.asset(
- "assets/record_screen.svg",
- color: _MenubarTheme.commonColor,
- width: Theme.of(context).iconTheme.size ?? 22.0,
- height: Theme.of(context).iconTheme.size ?? 22.0,
- ),
- ));
+ builder: (context, value, child) => MenuButton(
+ tooltip: value.start
+ ? translate('Stop session recording')
+ : translate('Start session recording'),
+ onPressed: () => value.toggle(),
+ icon: SvgPicture.asset(
+ "assets/rec.svg",
+ color: Colors.white,
+ ),
+ color:
+ value.start ? _MenubarTheme.redColor : _MenubarTheme.blueColor,
+ hoverColor: value.start
+ ? _MenubarTheme.hoverRedColor
+ : _MenubarTheme.hoverBlueColor,
+ ),
+ );
} else {
return Offstage();
}
@@ -679,15 +692,17 @@ class _RemoteMenubarState extends State {
}
Widget _buildClose(BuildContext context) {
- return IconButton(
+ return MenuButton(
tooltip: translate('Close'),
onPressed: () {
clientClose(widget.id, widget.ffi.dialogManager);
},
- icon: const Icon(
- Icons.close,
- color: _MenubarTheme.commonColor,
+ icon: SvgPicture.asset(
+ "assets/close.svg",
+ color: Colors.white,
),
+ color: _MenubarTheme.redColor,
+ hoverColor: _MenubarTheme.hoverRedColor,
);
}
@@ -699,9 +714,7 @@ class _RemoteMenubarState extends State {
padding: EdgeInsets.zero,
icon: SvgPicture.asset(
"assets/chat.svg",
- color: _MenubarTheme.commonColor,
- width: Theme.of(context).iconTheme.size ?? 24.0,
- height: Theme.of(context).iconTheme.size ?? 24.0,
+ color: Colors.white,
),
tooltip: translate('Chat'),
position: mod_menu.PopupMenuPosition.under,
@@ -709,7 +722,7 @@ class _RemoteMenubarState extends State {
.map((entry) => entry.build(
context,
const MenuConfig(
- commonColor: _MenubarTheme.commonColor,
+ commonColor: _MenubarTheme.blueColor,
height: _MenubarTheme.height,
dividerHeight: _MenubarTheme.dividerHeight,
)))
@@ -721,26 +734,15 @@ class _RemoteMenubarState extends State {
Widget _getVoiceCallIcon() {
switch (widget.ffi.chatModel.voiceCallStatus.value) {
case VoiceCallStatus.waitingForResponse:
- return IconButton(
- onPressed: () {
- widget.ffi.chatModel.closeVoiceCall(widget.id);
- },
- icon: SvgPicture.asset(
- "assets/voice_call_waiting.svg",
- color: Colors.red,
- width: Theme.of(context).iconTheme.size ?? 20.0,
- height: Theme.of(context).iconTheme.size ?? 20.0,
- ));
+ return SvgPicture.asset(
+ "assets/call_wait.svg",
+ color: Colors.white,
+ );
+
case VoiceCallStatus.connected:
- return IconButton(
- onPressed: () {
- widget.ffi.chatModel.closeVoiceCall(widget.id);
- },
- icon: Icon(
- Icons.phone_disabled_rounded,
- color: Colors.red,
- size: Theme.of(context).iconTheme.size ?? 22.0,
- ),
+ return SvgPicture.asset(
+ "assets/call_end.svg",
+ color: Colors.white,
);
default:
return const Offstage();
@@ -764,11 +766,12 @@ class _RemoteMenubarState extends State {
final tooltipText = _getVoiceCallTooltip();
return tooltipText == null
? const Offstage()
- : IconButton(
- padding: EdgeInsets.zero,
+ : MenuButton(
icon: _getVoiceCallIcon(),
tooltip: translate(tooltipText),
onPressed: () => bind.sessionRequestVoiceCall(id: widget.id),
+ color: _MenubarTheme.redColor,
+ hoverColor: _MenubarTheme.hoverRedColor,
);
},
);
@@ -1754,7 +1757,7 @@ class _DraggableShowHideState extends State<_DraggableShowHide> {
child: Icon(
Icons.drag_indicator,
size: 20,
- color: Colors.grey,
+ color: Colors.grey[800],
),
feedback: widget,
onDragStarted: (() {
@@ -1807,7 +1810,9 @@ class _DraggableShowHideState extends State<_DraggableShowHide> {
child: Container(
decoration: BoxDecoration(
color: Colors.white,
- border: Border.all(color: MyTheme.border),
+ borderRadius: BorderRadius.vertical(
+ bottom: Radius.circular(5),
+ ),
),
child: SizedBox(
height: 20,