Merge remote-tracking branch 'github/master' into sigma

This commit is contained in:
sjpark
2023-02-09 11:53:04 +09:00
38 changed files with 498 additions and 339 deletions

View File

@@ -64,23 +64,17 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
@override
Widget build(BuildContext context) {
final tabWidget = Container(
child: Overlay(initialEntries: [
OverlayEntry(builder: (context) {
gFFI.dialogManager.setOverlayState(Overlay.of(context));
return Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: DesktopTab(
controller: tabController,
tail: ActionIcon(
message: 'Settings',
icon: IconFont.menu,
onTap: DesktopTabPage.onAddSetting,
isClose: false,
),
));
})
]),
);
child: Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: DesktopTab(
controller: tabController,
tail: ActionIcon(
message: 'Settings',
icon: IconFont.menu,
onTap: DesktopTabPage.onAddSetting,
isClose: false,
),
)));
return Platform.isMacOS
? tabWidget
: Obx(

View File

@@ -80,6 +80,7 @@ class _FileManagerPageState extends State<FileManagerPage>
Entry? _lastClickEntry;
final _dropMaskVisible = false.obs; // TODO impl drop mask
final _overlayKeyState = OverlayKeyState();
ScrollController getBreadCrumbScrollController(bool isLocal) {
return isLocal ? _breadCrumbScrollerLocal : _breadCrumbScrollerRemote;
@@ -115,6 +116,7 @@ class _FileManagerPageState extends State<FileManagerPage>
// register location listener
_locationNodeLocal.addListener(onLocalLocationFocusChanged);
_locationNodeRemote.addListener(onRemoteLocationFocusChanged);
_ffi.dialogManager.setOverlayState(_overlayKeyState);
}
@override
@@ -137,9 +139,8 @@ class _FileManagerPageState extends State<FileManagerPage>
@override
Widget build(BuildContext context) {
super.build(context);
return Overlay(initialEntries: [
OverlayEntry(builder: (context) {
_ffi.dialogManager.setOverlayState(Overlay.of(context));
return Overlay(key: _overlayKeyState.key, initialEntries: [
OverlayEntry(builder: (_) {
return ChangeNotifierProvider.value(
value: _ffi.fileModel,
child: Consumer<FileModel>(builder: (context, model, child) {

View File

@@ -61,6 +61,8 @@ class _RemotePageState extends State<RemotePage>
late RxBool _remoteCursorMoved;
late RxBool _keyboardEnabled;
final _blockableOverlayState = BlockableOverlayState();
final FocusNode _rawKeyFocusNode = FocusNode(debugLabel: "rawkeyFocusNode");
Function(bool)? _onEnterOrLeaveImage4Menubar;
@@ -132,6 +134,13 @@ class _RemotePageState extends State<RemotePage>
// });
// _isCustomCursorInited = true;
// }
_ffi.dialogManager.setOverlayState(_blockableOverlayState);
_ffi.chatModel.setOverlayState(_blockableOverlayState);
// make remote page penetrable automatically, effective for chat over remote
_blockableOverlayState.onMiddleBlockedClick = () {
_blockableOverlayState.setMiddleBlocked(false);
};
}
@override
@@ -191,39 +200,50 @@ class _RemotePageState extends State<RemotePage>
Widget buildBody(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: Overlay(
initialEntries: [
OverlayEntry(builder: (context) {
_ffi.chatModel.setOverlayState(Overlay.of(context));
_ffi.dialogManager.setOverlayState(Overlay.of(context));
return Container(
color: Colors.black,
child: RawKeyFocusScope(
focusNode: _rawKeyFocusNode,
onFocusChange: (bool imageFocused) {
debugPrint(
"onFocusChange(window active:${!_isWindowBlur}) $imageFocused");
// See [onWindowBlur].
if (Platform.isWindows) {
if (_isWindowBlur) {
imageFocused = false;
Future.delayed(Duration.zero, () {
_rawKeyFocusNode.unfocus();
});
}
if (imageFocused) {
_ffi.inputModel.enterOrLeave(true);
} else {
_ffi.inputModel.enterOrLeave(false);
}
}
},
inputModel: _ffi.inputModel,
child: getBodyForDesktop(context)));
})
],
));
backgroundColor: Theme.of(context).backgroundColor,
/// the Overlay key will be set with _blockableOverlayState in BlockableOverlay
/// see override build() in [BlockableOverlay]
body: BlockableOverlay(
state: _blockableOverlayState,
underlying: Container(
color: Colors.black,
child: RawKeyFocusScope(
focusNode: _rawKeyFocusNode,
onFocusChange: (bool imageFocused) {
debugPrint(
"onFocusChange(window active:${!_isWindowBlur}) $imageFocused");
// See [onWindowBlur].
if (Platform.isWindows) {
if (_isWindowBlur) {
imageFocused = false;
Future.delayed(Duration.zero, () {
_rawKeyFocusNode.unfocus();
});
}
if (imageFocused) {
_ffi.inputModel.enterOrLeave(true);
} else {
_ffi.inputModel.enterOrLeave(false);
}
}
},
inputModel: _ffi.inputModel,
child: getBodyForDesktop(context))),
upperLayer: [
OverlayEntry(
builder: (context) => RemoteMenubar(
id: widget.id,
ffi: _ffi,
state: widget.menubarState,
onEnterOrLeaveImageSetter: (func) =>
_onEnterOrLeaveImage4Menubar = func,
onEnterOrLeaveImageCleaner: () =>
_onEnterOrLeaveImage4Menubar = null,
))
],
),
);
}
@override
@@ -344,13 +364,6 @@ class _RemotePageState extends State<RemotePage>
QualityMonitor(_ffi.qualityMonitorModel), null, null),
),
);
paints.add(RemoteMenubar(
id: widget.id,
ffi: _ffi,
state: widget.menubarState,
onEnterOrLeaveImageSetter: (func) => _onEnterOrLeaveImage4Menubar = func,
onEnterOrLeaveImageCleaner: () => _onEnterOrLeaveImage4Menubar = null,
));
return Stack(
children: paints,
);

View File

@@ -68,26 +68,19 @@ class _DesktopServerPageState extends State<DesktopServerPage>
],
child: Consumer<ServerModel>(
builder: (context, serverModel, child) => Container(
decoration: BoxDecoration(
border:
Border.all(color: MyTheme.color(context).border!)),
child: Overlay(initialEntries: [
OverlayEntry(builder: (context) {
gFFI.dialogManager.setOverlayState(Overlay.of(context));
return Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(child: ConnectionManager()),
],
),
),
);
})
]),
)));
decoration: BoxDecoration(
border: Border.all(color: MyTheme.color(context).border!)),
child: Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(child: ConnectionManager()),
],
),
),
))));
}
@override

View File

@@ -688,9 +688,11 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
);
}
final _chatButtonKey = GlobalKey();
Widget _buildChat(BuildContext context) {
FfiModel ffiModel = Provider.of<FfiModel>(context);
return mod_menu.PopupMenuButton(
key: _chatButtonKey,
padding: EdgeInsets.zero,
icon: SvgPicture.asset(
"assets/chat.svg",
@@ -779,8 +781,17 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
style: style,
),
proc: () {
RenderBox? renderBox =
_chatButtonKey.currentContext?.findRenderObject() as RenderBox?;
Offset? initPos;
if (renderBox != null) {
final pos = renderBox.localToGlobal(Offset.zero);
initPos = Offset(pos.dx, pos.dy + _MenubarTheme.dividerHeight);
}
widget.ffi.chatModel.changeCurrentID(ChatModel.clientModeID);
widget.ffi.chatModel.toggleChatOverlay();
widget.ffi.chatModel.toggleChatOverlay(chatInitPos: initPos);
},
padding: padding,
dismissOnClicked: true,

View File

@@ -327,14 +327,32 @@ class DesktopTab extends StatelessWidget {
));
}
List<Widget> _tabWidgets = [];
Widget _buildPageView() {
return _buildBlock(
child: Obx(() => PageView(
controller: state.value.pageController,
physics: NeverScrollableScrollPhysics(),
children: state.value.tabs
.map((tab) => tab.page)
.toList(growable: false))));
children: () {
/// to-do refactor, separate connection state and UI state for remote session.
/// [workaround] PageView children need an immutable list, after it has been passed into PageView
final tabLen = state.value.tabs.length;
if (tabLen == _tabWidgets.length) {
return _tabWidgets;
} else if (_tabWidgets.isNotEmpty &&
tabLen == _tabWidgets.length + 1) {
/// On add. Use the previous list(pointer) to prevent item's state init twice.
/// *[_tabWidgets.isNotEmpty] means TabsWindow(remote_tab_page or file_manager_tab_page) opened before, but was hidden. In this case, we have to reload, otherwise the child can't be built.
_tabWidgets.add(state.value.tabs.last.page);
return _tabWidgets;
} else {
/// On remove or change. Use new list(pointer) to reload list children so that items loading order is normal.
/// the Widgets in list must enable [AutomaticKeepAliveClientMixin]
final newList = state.value.tabs.map((v) => v.page).toList();
_tabWidgets = newList;
return newList;
}
}())));
}
/// Check whether to show ListView
@@ -767,7 +785,8 @@ class _ListView extends StatelessWidget {
tabBuilder: tabBuilder,
tabMenuBuilder: tabMenuBuilder,
maxLabelWidth: maxLabelWidth,
selectedTabBackgroundColor: selectedTabBackgroundColor ?? MyTheme.tabbar(context).selectedTabBackgroundColor,
selectedTabBackgroundColor: selectedTabBackgroundColor ??
MyTheme.tabbar(context).selectedTabBackgroundColor,
unSelectedTabBackgroundColor: unSelectedTabBackgroundColor,
);
}).toList()));
@@ -1121,7 +1140,8 @@ class TabbarTheme extends ThemeExtension<TabbarTheme> {
dividerColor: dividerColor ?? this.dividerColor,
hoverColor: hoverColor ?? this.hoverColor,
closeHoverColor: closeHoverColor ?? this.closeHoverColor,
selectedTabBackgroundColor: selectedTabBackgroundColor ?? this.selectedTabBackgroundColor,
selectedTabBackgroundColor:
selectedTabBackgroundColor ?? this.selectedTabBackgroundColor,
);
}
@@ -1147,7 +1167,8 @@ class TabbarTheme extends ThemeExtension<TabbarTheme> {
dividerColor: Color.lerp(dividerColor, other.dividerColor, t),
hoverColor: Color.lerp(hoverColor, other.hoverColor, t),
closeHoverColor: Color.lerp(closeHoverColor, other.closeHoverColor, t),
selectedTabBackgroundColor: Color.lerp(selectedTabBackgroundColor, other.selectedTabBackgroundColor, t),
selectedTabBackgroundColor: Color.lerp(
selectedTabBackgroundColor, other.selectedTabBackgroundColor, t),
);
}