4199 prevent activity menu tooltip from being interfered with my other overlays to ensure it always shows (#4215)

* don't show activity dropdown instructions if word card is open

* block other overlays from openning when tutorial overlay is open

* remove duplicate open overlay data, don't wait for construct banners to close if overlay fails to open
This commit is contained in:
ggurdin 2025-10-01 14:00:14 -04:00 committed by GitHub
parent 171dc55242
commit 97163ce221
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 64 additions and 53 deletions

View file

@ -1608,15 +1608,6 @@ class ChatController extends State<ChatPageWithRoom>
);
}
// #Pangea
/// Close the combined selection view overlay and clear the message
/// text and selection stored for the text in that overlay
void closeSelectionOverlay() {
MatrixState.pAnyState.closeAllOverlays();
// selectedTokenIndicies.clear();
}
// Pangea#
// #Pangea
// void clearSelectedEvents() => setState(() {
// selectedEvents.clear();
@ -1625,7 +1616,7 @@ class ChatController extends State<ChatPageWithRoom>
void clearSelectedEvents() {
if (!mounted) return;
setState(() {
closeSelectionOverlay();
MatrixState.pAnyState.closeAllOverlays();
selectedEvents.clear();
showEmojiPicker = false;
});

View file

@ -15,6 +15,7 @@ import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
import 'package:fluffychat/pangea/common/utils/overlay.dart';
import 'package:fluffychat/pangea/common/widgets/pressable_button.dart';
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
import 'package:fluffychat/widgets/matrix.dart';
class ActivityStatsButton extends StatefulWidget {
final ChatController controller;
@ -54,6 +55,9 @@ class _ActivityStatsButtonState extends State<ActivityStatsButton> {
bool get _shouldShowInstructions {
if (InstructionsEnum.activityStatsMenu.isToggledOff ||
MatrixState.pAnyState.isOverlayOpen(
RegExp(r"^word-zoom-card-.*$"),
) ||
_xpCount <= 0 ||
widget.controller.timeline == null) {
return false;
@ -111,7 +115,7 @@ class _ActivityStatsButtonState extends State<ActivityStatsButton> {
OverlayUtil.showTutorialOverlay(
context,
Center(
overlayContent: Center(
child: Container(
padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
@ -144,12 +148,13 @@ class _ActivityStatsButtonState extends State<ActivityStatsButton> {
),
),
),
cellRect,
overlayKey: "activity_stats_menu_instruction",
anchorRect: cellRect,
borderRadius: 12.0,
padding: 8.0,
onClick: () => widget.controller.setShowDropdown(true),
onDismiss: () {
onClick: () {
InstructionsEnum.activityStatsMenu.setToggledOff(true);
widget.controller.setShowDropdown(true);
},
);
}

View file

@ -40,7 +40,7 @@ class LevelUpUtil {
if (!context.mounted) return;
await OverlayUtil.showOverlay(
OverlayUtil.showOverlay(
overlayKey: "level_up_notification",
context: context,
child: LevelUpBanner(
@ -66,8 +66,7 @@ class LevelUpUtil {
static Future<void> _waitForSnackbars(BuildContext context) async {
final snackbarRegex = RegExp(r'_snackbar$');
while (MatrixState.pAnyState.activeOverlays
.any((id) => snackbarRegex.hasMatch(id))) {
while (MatrixState.pAnyState.isOverlayOpen(snackbarRegex)) {
await Future.delayed(const Duration(milliseconds: 100));
}
}

View file

@ -40,7 +40,6 @@ class ConstructNotificationUtil {
if (_closedOverlays.contains(overlayKey)) return;
_closedOverlays.add(overlayKey);
MatrixState.pAnyState.closeOverlay(overlayKey);
MatrixState.pAnyState.activeOverlays.remove(overlayKey);
unlockedConstructs.remove(construct);
closeCompleter?.complete();
closeCompleter = null;
@ -58,7 +57,7 @@ class ConstructNotificationUtil {
);
closeCompleter = Completer();
OverlayUtil.showOverlay(
final bool result = OverlayUtil.showOverlay(
overlayKey: "${construct.string}_snackbar",
context: context,
child: ConstructNotificationOverlay(
@ -72,13 +71,14 @@ class ConstructNotificationUtil {
canPop: false,
);
MatrixState.pAnyState.activeOverlays
.add("${construct.string}_snackbar");
// if the overlay could not be shown, break the loop
if (!result) {
showingNotification = false;
break;
}
await closeCompleter!.future;
} catch (e) {
MatrixState.pAnyState.activeOverlays
.remove("${construct.string}_snackbar");
showingNotification = false;
break;
}

View file

@ -9,16 +9,17 @@ class OverlayListEntry {
final OverlayEntry entry;
final String? key;
final bool canPop;
final bool blockOverlay;
OverlayListEntry(
this.entry, {
this.key,
this.canPop = true,
this.blockOverlay = false,
});
}
class PangeaAnyState {
final Set<String> activeOverlays = {};
final Map<String, LayerLinkAndKey> _layerLinkAndKeys = {};
List<OverlayListEntry> entries = [];
@ -39,16 +40,21 @@ class PangeaAnyState {
return _layerLinkAndKeys[transformTargetId]!;
}
void openOverlay(
bool openOverlay(
OverlayEntry entry,
BuildContext context, {
String? overlayKey,
bool canPop = true,
bool blockOverlay = false,
bool rootOverlay = false,
}) {
if (entries.any((e) => e.blockOverlay)) {
return false;
}
if (overlayKey != null &&
entries.any((element) => element.key == overlayKey)) {
return;
return false;
}
entries.add(
@ -56,17 +62,16 @@ class PangeaAnyState {
entry,
key: overlayKey,
canPop: canPop,
blockOverlay: blockOverlay,
),
);
if (overlayKey != null) {
activeOverlays.add(overlayKey);
}
Overlay.of(
context,
rootOverlay: rootOverlay,
).insert(entry);
return true;
}
void closeOverlay([String? overlayKey]) {
@ -89,10 +94,6 @@ class PangeaAnyState {
);
}
entries.remove(entry);
if (overlayKey != null) {
activeOverlays.remove(overlayKey);
}
}
}
@ -126,10 +127,6 @@ class PangeaAnyState {
);
}
if (shouldRemove[i].key != null) {
activeOverlays.remove(shouldRemove[i].key);
}
entries.remove(shouldRemove[i]);
}
}
@ -137,8 +134,10 @@ class PangeaAnyState {
RenderBox? getRenderBox(String key) =>
layerLinkAndKey(key).key.currentContext?.findRenderObject() as RenderBox?;
bool isOverlayOpen(String overlayKey) {
return entries.any((element) => element.key == overlayKey);
bool isOverlayOpen(RegExp regex) {
return entries.any(
(element) => element.key != null && regex.hasMatch(element.key!),
);
}
List<String> getMatchingOverlayKeys(RegExp regex) {

View file

@ -18,7 +18,7 @@ enum OverlayPositionEnum {
}
class OverlayUtil {
static showOverlay({
static bool showOverlay({
required BuildContext context,
required Widget child,
String? transformTargetId,
@ -35,6 +35,7 @@ class OverlayUtil {
Alignment? followerAnchor,
bool ignorePointer = false,
bool canPop = true,
bool rootOverlay = false,
}) {
try {
if (position == OverlayPositionEnum.transform) {
@ -96,11 +97,12 @@ class OverlayUtil {
),
);
MatrixState.pAnyState.openOverlay(
return MatrixState.pAnyState.openOverlay(
entry,
context,
overlayKey: overlayKey,
canPop: canPop,
rootOverlay: rootOverlay,
);
} catch (err, stack) {
debugger(when: kDebugMode);
@ -109,6 +111,7 @@ class OverlayUtil {
s: stack,
data: {},
);
return false;
}
}
@ -215,15 +218,17 @@ class OverlayUtil {
}
static void showTutorialOverlay(
BuildContext context,
Widget overlayContent,
Rect anchorRect, {
BuildContext context, {
required Widget overlayContent,
required String overlayKey,
required Rect anchorRect,
double? borderRadius,
double? padding,
final VoidCallback? onClick,
final VoidCallback? onDismiss,
}) {
MatrixState.pAnyState.closeAllOverlays();
// force close all overlays to prevent showing
// constuct / level up notification on top of tutorial
MatrixState.pAnyState.closeAllOverlays(force: true);
final entry = OverlayEntry(
builder: (context) {
return AnchoredOverlayWidget(
@ -231,7 +236,7 @@ class OverlayUtil {
borderRadius: borderRadius,
padding: padding,
onClick: onClick,
onDismiss: onDismiss,
overlayKey: overlayKey,
child: overlayContent,
);
},
@ -240,6 +245,9 @@ class OverlayUtil {
entry,
context,
rootOverlay: true,
overlayKey: overlayKey,
canPop: false,
blockOverlay: true,
);
}
}

View file

@ -7,18 +7,18 @@ import 'package:fluffychat/widgets/matrix.dart';
class AnchoredOverlayWidget extends StatefulWidget {
final Widget child;
final Rect anchorRect;
final String overlayKey;
final double? borderRadius;
final double? padding;
final VoidCallback? onClick;
final VoidCallback? onDismiss;
const AnchoredOverlayWidget({
required this.child,
required this.anchorRect,
required this.overlayKey,
this.borderRadius,
this.padding,
this.onClick,
this.onDismiss,
super.key,
});
@ -41,6 +41,17 @@ class _AnchoredOverlayWidgetState extends State<AnchoredOverlayWidget> {
);
}
Future<void> _closeOverlay() async {
if (mounted) {
setState(() {
_visible = false;
});
await Future.delayed(FluffyThemes.animationDuration);
}
MatrixState.pAnyState.closeOverlay(widget.overlayKey);
}
@override
Widget build(BuildContext context) {
final leftPosition = (widget.anchorRect.left +
@ -58,11 +69,9 @@ class _AnchoredOverlayWidgetState extends State<AnchoredOverlayWidget> {
onTapDown: (details) {
final tapPos = details.globalPosition;
if (widget.anchorRect.contains(tapPos)) {
_closeOverlay();
widget.onClick?.call();
}
widget.onDismiss?.call();
MatrixState.pAnyState.closeOverlay();
},
child: Stack(
children: [