refactor OverlayKeyState for OverlayDialogManager and ChatModel
This commit is contained in:
parent
0dba013089
commit
3d5aca18d6
@ -369,20 +369,25 @@ class Dialog<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class OverlayKeyState {
|
||||||
|
final _overlayKey = GlobalKey<OverlayState>();
|
||||||
|
|
||||||
|
/// use global overlay by default
|
||||||
|
OverlayState? get state =>
|
||||||
|
_overlayKey.currentState ?? globalKey.currentState?.overlay;
|
||||||
|
|
||||||
|
GlobalKey<OverlayState>? get key => _overlayKey;
|
||||||
|
}
|
||||||
|
|
||||||
class OverlayDialogManager {
|
class OverlayDialogManager {
|
||||||
OverlayState? _overlayState;
|
|
||||||
final Map<String, Dialog> _dialogs = {};
|
final Map<String, Dialog> _dialogs = {};
|
||||||
|
var _overlayKeyState = OverlayKeyState();
|
||||||
int _tagCount = 0;
|
int _tagCount = 0;
|
||||||
|
|
||||||
OverlayEntry? _mobileActionsOverlayEntry;
|
OverlayEntry? _mobileActionsOverlayEntry;
|
||||||
|
|
||||||
/// By default OverlayDialogManager use global overlay
|
void setOverlayState(OverlayKeyState overlayKeyState) {
|
||||||
OverlayDialogManager() {
|
_overlayKeyState = overlayKeyState;
|
||||||
_overlayState = globalKey.currentState?.overlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOverlayState(OverlayState? overlayState) {
|
|
||||||
_overlayState = overlayState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dismissAll() {
|
void dismissAll() {
|
||||||
@ -406,7 +411,7 @@ class OverlayDialogManager {
|
|||||||
bool useAnimation = true,
|
bool useAnimation = true,
|
||||||
bool forceGlobal = false}) {
|
bool forceGlobal = false}) {
|
||||||
final overlayState =
|
final overlayState =
|
||||||
forceGlobal ? globalKey.currentState?.overlay : _overlayState;
|
forceGlobal ? globalKey.currentState?.overlay : _overlayKeyState.state;
|
||||||
|
|
||||||
if (overlayState == null) {
|
if (overlayState == null) {
|
||||||
return Future.error(
|
return Future.error(
|
||||||
@ -510,7 +515,8 @@ class OverlayDialogManager {
|
|||||||
|
|
||||||
void showMobileActionsOverlay({FFI? ffi}) {
|
void showMobileActionsOverlay({FFI? ffi}) {
|
||||||
if (_mobileActionsOverlayEntry != null) return;
|
if (_mobileActionsOverlayEntry != null) return;
|
||||||
if (_overlayState == null) return;
|
final overlayState = _overlayKeyState.state;
|
||||||
|
if (overlayState == null) return;
|
||||||
|
|
||||||
// compute overlay position
|
// compute overlay position
|
||||||
final screenW = MediaQuery.of(globalKey.currentContext!).size.width;
|
final screenW = MediaQuery.of(globalKey.currentContext!).size.width;
|
||||||
@ -536,7 +542,7 @@ class OverlayDialogManager {
|
|||||||
onHidePressed: () => hideMobileActionsOverlay(),
|
onHidePressed: () => hideMobileActionsOverlay(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
_overlayState!.insert(overlay);
|
overlayState.insert(overlay);
|
||||||
_mobileActionsOverlayEntry = overlay;
|
_mobileActionsOverlayEntry = overlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1701,4 +1707,4 @@ Future<void> updateSystemWindowTheme() async {
|
|||||||
: SystemWindowTheme.dark);
|
: SystemWindowTheme.dark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -372,25 +372,12 @@ class QualityMonitor extends StatelessWidget {
|
|||||||
: const SizedBox.shrink()));
|
: const SizedBox.shrink()));
|
||||||
}
|
}
|
||||||
|
|
||||||
class PenetrableOverlayState {
|
class BlockableOverlayState extends OverlayKeyState {
|
||||||
final _middleBlocked = false.obs;
|
final _middleBlocked = false.obs;
|
||||||
final _overlayKey = GlobalKey<OverlayState>();
|
|
||||||
|
|
||||||
VoidCallback? onMiddleBlockedClick; // to-do use listener
|
VoidCallback? onMiddleBlockedClick; // to-do use listener
|
||||||
|
|
||||||
RxBool get middleBlocked => _middleBlocked;
|
RxBool get middleBlocked => _middleBlocked;
|
||||||
GlobalKey get overlayKey => _overlayKey;
|
|
||||||
OverlayState? get overlayState => _overlayKey.currentState;
|
|
||||||
|
|
||||||
OverlayState? getOverlayStateOrGlobal() {
|
|
||||||
if (overlayState == null) {
|
|
||||||
if (globalKey.currentState == null ||
|
|
||||||
globalKey.currentState!.overlay == null) return null;
|
|
||||||
return globalKey.currentState!.overlay;
|
|
||||||
} else {
|
|
||||||
return overlayState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addMiddleBlockedListener(void Function(bool) cb) {
|
void addMiddleBlockedListener(void Function(bool) cb) {
|
||||||
_middleBlocked.listen(cb);
|
_middleBlocked.listen(cb);
|
||||||
@ -403,13 +390,13 @@ class PenetrableOverlayState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PenetrableOverlay extends StatelessWidget {
|
class BlockableOverlay extends StatelessWidget {
|
||||||
final Widget underlying;
|
final Widget underlying;
|
||||||
final List<OverlayEntry>? upperLayer;
|
final List<OverlayEntry>? upperLayer;
|
||||||
|
|
||||||
final PenetrableOverlayState state;
|
final BlockableOverlayState state;
|
||||||
|
|
||||||
PenetrableOverlay(
|
BlockableOverlay(
|
||||||
{required this.underlying, required this.state, this.upperLayer});
|
{required this.underlying, required this.state, this.upperLayer});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -433,6 +420,7 @@ class PenetrableOverlay extends StatelessWidget {
|
|||||||
initialEntries.addAll(upperLayer!);
|
initialEntries.addAll(upperLayer!);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Overlay(key: state.overlayKey, initialEntries: initialEntries);
|
/// set key
|
||||||
|
return Overlay(key: state.key, initialEntries: initialEntries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
Entry? _lastClickEntry;
|
Entry? _lastClickEntry;
|
||||||
|
|
||||||
final _dropMaskVisible = false.obs; // TODO impl drop mask
|
final _dropMaskVisible = false.obs; // TODO impl drop mask
|
||||||
|
final _overlayKeyState = OverlayKeyState();
|
||||||
|
|
||||||
ScrollController getBreadCrumbScrollController(bool isLocal) {
|
ScrollController getBreadCrumbScrollController(bool isLocal) {
|
||||||
return isLocal ? _breadCrumbScrollerLocal : _breadCrumbScrollerRemote;
|
return isLocal ? _breadCrumbScrollerLocal : _breadCrumbScrollerRemote;
|
||||||
@ -115,6 +116,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
// register location listener
|
// register location listener
|
||||||
_locationNodeLocal.addListener(onLocalLocationFocusChanged);
|
_locationNodeLocal.addListener(onLocalLocationFocusChanged);
|
||||||
_locationNodeRemote.addListener(onRemoteLocationFocusChanged);
|
_locationNodeRemote.addListener(onRemoteLocationFocusChanged);
|
||||||
|
_ffi.dialogManager.setOverlayState(_overlayKeyState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -137,9 +139,8 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
return Overlay(initialEntries: [
|
return Overlay(key: _overlayKeyState.key, initialEntries: [
|
||||||
OverlayEntry(builder: (context) {
|
OverlayEntry(builder: (_) {
|
||||||
_ffi.dialogManager.setOverlayState(Overlay.of(context));
|
|
||||||
return ChangeNotifierProvider.value(
|
return ChangeNotifierProvider.value(
|
||||||
value: _ffi.fileModel,
|
value: _ffi.fileModel,
|
||||||
child: Consumer<FileModel>(builder: (context, model, child) {
|
child: Consumer<FileModel>(builder: (context, model, child) {
|
||||||
|
@ -62,7 +62,7 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
late RxBool _remoteCursorMoved;
|
late RxBool _remoteCursorMoved;
|
||||||
late RxBool _keyboardEnabled;
|
late RxBool _keyboardEnabled;
|
||||||
|
|
||||||
final overlayState = PenetrableOverlayState();
|
final _blockableOverlayState = BlockableOverlayState();
|
||||||
|
|
||||||
final FocusNode _rawKeyFocusNode = FocusNode(debugLabel: "rawkeyFocusNode");
|
final FocusNode _rawKeyFocusNode = FocusNode(debugLabel: "rawkeyFocusNode");
|
||||||
|
|
||||||
@ -136,10 +136,11 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
// _isCustomCursorInited = true;
|
// _isCustomCursorInited = true;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
_ffi.chatModel.setPenetrableOverlayState(overlayState);
|
_ffi.dialogManager.setOverlayState(_blockableOverlayState);
|
||||||
|
_ffi.chatModel.setOverlayState(_blockableOverlayState);
|
||||||
// make remote page penetrable automatically, effective for chat over remote
|
// make remote page penetrable automatically, effective for chat over remote
|
||||||
overlayState.onMiddleBlockedClick = () {
|
_blockableOverlayState.onMiddleBlockedClick = () {
|
||||||
overlayState.setMiddleBlocked(false);
|
_blockableOverlayState.setMiddleBlocked(false);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,8 +202,11 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
Widget buildBody(BuildContext context) {
|
Widget buildBody(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Theme.of(context).backgroundColor,
|
backgroundColor: Theme.of(context).backgroundColor,
|
||||||
body: PenetrableOverlay(
|
|
||||||
state: overlayState,
|
/// the Overlay key will be set with _blockableOverlayState in BlockableOverlay
|
||||||
|
/// see override build() in [BlockableOverlay]
|
||||||
|
body: BlockableOverlay(
|
||||||
|
state: _blockableOverlayState,
|
||||||
underlying: Container(
|
underlying: Container(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
child: RawKeyFocusScope(
|
child: RawKeyFocusScope(
|
||||||
|
@ -34,7 +34,7 @@ class ChatModel with ChangeNotifier {
|
|||||||
bool isConnManager = false;
|
bool isConnManager = false;
|
||||||
|
|
||||||
RxBool isWindowFocus = true.obs;
|
RxBool isWindowFocus = true.obs;
|
||||||
PenetrableOverlayState? pOverlayState;
|
BlockableOverlayState? _blockableOverlayState;
|
||||||
|
|
||||||
final ChatUser me = ChatUser(
|
final ChatUser me = ChatUser(
|
||||||
id: "",
|
id: "",
|
||||||
@ -53,10 +53,10 @@ class ChatModel with ChangeNotifier {
|
|||||||
|
|
||||||
bool get isShowCMChatPage => _isShowCMChatPage;
|
bool get isShowCMChatPage => _isShowCMChatPage;
|
||||||
|
|
||||||
void setPenetrableOverlayState(PenetrableOverlayState state) {
|
void setOverlayState(BlockableOverlayState blockableOverlayState) {
|
||||||
pOverlayState = state;
|
_blockableOverlayState = blockableOverlayState;
|
||||||
|
|
||||||
pOverlayState!.addMiddleBlockedListener((v) {
|
_blockableOverlayState!.addMiddleBlockedListener((v) {
|
||||||
if (!v) {
|
if (!v) {
|
||||||
isWindowFocus.value = false;
|
isWindowFocus.value = false;
|
||||||
if (isWindowFocus.value) {
|
if (isWindowFocus.value) {
|
||||||
@ -94,7 +94,7 @@ class ChatModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final overlayState = pOverlayState?.getOverlayStateOrGlobal();
|
final overlayState = _blockableOverlayState?.state;
|
||||||
if (overlayState == null) return;
|
if (overlayState == null) return;
|
||||||
|
|
||||||
final overlay = OverlayEntry(builder: (context) {
|
final overlay = OverlayEntry(builder: (context) {
|
||||||
@ -129,16 +129,16 @@ class ChatModel with ChangeNotifier {
|
|||||||
showChatWindowOverlay({Offset? chatInitPos}) {
|
showChatWindowOverlay({Offset? chatInitPos}) {
|
||||||
if (chatWindowOverlayEntry != null) return;
|
if (chatWindowOverlayEntry != null) return;
|
||||||
isWindowFocus.value = true;
|
isWindowFocus.value = true;
|
||||||
pOverlayState?.setMiddleBlocked(true);
|
_blockableOverlayState?.setMiddleBlocked(true);
|
||||||
|
|
||||||
final overlayState = pOverlayState?.getOverlayStateOrGlobal();
|
final overlayState = _blockableOverlayState?.state;
|
||||||
if (overlayState == null) return;
|
if (overlayState == null) return;
|
||||||
final overlay = OverlayEntry(builder: (context) {
|
final overlay = OverlayEntry(builder: (context) {
|
||||||
return Listener(
|
return Listener(
|
||||||
onPointerDown: (_) {
|
onPointerDown: (_) {
|
||||||
if (!isWindowFocus.value) {
|
if (!isWindowFocus.value) {
|
||||||
isWindowFocus.value = true;
|
isWindowFocus.value = true;
|
||||||
pOverlayState?.setMiddleBlocked(true);
|
_blockableOverlayState?.setMiddleBlocked(true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: DraggableChatWindow(
|
child: DraggableChatWindow(
|
||||||
@ -154,7 +154,7 @@ class ChatModel with ChangeNotifier {
|
|||||||
|
|
||||||
hideChatWindowOverlay() {
|
hideChatWindowOverlay() {
|
||||||
if (chatWindowOverlayEntry != null) {
|
if (chatWindowOverlayEntry != null) {
|
||||||
pOverlayState?.setMiddleBlocked(false);
|
_blockableOverlayState?.setMiddleBlocked(false);
|
||||||
chatWindowOverlayEntry!.remove();
|
chatWindowOverlayEntry!.remove();
|
||||||
chatWindowOverlayEntry = null;
|
chatWindowOverlayEntry = null;
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user