mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-08-07 08:21:56 +00:00
fix: the slash menu position sometimes is wrong (#7492)
This commit is contained in:
parent
c7d3d612ae
commit
9bd13ac29e
@ -36,12 +36,16 @@ class MobileSelectionMenu extends SelectionMenuService {
|
|||||||
Alignment _alignment = Alignment.topLeft;
|
Alignment _alignment = Alignment.topLeft;
|
||||||
final int itemCountFilter;
|
final int itemCountFilter;
|
||||||
final int startOffset;
|
final int startOffset;
|
||||||
|
ValueNotifier<_Position> _positionNotifier = ValueNotifier(_Position.zero);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dismiss() {
|
void dismiss() {
|
||||||
if (_selectionMenuEntry != null) {
|
if (_selectionMenuEntry != null) {
|
||||||
editorState.service.keyboardService?.enable();
|
editorState.service.keyboardService?.enable();
|
||||||
editorState.service.scrollService?.enable();
|
editorState.service.scrollService?.enable();
|
||||||
|
editorState
|
||||||
|
.removeScrollViewScrolledListener(_checkPositionAfterScrolling);
|
||||||
|
_positionNotifier.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
_selectionMenuEntry?.remove();
|
_selectionMenuEntry?.remove();
|
||||||
@ -53,23 +57,20 @@ class MobileSelectionMenu extends SelectionMenuService {
|
|||||||
final completer = Completer<void>();
|
final completer = Completer<void>();
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
_show();
|
_show();
|
||||||
|
editorState.addScrollViewScrolledListener(_checkPositionAfterScrolling);
|
||||||
completer.complete();
|
completer.complete();
|
||||||
});
|
});
|
||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _show() {
|
void _show() {
|
||||||
final selectionRects = editorState.selectionRects();
|
final position = _getCurrentPosition();
|
||||||
if (selectionRects.isEmpty) {
|
if (position == null) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
calculateSelectionMenuOffset(selectionRects.first);
|
|
||||||
final (left, top, right, bottom) = getPosition();
|
|
||||||
|
|
||||||
final editorHeight = editorState.renderBox!.size.height;
|
final editorHeight = editorState.renderBox!.size.height;
|
||||||
final editorWidth = editorState.renderBox!.size.width;
|
final editorWidth = editorState.renderBox!.size.width;
|
||||||
|
|
||||||
|
_positionNotifier = ValueNotifier(position);
|
||||||
_selectionMenuEntry = OverlayEntry(
|
_selectionMenuEntry = OverlayEntry(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
@ -80,47 +81,54 @@ class MobileSelectionMenu extends SelectionMenuService {
|
|||||||
onTap: dismiss,
|
onTap: dismiss,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Positioned(
|
ValueListenableBuilder(
|
||||||
top: top,
|
valueListenable: _positionNotifier,
|
||||||
bottom: bottom,
|
builder: (context, value, _) {
|
||||||
left: left,
|
return Positioned(
|
||||||
right: right,
|
top: value.top,
|
||||||
child: SingleChildScrollView(
|
bottom: value.bottom,
|
||||||
scrollDirection: Axis.horizontal,
|
left: value.left,
|
||||||
child: MobileSelectionMenuWidget(
|
right: value.right,
|
||||||
selectionMenuStyle: style,
|
child: SingleChildScrollView(
|
||||||
singleColumn: singleColumn,
|
scrollDirection: Axis.horizontal,
|
||||||
items: selectionMenuItems
|
child: MobileSelectionMenuWidget(
|
||||||
..forEach((element) {
|
selectionMenuStyle: style,
|
||||||
if (element is MobileSelectionMenuItem) {
|
singleColumn: singleColumn,
|
||||||
element.deleteSlash = false;
|
items: selectionMenuItems
|
||||||
element.deleteKeywords = deleteKeywordsByDefault;
|
..forEach((element) {
|
||||||
for (final e in element.children) {
|
if (element is MobileSelectionMenuItem) {
|
||||||
e.deleteSlash = deleteSlashByDefault;
|
element.deleteSlash = false;
|
||||||
e.deleteKeywords = deleteKeywordsByDefault;
|
element.deleteKeywords =
|
||||||
e.onSelected = () {
|
deleteKeywordsByDefault;
|
||||||
dismiss();
|
for (final e in element.children) {
|
||||||
};
|
e.deleteSlash = deleteSlashByDefault;
|
||||||
}
|
e.deleteKeywords = deleteKeywordsByDefault;
|
||||||
} else {
|
e.onSelected = () {
|
||||||
element.deleteSlash = deleteSlashByDefault;
|
dismiss();
|
||||||
element.deleteKeywords = deleteKeywordsByDefault;
|
};
|
||||||
element.onSelected = () {
|
}
|
||||||
dismiss();
|
} else {
|
||||||
};
|
element.deleteSlash = deleteSlashByDefault;
|
||||||
}
|
element.deleteKeywords =
|
||||||
}),
|
deleteKeywordsByDefault;
|
||||||
maxItemInRow: 5,
|
element.onSelected = () {
|
||||||
editorState: editorState,
|
dismiss();
|
||||||
itemCountFilter: itemCountFilter,
|
};
|
||||||
startOffset: startOffset,
|
}
|
||||||
menuService: this,
|
}),
|
||||||
onExit: () {
|
maxItemInRow: 5,
|
||||||
dismiss();
|
editorState: editorState,
|
||||||
},
|
itemCountFilter: itemCountFilter,
|
||||||
deleteSlashByDefault: deleteSlashByDefault,
|
startOffset: startOffset,
|
||||||
),
|
menuService: this,
|
||||||
),
|
onExit: () {
|
||||||
|
dismiss();
|
||||||
|
},
|
||||||
|
deleteSlashByDefault: deleteSlashByDefault,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -135,6 +143,34 @@ class MobileSelectionMenu extends SelectionMenuService {
|
|||||||
editorState.service.scrollService?.disable();
|
editorState.service.scrollService?.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// the workaround for: editor auto scrolling that will cause wrong position
|
||||||
|
/// of slash menu
|
||||||
|
void _checkPositionAfterScrolling() {
|
||||||
|
final position = _getCurrentPosition();
|
||||||
|
if (position == null) return;
|
||||||
|
if (position == _positionNotifier.value) {
|
||||||
|
Future.delayed(const Duration(milliseconds: 100)).then((_) {
|
||||||
|
final position = _getCurrentPosition();
|
||||||
|
if (position == null) return;
|
||||||
|
if (position != _positionNotifier.value) {
|
||||||
|
_positionNotifier.value = position;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_positionNotifier.value = position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_Position? _getCurrentPosition() {
|
||||||
|
final selectionRects = editorState.selectionRects();
|
||||||
|
if (selectionRects.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
calculateSelectionMenuOffset(selectionRects.first);
|
||||||
|
final (left, top, right, bottom) = getPosition();
|
||||||
|
return _Position(left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Alignment get alignment {
|
Alignment get alignment {
|
||||||
return _alignment;
|
return _alignment;
|
||||||
@ -166,7 +202,6 @@ class MobileSelectionMenu extends SelectionMenuService {
|
|||||||
bottom = offset.dy;
|
bottom = offset.dy;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (left, top, right, bottom);
|
return (left, top, right, bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,3 +252,28 @@ class MobileSelectionMenu extends SelectionMenuService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _Position {
|
||||||
|
const _Position(this.left, this.top, this.right, this.bottom);
|
||||||
|
|
||||||
|
final double? left;
|
||||||
|
final double? top;
|
||||||
|
final double? right;
|
||||||
|
final double? bottom;
|
||||||
|
|
||||||
|
static const _Position zero = _Position(0, 0, 0, 0);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is _Position &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
left == other.left &&
|
||||||
|
top == other.top &&
|
||||||
|
right == other.right &&
|
||||||
|
bottom == other.bottom;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
left.hashCode ^ top.hashCode ^ right.hashCode ^ bottom.hashCode;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user