main window add block mask, cm add keyboard block (#8640)

* block window body only so user can still click minisize button.
* cm doesn't show mask
* Remove focusable Offstage in tabbar_widget.dart

Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
21pages 2024-07-08 20:08:05 +08:00 committed by GitHub
parent eb5ab4d7d9
commit af66d2a73b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 162 additions and 135 deletions

View File

@ -2715,15 +2715,21 @@ Future<void> shouldBeBlocked(RxBool block, WhetherUseRemoteBlock? use) async {
} }
typedef WhetherUseRemoteBlock = Future<bool> Function(); typedef WhetherUseRemoteBlock = Future<bool> Function();
Widget buildRemoteBlock({required Widget child, WhetherUseRemoteBlock? use}) { Widget buildRemoteBlock(
var block = false.obs; {required Widget child,
required RxBool block,
required bool mask,
WhetherUseRemoteBlock? use}) {
return Obx(() => MouseRegion( return Obx(() => MouseRegion(
onEnter: (_) async { onEnter: (_) async {
await shouldBeBlocked(block, use); await shouldBeBlocked(block, use);
}, },
onExit: (event) => block.value = false, onExit: (event) => block.value = false,
child: Stack(children: [ child: Stack(children: [
child, // scope block tab
FocusScope(child: child, canRequestFocus: !block.value),
// mask block click, cm not block click and still use check_click_time to avoid block local click
if (mask)
Offstage( Offstage(
offstage: !block.value, offstage: !block.value,
child: Container( child: Container(

View File

@ -116,22 +116,14 @@ class _DesktopTabPageState extends State<DesktopTabPage>
isClose: false, isClose: false,
), ),
), ),
blockTab: _block,
))); )));
widget() => MouseRegion(
onEnter: (_) async {
// mouseIn = true;
await shouldBeBlocked(_block, canBeBlocked);
},
onExit: (_) {
// mouseIn = false;
},
child: FocusScope(child: tabWidget, canRequestFocus: !_block.value));
return isMacOS || kUseCompatibleUiMode return isMacOS || kUseCompatibleUiMode
? Obx(() => widget()) ? Obx(() => tabWidget)
: Obx( : Obx(
() => DragToResizeArea( () => DragToResizeArea(
resizeEdgeSize: stateGlobal.resizeEdgeSize.value, resizeEdgeSize: stateGlobal.resizeEdgeSize.value,
child: widget(), child: tabWidget,
), ),
); );
} }

View File

@ -104,7 +104,18 @@ class ConnectionManager extends StatefulWidget {
State<StatefulWidget> createState() => ConnectionManagerState(); State<StatefulWidget> createState() => ConnectionManagerState();
} }
class ConnectionManagerState extends State<ConnectionManager> { class ConnectionManagerState extends State<ConnectionManager>
with WidgetsBindingObserver {
final RxBool _block = false.obs;
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.resumed) {
shouldBeBlocked(_block, null);
}
}
@override @override
void initState() { void initState() {
gFFI.serverModel.updateClientState(); gFFI.serverModel.updateClientState();
@ -127,9 +138,16 @@ class ConnectionManagerState extends State<ConnectionManager> {
} }
}; };
gFFI.chatModel.isConnManager = true; gFFI.chatModel.isConnManager = true;
WidgetsBinding.instance.addObserver(this);
super.initState(); super.initState();
} }
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final serverModel = Provider.of<ServerModel>(context); final serverModel = Provider.of<ServerModel>(context);
@ -165,6 +183,7 @@ class ConnectionManagerState extends State<ConnectionManager> {
selectedBorderColor: MyTheme.accent, selectedBorderColor: MyTheme.accent,
maxLabelWidth: 100, maxLabelWidth: 100,
tail: null, //buildScrollJumper(), tail: null, //buildScrollJumper(),
blockTab: _block,
selectedTabBackgroundColor: selectedTabBackgroundColor:
Theme.of(context).hintColor.withOpacity(0), Theme.of(context).hintColor.withOpacity(0),
tabBuilder: (key, icon, label, themeConf) { tabBuilder: (key, icon, label, themeConf) {
@ -208,14 +227,9 @@ class ConnectionManagerState extends State<ConnectionManager> {
builder: (_, model, child) => SizedBox( builder: (_, model, child) => SizedBox(
width: realChatPageWidth, width: realChatPageWidth,
child: buildRemoteBlock( child: buildRemoteBlock(
child: Container( child: buildSidePage(),
decoration: BoxDecoration( block: _block,
border: Border( mask: true),
right: BorderSide(
color: Theme.of(context)
.dividerColor))),
child: buildSidePage()),
),
)), )),
SizedBox( SizedBox(
width: realClosedWidth, width: realClosedWidth,

View File

@ -248,6 +248,7 @@ class DesktopTab extends StatelessWidget {
final Color? selectedTabBackgroundColor; final Color? selectedTabBackgroundColor;
final Color? unSelectedTabBackgroundColor; final Color? unSelectedTabBackgroundColor;
final Color? selectedBorderColor; final Color? selectedBorderColor;
final RxBool? blockTab;
final DesktopTabController controller; final DesktopTabController controller;
@ -277,6 +278,7 @@ class DesktopTab extends StatelessWidget {
this.selectedTabBackgroundColor, this.selectedTabBackgroundColor,
this.unSelectedTabBackgroundColor, this.unSelectedTabBackgroundColor,
this.selectedBorderColor, this.selectedBorderColor,
this.blockTab,
}) : super(key: key) { }) : super(key: key) {
tabType = controller.tabType; tabType = controller.tabType;
isMainWindow = tabType == DesktopTabType.main || isMainWindow = tabType == DesktopTabType.main ||
@ -292,10 +294,10 @@ class DesktopTab extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column(children: [ return Column(children: [
Obx(() => Offstage( Obx(() {
offstage: !stateGlobal.showTabBar.isTrue || if (stateGlobal.showTabBar.isTrue &&
(kUseCompatibleUiMode && isHideSingleItem()), !(kUseCompatibleUiMode && isHideSingleItem())) {
child: SizedBox( return SizedBox(
height: _kTabBarHeight, height: _kTabBarHeight,
child: Column( child: Column(
children: [ children: [
@ -308,7 +310,11 @@ class DesktopTab extends StatelessWidget {
), ),
], ],
), ),
))), );
} else {
return Offstage();
}
}),
Expanded( Expanded(
child: pageViewBuilder != null child: pageViewBuilder != null
? pageViewBuilder!(_buildPageView()) ? pageViewBuilder!(_buildPageView())
@ -317,10 +323,15 @@ class DesktopTab extends StatelessWidget {
} }
Widget _buildBlock({required Widget child}) { Widget _buildBlock({required Widget child}) {
if (tabType != DesktopTabType.main) { if (blockTab != null) {
return buildRemoteBlock(
child: child,
block: blockTab!,
use: canBeBlocked,
mask: tabType == DesktopTabType.main);
} else {
return child; return child;
} }
return buildRemoteBlock(child: child, use: canBeBlocked);
} }
List<Widget> _tabWidgets = []; List<Widget> _tabWidgets = [];
@ -703,22 +714,22 @@ class WindowActionPanelState extends State<WindowActionPanel>
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Obx(() => Offstage( Obx(() {
offstage: if (showTabDowndown() && existingInvisibleTab().isNotEmpty) {
!(showTabDowndown() && existingInvisibleTab().isNotEmpty), return _TabDropDownButton(
child: _TabDropDownButton(
controller: widget.tabController, controller: widget.tabController,
labelGetter: widget.labelGetter, labelGetter: widget.labelGetter,
tabkeys: existingInvisibleTab()), tabkeys: existingInvisibleTab());
)), } else {
Offstage(offstage: widget.tail == null, child: widget.tail), return Offstage();
Offstage( }
offstage: kUseCompatibleUiMode, }),
child: Row( if (widget.tail != null) widget.tail!,
if (!kUseCompatibleUiMode)
Row(
children: [ children: [
Offstage( if (widget.showMinimize && !isMacOS)
offstage: !widget.showMinimize || isMacOS, ActionIcon(
child: ActionIcon(
message: 'Minimize', message: 'Minimize',
icon: IconFont.min, icon: IconFont.min,
onTap: () { onTap: () {
@ -729,10 +740,9 @@ class WindowActionPanelState extends State<WindowActionPanel>
} }
}, },
isClose: false, isClose: false,
)), ),
Offstage( if (widget.showMaximize && !isMacOS)
offstage: !widget.showMaximize || isMacOS, Obx(() => ActionIcon(
child: Obx(() => ActionIcon(
message: stateGlobal.isMaximized.isTrue message: stateGlobal.isMaximized.isTrue
? 'Restore' ? 'Restore'
: 'Maximize', : 'Maximize',
@ -743,10 +753,9 @@ class WindowActionPanelState extends State<WindowActionPanel>
? null ? null
: _toggleMaximize, : _toggleMaximize,
isClose: false, isClose: false,
))), )),
Offstage( if (widget.showClose && !isMacOS)
offstage: !widget.showClose || isMacOS, ActionIcon(
child: ActionIcon(
message: 'Close', message: 'Close',
icon: IconFont.close, icon: IconFont.close,
onTap: () async { onTap: () async {
@ -765,10 +774,9 @@ class WindowActionPanelState extends State<WindowActionPanel>
} }
}, },
isClose: true, isClose: true,
)) )
], ],
), ),
),
], ],
); );
} }
@ -1173,9 +1181,9 @@ class _CloseButton extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SizedBox( return SizedBox(
width: _kIconSize, width: _kIconSize,
child: Offstage( child: () {
offstage: !visible, if (visible) {
child: InkWell( return InkWell(
hoverColor: MyTheme.tabbar(context).closeHoverColor, hoverColor: MyTheme.tabbar(context).closeHoverColor,
customBorder: const CircleBorder(), customBorder: const CircleBorder(),
onTap: () => onClose(), onTap: () => onClose(),
@ -1186,8 +1194,12 @@ class _CloseButton extends StatelessWidget {
? MyTheme.tabbar(context).selectedIconColor ? MyTheme.tabbar(context).selectedIconColor
: MyTheme.tabbar(context).unSelectedIconColor, : MyTheme.tabbar(context).unSelectedIconColor,
), ),
), );
)).paddingOnly(left: 10); } else {
return Offstage();
}
}())
.paddingOnly(left: 10);
} }
} }
@ -1341,10 +1353,10 @@ class _TabDropDownButtonState extends State<_TabDropDownButton> {
child: InkWell(child: Text(label)), child: InkWell(child: Text(label)),
), ),
Obx( Obx(
() => Offstage( () {
offstage: !(tabInfo?.onTabCloseButton != null && if (tabInfo?.onTabCloseButton != null &&
menuHover.value), menuHover.value) {
child: InkWell( return InkWell(
onTap: () { onTap: () {
tabInfo?.onTabCloseButton?.call(); tabInfo?.onTabCloseButton?.call();
if (Navigator.of(context).canPop()) { if (Navigator.of(context).canPop()) {
@ -1359,9 +1371,12 @@ class _TabDropDownButtonState extends State<_TabDropDownButton> {
setState(() => btnHover.value = false), setState(() => btnHover.value = false),
child: Icon(Icons.close, child: Icon(Icons.close,
color: color:
btnHover.value ? Colors.red : null))), btnHover.value ? Colors.red : null)));
} else {
return Offstage();
}
},
), ),
)
], ],
), ),
), ),