From 0c3b735a0d40247b02983a8c7eb69776a2446531 Mon Sep 17 00:00:00 2001 From: Nutcake Date: Sat, 27 Jan 2024 15:39:33 +0100 Subject: [PATCH] Adjust datamodels and hub interactions --- lib/apis/contact_api.dart | 24 -- lib/clients/messaging_client.dart | 108 ++++++-- lib/clients/notification_client.dart | 16 +- lib/hub_manager.dart | 6 +- lib/lifecycle_event_handler.dart | 29 +++ lib/models/broadcast_group.dart | 8 + lib/models/hub_events.dart | 4 +- lib/models/users/contact.dart | 38 ++- lib/models/users/user.dart | 2 +- lib/widgets/friends/friend_list_tile.dart | 25 +- lib/widgets/friends/friends_list.dart | 2 +- lib/widgets/friends/user_list_tile.dart | 7 +- lib/widgets/friends/user_search.dart | 2 +- pubspec.lock | 284 +++++++++++----------- pubspec.yaml | 2 +- 15 files changed, 348 insertions(+), 209 deletions(-) create mode 100644 lib/lifecycle_event_handler.dart create mode 100644 lib/models/broadcast_group.dart diff --git a/lib/apis/contact_api.dart b/lib/apis/contact_api.dart index b4cc9fe..f57c264 100644 --- a/lib/apis/contact_api.dart +++ b/lib/apis/contact_api.dart @@ -2,10 +2,6 @@ import 'dart:convert'; import 'package:recon/clients/api_client.dart'; import 'package:recon/models/users/contact.dart'; -import 'package:recon/models/users/contact_status.dart'; -import 'package:recon/models/users/user.dart'; -import 'package:recon/models/users/user_profile.dart'; -import 'package:recon/models/users/user_status.dart'; class ContactApi { static Future> getFriendsList(ApiClient client, {DateTime? lastStatusUpdate}) async { @@ -14,24 +10,4 @@ class ContactApi { final data = jsonDecode(response.body) as List; return data.map((e) => Contact.fromMap(e)).toList(); } - - static Future addUserAsFriend(ApiClient client, {required User user}) async { - final friend = Contact( - id: user.id, - contactUsername: user.username, - ownerId: client.userId, - userStatus: UserStatus.empty(), - userProfile: UserProfile.empty(), - friendStatus: ContactStatus.accepted, - latestMessageTime: DateTime.now(), - ); - final body = jsonEncode(friend.toMap(shallow: true)); - final response = await client.put("/users/${client.userId}/contacts/${user.id}", body: body); - client.checkResponse(response); - } - - static Future removeUserAsFriend(ApiClient client, {required User user}) async { - final response = await client.delete("/users/${client.userId}/friends/${user.id}"); - client.checkResponse(response); - } } \ No newline at end of file diff --git a/lib/clients/messaging_client.dart b/lib/clients/messaging_client.dart index 21fbd5f..fabe4bb 100644 --- a/lib/clients/messaging_client.dart +++ b/lib/clients/messaging_client.dart @@ -9,10 +9,12 @@ import 'package:recon/clients/notification_client.dart'; import 'package:recon/clients/settings_client.dart'; import 'package:recon/crypto_helper.dart'; import 'package:recon/hub_manager.dart'; +import 'package:recon/models/broadcast_group.dart'; import 'package:recon/models/hub_events.dart'; import 'package:recon/models/message.dart'; import 'package:recon/models/session.dart'; import 'package:recon/models/users/contact.dart'; +import 'package:recon/models/users/contact_status.dart'; import 'package:recon/models/users/online_status.dart'; import 'package:recon/models/users/user.dart'; import 'package:recon/models/users/user_status.dart'; @@ -79,14 +81,14 @@ class MessagingClient extends ChangeNotifier { List get cachedFriends => _sortedFriendsCache; - List getUnreadsForFriend(Contact friend) => _unreads[friend.id] ?? []; + List getUnreadsForContact(Contact contact) => _unreads[contact.id] ?? []; - bool friendHasUnreads(Contact friend) => _unreads.containsKey(friend.id); + bool contactHasUnreads(Contact contact) => _unreads.containsKey(contact.id); bool messageIsUnread(Message message) => _unreads[message.senderId]?.any((element) => element.id == message.id) ?? false; - Contact? getAsFriend(String userId) => Contact.fromMapOrNull(Hive.box(_messageBoxKey).get(userId)); + Contact? getAsContact(String userId) => Contact.fromMapOrNull(Hive.box(_messageBoxKey).get(userId)); MessageCache? getUserMessageCache(String userId) => _messageCache[userId]; @@ -130,7 +132,7 @@ class MessagingClient extends ChangeNotifier { clearUnreadsForUser(batch.senderId); } - Future setOnlineStatus(OnlineStatus status) async { + Future setOnlineStatus(OnlineStatus status, {String? target}) async { final pkginfo = await PackageInfo.fromPlatform(); final now = DateTime.now(); _userStatus = _userStatus.copyWith( @@ -147,15 +149,16 @@ class MessagingClient extends ChangeNotifier { arguments: [ _userStatus.toMap(), { - "group": 1, - "targetIds": null, + "group": target == null ? BroadcastGroup.allContacts.index : BroadcastGroup.specificContacts.index, + "targetIds": target, } ], ); - - final self = getAsFriend(_apiClient.userId); - if (self != null) { - await _updateContactLocal(self.copyWith(userStatus: _userStatus)); + if (target == null) { + final self = getAsContact(_apiClient.userId); + if (self != null) { + await _updateContactLocal(self.copyWith(userStatus: _userStatus)); + } } notifyListeners(); } @@ -170,7 +173,10 @@ class MessagingClient extends ChangeNotifier { } messages.sort(); _sortFriendsCache(); - _notificationClient.showUnreadMessagesNotification(messages.reversed); + _notificationClient.showUnreadMessagesNotification( + messages.reversed, + getAsContact, + ); notifyListeners(); } @@ -205,7 +211,7 @@ class MessagingClient extends ChangeNotifier { } Future updateFriendStatus(String userId) async { - final friend = getAsFriend(userId); + final friend = getAsContact(userId); if (friend == null) return; final newStatus = await UserApi.getUserStatus(_apiClient, userId: userId); await _updateContactLocal(friend.copyWith(userStatus: newStatus)); @@ -218,7 +224,27 @@ class MessagingClient extends ChangeNotifier { } void addUserAsFriend(User user) { - _hubManager.send("UpdateContact", arguments: [user.asContactRequest(_apiClient.userId)]); + _hubManager.send( + "UpdateContact", + arguments: [ + user.asContactRequest( + ownerId: _apiClient.userId, + contactStatus: ContactStatus.accepted, + ) + ], + ); + } + + void removeUserAsFriend(User user) { + _hubManager.send( + "UpdateContact", + arguments: [ + user.asContactRequest( + ownerId: _apiClient.userId, + contactStatus: ContactStatus.ignored, + ) + ], + ); } Future _refreshUnreads() async { @@ -230,8 +256,12 @@ class MessagingClient extends ChangeNotifier { void _sortFriendsCache() { _sortedFriendsCache.sort((a, b) { - var aVal = friendHasUnreads(a) ? -3 : 0; - var bVal = friendHasUnreads(b) ? -3 : 0; + if (a.isContactRequest != b.isContactRequest) { + return a.isContactRequest ? -1 : 1; + } + + var aVal = contactHasUnreads(a) ? -3 : 0; + var bVal = contactHasUnreads(b) ? -3 : 0; aVal -= a.latestMessageTime.compareTo(b.latestMessageTime); aVal += a.userStatus.onlineStatus.compareTo(b.userStatus.onlineStatus) * 2; @@ -271,6 +301,7 @@ class MessagingClient extends ChangeNotifier { _hubManager.setHandler(EventTarget.receiveStatusUpdate, _onReceiveStatusUpdate); _hubManager.setHandler(EventTarget.receiveSessionUpdate, _onReceiveSessionUpdate); _hubManager.setHandler(EventTarget.removeSession, _onRemoveSession); + _hubManager.setHandler(EventTarget.contactAddedOrUpdated, _onContactAddedOrUpdated); await _hubManager.start(); _hubManager.send( @@ -300,6 +331,51 @@ class MessagingClient extends ChangeNotifier { return _sessionMap.map((key, value) => MapEntry(CryptoHelper.idHash(value.id + salt), value)); } + void _onContactAddedOrUpdated(List args) { + bool shouldUpdateRequestCount = false; + bool shouldRegisterNewContact = false; + for (var request in args) { + final newContact = Contact.fromMap(request); + Contact? existingContact = getAsContact(newContact.id); + if (existingContact != null) { + if (!existingContact.isAccepted && newContact.isAccepted) { + shouldRegisterNewContact = true; + } + if (newContact.isContactRequest != existingContact.isContactRequest) { + shouldUpdateRequestCount = true; + } + } else { + if (newContact.isAccepted) { + shouldRegisterNewContact = true; + } + if (newContact.isContactRequest) { + shouldUpdateRequestCount = true; + } + } + _updateContactLocal(newContact); + if (shouldRegisterNewContact) { + final isInvisible = userStatus.onlineStatus == OnlineStatus.invisible; + _hubManager.send("ListenOnContact", arguments: [newContact.id]); + _hubManager.send("RequestStatus", arguments: [newContact.id, isInvisible]); + if (!isInvisible) { + _hubManager.send( + "BroadcastStatus", + arguments: [ + userStatus.toMap(shallow: true), + { + "group": BroadcastGroup.specificContacts.index, + "targetIds": newContact.id, + }, + ], + ); + } + } + if (shouldUpdateRequestCount) { + _notificationClient.showContactRequestNotification(newContact); + } + } + } + void _onMessageSent(List args) { final msg = args[0]; final message = Message.fromMap(msg, withState: MessageState.sent); @@ -342,7 +418,7 @@ class MessagingClient extends ChangeNotifier { decodedSessions: status.sessions .map((e) => sessionMap[e.sessionHash] ?? Session.none().copyWith(accessLevel: e.accessLevel)) .toList()); - final friend = getAsFriend(statusUpdate["userId"])?.copyWith(userStatus: status); + final friend = getAsContact(statusUpdate["userId"])?.copyWith(userStatus: status); if (friend != null) { _updateContactLocal(friend); } diff --git a/lib/clients/notification_client.dart b/lib/clients/notification_client.dart index 812cdde..06388d9 100644 --- a/lib/clients/notification_client.dart +++ b/lib/clients/notification_client.dart @@ -5,6 +5,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart' as import 'package:recon/auxiliary.dart'; import 'package:recon/models/message.dart'; import 'package:recon/models/session.dart'; +import 'package:recon/models/users/contact.dart'; class NotificationChannel { final String id; @@ -29,13 +30,13 @@ class NotificationClient { linux: fln.LinuxInitializationSettings(defaultActionName: "Open ReCon"), )); - Future showUnreadMessagesNotification(Iterable messages) async { + Future showUnreadMessagesNotification(Iterable messages, Contact? Function(String userId) contactGetter) async { if (messages.isEmpty) return; final bySender = groupBy(messages, (p0) => p0.senderId); - for (final entry in bySender.entries) { - final uname = entry.key.stripUid(); + final contact = contactGetter(entry.key); + final uname = contact?.contactUsername ?? "Unknown"; await _notifier.show( uname.hashCode, null, @@ -93,4 +94,13 @@ class NotificationClient { ); } } + + Future showContactRequestNotification(Contact contact) async { + await _notifier.show( + contact.contactUsername.hashCode, + "New Contact request", + "User ${contact.contactUsername} wants to be your friend.", + null + ); + } } diff --git a/lib/hub_manager.dart b/lib/hub_manager.dart index 0b8333c..e28474d 100644 --- a/lib/hub_manager.dart +++ b/lib/hub_manager.dart @@ -105,12 +105,13 @@ class HubManager { } void _handleInvocation(body) async { + _logger.info(body); final target = EventTarget.parse(body["target"]); final args = body["arguments"] ?? []; final handler = _handlers[target]; if (handler == null) { _logger.warning("Unhandled event received"); - if (kDebugMode) _logger.warning("Invocation target: ${target.name}, args:\n$args"); + if (kDebugMode) _logger.warning("Invocation target: ${body["target"]}, args:\n$args"); return; } handler(args); @@ -132,6 +133,9 @@ class HubManager { } void dispose() { + _handlers.clear(); + _responseHandlers.clear(); _wsChannel?.close(); + _wsChannel = null; } } diff --git a/lib/lifecycle_event_handler.dart b/lib/lifecycle_event_handler.dart new file mode 100644 index 0000000..3cd69f0 --- /dev/null +++ b/lib/lifecycle_event_handler.dart @@ -0,0 +1,29 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +class LifecycleEventHandler extends WidgetsBindingObserver { + final AsyncCallback? resumeCallBack; + final AsyncCallback? suspendingCallBack; + + LifecycleEventHandler({ + this.resumeCallBack, + this.suspendingCallBack, + }); + + @override + void didChangeAppLifecycleState(AppLifecycleState state) async { + super.didChangeAppLifecycleState(state); + switch (state) { + case AppLifecycleState.resumed: + await resumeCallBack?.call(); + break; + case AppLifecycleState.inactive: + case AppLifecycleState.paused: + case AppLifecycleState.detached: + await suspendingCallBack?.call(); + break; + default: + break; + } + } +} diff --git a/lib/models/broadcast_group.dart b/lib/models/broadcast_group.dart new file mode 100644 index 0000000..fd65d16 --- /dev/null +++ b/lib/models/broadcast_group.dart @@ -0,0 +1,8 @@ +enum BroadcastGroup +{ + public, + allContacts, + specificContacts, + broadcastKey, + connectionIds, +} \ No newline at end of file diff --git a/lib/models/hub_events.dart b/lib/models/hub_events.dart index c9c086a..c5e1348 100644 --- a/lib/models/hub_events.dart +++ b/lib/models/hub_events.dart @@ -16,7 +16,9 @@ enum EventTarget { messagesRead, receiveSessionUpdate, removeSession, - receiveStatusUpdate; + receiveStatusUpdate, + sendStatusToUser, + contactAddedOrUpdated; factory EventTarget.parse(String? text) { if (text == null) return EventTarget.unknown; diff --git a/lib/models/users/contact.dart b/lib/models/users/contact.dart index df020c4..4960404 100644 --- a/lib/models/users/contact.dart +++ b/lib/models/users/contact.dart @@ -10,13 +10,17 @@ class Contact implements Comparable { final String id; final String contactUsername; final String ownerId; + final bool isAccepted; + final bool isMigrated; + final bool isCounterpartMigrated; final UserStatus userStatus; final UserProfile userProfile; - final ContactStatus friendStatus; + final ContactStatus contactStatus; final DateTime latestMessageTime; - const Contact({required this.id, required this.contactUsername, required this.ownerId, required this.userStatus, required this.userProfile, - required this.friendStatus, required this.latestMessageTime, + const Contact({required this.id, required this.contactUsername, required this.ownerId, required this.isAccepted, + required this.isMigrated, required this.isCounterpartMigrated, required this.userStatus, required this.userProfile, + required this.contactStatus, required this.latestMessageTime, }); bool get isHeadless => userStatus.outputDevice == "Headless"; @@ -27,10 +31,13 @@ class Contact implements Comparable { id: map["id"], contactUsername: map["contactUsername"], ownerId: map["ownerId"] ?? map["id"], - // Neos bot status is always offline but should be displayed as online + isAccepted: map["isAccepted"] ?? false, + isMigrated: map["isMigrated"] ?? false, + isCounterpartMigrated: map["isCounterpartMigrated"] ?? false, + // Resonite bot status is always offline but should be displayed as online userStatus: map["id"] == _resoniteBotId ? userStatus.copyWith(onlineStatus: OnlineStatus.online) : userStatus, userProfile: UserProfile.fromMap(map["profile"] ?? {}), - friendStatus: ContactStatus.fromString(map["contactStatus"]), + contactStatus: ContactStatus.fromString(map["contactStatus"]), latestMessageTime: map["latestMessageTime"] == null ? DateTime.fromMillisecondsSinceEpoch(0) : DateTime.parse(map["latestMessageTime"]), ); @@ -46,25 +53,33 @@ class Contact implements Comparable { id: _emptyId, contactUsername: "", ownerId: "", + isAccepted: false, + isMigrated: false, + isCounterpartMigrated: false, userStatus: UserStatus.empty(), userProfile: UserProfile.empty(), - friendStatus: ContactStatus.none, + contactStatus: ContactStatus.none, latestMessageTime: DateTimeX.epoch ); } bool get isEmpty => id == _emptyId; + bool get isPartiallyMigrated => isMigrated && !isCounterpartMigrated; + bool get isContactRequest => !isPartiallyMigrated && isAccepted && contactStatus == ContactStatus.requested; Contact copyWith({ - String? id, String? contactUsername, String? ownerId, UserStatus? userStatus, UserProfile? userProfile, - ContactStatus? friendStatus, DateTime? latestMessageTime}) { + String? id, String? contactUsername, String? ownerId, UserStatus? userStatus, bool? isAccepted, bool? isMigrated, + bool? isCounterpartMigrated, UserProfile? userProfile, ContactStatus? contactStatus, DateTime? latestMessageTime}) { return Contact( id: id ?? this.id, contactUsername: contactUsername ?? this.contactUsername, ownerId: ownerId ?? this.ownerId, + isAccepted: isAccepted ?? this.isAccepted, + isMigrated: isMigrated ?? this.isMigrated, + isCounterpartMigrated: isCounterpartMigrated ?? this.isCounterpartMigrated, userStatus: userStatus ?? this.userStatus, userProfile: userProfile ?? this.userProfile, - friendStatus: friendStatus ?? this.friendStatus, + contactStatus: contactStatus ?? this.contactStatus, latestMessageTime: latestMessageTime ?? this.latestMessageTime, ); } @@ -74,9 +89,12 @@ class Contact implements Comparable { "id": id, "contactUsername": contactUsername, "ownerId": ownerId, + "isAccepted": isAccepted, + "isMigrated": isMigrated, + "isCounterpartMigrated": isCounterpartMigrated, "userStatus": userStatus.toMap(shallow: shallow), "profile": userProfile.toMap(), - "contactStatus": friendStatus.name, + "contactStatus": contactStatus.name, "latestMessageTime": latestMessageTime.toIso8601String(), }; } diff --git a/lib/models/users/user.dart b/lib/models/users/user.dart index b1e0b7b..c63753b 100644 --- a/lib/models/users/user.dart +++ b/lib/models/users/user.dart @@ -33,7 +33,7 @@ class User { }; } - Map asContactRequest(String ownerId) { + Map asContactRequest({required String ownerId, required ContactStatus contactStatus}) { return { "ownerId": ownerId, "id": id, diff --git a/lib/widgets/friends/friend_list_tile.dart b/lib/widgets/friends/friend_list_tile.dart index a2a7d34..710b500 100644 --- a/lib/widgets/friends/friend_list_tile.dart +++ b/lib/widgets/friends/friend_list_tile.dart @@ -30,12 +30,25 @@ class FriendListTile extends StatelessWidget { leading: GenericAvatar( imageUri: imageUri, ), - trailing: unreads != 0 - ? Text( - "+$unreads", - style: theme.textTheme.bodyMedium?.copyWith(color: theme.colorScheme.primary), + trailing: friend.isContactRequest + ? IconButton( + splashRadius: 24, + iconSize: 20, + icon: const Icon(Icons.person_add), + style: IconButton.styleFrom( + foregroundColor: Theme.of(context).colorScheme.onBackground, + side: BorderSide(color: Theme.of(context).colorScheme.primary, width: 2), + ), + onPressed: () async { + final mClient = Provider.of(context, listen: false); + }, ) - : null, + : unreads != 0 + ? Text( + "+$unreads", + style: theme.textTheme.bodyMedium?.copyWith(color: theme.colorScheme.primary), + ) + : null, title: Row( children: [ Text(friend.contactUsername), @@ -92,7 +105,7 @@ class FriendListTile extends StatelessWidget { onTap: () async { onTap?.call(); mClient.loadUserMessageCache(friend.id); - final unreads = mClient.getUnreadsForFriend(friend); + final unreads = mClient.getUnreadsForContact(friend); if (unreads.isNotEmpty) { final readBatch = MarkReadBatch( senderId: friend.id, diff --git a/lib/widgets/friends/friends_list.dart b/lib/widgets/friends/friends_list.dart index c162c36..a7b702f 100644 --- a/lib/widgets/friends/friends_list.dart +++ b/lib/widgets/friends/friends_list.dart @@ -54,7 +54,7 @@ class _FriendsListState extends State with AutomaticKeepAliveClient itemCount: friends.length, itemBuilder: (context, index) { final friend = friends[index]; - final unreads = mClient.getUnreadsForFriend(friend); + final unreads = mClient.getUnreadsForContact(friend); return FriendListTile( friend: friend, unreads: unreads.length, diff --git a/lib/widgets/friends/user_list_tile.dart b/lib/widgets/friends/user_list_tile.dart index 0d6b01d..09b12eb 100644 --- a/lib/widgets/friends/user_list_tile.dart +++ b/lib/widgets/friends/user_list_tile.dart @@ -1,7 +1,5 @@ import 'package:provider/provider.dart'; -import 'package:recon/apis/contact_api.dart'; import 'package:recon/auxiliary.dart'; -import 'package:recon/client_holder.dart'; import 'package:recon/clients/messaging_client.dart'; import 'package:recon/models/users/user.dart'; import 'package:recon/widgets/generic_avatar.dart'; @@ -61,10 +59,7 @@ class _UserListTileState extends State { }); try { if (_localAdded) { - await ContactApi.removeUserAsFriend( - ClientHolder.of(context).apiClient, - user: widget.user, - ); + mClient.removeUserAsFriend(widget.user); } else { mClient.addUserAsFriend(widget.user); } diff --git a/lib/widgets/friends/user_search.dart b/lib/widgets/friends/user_search.dart index f694272..056244e 100644 --- a/lib/widgets/friends/user_search.dart +++ b/lib/widgets/friends/user_search.dart @@ -72,7 +72,7 @@ class _UserSearchState extends State { onChanged: () { mClient.refreshFriendsList(); }, - isFriend: mClient.getAsFriend(user.id) != null, + isFriend: mClient.getAsContact(user.id) != null, ); }, ); diff --git a/pubspec.lock b/pubspec.lock index d788584..0e3b753 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,18 +21,18 @@ packages: dependency: transitive description: name: audio_session - sha256: "8a2bc5e30520e18f3fb0e366793d78057fb64cd5287862c76af0c8771f2a52ad" + sha256: "6fdf255ed3af86535c96452c33ecff1245990bb25a605bfb1958661ccc3d467f" url: "https://pub.dev" source: hosted - version: "0.1.16" + version: "0.1.18" background_downloader: dependency: "direct main" description: name: background_downloader - sha256: f74abc807173daac213cd810769532c62755279936532311d994418079d16013 + sha256: "0873a939f5a301872cb7614e12f759fbccef2e3ed0d0d37b540dde7611275b12" url: "https://pub.dev" source: hosted - version: "7.12.2" + version: "7.12.3" boolean_selector: dependency: transitive description: @@ -45,66 +45,66 @@ packages: dependency: "direct main" description: name: cached_network_image - sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f + sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f" url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "3.3.1" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613" + sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "4.0.0" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257" + sha256: "42a835caa27c220d1294311ac409a43361088625a4f23c820b006dd9bffb3316" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" camera: dependency: "direct main" description: name: camera - sha256: "1f9010f0689774380fbcd7d6b7820a5157e8e97685fa66d619e1d1f58b3fdf93" + sha256: "9499cbc2e51d8eb0beadc158b288380037618ce4e30c9acbc4fae1ac3ecb5797" url: "https://pub.dev" source: hosted - version: "0.10.5+5" + version: "0.10.5+9" camera_android: dependency: transitive description: name: camera_android - sha256: "58463140f1b39591b8e2155861b436abad4ceb48160058be8374164ff0309ef3" + sha256: "351429510121d179b9aac5a2e8cb525c3cd6c39f4d709c5f72dfb21726e52371" url: "https://pub.dev" source: hosted - version: "0.10.8+13" + version: "0.10.8+16" camera_avfoundation: dependency: transitive description: name: camera_avfoundation - sha256: "9495e633cda700717bbe299b0979e6c4a08cee45f298945973dc9cf3e4c1cba5" + sha256: "7d0763dfcbf060f56aa254a68c103210280bee9e97bbe4fdef23e257a4f70ab9" url: "https://pub.dev" source: hosted - version: "0.9.13+6" + version: "0.9.14" camera_platform_interface: dependency: transitive description: name: camera_platform_interface - sha256: "86fd4fc597c6e455265ddb5884feb352d0171ad14b9cdf3aba30da59b25738c4" + sha256: e971ebca970f7cfee396f76ef02070b5e441b4aa04942da9c108d725f57bbd32 url: "https://pub.dev" source: hosted - version: "2.6.0" + version: "2.7.2" camera_web: dependency: transitive description: name: camera_web - sha256: d4c2c571c7af04f8b10702ca16bb9ed2a26e64534171e8f75c9349b2c004d8f1 + sha256: f18ccfb33b2a7c49a52ad5aa3f07330b7422faaecbdfd9b9fe8e51182f6ad67d url: "https://pub.dev" source: hosted - version: "0.3.2+3" + version: "0.3.2+4" characters: dependency: transitive description: @@ -125,10 +125,10 @@ packages: dependency: "direct main" description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" color: dependency: "direct main" description: @@ -141,10 +141,10 @@ packages: dependency: transitive description: name: cross_file - sha256: "445db18de832dba8d851e287aff8ccf169bed30d2e94243cb54c7d2f1ed2142c" + sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e url: "https://pub.dev" source: hosted - version: "0.3.3+6" + version: "0.3.3+8" crypto: dependency: "direct main" description: @@ -165,18 +165,18 @@ packages: dependency: transitive description: name: dbus - sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" url: "https://pub.dev" source: hosted - version: "0.7.8" + version: "0.7.10" dynamic_color: dependency: "direct main" description: name: dynamic_color - sha256: "8b8bd1d798bd393e11eddeaa8ae95b12ff028bf7d5998fc5d003488cd5f4ce2f" + sha256: a866f1f8947bfdaf674d7928e769eac7230388a2e7a2542824fad4bb5b87be3b url: "https://pub.dev" source: hosted - version: "1.6.8" + version: "1.6.9" fake_async: dependency: transitive description: @@ -245,10 +245,10 @@ packages: dependency: transitive description: name: file_selector_platform_interface - sha256: "0aa47a725c346825a2bd396343ce63ac00bda6eff2fbc43eabe99737dede8262" + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "2.6.2" file_selector_windows: dependency: transitive description: @@ -257,6 +257,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -290,10 +298,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "6d11ea777496061e583623aaf31923f93a9409ef8fcaeeefdd6cd78bf4fe5bb3" + sha256: c18f1de98fe0bb9dd5ba91e1330d4febc8b6a7de6aae3ffe475ef423723e72f3 url: "https://pub.dev" source: hosted - version: "16.1.0" + version: "16.3.2" flutter_local_notifications_linux: dependency: transitive description: @@ -412,10 +420,10 @@ packages: dependency: "direct main" description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" http_parser: dependency: "direct main" description: @@ -428,34 +436,34 @@ packages: dependency: "direct main" description: name: image_picker - sha256: "7d7f2768df2a8b0a3cefa5ef4f84636121987d403130e70b17ef7e2cf650ba84" + sha256: "26222b01a0c9a2c8fe02fc90b8208bd3325da5ed1f4a2acabf75939031ac0bdd" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.7" image_picker_android: dependency: transitive description: name: image_picker_android - sha256: d6a6e78821086b0b737009b09363018309bbc6de3fd88cc5c26bc2bb44a4957f + sha256: "39f2bfe497e495450c81abcd44b62f56c2a36a37a175da7d137b4454977b51b1" url: "https://pub.dev" source: hosted - version: "0.8.8+2" + version: "0.8.9+3" image_picker_for_web: dependency: transitive description: name: image_picker_for_web - sha256: "869fe8a64771b7afbc99fc433a5f7be2fea4d1cb3d7c11a48b6b579eb9c797f0" + sha256: e2423c53a68b579a7c37a1eda967b8ae536c3d98518e5db95ca1fe5719a730a3 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "3.0.2" image_picker_ios: dependency: transitive description: name: image_picker_ios - sha256: "76ec722aeea419d03aa915c2c96bf5b47214b053899088c9abb4086ceecf97a7" + sha256: fadafce49e8569257a0cad56d24438a6fa1f0cbd7ee0af9b631f7492818a4ca3 url: "https://pub.dev" source: hosted - version: "0.8.8+4" + version: "0.8.9+1" image_picker_linux: dependency: transitive description: @@ -476,10 +484,10 @@ packages: dependency: transitive description: name: image_picker_platform_interface - sha256: ed9b00e63977c93b0d2d2b343685bed9c324534ba5abafbb3dfbd6a780b1b514 + sha256: fa4e815e6fcada50e35718727d83ba1c92f1edf95c0b4436554cec301b56233b url: "https://pub.dev" source: hosted - version: "2.9.1" + version: "2.9.3" image_picker_windows: dependency: transitive description: @@ -508,26 +516,26 @@ packages: dependency: "direct main" description: name: just_audio - sha256: "5ed0cd723e17dfd8cd4b0253726221e67f6546841ea4553635cf895061fc335b" + sha256: b607cd1a43bac03d85c3aaee00448ff4a589ef2a77104e3d409889ff079bf823 url: "https://pub.dev" source: hosted - version: "0.9.35" + version: "0.9.36" just_audio_platform_interface: dependency: transitive description: name: just_audio_platform_interface - sha256: d8409da198bbc59426cd45d4c92fca522a2ec269b576ce29459d6d6fcaeb44df + sha256: c3dee0014248c97c91fe6299edb73dc4d6c6930a2f4f713579cd692d9e47f4a1 url: "https://pub.dev" source: hosted - version: "4.2.1" + version: "4.2.2" just_audio_web: dependency: transitive description: name: just_audio_web - sha256: ff62f733f437b25a0ff590f0e295fa5441dcb465f1edbdb33b3dea264705bc13 + sha256: "134356b0fe3d898293102b33b5fd618831ffdc72bb7a1b726140abdf22772b70" url: "https://pub.dev" source: hosted - version: "0.4.8" + version: "0.4.9" lints: dependency: transitive description: @@ -564,18 +572,18 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" mime: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" nested: dependency: transitive description: @@ -620,26 +628,26 @@ packages: dependency: "direct main" description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" path_provider_linux: dependency: transitive description: @@ -652,10 +660,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_windows: dependency: transitive description: @@ -668,50 +676,58 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8" + sha256: "45ff3fbcb99040fde55c528d5e3e6ca29171298a85436274d49c6201002087d6" url: "https://pub.dev" source: hosted - version: "11.0.1" + version: "11.2.0" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: f9fddd3b46109bd69ff3f9efa5006d2d309b7aec0f3c1c5637a60a2d5659e76e + sha256: "758284a0976772f9c744d6384fc5dc4834aa61e3f7aa40492927f244767374eb" url: "https://pub.dev" source: hosted - version: "11.1.0" + version: "12.0.3" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" + sha256: c6bf440f80acd2a873d3d91a699e4cc770f86e7e6b576dda98759e8b92b39830 url: "https://pub.dev" source: hosted - version: "9.1.4" + version: "9.3.0" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d" + url: "https://pub.dev" + source: hosted + version: "0.1.1" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4" + sha256: "5c43148f2bfb6d14c5a8162c0a712afe891f2d847f35fcff29c406b37da43c3c" url: "https://pub.dev" source: hosted - version: "3.12.0" + version: "4.1.0" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" url: "https://pub.dev" source: hosted - version: "0.1.3" + version: "0.2.1" petitparser: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.2" photo_view: dependency: "direct main" description: @@ -724,58 +740,50 @@ packages: dependency: transitive description: name: platform - sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.8" provider: dependency: "direct main" description: name: provider - sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" url: "https://pub.dev" source: hosted - version: "6.0.5" - quiver: - dependency: transitive - description: - name: quiver - sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 - url: "https://pub.dev" - source: hosted - version: "3.2.1" + version: "6.1.1" record: dependency: "direct main" description: name: record - sha256: be9b710f42edf94f939dda1a1688e82a68dcd391be0a836c01e639a249f133d3 + sha256: "5c8e12c692a4800b33f5f8b6c821ea083b12bfdbd031b36ba9322c40a4eeecc9" url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "5.0.4" record_android: dependency: transitive description: name: record_android - sha256: "5a96286f051cf46dffd1ae7cd5f1baa82cf6a983d26389c2f8d03d03dddc711b" + sha256: "805ecaa232a671aff2ee9ec4730ef6addb97c548d2db6b1fbd5197f1d4f47a5a" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" record_darwin: dependency: transitive description: name: record_darwin - sha256: "78dba641ae271e555035ee68b637f7605ba9f8c60ccfd5c03b835e0b77ea201f" + sha256: ee8cb1bb1712d7ce38140ecabe70e5c286c02f05296d66043bee865ace7eb1b9 url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.1" record_linux: dependency: transitive description: @@ -796,18 +804,18 @@ packages: dependency: transitive description: name: record_web - sha256: be8c62759b385a04dbc4ae7f5d3f78e6f0c532e72935d288aee87432bbbbb8f6 + sha256: "24847cdbcf999f7a5762170792f622ac844858766becd0f2370ec8ae22f7526e" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.5" record_windows: dependency: transitive description: name: record_windows - sha256: "326bfbe6f5232dd773ad6b848cd94f78148f02557abff1dd4627d056b688dbdb" + sha256: "39998b3ea7d8d28b04159d82220e6e5e32a7c357c6fb2794f5736beea272f6c3" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.2" rxdart: dependency: transitive description: @@ -857,34 +865,34 @@ packages: dependency: transitive description: name: sqflite - sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" + sha256: c2c32eb0c74021d987336522acc3b6bf0082fbd0c540c36a9cf4ddb8ba891ddc url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a" + sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5" url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.5.3" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -905,10 +913,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.0+1" term_glyph: dependency: transitive description: @@ -921,10 +929,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" timezone: dependency: transitive description: @@ -945,34 +953,34 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: b1c9e98774adf8820c96fbc7ae3601231d324a7d5ebd8babe27b6dfac91357ba + sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c url: "https://pub.dev" source: hosted - version: "6.2.1" + version: "6.2.4" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" + sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.2.2" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "4ac97281cf60e2e8c5cc703b2b28528f9b50c8f7cebc71df6bdf0845f647268a" + sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.2.4" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "9f2d390e096fdbe1e6e6256f97851e51afc2d9c423d3432f1d6a02a8a9a8b9fd" + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" url_launcher_macos: dependency: transitive description: @@ -985,34 +993,34 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" + sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" + sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.3" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "7754a1ad30ee896b265f8d14078b0513a4dba28d358eabb9d5f339886f4a1adc" + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" uuid: dependency: "direct main" description: name: uuid - sha256: b715b8d3858b6fa9f68f87d20d98830283628014750c2b09b6f516c1da4af2a7 + sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 url: "https://pub.dev" source: hosted - version: "4.1.0" + version: "4.3.3" vector_math: dependency: transitive description: @@ -1025,10 +1033,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" web_socket_channel: dependency: "direct main" description: @@ -1041,34 +1049,34 @@ packages: dependency: transitive description: name: win32 - sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" + sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" url: "https://pub.dev" source: hosted - version: "5.0.9" + version: "5.2.0" workmanager: dependency: "direct main" description: name: workmanager - sha256: e0be7e35d644643f164ee45d2ce14414f0e0fdde19456aa66065f35a0b1d2ea1 + sha256: ed13530cccd28c5c9959ad42d657cd0666274ca74c56dea0ca183ddd527d3a00 url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.5.2" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" xml: dependency: transitive description: name: xml - sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.5.0" sdks: - dart: ">=3.1.0 <4.0.0" - flutter: ">=3.13.0" + dart: ">=3.2.3 <4.0.0" + flutter: ">=3.16.6" diff --git a/pubspec.yaml b/pubspec.yaml index 82ccde5..7fc7ea6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.11.1-beta+1 +version: 0.11.3-beta+1 environment: sdk: ">=3.0.1"