refactor OverlayKeyState for OverlayDialogManager and ChatModel

This commit is contained in:
csf 2023-02-08 22:01:15 +09:00
parent 0dba013089
commit 3d5aca18d6
5 changed files with 47 additions and 48 deletions

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}

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

@ -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(

View File

@ -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;