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 {
|
||||
OverlayState? _overlayState;
|
||||
final Map<String, Dialog> _dialogs = {};
|
||||
var _overlayKeyState = OverlayKeyState();
|
||||
int _tagCount = 0;
|
||||
|
||||
OverlayEntry? _mobileActionsOverlayEntry;
|
||||
|
||||
/// By default OverlayDialogManager use global overlay
|
||||
OverlayDialogManager() {
|
||||
_overlayState = globalKey.currentState?.overlay;
|
||||
}
|
||||
|
||||
void setOverlayState(OverlayState? overlayState) {
|
||||
_overlayState = overlayState;
|
||||
void setOverlayState(OverlayKeyState overlayKeyState) {
|
||||
_overlayKeyState = overlayKeyState;
|
||||
}
|
||||
|
||||
void dismissAll() {
|
||||
@ -406,7 +411,7 @@ class OverlayDialogManager {
|
||||
bool useAnimation = true,
|
||||
bool forceGlobal = false}) {
|
||||
final overlayState =
|
||||
forceGlobal ? globalKey.currentState?.overlay : _overlayState;
|
||||
forceGlobal ? globalKey.currentState?.overlay : _overlayKeyState.state;
|
||||
|
||||
if (overlayState == null) {
|
||||
return Future.error(
|
||||
@ -510,7 +515,8 @@ class OverlayDialogManager {
|
||||
|
||||
void showMobileActionsOverlay({FFI? ffi}) {
|
||||
if (_mobileActionsOverlayEntry != null) return;
|
||||
if (_overlayState == null) return;
|
||||
final overlayState = _overlayKeyState.state;
|
||||
if (overlayState == null) return;
|
||||
|
||||
// compute overlay position
|
||||
final screenW = MediaQuery.of(globalKey.currentContext!).size.width;
|
||||
@ -536,7 +542,7 @@ class OverlayDialogManager {
|
||||
onHidePressed: () => hideMobileActionsOverlay(),
|
||||
);
|
||||
});
|
||||
_overlayState!.insert(overlay);
|
||||
overlayState.insert(overlay);
|
||||
_mobileActionsOverlayEntry = overlay;
|
||||
}
|
||||
|
||||
@ -1701,4 +1707,4 @@ Future<void> updateSystemWindowTheme() async {
|
||||
: SystemWindowTheme.dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -372,25 +372,12 @@ class QualityMonitor extends StatelessWidget {
|
||||
: const SizedBox.shrink()));
|
||||
}
|
||||
|
||||
class PenetrableOverlayState {
|
||||
class BlockableOverlayState extends OverlayKeyState {
|
||||
final _middleBlocked = false.obs;
|
||||
final _overlayKey = GlobalKey<OverlayState>();
|
||||
|
||||
VoidCallback? onMiddleBlockedClick; // to-do use listener
|
||||
|
||||
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) {
|
||||
_middleBlocked.listen(cb);
|
||||
@ -403,13 +390,13 @@ class PenetrableOverlayState {
|
||||
}
|
||||
}
|
||||
|
||||
class PenetrableOverlay extends StatelessWidget {
|
||||
class BlockableOverlay extends StatelessWidget {
|
||||
final Widget underlying;
|
||||
final List<OverlayEntry>? upperLayer;
|
||||
|
||||
final PenetrableOverlayState state;
|
||||
final BlockableOverlayState state;
|
||||
|
||||
PenetrableOverlay(
|
||||
BlockableOverlay(
|
||||
{required this.underlying, required this.state, this.upperLayer});
|
||||
|
||||
@override
|
||||
@ -433,6 +420,7 @@ class PenetrableOverlay extends StatelessWidget {
|
||||
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;
|
||||
|
||||
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) {
|
||||
|
@ -62,7 +62,7 @@ class _RemotePageState extends State<RemotePage>
|
||||
late RxBool _remoteCursorMoved;
|
||||
late RxBool _keyboardEnabled;
|
||||
|
||||
final overlayState = PenetrableOverlayState();
|
||||
final _blockableOverlayState = BlockableOverlayState();
|
||||
|
||||
final FocusNode _rawKeyFocusNode = FocusNode(debugLabel: "rawkeyFocusNode");
|
||||
|
||||
@ -136,10 +136,11 @@ class _RemotePageState extends State<RemotePage>
|
||||
// _isCustomCursorInited = true;
|
||||
// }
|
||||
|
||||
_ffi.chatModel.setPenetrableOverlayState(overlayState);
|
||||
_ffi.dialogManager.setOverlayState(_blockableOverlayState);
|
||||
_ffi.chatModel.setOverlayState(_blockableOverlayState);
|
||||
// make remote page penetrable automatically, effective for chat over remote
|
||||
overlayState.onMiddleBlockedClick = () {
|
||||
overlayState.setMiddleBlocked(false);
|
||||
_blockableOverlayState.onMiddleBlockedClick = () {
|
||||
_blockableOverlayState.setMiddleBlocked(false);
|
||||
};
|
||||
}
|
||||
|
||||
@ -201,8 +202,11 @@ class _RemotePageState extends State<RemotePage>
|
||||
Widget buildBody(BuildContext context) {
|
||||
return Scaffold(
|
||||
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(
|
||||
color: Colors.black,
|
||||
child: RawKeyFocusScope(
|
||||
|
@ -34,7 +34,7 @@ class ChatModel with ChangeNotifier {
|
||||
bool isConnManager = false;
|
||||
|
||||
RxBool isWindowFocus = true.obs;
|
||||
PenetrableOverlayState? pOverlayState;
|
||||
BlockableOverlayState? _blockableOverlayState;
|
||||
|
||||
final ChatUser me = ChatUser(
|
||||
id: "",
|
||||
@ -53,10 +53,10 @@ class ChatModel with ChangeNotifier {
|
||||
|
||||
bool get isShowCMChatPage => _isShowCMChatPage;
|
||||
|
||||
void setPenetrableOverlayState(PenetrableOverlayState state) {
|
||||
pOverlayState = state;
|
||||
void setOverlayState(BlockableOverlayState blockableOverlayState) {
|
||||
_blockableOverlayState = blockableOverlayState;
|
||||
|
||||
pOverlayState!.addMiddleBlockedListener((v) {
|
||||
_blockableOverlayState!.addMiddleBlockedListener((v) {
|
||||
if (!v) {
|
||||
isWindowFocus.value = false;
|
||||
if (isWindowFocus.value) {
|
||||
@ -94,7 +94,7 @@ class ChatModel with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
final overlayState = pOverlayState?.getOverlayStateOrGlobal();
|
||||
final overlayState = _blockableOverlayState?.state;
|
||||
if (overlayState == null) return;
|
||||
|
||||
final overlay = OverlayEntry(builder: (context) {
|
||||
@ -129,16 +129,16 @@ class ChatModel with ChangeNotifier {
|
||||
showChatWindowOverlay({Offset? chatInitPos}) {
|
||||
if (chatWindowOverlayEntry != null) return;
|
||||
isWindowFocus.value = true;
|
||||
pOverlayState?.setMiddleBlocked(true);
|
||||
_blockableOverlayState?.setMiddleBlocked(true);
|
||||
|
||||
final overlayState = pOverlayState?.getOverlayStateOrGlobal();
|
||||
final overlayState = _blockableOverlayState?.state;
|
||||
if (overlayState == null) return;
|
||||
final overlay = OverlayEntry(builder: (context) {
|
||||
return Listener(
|
||||
onPointerDown: (_) {
|
||||
if (!isWindowFocus.value) {
|
||||
isWindowFocus.value = true;
|
||||
pOverlayState?.setMiddleBlocked(true);
|
||||
_blockableOverlayState?.setMiddleBlocked(true);
|
||||
}
|
||||
},
|
||||
child: DraggableChatWindow(
|
||||
@ -154,7 +154,7 @@ class ChatModel with ChangeNotifier {
|
||||
|
||||
hideChatWindowOverlay() {
|
||||
if (chatWindowOverlayEntry != null) {
|
||||
pOverlayState?.setMiddleBlocked(false);
|
||||
_blockableOverlayState?.setMiddleBlocked(false);
|
||||
chatWindowOverlayEntry!.remove();
|
||||
chatWindowOverlayEntry = null;
|
||||
return;
|
||||
|
Loading…
x
Reference in New Issue
Block a user