refactor: move construct notifications to the top of the screen (#2298)
* refactor: move construct notifications to the top of the screen --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
88369ba8f7
commit
448fbbf668
15 changed files with 299 additions and 261 deletions
|
|
@ -1,7 +1,9 @@
|
|||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
|
||||
abstract class AppConfig {
|
||||
// #Pangea
|
||||
// static String _applicationName = 'FluffyChat';
|
||||
|
|
|
|||
|
|
@ -395,8 +395,8 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
context,
|
||||
);
|
||||
} else if (update['unlocked_constructs'] != null) {
|
||||
showUnlockedMorphsSnackbar(
|
||||
update['unlocked_constructs'],
|
||||
ConstructNotificationUtil.addUnlockedConstruct(
|
||||
List.from(update['unlocked_constructs']),
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,7 +146,9 @@ class GetAnalyticsController extends BaseController {
|
|||
await _getConstructs(forceUpdate: true);
|
||||
}
|
||||
if (oldLevel < constructListModel.level) {
|
||||
await _onLevelUp(oldLevel, constructListModel.level);
|
||||
// do not await this - it's not necessary for this to finish
|
||||
// before the function completes and it blocks the UI
|
||||
_onLevelUp(oldLevel, constructListModel.level);
|
||||
}
|
||||
if (oldLevel > constructListModel.level) {
|
||||
await _onLevelDown(constructListModel.level, oldLevel);
|
||||
|
|
|
|||
|
|
@ -1,76 +1,206 @@
|
|||
// ignore_for_file: depend_on_referenced_packages, implementation_imports
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/overlay.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart';
|
||||
import 'package:fluffychat/pangea/morphs/morph_features_enum.dart';
|
||||
import 'package:fluffychat/pangea/morphs/morph_icon.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
void showUnlockedMorphsSnackbar(
|
||||
Set<ConstructIdentifier> unlockedConstructs,
|
||||
BuildContext context,
|
||||
) {
|
||||
for (final construct in unlockedConstructs) {
|
||||
final copy = getGrammarCopy(
|
||||
category: construct.category,
|
||||
lemma: construct.lemma,
|
||||
context: context,
|
||||
class ConstructNotificationUtil {
|
||||
static Completer? closeCompleter;
|
||||
static final Set<ConstructIdentifier> unlockedConstructs = {};
|
||||
static bool showingNotification = false;
|
||||
|
||||
static void addUnlockedConstruct(
|
||||
List<ConstructIdentifier> constructs,
|
||||
BuildContext context,
|
||||
) {
|
||||
unlockedConstructs.addAll(constructs);
|
||||
if (!showingNotification) {
|
||||
showUnlockedMorphsSnackbar(context);
|
||||
}
|
||||
}
|
||||
|
||||
static void onClose(ConstructIdentifier construct) {
|
||||
MatrixState.pAnyState.closeOverlay("${construct.string}_snackbar");
|
||||
unlockedConstructs.remove(construct);
|
||||
closeCompleter?.complete();
|
||||
closeCompleter = null;
|
||||
}
|
||||
|
||||
static Future<void> showUnlockedMorphsSnackbar(BuildContext context) async {
|
||||
showingNotification = true;
|
||||
while (unlockedConstructs.isNotEmpty) {
|
||||
final construct = unlockedConstructs.first;
|
||||
try {
|
||||
final copy = getGrammarCopy(
|
||||
category: construct.category,
|
||||
lemma: construct.lemma,
|
||||
context: context,
|
||||
);
|
||||
closeCompleter = Completer();
|
||||
|
||||
OverlayUtil.showOverlay(
|
||||
overlayKey: "${construct.string}_snackbar",
|
||||
context: context,
|
||||
child: ConstructNotificationOverlay(
|
||||
construct: construct,
|
||||
copy: copy,
|
||||
),
|
||||
transformTargetId: "",
|
||||
position: OverlayPositionEnum.top,
|
||||
backDropToDismiss: false,
|
||||
closePrevOverlay: false,
|
||||
canPop: false,
|
||||
);
|
||||
|
||||
await closeCompleter!.future;
|
||||
} catch (e) {
|
||||
showingNotification = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
showingNotification = false;
|
||||
}
|
||||
}
|
||||
|
||||
class ConstructNotificationOverlay extends StatefulWidget {
|
||||
final ConstructIdentifier construct;
|
||||
final String? copy;
|
||||
|
||||
const ConstructNotificationOverlay({
|
||||
super.key,
|
||||
required this.construct,
|
||||
this.copy,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ConstructNotificationOverlay> createState() =>
|
||||
ConstructNotificationOverlayState();
|
||||
}
|
||||
|
||||
class ConstructNotificationOverlayState
|
||||
extends State<ConstructNotificationOverlay> with TickerProviderStateMixin {
|
||||
AnimationController? _controller;
|
||||
Animation<double>? _animation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
vsync: this,
|
||||
);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
behavior: FluffyThemes.isColumnMode(context)
|
||||
? SnackBarBehavior.floating
|
||||
: SnackBarBehavior.fixed,
|
||||
width: FluffyThemes.isColumnMode(context)
|
||||
? MediaQuery.of(context).size.width
|
||||
: null,
|
||||
showCloseIcon: true,
|
||||
duration: const Duration(seconds: 5),
|
||||
dismissDirection: DismissDirection.none,
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Wrap(
|
||||
spacing: 16.0,
|
||||
alignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
L10n.of(context).youUnlocked,
|
||||
style: TextStyle(
|
||||
fontSize: FluffyThemes.isColumnMode(context) ? 32.0 : 16.0,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
||||
_animation = CurvedAnimation(
|
||||
parent: _controller!,
|
||||
curve: Curves.easeInOut,
|
||||
);
|
||||
|
||||
_controller!.forward().then((_) {
|
||||
Future.delayed(const Duration(seconds: 5), () {
|
||||
if (mounted) _close();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _close() {
|
||||
_controller?.reverse().then((_) {
|
||||
ConstructNotificationUtil.onClose(widget.construct);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
type: MaterialType.transparency,
|
||||
child: SizeTransition(
|
||||
sizeFactor: _animation!,
|
||||
axisAlignment: -1.0,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: Theme.of(context).colorScheme.onSurface.withAlpha(50),
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 16.0,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
copy ?? construct.lemma,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 50.0,
|
||||
height: 50.0,
|
||||
),
|
||||
Expanded(
|
||||
child: Wrap(
|
||||
spacing: 16.0,
|
||||
alignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
L10n.of(context).youUnlocked,
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
FluffyThemes.isColumnMode(context) ? 32.0 : 16.0,
|
||||
color: AppConfig.gold,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
MorphIcon(
|
||||
morphFeature: MorphFeaturesEnumExtension.fromString(
|
||||
construct.category,
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 16.0,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
widget.copy ?? widget.construct.lemma,
|
||||
style: TextStyle(
|
||||
fontSize: FluffyThemes.isColumnMode(context)
|
||||
? 32.0
|
||||
: 16.0,
|
||||
color: AppConfig.gold,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
MorphIcon(
|
||||
morphFeature: MorphFeaturesEnumExtension.fromString(
|
||||
widget.construct.category,
|
||||
),
|
||||
morphTag: widget.construct.lemma,
|
||||
),
|
||||
],
|
||||
),
|
||||
morphTag: construct.lemma,
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
width: 50.0,
|
||||
child: IconButton(
|
||||
icon: const Icon(
|
||||
Icons.close,
|
||||
),
|
||||
],
|
||||
onPressed: _close,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -8,19 +8,19 @@ import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
|||
class OverlayListEntry {
|
||||
final OverlayEntry entry;
|
||||
final String? key;
|
||||
final bool canPop;
|
||||
|
||||
OverlayListEntry(this.entry, {this.key});
|
||||
OverlayListEntry(
|
||||
this.entry, {
|
||||
this.key,
|
||||
this.canPop = true,
|
||||
});
|
||||
}
|
||||
|
||||
class PangeaAnyState {
|
||||
final Map<String, LayerLinkAndKey> _layerLinkAndKeys = {};
|
||||
List<OverlayListEntry> entries = [];
|
||||
|
||||
dispose() {
|
||||
closeOverlay();
|
||||
_layerLinkAndKeys.clear();
|
||||
}
|
||||
|
||||
LayerLinkAndKey layerLinkAndKey(
|
||||
String transformTargetId, [
|
||||
throwErrorIfNotThere = false,
|
||||
|
|
@ -38,34 +38,34 @@ class PangeaAnyState {
|
|||
return _layerLinkAndKeys[transformTargetId]!;
|
||||
}
|
||||
|
||||
void disposeByWidgetKey(String transformTargetId) {
|
||||
final index =
|
||||
entries.indexWhere((element) => element.key == transformTargetId);
|
||||
if (index != -1) {
|
||||
entries[index].entry.remove();
|
||||
entries.removeAt(index);
|
||||
}
|
||||
_layerLinkAndKeys.remove(transformTargetId);
|
||||
}
|
||||
|
||||
void openOverlay(
|
||||
OverlayEntry entry,
|
||||
BuildContext context, {
|
||||
String? overlayKey,
|
||||
bool canPop = true,
|
||||
}) {
|
||||
if (overlayKey != null &&
|
||||
entries.any((element) => element.key == overlayKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
entries.add(OverlayListEntry(entry, key: overlayKey));
|
||||
entries.add(
|
||||
OverlayListEntry(
|
||||
entry,
|
||||
key: overlayKey,
|
||||
canPop: canPop,
|
||||
),
|
||||
);
|
||||
Overlay.of(context).insert(entry);
|
||||
}
|
||||
|
||||
void closeOverlay([String? overlayKey]) {
|
||||
debugPrint("CLOSE OVERLAY WITH KEY: $overlayKey");
|
||||
final entry = overlayKey != null
|
||||
? entries.firstWhereOrNull((element) => element.key == overlayKey)
|
||||
: entries.lastOrNull;
|
||||
: entries.lastWhereOrNull(
|
||||
(element) => element.canPop,
|
||||
);
|
||||
|
||||
if (entry != null) {
|
||||
try {
|
||||
|
|
@ -84,28 +84,24 @@ class PangeaAnyState {
|
|||
}
|
||||
|
||||
void closeAllOverlays() {
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
final shouldRemove = entries.where((element) => element.canPop).toList();
|
||||
if (shouldRemove.isEmpty) return;
|
||||
for (int i = 0; i < shouldRemove.length; i++) {
|
||||
try {
|
||||
entries.last.entry.remove();
|
||||
shouldRemove[i].entry.remove();
|
||||
} catch (err, s) {
|
||||
ErrorHandler.logError(
|
||||
e: err,
|
||||
s: s,
|
||||
data: {
|
||||
"overlay": entries.last,
|
||||
"overlay": shouldRemove[i],
|
||||
},
|
||||
);
|
||||
}
|
||||
entries.removeLast();
|
||||
entries.remove(shouldRemove[i]);
|
||||
}
|
||||
}
|
||||
|
||||
LayerLinkAndKey messageLinkAndKey(String eventId) => layerLinkAndKey(eventId);
|
||||
|
||||
// String chatViewTargetKey(String? roomId) => "chatViewKey$roomId";
|
||||
// LayerLinkAndKey chatViewLinkAndKey(String? roomId) =>
|
||||
// layerLinkAndKey(chatViewTargetKey(roomId));
|
||||
|
||||
RenderBox? getRenderBox(String key) =>
|
||||
layerLinkAndKey(key).key.currentContext?.findRenderObject() as RenderBox?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import 'error_handler.dart';
|
|||
enum OverlayPositionEnum {
|
||||
transform,
|
||||
centered,
|
||||
top,
|
||||
}
|
||||
|
||||
class OverlayUtil {
|
||||
|
|
@ -33,6 +34,7 @@ class OverlayUtil {
|
|||
Alignment? targetAnchor,
|
||||
Alignment? followerAnchor,
|
||||
bool ignorePointer = false,
|
||||
bool canPop = true,
|
||||
}) {
|
||||
try {
|
||||
if (closePrevOverlay) {
|
||||
|
|
@ -54,9 +56,18 @@ class OverlayUtil {
|
|||
blurBackground: blurBackground,
|
||||
),
|
||||
Positioned(
|
||||
top: (position == OverlayPositionEnum.centered) ? 0 : null,
|
||||
right: (position == OverlayPositionEnum.centered) ? 0 : null,
|
||||
left: (position == OverlayPositionEnum.centered) ? 0 : null,
|
||||
top: (position == OverlayPositionEnum.centered ||
|
||||
position == OverlayPositionEnum.top)
|
||||
? 0
|
||||
: null,
|
||||
right: (position == OverlayPositionEnum.centered ||
|
||||
position == OverlayPositionEnum.top)
|
||||
? 0
|
||||
: null,
|
||||
left: (position == OverlayPositionEnum.centered ||
|
||||
position == OverlayPositionEnum.top)
|
||||
? 0
|
||||
: null,
|
||||
bottom: (position == OverlayPositionEnum.centered) ? 0 : null,
|
||||
child: (position != OverlayPositionEnum.transform)
|
||||
? child
|
||||
|
|
@ -82,6 +93,7 @@ class OverlayUtil {
|
|||
entry,
|
||||
context,
|
||||
overlayKey: overlayKey,
|
||||
canPop: canPop,
|
||||
);
|
||||
} catch (err, stack) {
|
||||
debugger(when: kDebugMode);
|
||||
|
|
@ -191,74 +203,6 @@ class OverlayUtil {
|
|||
}
|
||||
}
|
||||
|
||||
// /// calculates the card offset relative to the target
|
||||
// /// identified by [transformTargetKey]
|
||||
// static Offset _calculateCardOffset({
|
||||
// required Size cardSize,
|
||||
// required BuildContext transformTargetContext,
|
||||
// final double minPadding = 10.0,
|
||||
// }) {
|
||||
// // debugger(when: kDebugMode);
|
||||
// //Note: assumes overlay in chatview
|
||||
// final OverlayConstraints constraints =
|
||||
// ChatViewConstraints(transformTargetContext);
|
||||
|
||||
// final RenderObject? targetRenderBox =
|
||||
// transformTargetContext.findRenderObject();
|
||||
// if (targetRenderBox == null) return Offset.zero;
|
||||
// final Offset transformTargetOffset =
|
||||
// (targetRenderBox as RenderBox).localToGlobal(Offset.zero);
|
||||
// final Size transformTargetSize = targetRenderBox.size;
|
||||
|
||||
// // ideally horizontally centered on target
|
||||
// double dx = transformTargetSize.width / 2 - cardSize.width / 2;
|
||||
// // make sure it's not off the left edge of the screen
|
||||
// // if transformTargetOffset.dx + dc < constraints.x0 + minPadding
|
||||
|
||||
// if (transformTargetOffset.dx + dx < minPadding + constraints.x0) {
|
||||
// debugPrint("setting dx");
|
||||
// dx = minPadding + constraints.x0 - transformTargetOffset.dx;
|
||||
// }
|
||||
// // make sure it's not off the right edge of the screen
|
||||
// if (transformTargetOffset.dx + dx + cardSize.width + minPadding >
|
||||
// constraints.x1) {
|
||||
// dx = constraints.x1 -
|
||||
// transformTargetOffset.dx -
|
||||
// cardSize.width -
|
||||
// minPadding;
|
||||
// }
|
||||
|
||||
// // if there's more room above target,
|
||||
// // put the card there
|
||||
// // else,
|
||||
// // put it below
|
||||
// // debugPrint(
|
||||
// // "transformTargetOffset.dx ${transformTargetOffset.dx} transformTargetOffset.dy ${transformTargetOffset.dy}");
|
||||
// // debugPrint(
|
||||
// // "transformTargetSize.width ${transformTargetSize.width} transformTargetSize.height ${transformTargetSize.height}");
|
||||
// double dy = transformTargetOffset.dy >
|
||||
// constraints.y1 -
|
||||
// transformTargetOffset.dy -
|
||||
// transformTargetSize.height
|
||||
// ? -cardSize.height - minPadding
|
||||
// : transformTargetSize.height + minPadding;
|
||||
// // make sure it's not off the top edge of the screen
|
||||
// if (dy < minPadding + constraints.y0 - transformTargetOffset.dy) {
|
||||
// dy = minPadding + constraints.y0 - transformTargetOffset.dy;
|
||||
// }
|
||||
// // make sure it's not off the bottom edge of the screen
|
||||
// if (transformTargetOffset.dy + dy + cardSize.height + minPadding >
|
||||
// constraints.y1) {
|
||||
// dy = constraints.y1 -
|
||||
// transformTargetOffset.dy -
|
||||
// cardSize.height -
|
||||
// minPadding;
|
||||
// }
|
||||
// // debugPrint("dx $dx dy $dy");
|
||||
|
||||
// return Offset(dx, dy);
|
||||
// }
|
||||
|
||||
static bool get isOverlayOpen => MatrixState.pAnyState.entries.isNotEmpty;
|
||||
}
|
||||
|
||||
|
|
@ -363,49 +307,3 @@ class TransparentBackdropState extends State<TransparentBackdrop>
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
// /// global coordinates that the overlay should stay inside
|
||||
// abstract class OverlayConstraints {
|
||||
// late double x0;
|
||||
// late double y0;
|
||||
// late double x1;
|
||||
// late double y1;
|
||||
// }
|
||||
|
||||
// class ChatViewConstraints implements OverlayConstraints {
|
||||
// @override
|
||||
// late double x0;
|
||||
// @override
|
||||
// late double y0;
|
||||
// @override
|
||||
// late double x1;
|
||||
// @override
|
||||
// late double y1;
|
||||
|
||||
// ChatViewConstraints(BuildContext context) {
|
||||
// final MediaQueryData mediaQueryData =
|
||||
// MediaQuery.of(Scaffold.of(context).context);
|
||||
// final bool isColumnMode = FluffyThemes.isColumnMode(context);
|
||||
|
||||
// x0 = isColumnMode
|
||||
// ? AppConfig.columnWidth + 70.0
|
||||
// : max(mediaQueryData.viewPadding.left, mediaQueryData.viewInsets.left);
|
||||
// y0 = max(mediaQueryData.viewPadding.top, mediaQueryData.viewInsets.top);
|
||||
// x1 = mediaQueryData.size.width -
|
||||
// max(mediaQueryData.viewPadding.right, mediaQueryData.viewInsets.right);
|
||||
// y1 = mediaQueryData.size.height -
|
||||
// max(
|
||||
// mediaQueryData.viewPadding.bottom,
|
||||
// mediaQueryData.viewInsets.bottom,
|
||||
// );
|
||||
|
||||
// // https://medium.com/flutter-community/a-flutter-guide-to-visual-overlap-padding-viewpadding-and-viewinsets-a63e214be6e8
|
||||
// // debugPrint(
|
||||
// // "viewInsets ${mediaQueryData.viewInsets.left} ${mediaQueryData.viewInsets.top} ${mediaQueryData.viewInsets.right} ${mediaQueryData.viewInsets.bottom}");
|
||||
// // debugPrint(
|
||||
// // "padding ${mediaQueryData.padding.left} ${mediaQueryData.padding.top} ${mediaQueryData.padding.right} ${mediaQueryData.padding.bottom}");
|
||||
// // debugPrint(
|
||||
// // "viewPadding ${mediaQueryData.viewPadding.left} ${mediaQueryData.viewPadding.top} ${mediaQueryData.viewPadding.right} ${mediaQueryData.viewPadding.bottom}");
|
||||
// // debugPrint("chatViewConstraints x0: $x0 y0: $y0 x1: $x1 y1: $y1");
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
class InstructionsInlineTooltip extends StatefulWidget {
|
||||
final InstructionsEnum instructionsEnum;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class LemmaEmojiRowState extends State<LemmaEmojiRow> {
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
MatrixState.pAnyState.disposeByWidgetKey(widget.cId.string);
|
||||
MatrixState.pAnyState.closeOverlay(widget.cId.string);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
|
||||
|
|
@ -17,10 +23,6 @@ import 'package:fluffychat/pangea/practice_activities/practice_record.dart';
|
|||
import 'package:fluffychat/pangea/practice_activities/practice_target.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/relevant_span_display_details.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
class PracticeActivityModel {
|
||||
List<PangeaToken> targetTokens;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,12 @@ import 'dart:async';
|
|||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:http/http.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/network/requests.dart';
|
||||
|
|
@ -19,10 +25,6 @@ import 'package:fluffychat/pangea/practice_activities/practice_activity_model.da
|
|||
import 'package:fluffychat/pangea/practice_activities/word_focus_listening_generator.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/event_wrappers/practice_activity_event.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
/// Represents an item in the completion cache.
|
||||
class _RequestCacheItem {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/constructs/construct_form.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_choice.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PracticeMatchActivity {
|
||||
/// The constructIdenfifiers involved in the activity
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
|
|
@ -14,7 +16,6 @@ import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart';
|
|||
import 'package:fluffychat/pangea/practice_activities/practice_activity_model.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_record_repo.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_target.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class PracticeRecord {
|
||||
late DateTime createdAt;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/morphs/morph_features_enum.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_record.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_record_repo.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// Picks which tokens to do activities on and what types of activities to do
|
||||
/// Caches result so that we don't have to recompute it
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
}
|
||||
// close overlay of previous token
|
||||
if (selectedToken != null) {
|
||||
MatrixState.pAnyState.disposeByWidgetKey(
|
||||
MatrixState.pAnyState.closeOverlay(
|
||||
selectedToken!.text.uniqueKey,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
94
pubspec.lock
94
pubspec.lock
|
|
@ -114,10 +114,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: async
|
||||
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
|
||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.12.0"
|
||||
version: "2.11.0"
|
||||
audio_session:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -218,10 +218,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
version: "2.1.1"
|
||||
cached_network_image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -266,10 +266,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: characters
|
||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
||||
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
version: "1.3.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -306,18 +306,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
version: "1.1.1"
|
||||
collection:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: collection
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
version: "1.19.0"
|
||||
colorize:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -506,10 +506,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
|
||||
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
version: "1.3.1"
|
||||
fcm_shared_isolate:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -529,10 +529,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
version: "7.0.0"
|
||||
file_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -1389,18 +1389,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
|
||||
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.8"
|
||||
version: "10.0.7"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
|
||||
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.9"
|
||||
version: "3.0.8"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1477,10 +1477,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.17"
|
||||
version: "0.12.16+1"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1510,10 +1510,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
version: "1.15.0"
|
||||
mgrs_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1694,10 +1694,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
version: "1.9.0"
|
||||
path_parsing:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1822,10 +1822,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||
sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.6"
|
||||
version: "3.1.5"
|
||||
platform_detect:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1902,10 +1902,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d"
|
||||
sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.3"
|
||||
version: "5.0.2"
|
||||
proj4dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -2283,10 +2283,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.1"
|
||||
version: "1.10.0"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -2363,26 +2363,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.1"
|
||||
version: "1.12.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
||||
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
version: "1.3.0"
|
||||
string_validator:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -2435,34 +2435,34 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
version: "1.2.1"
|
||||
test:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test
|
||||
sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e"
|
||||
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.25.15"
|
||||
version: "1.25.8"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
|
||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.4"
|
||||
version: "0.7.3"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa"
|
||||
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.8"
|
||||
version: "0.6.5"
|
||||
text_to_speech:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -2755,10 +2755,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
|
||||
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.1"
|
||||
version: "14.3.0"
|
||||
wakelock_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -2888,5 +2888,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.7.0-0 <4.0.0"
|
||||
dart: ">=3.6.0 <4.0.0"
|
||||
flutter: ">=3.27.0"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue