diff --git a/lib/controls/timeline/interactions_bar_control.dart b/lib/controls/timeline/interactions_bar_control.dart index f8728e3..0b963b0 100644 --- a/lib/controls/timeline/interactions_bar_control.dart +++ b/lib/controls/timeline/interactions_bar_control.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; import 'package:relatica/models/exec_error.dart'; -import 'package:relatica/services/auth_service.dart'; import 'package:result_monad/result_monad.dart'; import '../../globals.dart'; @@ -112,18 +111,6 @@ class _InteractionsBarControlState extends State { } Future addComment() async { - final needingReshareIdFix = getIt() - .canUseFeature(RelaticaFeatures.reshareIdFix); - final myId = getIt().currentProfile.userId; - - if (needingReshareIdFix && - widget.entry.reshareOriginalPostId.isNotEmpty && - widget.entry.reshareAuthorId != myId) { - await showConfirmDialog(context, - 'Unable to comment on reshared posts with your current version of Friendica server.'); - return; - } - if (mounted) { context.push('/comment/new?parent_id=${widget.entry.id}'); } diff --git a/lib/controls/timeline/status_header_control.dart b/lib/controls/timeline/status_header_control.dart index 1a4f1a7..4a70f5f 100644 --- a/lib/controls/timeline/status_header_control.dart +++ b/lib/controls/timeline/status_header_control.dart @@ -7,7 +7,9 @@ import '../../models/connection.dart'; import '../../models/timeline_entry.dart'; import '../../models/visibility.dart'; import '../../routes.dart'; +import '../../services/auth_service.dart'; import '../../services/connections_manager.dart'; +import '../../services/reshared_via_service.dart'; import '../../utils/active_profile_selector.dart'; import '../../utils/dateutils.dart'; import '../image_control.dart'; @@ -32,14 +34,21 @@ class StatusHeaderControl extends StatelessWidget { Widget build(BuildContext context) { late final Connection author; late final Connection reshareAuthor; + final activeProfile = getIt().currentProfile; + final reshareId = getIt>() + .getForProfile(activeProfile) + .transform((s) => s.getForPost(entry.id)?.resharers.firstOrNull) + .getValueOrElse(() => null); - getIt>().activeEntry.match( + getIt>() + .getForProfile(activeProfile) + .match( onSuccess: (manager) { author = manager.getById(entry.authorId).getValueOrElse(() => Connection()); - reshareAuthor = manager - .getById(entry.reshareAuthorId) - .getValueOrElse(() => Connection()); + reshareAuthor = reshareId == null + ? Connection() + : manager.getById(reshareId).getValueOrElse(() => Connection()); }, onError: (error) { _logger.severe('Error getting connections manageR: $error'); @@ -75,9 +84,10 @@ class StatusHeaderControl extends StatelessWidget { ), ], ), - if (reshareAuthor.isNotEmpty) ...[ + if (reshareAuthor.isNotEmpty && + author.id != activeProfile.userId) ...[ const HorizontalPadding(width: 3.0), - const Text('reshared post by: '), + const Text('reshared by '), const HorizontalPadding(width: 3.0), Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/di_initialization.dart b/lib/di_initialization.dart index 1648b12..b25ea8f 100644 --- a/lib/di_initialization.dart +++ b/lib/di_initialization.dart @@ -29,6 +29,7 @@ import 'services/interactions_manager.dart'; import 'services/network_status_service.dart'; import 'services/notifications_manager.dart'; import 'services/persistent_info_service.dart'; +import 'services/reshared_via_service.dart'; import 'services/secrets_service.dart'; import 'services/setting_service.dart'; import 'services/timeline_entry_filter_service.dart'; @@ -91,6 +92,9 @@ Future dependencyInjectionInitialization() async { getIt.registerSingleton(accountsService); getIt>().subscribeToProfileSwaps(); getIt>().subscribeToProfileSwaps(); + getIt.registerSingleton>( + ActiveProfileSelector((p) => ReshareViaService()) + ..subscribeToProfileSwaps()); getIt.registerSingleton>( ActiveProfileSelector((p) => MemoryGroupsRepo()) diff --git a/lib/models/friendica_version.dart b/lib/models/friendica_version.dart index ce78e16..4123e21 100644 --- a/lib/models/friendica_version.dart +++ b/lib/models/friendica_version.dart @@ -154,6 +154,8 @@ final FriendicaVersion v2023_04_01 = FriendicaVersion( DateTime(2023, 04), extra: '1', ); +final FriendicaVersion v2023_05 = FriendicaVersion(DateTime(2023, 05)); +final FriendicaVersion v2023_09 = FriendicaVersion(DateTime(2023, 09)); final knownFriendicaVersions = [ // 2018 Versions @@ -192,6 +194,8 @@ final knownFriendicaVersions = [ v2023_01, v2023_04, v2023_04_01, + v2023_05, + v2023_09, ]; FriendicaVersion latestVersion() => knownFriendicaVersions.last; diff --git a/lib/models/timeline_entry.dart b/lib/models/timeline_entry.dart index 69f286b..78aaa63 100644 --- a/lib/models/timeline_entry.dart +++ b/lib/models/timeline_entry.dart @@ -16,12 +16,6 @@ class TimelineEntry { final String parentAuthorId; - final String reshareOriginalPostId; - - final String reshareAuthor; - - final String reshareAuthorId; - final int creationTimestamp; final int backdatedTimestamp; @@ -65,7 +59,6 @@ class TimelineEntry { TimelineEntry( {this.id = '', this.parentId = '', - this.reshareOriginalPostId = '', this.creationTimestamp = 0, this.backdatedTimestamp = 0, this.modificationTimestamp = 0, @@ -78,8 +71,6 @@ class TimelineEntry { this.authorId = '', this.parentAuthor = '', this.parentAuthorId = '', - this.reshareAuthor = '', - this.reshareAuthorId = '', this.externalLink = '', this.locationData = const LocationData(), this.isFavorited = false, @@ -97,7 +88,6 @@ class TimelineEntry { backdatedTimestamp = DateTime.now().millisecondsSinceEpoch, modificationTimestamp = DateTime.now().millisecondsSinceEpoch, id = randomId(), - reshareOriginalPostId = '', youReshared = DateTime.now().second ~/ 2 == 0 ? true : false, visibility = DateTime.now().second ~/ 2 == 0 ? Visibility.public() @@ -111,8 +101,6 @@ class TimelineEntry { authorId = 'Random authorId ${randomId()}', parentAuthor = 'Random parent author ${randomId()}', parentAuthorId = 'Random parent author id ${randomId()}', - reshareAuthor = 'Random parent author ${randomId()}', - reshareAuthorId = 'Random parent author id ${randomId()}', locationData = LocationData.randomBuilt(), isFavorited = DateTime.now().second ~/ 2 == 0 ? true : false, tags = [], @@ -158,8 +146,6 @@ class TimelineEntry { modificationTimestamp: modificationTimestamp ?? this.modificationTimestamp, id: id ?? this.id, - reshareOriginalPostId: - reshareOriginalPostId ?? this.reshareOriginalPostId, youReshared: isReshare ?? this.youReshared, visibility: visibility ?? this.visibility, parentId: parentId ?? this.parentId, @@ -171,8 +157,6 @@ class TimelineEntry { authorId: authorId ?? this.authorId, parentAuthor: parentAuthor ?? this.parentAuthor, parentAuthorId: parentAuthorId ?? this.parentAuthorId, - reshareAuthor: parentAuthor ?? this.reshareAuthor, - reshareAuthorId: parentAuthorId ?? this.reshareAuthorId, locationData: locationData ?? this.locationData, isFavorited: isFavorited ?? this.isFavorited, tags: tags ?? this.tags, @@ -200,12 +184,9 @@ class TimelineEntry { other is TimelineEntry && runtimeType == other.runtimeType && id == other.id && - reshareOriginalPostId == other.reshareOriginalPostId && parentId == other.parentId && parentAuthor == other.parentAuthor && parentAuthorId == other.parentAuthorId && - reshareAuthor == other.reshareAuthor && - reshareAuthorId == other.reshareAuthorId && creationTimestamp == other.creationTimestamp && backdatedTimestamp == other.backdatedTimestamp && modificationTimestamp == other.modificationTimestamp && @@ -229,12 +210,9 @@ class TimelineEntry { @override int get hashCode => id.hashCode ^ - reshareOriginalPostId.hashCode ^ parentId.hashCode ^ parentAuthor.hashCode ^ parentAuthorId.hashCode ^ - reshareAuthor.hashCode ^ - reshareAuthorId.hashCode ^ creationTimestamp.hashCode ^ backdatedTimestamp.hashCode ^ modificationTimestamp.hashCode ^ diff --git a/lib/serializers/mastodon/notification_mastodon_extension.dart b/lib/serializers/mastodon/notification_mastodon_extension.dart index 06fbc40..afd0f8e 100644 --- a/lib/serializers/mastodon/notification_mastodon_extension.dart +++ b/lib/serializers/mastodon/notification_mastodon_extension.dart @@ -42,10 +42,10 @@ extension NotificationMastodonExtension on UserNotification { case NotificationType.unknown: content = '${from.name} has unknown interaction notification'; break; - case NotificationType.favourite: - case NotificationType.mention: case NotificationType.reshare: case NotificationType.reblog: + case NotificationType.favourite: + case NotificationType.mention: case NotificationType.status: final status = TimelineEntryMastodonExtensions.fromJson(json['status']); statusId = status.id; @@ -58,11 +58,8 @@ extension NotificationMastodonExtension on UserNotification { final baseContent = type == NotificationType.mention ? "${from.name} ${type.toVerb()}" : "${from.name} ${type.toVerb()} ${status.author}'s"; - final shareInfo = status.reshareAuthorId.isNotEmpty - ? "reshare of ${status.reshareAuthor}'s" - : ''; final bodyText = htmlToSimpleText(status.body).truncate(length: 100); - content = "$baseContent $shareInfo $referenceType: $bodyText"; + content = "$baseContent $referenceType: $bodyText"; break; case NotificationType.direct_message: // this is a Relatica internal type so nothing to do here diff --git a/lib/serializers/mastodon/timeline_entry_mastodon_extensions.dart b/lib/serializers/mastodon/timeline_entry_mastodon_extensions.dart index d7751d3..29db1f3 100644 --- a/lib/serializers/mastodon/timeline_entry_mastodon_extensions.dart +++ b/lib/serializers/mastodon/timeline_entry_mastodon_extensions.dart @@ -1,4 +1,6 @@ import 'package:logging/logging.dart'; +import 'package:relatica/services/auth_service.dart'; +import 'package:relatica/services/reshared_via_service.dart'; import '../../globals.dart'; import '../../models/engagement_summary.dart'; @@ -19,6 +21,45 @@ final _logger = Logger('TimelineEntryMastodonExtensions'); extension TimelineEntryMastodonExtensions on TimelineEntry { static TimelineEntry fromJson(Map json) { + final activeProfile = getIt().currentProfile; + final resharedViaService = getIt>() + .getForProfile(activeProfile) + .fold( + onSuccess: (s) => s, + onError: (error) { + _logger.severe('Error getting reshared via service: $error'); + return null; + }); + + final connectionManager = getIt>() + .getForProfile(activeProfile) + .fold( + onSuccess: (m) => m, + onError: (error) { + _logger.severe('Error getting connection manager: $error'); + return null; + }); + + final id = json['id'] ?? ''; + final parentId = json['in_reply_to_id'] ?? ''; + final parentAuthor = json['in_reply_to_account_id'] ?? ''; + final parentAuthorId = json['in_reply_to_account_id'] ?? ''; + final author = json['account']['display_name']; + final authorId = json['account']['id']; + final resharePostData = json['reblog']; + + if (resharePostData != null) { + final rebloggedUser = + ConnectionMastodonExtensions.fromJson(resharePostData['account']); + connectionManager?.upsertConnection(rebloggedUser); + final resharedPost = fromJson(resharePostData); + resharedViaService?.upsertResharedVia( + postId: resharedPost.id, + resharerId: authorId, + ); + return resharedPost; + } + final int timestamp = json.containsKey('created_at') ? OffsetDateTimeUtils.epochSecTimeFromTimeZoneString(json['created_at']) .fold( @@ -28,21 +69,18 @@ extension TimelineEntryMastodonExtensions on TimelineEntry { return 0; }) : 0; - final id = json['id'] ?? ''; + final youReshared = json['reblogged'] ?? false; final visibility = ['public', 'unlisted'].contains(json['visibility']) ? Visibility.public() : Visibility.private(); - final parentId = json['in_reply_to_id'] ?? ''; - final parentAuthor = json['in_reply_to_account_id'] ?? ''; - final parentAuthorId = json['in_reply_to_account_id'] ?? ''; - final body = json['content'] ?? ''; - final author = json['account']['display_name']; - final authorId = json['account']['id']; + const title = ''; + final body = json['content'] ?? ''; final spoilerText = json['spoiler_text'] ?? ''; final externalLink = json['uri'] ?? ''; - final actualLocationData = LocationData(); + const actualLocationData = LocationData(); + final modificationTimestamp = timestamp; final backdatedTimestamp = timestamp; final isFavorited = json['favourited'] ?? false; @@ -61,35 +99,9 @@ extension TimelineEntryMastodonExtensions on TimelineEntry { rebloggedCount: rebloggedCount, repliesCount: repliesCount, ); - final linkPreviewData = - LinkPreviewMastodonExtensions.fromJson(json['card']); - - final connectionManager = - getIt>().activeEntry.fold( - onSuccess: (m) => m, - onError: (error) { - _logger.severe('Error getting connection manager: $error'); - return null; - }); - final connection = ConnectionMastodonExtensions.fromJson(json['account']); - connectionManager?.upsertConnection(connection); - - late final String reshareAuthor; - late final String reshareAuthorId; - late final String reshareOriginalPostId; - if (json['reblog'] != null) { - final rebloggedUser = - ConnectionMastodonExtensions.fromJson(json['reblog']['account']); - connectionManager?.upsertConnection(rebloggedUser); - reshareAuthor = rebloggedUser.name; - reshareAuthorId = rebloggedUser.id; - reshareOriginalPostId = json['reblog']['id'] ?? id; - } else { - reshareAuthorId = ''; - reshareAuthor = ''; - reshareOriginalPostId = ''; - } - + final linkPreviewData = LinkPreviewMastodonExtensions.fromJson( + json['card'], + ); final List? tagsJson = json['tags']; final tags = []; if (tagsJson?.isNotEmpty ?? false) { @@ -101,6 +113,9 @@ extension TimelineEntryMastodonExtensions on TimelineEntry { } } + final connection = ConnectionMastodonExtensions.fromJson(json['account']); + connectionManager?.upsertConnection(connection); + return TimelineEntry( creationTimestamp: timestamp, modificationTimestamp: modificationTimestamp, @@ -111,11 +126,8 @@ extension TimelineEntryMastodonExtensions on TimelineEntry { youReshared: youReshared, visibility: visibility, id: id, - reshareOriginalPostId: reshareOriginalPostId, parentId: parentId, parentAuthorId: parentAuthorId, - reshareAuthor: reshareAuthor, - reshareAuthorId: reshareAuthorId, isFavorited: isFavorited, externalLink: externalLink, author: author, diff --git a/lib/services/entry_manager_service.dart b/lib/services/entry_manager_service.dart index a599a52..14478b4 100644 --- a/lib/services/entry_manager_service.dart +++ b/lib/services/entry_manager_service.dart @@ -5,7 +5,6 @@ import 'package:result_monad/result_monad.dart'; import '../friendica_client/friendica_client.dart'; import '../friendica_client/paging_data.dart'; -import '../globals.dart'; import '../models/TimelineIdentifiers.dart'; import '../models/auth/profile.dart'; import '../models/entry_tree_item.dart'; @@ -14,7 +13,6 @@ import '../models/image_entry.dart'; import '../models/media_attachment_uploads/new_entry_media_items.dart'; import '../models/timeline_entry.dart'; import '../models/visibility.dart'; -import 'feature_version_checker.dart'; import 'media_upload_attachment_helper.dart'; class EntryManagerService extends ChangeNotifier { @@ -48,7 +46,7 @@ class EntryManagerService extends ChangeNotifier { Result getPostTreeEntryBy(String id) { _logger.finest('Getting post: $id'); - final idForCall = mapInteractionId(id); + final idForCall = id; final postNode = _getPostRootNode(idForCall); if (postNode == null) { return Result.error(ExecError( @@ -180,7 +178,7 @@ class EntryManagerService extends ChangeNotifier { required Visibility newMediaItemVisibility, }) async { _logger.finest('Editing post: $text'); - final idForCall = mapInteractionId(id); + final idForCall = id; final mediaIds = existingMediaItems .map((m) => m.scales.isEmpty ? m.id : m.scales.first.id) .toList(); @@ -397,54 +395,20 @@ class EntryManagerService extends ChangeNotifier { return updatedPosts; } - String mapInteractionId(String id) { - return getEntryById(id).transform((e) { - if (e.reshareOriginalPostId.isEmpty) { - return id; - } - - final fvc = getIt(); - if (fvc.canUseFeature(RelaticaFeatures.reshareIdFix)) { - return e.reshareOriginalPostId; - } - - return id; - }).getValueOrElse(() => id); - } - FutureResult refreshStatusChain(String id) async { _logger.finest('Refreshing post: $id'); final client = StatusesClient(profile); - final idForCall = mapInteractionId(id); - var parentId = ''; final result = await client - .getPostOrComment(idForCall, fullContext: false) - .withResult((entries) => - parentId = entries.isEmpty ? '' : entries.first.parentId) + .getPostOrComment(id, fullContext: false) .andThenAsync((rootItems) async => await client - .getPostOrComment(idForCall, fullContext: true) + .getPostOrComment(id, fullContext: true) .andThenSuccessAsync( (contextItems) async => [...rootItems, ...contextItems])) .withResult((items) async { + _cleanupEntriesForId(id); await processNewItems(items, client.profile.username, null); }); - if (parentId.isNotEmpty && - getIt() - .canUseFeature(RelaticaFeatures.reshareIdFix)) { - final parentIdForCall = mapInteractionId(parentId); - await client - .getPostOrComment(parentIdForCall, fullContext: false) - .withResult((entries) => - parentId = entries.isEmpty ? '' : entries.first.parentId) - .andThenAsync((rootItems) async => await client - .getPostOrComment(idForCall, fullContext: true) - .transformAsync( - (contextItems) async => [...rootItems, ...contextItems])) - .withResult((items) async { - await processNewItems(items, client.profile.username, null); - }); - } return result.mapValue((_) { _logger.finest('$id post updated'); return _nodeToTreeItem(_getPostRootNode(id)!, client.profile.userId); @@ -462,7 +426,7 @@ class EntryManagerService extends ChangeNotifier { FutureResult resharePost(String id) async { _logger.finest('Resharing post: $id'); final client = StatusesClient(profile); - final idForCall = mapInteractionId(id); + final idForCall = id; final result = await client.resharePost(idForCall).andThenSuccessAsync((item) async { await processNewItems([item], client.profile.username, null); @@ -485,7 +449,7 @@ class EntryManagerService extends ChangeNotifier { FutureResult unResharePost(String id) async { _logger.finest('Unresharing post: $id'); final client = StatusesClient(profile); - final idForCall = mapInteractionId(id); + final idForCall = id; final result = await client.unResharePost(idForCall).andThenSuccessAsync((item) async { await processNewItems([item], client.profile.username, null); @@ -505,7 +469,7 @@ class EntryManagerService extends ChangeNotifier { String id, bool newStatus) async { final interactionClient = InteractionsClient(profile); final postsClient = StatusesClient(profile); - final idForCall = mapInteractionId(id); + final idForCall = id; final result = await interactionClient.changeFavoriteStatus(idForCall, newStatus); if (result.isFailure) { @@ -533,8 +497,7 @@ class EntryManagerService extends ChangeNotifier { childenEntries[c.id] = _nodeToTreeItem(c, currentId); } final entry = _entries[node.id]!; - final isMine = - entry.authorId == currentId || entry.reshareAuthorId == currentId; + final isMine = entry.authorId == currentId; return EntryTreeItem( _entries[node.id]!, isMine: isMine, @@ -544,7 +507,9 @@ class EntryManagerService extends ChangeNotifier { void _cleanupEntriesForId(String id) { if (_parentPostIds.containsKey(id)) { - _parentPostIds.remove(id); + final parentPostId = _parentPostIds.remove(id); + final parentPostNode = _postNodes[parentPostId]; + parentPostNode?.removeChildById(id); } if (_entries.containsKey(id)) { @@ -573,7 +538,7 @@ class _Node { _children[node.id] = node; } - _Node? removeChildById(String id) { + void removeChildById(String id) { if (_children.containsKey(id)) { _children.remove(id); } diff --git a/lib/services/feature_version_checker.dart b/lib/services/feature_version_checker.dart index f26300e..21bed06 100644 --- a/lib/services/feature_version_checker.dart +++ b/lib/services/feature_version_checker.dart @@ -78,9 +78,6 @@ class FriendicaVersionChecker { v2023_04, ), RelaticaFeatures.postSpoilerText: FriendicaVersionRequirement(v2023_04), - RelaticaFeatures.reshareIdFix: FriendicaVersionRequirement( - v2023_04, - ), RelaticaFeatures.statusEditing: FriendicaVersionRequirement(v2023_04), RelaticaFeatures.usingActualFollowRequests: FriendicaVersionRequirement( v2023_04, diff --git a/lib/services/interactions_manager.dart b/lib/services/interactions_manager.dart index c0c84af..ff533ee 100644 --- a/lib/services/interactions_manager.dart +++ b/lib/services/interactions_manager.dart @@ -6,8 +6,7 @@ import '../globals.dart'; import '../models/auth/profile.dart'; import '../models/connection.dart'; import '../models/exec_error.dart'; -import '../utils/active_profile_selector.dart'; -import 'entry_manager_service.dart'; +import 'auth_service.dart'; class InteractionsManager extends ChangeNotifier { final _likesByStatusId = >{}; @@ -43,8 +42,9 @@ class InteractionsManager extends ChangeNotifier { FutureResult, ExecError> updateLikesForStatus( String statusId) async { - final idForCall = _mapStatusId(statusId); - final likesResult = await InteractionsClient(profile).getLikes(idForCall); + final likesResult = + await InteractionsClient(getIt().currentProfile) + .getLikes(statusId); if (likesResult.isSuccess) { _likesByStatusId[statusId] = likesResult.value; notifyListeners(); @@ -54,20 +54,13 @@ class InteractionsManager extends ChangeNotifier { FutureResult, ExecError> updateResharesForStatus( String statusId) async { - final idForCall = _mapStatusId(statusId); final resharesResult = - await InteractionsClient(profile).getReshares(idForCall); + await InteractionsClient(getIt().currentProfile) + .getReshares(statusId); if (resharesResult.isSuccess) { _resharesByStatusId[statusId] = resharesResult.value; notifyListeners(); } return resharesResult; } - - String _mapStatusId(String statusId) { - return getIt>() - .getForProfile(profile) - .transform((m) => m.mapInteractionId(statusId)) - .getValueOrElse(() => statusId); - } } diff --git a/lib/services/reshared_via_service.dart b/lib/services/reshared_via_service.dart new file mode 100644 index 0000000..fa1ec9a --- /dev/null +++ b/lib/services/reshared_via_service.dart @@ -0,0 +1,31 @@ +class ReshareViaService { + final _postsVia = {}; + + ResharedViaData? getForPost(String postId) => _postsVia[postId]; + + void upsertResharedVia({required String postId, required String resharerId}) { + final resharedData = _postsVia.putIfAbsent( + postId, + () => ResharedViaData(postId: postId), + ); + + _postsVia[postId] = resharedData.withUpsertedResharer(resharerId); + } +} + +class ResharedViaData { + final String postId; + final Set resharers; + + bool get hasResharedVia => resharers.isNotEmpty; + + const ResharedViaData({ + required this.postId, + this.resharers = const {}, + }); + + ResharedViaData withUpsertedResharer(String resharerId) => ResharedViaData( + postId: postId, + resharers: {resharerId, ...resharers}, + ); +} diff --git a/lib/utils/filter_runner.dart b/lib/utils/filter_runner.dart index 7a712fc..a1d1c89 100644 --- a/lib/utils/filter_runner.dart +++ b/lib/utils/filter_runner.dart @@ -95,7 +95,6 @@ extension TimelineEntryFilterOps on TimelineEntryFilter { var authorFiltered = authorFilters.isEmpty ? true : false; for (final filter in authorFilters) { if (filter.isFiltered(entry.authorId) || - filter.isFiltered(entry.reshareAuthorId) || filter.isFiltered(entry.parentAuthorId)) { authorFiltered = true; break; diff --git a/pubspec.lock b/pubspec.lock index 8cfd954..e210037 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1452,5 +1452,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=3.0.0-0 <4.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.7.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1d57132..2189ddd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 0.6.0+1 environment: - sdk: '>=2.18.2 <3.0.0' + sdk: '>=3.0.0 <4.0.0' dependencies: flutter: