mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
[infra_ui][overlay] (WIP) Impl new overlay lifecycle actions
This commit is contained in:
@ -1,37 +1,104 @@
|
|||||||
|
import 'dart:ui' show window;
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'overlay_basis.dart';
|
import 'overlay_basis.dart';
|
||||||
import 'overlay_layout_delegate.dart';
|
import 'overlay_layout_delegate.dart';
|
||||||
|
|
||||||
class OverlayPannel extends StatelessWidget {
|
class OverlayPannel extends StatefulWidget {
|
||||||
const OverlayPannel({
|
const OverlayPannel({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.child,
|
this.focusNode,
|
||||||
required this.targetRect,
|
|
||||||
required this.anchorRect,
|
|
||||||
this.safeAreaEnabled = true,
|
|
||||||
this.anchorDirection = AnchorDirection.topRight,
|
|
||||||
this.insets = EdgeInsets.zero,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final AnchorDirection anchorDirection;
|
final FocusNode? focusNode;
|
||||||
final bool safeAreaEnabled;
|
|
||||||
final EdgeInsets insets;
|
@override
|
||||||
final Rect targetRect;
|
_OverlayPannelState createState() => _OverlayPannelState();
|
||||||
final Rect anchorRect;
|
}
|
||||||
final Widget child;
|
|
||||||
|
class _OverlayPannelState extends State<OverlayPannel> with WidgetsBindingObserver {
|
||||||
|
FocusNode? _internalNode;
|
||||||
|
FocusNode? get focusNode => widget.focusNode ?? _internalNode;
|
||||||
|
late FocusHighlightMode _focusHighlightMode;
|
||||||
|
bool _hasPrimaryFocus = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
if (widget.focusNode == null) {
|
||||||
|
_internalNode ??= _createFocusNode();
|
||||||
|
}
|
||||||
|
focusNode!.addListener(_handleFocusChanged);
|
||||||
|
final FocusManager focusManager = WidgetsBinding.instance!.focusManager;
|
||||||
|
_focusHighlightMode = focusManager.highlightMode;
|
||||||
|
focusManager.addHighlightModeListener(_handleFocusHighlightModeChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
WidgetsBinding.instance!.removeObserver(this);
|
||||||
|
focusNode!.removeListener(_handleFocusChanged);
|
||||||
|
WidgetsBinding.instance!.focusManager.removeHighlightModeListener(_handleFocusHighlightModeChanged);
|
||||||
|
_internalNode?.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return CustomSingleChildLayout(
|
return Container();
|
||||||
delegate: OverlayLayoutDelegate(
|
}
|
||||||
targetRect: targetRect,
|
|
||||||
anchorRect: anchorRect,
|
@override
|
||||||
safeAreaEnabled: safeAreaEnabled,
|
void didUpdateWidget(OverlayPannel oldWidget) {
|
||||||
anchorDirection: anchorDirection,
|
super.didUpdateWidget(oldWidget);
|
||||||
insets: insets,
|
if (widget.focusNode != oldWidget.focusNode) {
|
||||||
),
|
oldWidget.focusNode?.removeListener(_handleFocusChanged);
|
||||||
child: child,
|
if (widget.focusNode == null) {
|
||||||
);
|
_internalNode ??= _createFocusNode();
|
||||||
|
}
|
||||||
|
_hasPrimaryFocus = focusNode!.hasPrimaryFocus;
|
||||||
|
focusNode!.addListener(_handleFocusChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Focus & Route
|
||||||
|
|
||||||
|
FocusNode _createFocusNode() {
|
||||||
|
return FocusNode(debugLabel: '${widget.runtimeType}');
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleFocusChanged() {
|
||||||
|
if (_hasPrimaryFocus != focusNode!.hasPrimaryFocus) {
|
||||||
|
setState(() {
|
||||||
|
_hasPrimaryFocus = focusNode!.hasPrimaryFocus;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleFocusHighlightModeChanged(FocusHighlightMode mode) {
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_focusHighlightMode = mode;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _removeOverlayRoute() {
|
||||||
|
// TODO: junlin
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Layout
|
||||||
|
|
||||||
|
Orientation _getOrientation(BuildContext context) {
|
||||||
|
Orientation? result = MediaQuery.maybeOf(context)?.orientation;
|
||||||
|
if (result == null) {
|
||||||
|
// If there's no MediaQuery, then use the window aspect to determine
|
||||||
|
// orientation.
|
||||||
|
final Size size = window.physicalSize;
|
||||||
|
result = size.width > size.height ? Orientation.landscape : Orientation.portrait;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user