diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index 59020f2..8336767 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -690,5 +690,8 @@ "aboutScreenCopyright": "© {} {}. All rights reserved.", "aboutScreenFailedToLoadPackageInfo": "Failed to load package info: {error}", "copiedToClipboard": "Copied to clipboard", - "copyToClipboardTooltip": "Copy to clipboard" + "copyToClipboardTooltip": "Copy to clipboard", + "postForwardingTo": "Forwarding to", + "postReplyingTo": "Replying to", + "postEditing": "You are editing an existing post" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 72b7835..0caad72 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:image_picker_android/image_picker_android.dart'; import 'package:island/firebase_options.dart'; @@ -45,6 +46,10 @@ void main() async { FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); } + if (kIsWeb) { + GoRouter.optionURLReflectsImperativeAPIs = true; + } + try { await EasyLocalization.ensureInitialized(); await Firebase.initializeApp( diff --git a/lib/route.dart b/lib/route.dart index 82d2fa1..78b97e8 100644 --- a/lib/route.dart +++ b/lib/route.dart @@ -65,6 +65,9 @@ final routerProvider = Provider((ref) { builder: (context, state) => PostComposeScreen( initialState: state.extra as PostComposeInitialState?, + type: + int.tryParse(state.uri.queryParameters['type'] ?? '0') ?? + 0, ), ), GoRoute( diff --git a/lib/screens/creators/hub.dart b/lib/screens/creators/hub.dart index 598f9c5..0b834b2 100644 --- a/lib/screens/creators/hub.dart +++ b/lib/screens/creators/hub.dart @@ -108,15 +108,18 @@ class CreatorHubShellScreen extends StatelessWidget { Widget build(BuildContext context) { final isWide = isWideScreen(context); if (isWide) { - return Row( - children: [ - SizedBox(width: 360, child: const CreatorHubScreen(isAside: true)), - const VerticalDivider(width: 1), - Expanded(child: child), - ], + return AppBackground( + isRoot: true, + child: Row( + children: [ + SizedBox(width: 360, child: const CreatorHubScreen(isAside: true)), + const VerticalDivider(width: 1), + Expanded(child: child), + ], + ), ); } - return child; + return AppBackground(isRoot: true, child: child); } } @@ -198,7 +201,6 @@ class CreatorHubScreen extends HookConsumerWidget { ); return AppScaffold( - noBackground: false, appBar: AppBar( leading: !isWide ? const PageBackButton() : null, title: Text('creatorHub').tr(), diff --git a/lib/screens/creators/posts/post_manage_list.dart b/lib/screens/creators/posts/post_manage_list.dart index 1d1bf84..357e64d 100644 --- a/lib/screens/creators/posts/post_manage_list.dart +++ b/lib/screens/creators/posts/post_manage_list.dart @@ -26,7 +26,7 @@ class CreatorPostListScreen extends HookConsumerWidget { children: [ ListTile( leading: const Icon(Symbols.edit), - title: Text('postContent'.tr()), + title: Text('Post'), subtitle: Text('Create a regular post'), onTap: () async { Navigator.pop(context); diff --git a/lib/screens/developers/hub.dart b/lib/screens/developers/hub.dart index 85321ab..22de1d4 100644 --- a/lib/screens/developers/hub.dart +++ b/lib/screens/developers/hub.dart @@ -47,15 +47,21 @@ class DeveloperHubShellScreen extends StatelessWidget { Widget build(BuildContext context) { final isWide = isWideScreen(context); if (isWide) { - return Row( - children: [ - SizedBox(width: 360, child: const DeveloperHubScreen(isAside: true)), - const VerticalDivider(width: 1), - Expanded(child: child), - ], + return AppBackground( + isRoot: true, + child: Row( + children: [ + SizedBox( + width: 360, + child: const DeveloperHubScreen(isAside: true), + ), + const VerticalDivider(width: 1), + Expanded(child: child), + ], + ), ); } - return child; + return AppBackground(isRoot: true, child: child); } } @@ -238,8 +244,8 @@ class DeveloperHubScreen extends HookConsumerWidget { ), onTap: () { context.push( - '/developers/${currentDeveloper.value!.name}/apps', - ); + '/developers/${currentDeveloper.value!.name}/apps', + ); }, ), ], diff --git a/lib/screens/posts/compose.dart b/lib/screens/posts/compose.dart index e3dd042..00911cf 100644 --- a/lib/screens/posts/compose.dart +++ b/lib/screens/posts/compose.dart @@ -33,6 +33,8 @@ sealed class PostComposeInitialState with _$PostComposeInitialState { String? content, @Default([]) List attachments, int? visibility, + SnPost? replyingTo, + SnPost? forwardingTo, }) = _PostComposeInitialState; factory PostComposeInitialState.fromJson(Map json) => @@ -66,23 +68,22 @@ class PostEditScreen extends HookConsumerWidget { class PostComposeScreen extends HookConsumerWidget { final SnPost? originalPost; - final SnPost? repliedPost; - final SnPost? forwardedPost; final int? type; final PostComposeInitialState? initialState; const PostComposeScreen({ super.key, - this.originalPost, - this.repliedPost, - this.forwardedPost, this.type, this.initialState, + this.originalPost, }); @override Widget build(BuildContext context, WidgetRef ref) { // Determine the compose type: auto-detect from edited post or use query parameter final composeType = originalPost?.type ?? type ?? 0; + final repliedPost = initialState?.replyingTo ?? originalPost?.repliedPost; + final forwardedPost = + initialState?.forwardingTo ?? originalPost?.forwardedPost; // If type is 1 (article), return ArticleComposeScreen if (composeType == 1) { @@ -136,7 +137,10 @@ class PostComposeScreen extends HookConsumerWidget { // Initialize publisher once when data is available useEffect(() { if (publishers.value?.isNotEmpty ?? false) { - state.currentPublisher.value = publishers.value!.first; + if (state.currentPublisher.value == null) { + // If no publisher is set, use the first available one + state.currentPublisher.value = publishers.value!.first; + } } return null; }, [publishers]); @@ -480,8 +484,10 @@ class PostComposeScreen extends HookConsumerWidget { Widget _buildInfoBanner(BuildContext context) { // When editing, preserve the original replied/forwarded post references - final effectiveRepliedPost = repliedPost ?? originalPost?.repliedPost; - final effectiveForwardedPost = forwardedPost ?? originalPost?.forwardedPost; + final effectiveRepliedPost = + initialState?.replyingTo ?? originalPost?.repliedPost; + final effectiveForwardedPost = + initialState?.forwardingTo ?? originalPost?.forwardedPost; // Show editing banner when editing a post if (originalPost != null) { @@ -497,15 +503,15 @@ class PostComposeScreen extends HookConsumerWidget { size: 16, color: Theme.of(context).colorScheme.onPrimaryContainer, ), - const Gap(4), + const Gap(8), Text( - 'edit'.tr(), + 'postEditing'.tr(), style: Theme.of(context).textTheme.labelMedium?.copyWith( color: Theme.of(context).colorScheme.onPrimaryContainer, ), ), ], - ).padding(all: 16), + ).padding(horizontal: 16, vertical: 8), ), // Show reply/forward banners below editing banner if they exist if (effectiveRepliedPost != null) @@ -615,6 +621,7 @@ class PostComposeScreen extends HookConsumerWidget { showModalBottomSheet( context: context, isScrollControlled: true, + backgroundColor: Colors.transparent, builder: (context) => DraggableScrollableSheet( initialChildSize: 0.7, diff --git a/lib/screens/posts/compose.freezed.dart b/lib/screens/posts/compose.freezed.dart index 3987fb7..3ed22f5 100644 --- a/lib/screens/posts/compose.freezed.dart +++ b/lib/screens/posts/compose.freezed.dart @@ -16,7 +16,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$PostComposeInitialState { - String? get title; String? get description; String? get content; List get attachments; int? get visibility; + String? get title; String? get description; String? get content; List get attachments; int? get visibility; SnPost? get replyingTo; SnPost? get forwardingTo; /// Create a copy of PostComposeInitialState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -29,16 +29,16 @@ $PostComposeInitialStateCopyWith get copyWith => _$Post @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is PostComposeInitialState&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.visibility, visibility) || other.visibility == visibility)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is PostComposeInitialState&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.replyingTo, replyingTo) || other.replyingTo == replyingTo)&&(identical(other.forwardingTo, forwardingTo) || other.forwardingTo == forwardingTo)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,title,description,content,const DeepCollectionEquality().hash(attachments),visibility); +int get hashCode => Object.hash(runtimeType,title,description,content,const DeepCollectionEquality().hash(attachments),visibility,replyingTo,forwardingTo); @override String toString() { - return 'PostComposeInitialState(title: $title, description: $description, content: $content, attachments: $attachments, visibility: $visibility)'; + return 'PostComposeInitialState(title: $title, description: $description, content: $content, attachments: $attachments, visibility: $visibility, replyingTo: $replyingTo, forwardingTo: $forwardingTo)'; } @@ -49,11 +49,11 @@ abstract mixin class $PostComposeInitialStateCopyWith<$Res> { factory $PostComposeInitialStateCopyWith(PostComposeInitialState value, $Res Function(PostComposeInitialState) _then) = _$PostComposeInitialStateCopyWithImpl; @useResult $Res call({ - String? title, String? description, String? content, List attachments, int? visibility + String? title, String? description, String? content, List attachments, int? visibility, SnPost? replyingTo, SnPost? forwardingTo }); - +$SnPostCopyWith<$Res>? get replyingTo;$SnPostCopyWith<$Res>? get forwardingTo; } /// @nodoc @@ -66,17 +66,43 @@ class _$PostComposeInitialStateCopyWithImpl<$Res> /// Create a copy of PostComposeInitialState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? title = freezed,Object? description = freezed,Object? content = freezed,Object? attachments = null,Object? visibility = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? title = freezed,Object? description = freezed,Object? content = freezed,Object? attachments = null,Object? visibility = freezed,Object? replyingTo = freezed,Object? forwardingTo = freezed,}) { return _then(_self.copyWith( title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable as String?,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable as String?,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable as List,visibility: freezed == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable -as int?, +as int?,replyingTo: freezed == replyingTo ? _self.replyingTo : replyingTo // ignore: cast_nullable_to_non_nullable +as SnPost?,forwardingTo: freezed == forwardingTo ? _self.forwardingTo : forwardingTo // ignore: cast_nullable_to_non_nullable +as SnPost?, )); } +/// Create a copy of PostComposeInitialState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnPostCopyWith<$Res>? get replyingTo { + if (_self.replyingTo == null) { + return null; + } + return $SnPostCopyWith<$Res>(_self.replyingTo!, (value) { + return _then(_self.copyWith(replyingTo: value)); + }); +}/// Create a copy of PostComposeInitialState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnPostCopyWith<$Res>? get forwardingTo { + if (_self.forwardingTo == null) { + return null; + } + + return $SnPostCopyWith<$Res>(_self.forwardingTo!, (value) { + return _then(_self.copyWith(forwardingTo: value)); + }); +} } @@ -84,7 +110,7 @@ as int?, @JsonSerializable() class _PostComposeInitialState implements PostComposeInitialState { - const _PostComposeInitialState({this.title, this.description, this.content, final List attachments = const [], this.visibility}): _attachments = attachments; + const _PostComposeInitialState({this.title, this.description, this.content, final List attachments = const [], this.visibility, this.replyingTo, this.forwardingTo}): _attachments = attachments; factory _PostComposeInitialState.fromJson(Map json) => _$PostComposeInitialStateFromJson(json); @override final String? title; @@ -98,6 +124,8 @@ class _PostComposeInitialState implements PostComposeInitialState { } @override final int? visibility; +@override final SnPost? replyingTo; +@override final SnPost? forwardingTo; /// Create a copy of PostComposeInitialState /// with the given fields replaced by the non-null parameter values. @@ -112,16 +140,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _PostComposeInitialState&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.visibility, visibility) || other.visibility == visibility)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _PostComposeInitialState&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.replyingTo, replyingTo) || other.replyingTo == replyingTo)&&(identical(other.forwardingTo, forwardingTo) || other.forwardingTo == forwardingTo)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,title,description,content,const DeepCollectionEquality().hash(_attachments),visibility); +int get hashCode => Object.hash(runtimeType,title,description,content,const DeepCollectionEquality().hash(_attachments),visibility,replyingTo,forwardingTo); @override String toString() { - return 'PostComposeInitialState(title: $title, description: $description, content: $content, attachments: $attachments, visibility: $visibility)'; + return 'PostComposeInitialState(title: $title, description: $description, content: $content, attachments: $attachments, visibility: $visibility, replyingTo: $replyingTo, forwardingTo: $forwardingTo)'; } @@ -132,11 +160,11 @@ abstract mixin class _$PostComposeInitialStateCopyWith<$Res> implements $PostCom factory _$PostComposeInitialStateCopyWith(_PostComposeInitialState value, $Res Function(_PostComposeInitialState) _then) = __$PostComposeInitialStateCopyWithImpl; @override @useResult $Res call({ - String? title, String? description, String? content, List attachments, int? visibility + String? title, String? description, String? content, List attachments, int? visibility, SnPost? replyingTo, SnPost? forwardingTo }); - +@override $SnPostCopyWith<$Res>? get replyingTo;@override $SnPostCopyWith<$Res>? get forwardingTo; } /// @nodoc @@ -149,18 +177,44 @@ class __$PostComposeInitialStateCopyWithImpl<$Res> /// Create a copy of PostComposeInitialState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? title = freezed,Object? description = freezed,Object? content = freezed,Object? attachments = null,Object? visibility = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? title = freezed,Object? description = freezed,Object? content = freezed,Object? attachments = null,Object? visibility = freezed,Object? replyingTo = freezed,Object? forwardingTo = freezed,}) { return _then(_PostComposeInitialState( title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable as String?,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable as String?,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable as List,visibility: freezed == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable -as int?, +as int?,replyingTo: freezed == replyingTo ? _self.replyingTo : replyingTo // ignore: cast_nullable_to_non_nullable +as SnPost?,forwardingTo: freezed == forwardingTo ? _self.forwardingTo : forwardingTo // ignore: cast_nullable_to_non_nullable +as SnPost?, )); } +/// Create a copy of PostComposeInitialState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnPostCopyWith<$Res>? get replyingTo { + if (_self.replyingTo == null) { + return null; + } + return $SnPostCopyWith<$Res>(_self.replyingTo!, (value) { + return _then(_self.copyWith(replyingTo: value)); + }); +}/// Create a copy of PostComposeInitialState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnPostCopyWith<$Res>? get forwardingTo { + if (_self.forwardingTo == null) { + return null; + } + + return $SnPostCopyWith<$Res>(_self.forwardingTo!, (value) { + return _then(_self.copyWith(forwardingTo: value)); + }); +} } // dart format on diff --git a/lib/screens/posts/compose.g.dart b/lib/screens/posts/compose.g.dart index 1faba5c..e9b29d6 100644 --- a/lib/screens/posts/compose.g.dart +++ b/lib/screens/posts/compose.g.dart @@ -18,6 +18,14 @@ _PostComposeInitialState _$PostComposeInitialStateFromJson( .toList() ?? const [], visibility: (json['visibility'] as num?)?.toInt(), + replyingTo: + json['replying_to'] == null + ? null + : SnPost.fromJson(json['replying_to'] as Map), + forwardingTo: + json['forwarding_to'] == null + ? null + : SnPost.fromJson(json['forwarding_to'] as Map), ); Map _$PostComposeInitialStateToJson( @@ -28,4 +36,6 @@ Map _$PostComposeInitialStateToJson( 'content': instance.content, 'attachments': instance.attachments.map((e) => e.toJson()).toList(), 'visibility': instance.visibility, + 'replying_to': instance.replyingTo?.toJson(), + 'forwarding_to': instance.forwardingTo?.toJson(), }; diff --git a/lib/screens/posts/post_detail.dart b/lib/screens/posts/post_detail.dart index 8b730b1..03cf829 100644 --- a/lib/screens/posts/post_detail.dart +++ b/lib/screens/posts/post_detail.dart @@ -21,9 +21,10 @@ Future post(Ref ref, String id) async { return SnPost.fromJson(resp.data); } -final postStateProvider = StateNotifierProvider.family, String>( - (ref, id) => PostState(ref, id), -); +final postStateProvider = + StateNotifierProvider.family, String>( + (ref, id) => PostState(ref, id), + ); class PostState extends StateNotifier> { final Ref _ref; @@ -74,7 +75,9 @@ class PostDetailScreen extends HookConsumerWidget { backgroundColor: isWide ? Colors.transparent : null, onUpdate: (newItem) { // Update the local state with the new post data - ref.read(postStateProvider(id).notifier).updatePost(newItem); + ref + .read(postStateProvider(id).notifier) + .updatePost(newItem); }, ), const Divider(height: 1), @@ -92,20 +95,25 @@ class PostDetailScreen extends HookConsumerWidget { right: 0, child: Material( elevation: 2, - child: postState.when( - data: (post) => PostQuickReply( - parent: post!, - onPosted: () { - ref.invalidate(postRepliesNotifierProvider(id)); - }, - ), - loading: () => const SizedBox.shrink(), - error: (_, __) => const SizedBox.shrink(), - ).padding( - bottom: MediaQuery.of(context).padding.bottom + 16, - top: 16, - horizontal: 16, - ), + child: postState + .when( + data: + (post) => PostQuickReply( + parent: post!, + onPosted: () { + ref.invalidate( + postRepliesNotifierProvider(id), + ); + }, + ), + loading: () => const SizedBox.shrink(), + error: (_, _) => const SizedBox.shrink(), + ) + .padding( + bottom: MediaQuery.of(context).padding.bottom + 16, + top: 16, + horizontal: 16, + ), ), ), ], diff --git a/lib/widgets/post/compose_shared.dart b/lib/widgets/post/compose_shared.dart index bda1982..6ec31e6 100644 --- a/lib/widgets/post/compose_shared.dart +++ b/lib/widgets/post/compose_shared.dart @@ -98,19 +98,11 @@ class ComposeLogic { descriptionController: TextEditingController( text: originalPost?.description, ), - contentController: TextEditingController( - text: - originalPost?.content ?? - (forwardedPost != null - ? '''> ${forwardedPost.content} - -''' - : null), - ), + contentController: TextEditingController(text: originalPost?.content), visibility: ValueNotifier(originalPost?.visibility ?? 0), submitting: ValueNotifier(false), attachmentProgress: ValueNotifier>({}), - currentPublisher: ValueNotifier(null), + currentPublisher: ValueNotifier(originalPost?.publisher), tagsController: tagsController, categoriesController: categoriesController, draftId: id, diff --git a/lib/widgets/post/post_item.dart b/lib/widgets/post/post_item.dart index c18e6bc..203f827 100644 --- a/lib/widgets/post/post_item.dart +++ b/lib/widgets/post/post_item.dart @@ -11,6 +11,7 @@ import 'package:island/models/post.dart'; import 'package:island/pods/config.dart'; import 'package:island/pods/network.dart'; import 'package:island/pods/userinfo.dart'; +import 'package:island/screens/posts/compose.dart'; import 'package:island/services/responsive.dart'; import 'package:island/services/time.dart'; import 'package:island/widgets/account/account_name.dart'; @@ -116,14 +117,20 @@ class PostItem extends HookConsumerWidget { title: 'reply'.tr(), image: MenuImage.icon(Symbols.reply), callback: () { - context.push('/posts/compose', extra: {'repliedPost': item}); + context.push( + '/posts/compose', + extra: PostComposeInitialState(replyingTo: item), + ); }, ), MenuAction( title: 'forward'.tr(), image: MenuImage.icon(Symbols.forward), callback: () { - context.push('/posts/compose', extra: {'forwardedPost': item}); + context.push( + '/posts/compose', + extra: PostComposeInitialState(forwardingTo: item), + ); }, ), MenuSeparator(), diff --git a/lib/widgets/post/post_item_creator.dart b/lib/widgets/post/post_item_creator.dart index d8153e9..d56dec2 100644 --- a/lib/widgets/post/post_item_creator.dart +++ b/lib/widgets/post/post_item_creator.dart @@ -87,7 +87,7 @@ class PostItemCreator extends HookConsumerWidget { ); }, child: Material( - color: Colors.transparent, + color: backgroundColor ?? Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(12), elevation: 1, child: InkWell( diff --git a/pubspec.lock b/pubspec.lock index c861c92..89aa24f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1025,7 +1025,7 @@ packages: source: hosted version: "4.0.0" flutter_web_plugins: - dependency: transitive + dependency: "direct main" description: flutter source: sdk version: "0.0.0" @@ -1097,10 +1097,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: ac294be30ba841830cfa146e5a3b22bb09f8dc5a0fdd9ca9332b04b0bde99ebf + sha256: c489908a54ce2131f1d1b7cc631af9c1a06fac5ca7c449e959192089f9489431 url: "https://pub.dev" source: hosted - version: "15.2.4" + version: "16.0.0" google_fonts: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index ad2a3eb..5176593 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,8 @@ environment: dependencies: flutter: sdk: flutter + flutter_web_plugins: + sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. @@ -37,7 +39,7 @@ dependencies: flutter_hooks: ^0.21.2 hooks_riverpod: ^2.6.1 bitsdojo_window: ^0.1.6 - go_router: ^15.1.3 + go_router: ^16.0.0 styled_widget: ^0.4.1 shared_preferences: ^2.5.3 flutter_riverpod: ^2.6.1