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>
pull/1817/head
ggurdin 7 months ago committed by GitHub
parent 88369ba8f7
commit 448fbbf668
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -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,40 +1,155 @@
// 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';
class ConstructNotificationUtil {
static Completer? closeCompleter;
static final Set<ConstructIdentifier> unlockedConstructs = {};
static bool showingNotification = false;
void showUnlockedMorphsSnackbar(
Set<ConstructIdentifier> unlockedConstructs,
static void addUnlockedConstruct(
List<ConstructIdentifier> constructs,
BuildContext context,
) {
for (final construct in unlockedConstructs) {
) {
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,
);
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),
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,
);
_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),
),
),
),
child: Row(
children: [
const SizedBox(
width: 50.0,
height: 50.0,
),
Expanded(
child: Wrap(
spacing: 16.0,
alignment: WrapAlignment.center,
@ -43,7 +158,8 @@ void showUnlockedMorphsSnackbar(
Text(
L10n.of(context).youUnlocked,
style: TextStyle(
fontSize: FluffyThemes.isColumnMode(context) ? 32.0 : 16.0,
fontSize:
FluffyThemes.isColumnMode(context) ? 32.0 : 16.0,
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold,
),
@ -54,10 +170,11 @@ void showUnlockedMorphsSnackbar(
children: [
Flexible(
child: Text(
copy ?? construct.lemma,
widget.copy ?? widget.construct.lemma,
style: TextStyle(
fontSize:
FluffyThemes.isColumnMode(context) ? 32.0 : 16.0,
fontSize: FluffyThemes.isColumnMode(context)
? 32.0
: 16.0,
color: AppConfig.gold,
fontWeight: FontWeight.bold,
),
@ -66,15 +183,28 @@ void showUnlockedMorphsSnackbar(
),
MorphIcon(
morphFeature: MorphFeaturesEnumExtension.fromString(
construct.category,
widget.construct.category,
),
morphTag: construct.lemma,
morphTag: widget.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,
);
}

@ -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…
Cancel
Save