From 18db50d80cac0ab53ebaab23fda50409ab6d5705 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 20 Jul 2025 02:31:50 +0800 Subject: [PATCH] :bug: Dozens of bug fixes --- assets/i18n/en-US.json | 6 +- lib/screens/about.dart | 41 ++- .../account/me/settings_auth_factors.dart | 4 +- .../account/me/settings_connections.dart | 4 +- lib/screens/account/me/settings_contacts.dart | 2 +- lib/screens/account/profile.dart | 10 +- lib/screens/account/profile.g.dart | 8 +- lib/screens/account/relationship.dart | 6 +- lib/screens/account/relationship.g.dart | 2 +- lib/screens/chat/chat.dart | 233 +++++++++--------- lib/screens/chat/room_detail.dart | 13 +- lib/screens/creators/hub.g.dart | 2 +- lib/screens/creators/stickers/stickers.g.dart | 4 +- lib/screens/developers/hub.g.dart | 4 +- lib/screens/discovery/articles.dart | 2 +- lib/screens/notification.dart | 2 +- lib/screens/notification.g.dart | 2 +- lib/screens/posts/post_search.dart | 2 +- lib/screens/posts/pub_profile.dart | 11 +- lib/screens/realm/realm_detail.g.dart | 2 +- lib/screens/realm/realms.dart | 231 ++++++++--------- lib/screens/tabs.dart | 6 +- lib/screens/wallet.g.dart | 2 +- lib/services/abuse_report_service.dart | 9 +- lib/widgets/account/fortune_graph.dart | 3 +- .../content/cloud_file_collection.dart | 6 +- lib/widgets/content/cloud_files.dart | 4 +- lib/widgets/post/post_item.dart | 37 ++- lib/widgets/post/post_quick_reply.dart | 2 +- lib/widgets/post/post_replies.dart | 11 +- lib/widgets/post/post_replies.g.dart | 2 +- lib/widgets/realm/realm_list.g.dart | 2 +- lib/widgets/safety/abuse_report_sheet.dart | 2 +- 33 files changed, 359 insertions(+), 318 deletions(-) diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index d26cc9a..70314b0 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -698,5 +698,9 @@ "postForwardingTo": "Forwarding to", "postReplyingTo": "Replying to", "postEditing": "You are editing an existing post", - "postArticle": "Article" + "postArticle": "Article", + "aboutDeviceName": "Device Name", + "aboutDeviceIdentifier": "Device Identifier", + "donate": "Donate", + "donateDescription": "Support us to continue developing the Solar Network and keep the server up and running." } \ No newline at end of file diff --git a/lib/screens/about.dart b/lib/screens/about.dart index 7571ee2..ccbd320 100644 --- a/lib/screens/about.dart +++ b/lib/screens/about.dart @@ -1,18 +1,19 @@ +import 'dart:io'; + import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:island/pods/network.dart'; -import 'package:island/services/notify.dart'; import 'package:island/services/udid.native.dart'; -import 'package:island/widgets/alert.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:url_launcher/url_launcher_string.dart'; class AboutScreen extends ConsumerStatefulWidget { const AboutScreen({super.key}); @@ -168,34 +169,16 @@ class _AboutScreenState extends ConsumerState { _buildInfoItem( context, icon: Symbols.label, - label: 'Device Name', + label: 'aboutDeviceName'.tr(), value: _deviceInfo?.data['name'], ), _buildInfoItem( context, icon: Symbols.fingerprint, - label: 'Device Identifier', + label: 'aboutDeviceIdentifier'.tr(), value: _deviceUdid ?? 'N/A', copyable: true, ), - const Divider(height: 1), - _buildListTile( - context, - icon: Symbols.notifications_active, - title: 'Reactivate Push Notifications', - onTap: () async { - showLoadingModal(context); - try { - await subscribePushNotification( - ref.watch(apiClientProvider), - ); - } catch (err) { - showErrorAlert(err); - } finally { - if (context.mounted) hideLoadingModal(context); - } - }, - ), ], ), @@ -266,6 +249,18 @@ class _AboutScreenState extends ConsumerState { 'https://github.com/Solsynth/Solian/blob/v3/LICENSE.txt', ), ), + if (kIsWeb || !(Platform.isMacOS || Platform.isIOS)) + _buildListTile( + context, + icon: Symbols.favorite, + title: 'donate'.tr(), + subtitle: 'donateDescription'.tr(), + onTap: () { + launchUrlString( + 'https://afdian.com/@littlesheep', + ); + }, + ), ], ), diff --git a/lib/screens/account/me/settings_auth_factors.dart b/lib/screens/account/me/settings_auth_factors.dart index 57d0e8d..246c02d 100644 --- a/lib/screens/account/me/settings_auth_factors.dart +++ b/lib/screens/account/me/settings_auth_factors.dart @@ -106,7 +106,7 @@ class AuthFactorSheet extends HookConsumerWidget { showLoadingModal(context); final client = ref.read(apiClientProvider); await client.post( - '/accounts/me/factors/${factor.id}/enable', + '/id/accounts/me/factors/${factor.id}/enable', data: jsonEncode(password), ); if (context.mounted) Navigator.pop(context, true); @@ -193,7 +193,7 @@ class AuthFactorNewSheet extends HookConsumerWidget { showLoadingModal(context); final apiClient = ref.read(apiClientProvider); final resp = await apiClient.post( - '/accounts/me/factors', + '/id/accounts/me/factors', data: {'type': factorType.value, 'secret': secretController.text}, ); final factor = SnAuthFactor.fromJson(resp.data); diff --git a/lib/screens/account/me/settings_connections.dart b/lib/screens/account/me/settings_connections.dart index 5e942af..9e127d4 100644 --- a/lib/screens/account/me/settings_connections.dart +++ b/lib/screens/account/me/settings_connections.dart @@ -174,7 +174,7 @@ class AccountConnectionNewSheet extends HookConsumerWidget { if (context.mounted) showLoadingModal(context); await client.post( - '/auth/connect/apple/mobile', + '/id/auth/connect/apple/mobile', data: { 'identity_token': credential.identityToken!, 'authorization_code': credential.authorizationCode, @@ -336,7 +336,7 @@ class AccountConnectionsSheet extends HookConsumerWidget { try { final client = ref.read(apiClientProvider); await client.delete( - '/accounts/me/connections/${connection.id}', + '/id/accounts/me/connections/${connection.id}', ); ref.invalidate(accountConnectionsProvider); return true; diff --git a/lib/screens/account/me/settings_contacts.dart b/lib/screens/account/me/settings_contacts.dart index 50c111e..9d59c03 100644 --- a/lib/screens/account/me/settings_contacts.dart +++ b/lib/screens/account/me/settings_contacts.dart @@ -160,7 +160,7 @@ class ContactMethodNewSheet extends HookConsumerWidget { showLoadingModal(context); final apiClient = ref.read(apiClientProvider); await apiClient.post( - '/accounts/me/contacts', + '/id/accounts/me/contacts', data: {'type': contactType.value, 'content': contentController.text}, ); if (context.mounted) { diff --git a/lib/screens/account/profile.dart b/lib/screens/account/profile.dart index 14bb03d..a4b6643 100644 --- a/lib/screens/account/profile.dart +++ b/lib/screens/account/profile.dart @@ -39,14 +39,14 @@ Future account(Ref ref, String uname) async { } } final apiClient = ref.watch(apiClientProvider); - final resp = await apiClient.get("/accounts/$uname"); + final resp = await apiClient.get("/id/accounts/$uname"); return SnAccount.fromJson(resp.data); } @riverpod Future> accountBadges(Ref ref, String uname) async { final apiClient = ref.watch(apiClientProvider); - final resp = await apiClient.get("/accounts/$uname/badges"); + final resp = await apiClient.get("/id/accounts/$uname/badges"); return List.from( resp.data.map((x) => SnAccountBadge.fromJson(x)), ); @@ -78,7 +78,7 @@ Future accountDirectChat(Ref ref, String uname) async { final account = await ref.watch(accountProvider(uname).future); final apiClient = ref.watch(apiClientProvider); try { - final resp = await apiClient.get("/chat/direct/${account.id}"); + final resp = await apiClient.get("/sphere/chat/direct/${account.id}"); return SnChatRoom.fromJson(resp.data); } catch (err) { if (err is DioException && err.response?.statusCode == 404) { @@ -95,7 +95,7 @@ Future accountRelationship(Ref ref, String uname) async { final account = await ref.watch(accountProvider(uname).future); final apiClient = ref.watch(apiClientProvider); try { - final resp = await apiClient.get("/relationships/${account.id}"); + final resp = await apiClient.get("/id/relationships/${account.id}"); return SnRelationship.fromJson(resp.data); } catch (err) { if (err is DioException && err.response?.statusCode == 404) { @@ -174,7 +174,7 @@ class AccountProfileScreen extends HookConsumerWidget { try { final client = ref.watch(apiClientProvider); final resp = await client.post( - '/chat/direct', + '/sphere/chat/direct', data: {'related_user_id': account.value!.id}, ); final chat = SnChatRoom.fromJson(resp.data); diff --git a/lib/screens/account/profile.g.dart b/lib/screens/account/profile.g.dart index 1fd7db1..98e0838 100644 --- a/lib/screens/account/profile.g.dart +++ b/lib/screens/account/profile.g.dart @@ -6,7 +6,7 @@ part of 'profile.dart'; // RiverpodGenerator // ************************************************************************** -String _$accountHash() => r'd2b0579617e6264452d98f47f695a9cdf45b24ec'; +String _$accountHash() => r'ce7264a04f69e32a5cb07bc10ca5fa47ae1fddaa'; /// Copied from Dart SDK class _SystemHash { @@ -145,7 +145,7 @@ class _AccountProviderElement String get uname => (origin as AccountProvider).uname; } -String _$accountBadgesHash() => r'4bfe5fb0d6ac0d4cde4563460bde289289188f6d'; +String _$accountBadgesHash() => r'1de05e122c23ff2c6ac6d318977165761e2ad177'; /// See also [accountBadges]. @ProviderFor(accountBadges) @@ -395,7 +395,7 @@ class _AccountAppbarForcegroundColorProviderElement String get uname => (origin as AccountAppbarForcegroundColorProvider).uname; } -String _$accountDirectChatHash() => r'3d28c8ba8079159f724fe3cd47bbe00db55cedcc'; +String _$accountDirectChatHash() => r'149ea3a3730672cfbbb8c16fe1f2caa0bb9f0e17'; /// See also [accountDirectChat]. @ProviderFor(accountDirectChat) @@ -517,7 +517,7 @@ class _AccountDirectChatProviderElement } String _$accountRelationshipHash() => - r'0be2420e1f6a65b8dcead9617191471924aaf232'; + r'9a3a4e8c6c6706f73df95feccb86736fcad33f30'; /// See also [accountRelationship]. @ProviderFor(accountRelationship) diff --git a/lib/screens/account/relationship.dart b/lib/screens/account/relationship.dart index a8f2640..9a7cdf7 100644 --- a/lib/screens/account/relationship.dart +++ b/lib/screens/account/relationship.dart @@ -42,7 +42,7 @@ class RelationshipListNotifier extends _$RelationshipListNotifier final take = 20; final response = await client.get( - '/relationships', + '/id/relationships', queryParameters: {'offset': offset, 'take': take}, ); @@ -235,7 +235,7 @@ class RelationshipScreen extends HookConsumerWidget { submitting.value = true; final client = ref.read(apiClientProvider); await client.post( - '/relationships/${relationship.accountId}/friends/${isAccept ? 'accept' : 'decline'}', + '/id/relationships/${relationship.accountId}/friends/${isAccept ? 'accept' : 'decline'}', ); relationshipNotifier.forceRefresh(); if (!context.mounted) return; @@ -262,7 +262,7 @@ class RelationshipScreen extends HookConsumerWidget { ) async { final client = ref.read(apiClientProvider); await client.patch( - '/relationships/${relationship.accountId}', + '/id/relationships/${relationship.accountId}', data: {'status': newStatus}, ); relationshipNotifier.forceRefresh(); diff --git a/lib/screens/account/relationship.g.dart b/lib/screens/account/relationship.g.dart index 8100174..3fa1683 100644 --- a/lib/screens/account/relationship.g.dart +++ b/lib/screens/account/relationship.g.dart @@ -27,7 +27,7 @@ final sentFriendRequestProvider = typedef SentFriendRequestRef = AutoDisposeFutureProviderRef>; String _$relationshipListNotifierHash() => - r'560410cba6e4c26affd91aa86b3666319bd31f24'; + r'0a134ce69489a4f2002d2223853855b6f22e4e9f'; /// See also [RelationshipListNotifier]. @ProviderFor(RelationshipListNotifier) diff --git a/lib/screens/chat/chat.dart b/lib/screens/chat/chat.dart index 4ad40bd..21ea91b 100644 --- a/lib/screens/chat/chat.dart +++ b/lib/screens/chat/chat.dart @@ -298,6 +298,7 @@ class ChatListScreen extends HookConsumerWidget { ), onPressed: () { showModalBottomSheet( + useRootNavigator: true, isScrollControlled: true, context: context, builder: (context) => const _ChatInvitesSheet(), @@ -608,127 +609,129 @@ class EditChatScreen extends HookConsumerWidget { title: Text(id == null ? 'createChatRoom' : 'editChatRoom').tr(), leading: const PageBackButton(), ), - body: Column( - children: [ - RealmSelectionDropdown( - value: currentRealm.value, - realms: joinedRealms.when( - data: (realms) => realms, - loading: () => [], - error: (_, _) => [], + body: SingleChildScrollView( + child: Column( + children: [ + RealmSelectionDropdown( + value: currentRealm.value, + realms: joinedRealms.when( + data: (realms) => realms, + loading: () => [], + error: (_, _) => [], + ), + onChanged: (SnRealm? value) { + currentRealm.value = value; + }, + isLoading: joinedRealms.isLoading, + error: joinedRealms.error?.toString(), ), - onChanged: (SnRealm? value) { - currentRealm.value = value; - }, - isLoading: joinedRealms.isLoading, - error: joinedRealms.error?.toString(), - ), - AspectRatio( - aspectRatio: 16 / 7, - child: Stack( - clipBehavior: Clip.none, - fit: StackFit.expand, - children: [ - GestureDetector( - child: Container( - color: Theme.of(context).colorScheme.surfaceContainerHigh, - child: - background.value != null - ? CloudFileWidget( - item: background.value!, - fit: BoxFit.cover, - ) - : const SizedBox.shrink(), - ), - onTap: () { - setPicture('background'); - }, - ), - Positioned( - left: 20, - bottom: -32, - child: GestureDetector( - child: ProfilePictureWidget( - fileId: picture.value?.id, - radius: 40, - fallbackIcon: Symbols.group, + AspectRatio( + aspectRatio: 16 / 7, + child: Stack( + clipBehavior: Clip.none, + fit: StackFit.expand, + children: [ + GestureDetector( + child: Container( + color: Theme.of(context).colorScheme.surfaceContainerHigh, + child: + background.value != null + ? CloudFileWidget( + item: background.value!, + fit: BoxFit.cover, + ) + : const SizedBox.shrink(), ), onTap: () { - setPicture('picture'); + setPicture('background'); }, ), - ), - ], + Positioned( + left: 20, + bottom: -32, + child: GestureDetector( + child: ProfilePictureWidget( + fileId: picture.value?.id, + radius: 40, + fallbackIcon: Symbols.group, + ), + onTap: () { + setPicture('picture'); + }, + ), + ), + ], + ), + ).padding(bottom: 32), + Form( + key: formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextFormField( + controller: nameController, + decoration: const InputDecoration(labelText: 'Name'), + onTapOutside: + (_) => FocusManager.instance.primaryFocus?.unfocus(), + ), + const SizedBox(height: 16), + TextFormField( + controller: descriptionController, + decoration: const InputDecoration( + labelText: 'Description', + alignLabelWithHint: true, + ), + minLines: 3, + maxLines: null, + onTapOutside: + (_) => FocusManager.instance.primaryFocus?.unfocus(), + ), + const SizedBox(height: 16), + Card( + margin: EdgeInsets.zero, + child: Column( + children: [ + CheckboxListTile( + secondary: const Icon(Symbols.public), + title: Text('publicChat').tr(), + subtitle: Text('publicChatDescription').tr(), + value: isPublic.value, + onChanged: (value) { + isPublic.value = value ?? true; + }, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + CheckboxListTile( + secondary: const Icon(Symbols.travel_explore), + title: Text('communityChat').tr(), + subtitle: Text('communityChatDescription').tr(), + value: isCommunity.value, + onChanged: (value) { + isCommunity.value = value ?? false; + }, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ], + ), + ), + const SizedBox(height: 16), + Align( + alignment: Alignment.centerRight, + child: TextButton.icon( + onPressed: submitting.value ? null : performAction, + label: const Text('Save'), + icon: const Icon(Symbols.save), + ), + ), + ], + ).padding(all: 24), ), - ).padding(bottom: 32), - Form( - key: formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextFormField( - controller: nameController, - decoration: const InputDecoration(labelText: 'Name'), - onTapOutside: - (_) => FocusManager.instance.primaryFocus?.unfocus(), - ), - const SizedBox(height: 16), - TextFormField( - controller: descriptionController, - decoration: const InputDecoration( - labelText: 'Description', - alignLabelWithHint: true, - ), - minLines: 3, - maxLines: null, - onTapOutside: - (_) => FocusManager.instance.primaryFocus?.unfocus(), - ), - const SizedBox(height: 16), - Card( - margin: EdgeInsets.zero, - child: Column( - children: [ - CheckboxListTile( - secondary: const Icon(Symbols.public), - title: Text('publicChat').tr(), - subtitle: Text('publicChatDescription').tr(), - value: isPublic.value, - onChanged: (value) { - isPublic.value = value ?? true; - }, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - CheckboxListTile( - secondary: const Icon(Symbols.travel_explore), - title: Text('communityChat').tr(), - subtitle: Text('communityChatDescription').tr(), - value: isCommunity.value, - onChanged: (value) { - isCommunity.value = value ?? false; - }, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - ], - ), - ), - const SizedBox(height: 16), - Align( - alignment: Alignment.centerRight, - child: TextButton.icon( - onPressed: submitting.value ? null : performAction, - label: const Text('Save'), - icon: const Icon(Symbols.save), - ), - ), - ], - ).padding(all: 24), - ), - ], + ], + ), ), ); } diff --git a/lib/screens/chat/room_detail.dart b/lib/screens/chat/room_detail.dart index b478054..3ebea4f 100644 --- a/lib/screens/chat/room_detail.dart +++ b/lib/screens/chat/room_detail.dart @@ -389,7 +389,10 @@ class _ChatRoomActionMenu extends HookConsumerWidget { if ((chatIdentity.value?.role ?? 0) >= 50) PopupMenuItem( onTap: () { - context.pushReplacement('/sphere/chat/$id/edit'); + context.pushReplacementNamed( + 'chatEdit', + pathParameters: {'id': id}, + ); }, child: Row( children: [ @@ -502,7 +505,7 @@ class ChatMemberNotifier extends StateNotifier { try { final response = await _apiClient.get( - '/chat/$roomId/members', + '/sphere/chat/$roomId/members', queryParameters: {'offset': offset, 'take': take}, ); @@ -540,7 +543,7 @@ class ChatMemberListNotifier extends _$ChatMemberListNotifier final apiClient = ref.watch(apiClientProvider); final response = await apiClient.get( - '/chat/$roomId/members', + '/sphere/chat/$roomId/members', queryParameters: {'offset': offset, 'take': take}, ); @@ -592,7 +595,7 @@ class _ChatMemberListSheet extends HookConsumerWidget { try { final apiClient = ref.watch(apiClientProvider); await apiClient.post( - '/chat/invites/$roomId', + '/sphere/chat/invites/$roomId', data: {'related_user_id': result.id, 'role': 0}, ); // Refresh both providers @@ -846,7 +849,7 @@ class _ChatMemberRoleSheet extends HookConsumerWidget { final apiClient = ref.read(apiClientProvider); await apiClient.patch( - '/chat/$roomId/members/${member.accountId}/role', + '/sphere/chat/$roomId/members/${member.accountId}/role', data: newRole, ); diff --git a/lib/screens/creators/hub.g.dart b/lib/screens/creators/hub.g.dart index b9d6ce5..42dd6fe 100644 --- a/lib/screens/creators/hub.g.dart +++ b/lib/screens/creators/hub.g.dart @@ -414,7 +414,7 @@ final publisherInvitesProvider = typedef PublisherInvitesRef = AutoDisposeFutureProviderRef>; String _$publisherMemberListNotifierHash() => - r'237e8f39c9757a6cbdff817853c697539242ad2a'; + r'b4afd5d591a6f3d29f1b45fb1b6d17cb34f3f11b'; abstract class _$PublisherMemberListNotifier extends diff --git a/lib/screens/creators/stickers/stickers.g.dart b/lib/screens/creators/stickers/stickers.g.dart index 69bbf9b..82f1add 100644 --- a/lib/screens/creators/stickers/stickers.g.dart +++ b/lib/screens/creators/stickers/stickers.g.dart @@ -6,7 +6,7 @@ part of 'stickers.dart'; // RiverpodGenerator // ************************************************************************** -String _$stickerPackHash() => r'4f70d26e695ba1d8c7273d12730f77da79361733'; +String _$stickerPackHash() => r'71ef84471237c8191918095094bdfc87d3920e77'; /// Copied from Dart SDK class _SystemHash { @@ -148,7 +148,7 @@ class _StickerPackProviderElement } String _$stickerPacksNotifierHash() => - r'dc0cc4ec27fdd6d5da28f982ff10c852f8107a18'; + r'0a8edcf9c35396c411f1214f5e77b1e8fac6a3e6'; abstract class _$StickerPacksNotifier extends BuildlessAutoDisposeAsyncNotifier> { diff --git a/lib/screens/developers/hub.g.dart b/lib/screens/developers/hub.g.dart index df18385..732c4b5 100644 --- a/lib/screens/developers/hub.g.dart +++ b/lib/screens/developers/hub.g.dart @@ -6,7 +6,7 @@ part of 'hub.dart'; // RiverpodGenerator // ************************************************************************** -String _$developerStatsHash() => r'783398cbde09c3d956c3e20b02a1cebd1f8ab748'; +String _$developerStatsHash() => r'baa708f3586e8987e221cc8ab825d759658c0f55'; /// Copied from Dart SDK class _SystemHash { @@ -149,7 +149,7 @@ class _DeveloperStatsProviderElement String? get uname => (origin as DeveloperStatsProvider).uname; } -String _$developersHash() => r'f52639d3c21aafbf235c8ae33f35448baf2989a1'; +String _$developersHash() => r'f11335fdf553c661110281edeec70ef89c64727d'; /// See also [developers]. @ProviderFor(developers) diff --git a/lib/screens/discovery/articles.dart b/lib/screens/discovery/articles.dart index 46cef66..9578ce5 100644 --- a/lib/screens/discovery/articles.dart +++ b/lib/screens/discovery/articles.dart @@ -39,7 +39,7 @@ class ArticlesListNotifier extends _$ArticlesListNotifier try { final response = await client.get( - '/feeds/articles', + '/sphere/feeds/articles', queryParameters: queryParams, ); diff --git a/lib/screens/notification.dart b/lib/screens/notification.dart index b408059..3836612 100644 --- a/lib/screens/notification.dart +++ b/lib/screens/notification.dart @@ -82,7 +82,7 @@ class NotificationListNotifier extends _$NotificationListNotifier final queryParams = {'offset': offset, 'take': _pageSize}; final response = await client.get( - '/notifications', + '/pusher/notifications', queryParameters: queryParams, ); final total = int.parse(response.headers.value('X-Total') ?? '0'); diff --git a/lib/screens/notification.g.dart b/lib/screens/notification.g.dart index db8849a..dd8f452 100644 --- a/lib/screens/notification.g.dart +++ b/lib/screens/notification.g.dart @@ -28,7 +28,7 @@ final notificationUnreadCountNotifierProvider = typedef _$NotificationUnreadCountNotifier = AutoDisposeAsyncNotifier; String _$notificationListNotifierHash() => - r'934a47bc2ce9e75699a4f53e2169470fd0c04a53'; + r'5099466db475bbcf1ab6b514eb072f1dc4c6f930'; /// See also [NotificationListNotifier]. @ProviderFor(NotificationListNotifier) diff --git a/lib/screens/posts/post_search.dart b/lib/screens/posts/post_search.dart index 7040a45..dabf3f8 100644 --- a/lib/screens/posts/post_search.dart +++ b/lib/screens/posts/post_search.dart @@ -50,7 +50,7 @@ class PostSearchNotifier final offset = cursor == null ? 0 : int.parse(cursor); final response = await client.get( - '/posts/search', + '/sphere/posts/search', queryParameters: { 'query': _currentQuery, 'offset': offset, diff --git a/lib/screens/posts/pub_profile.dart b/lib/screens/posts/pub_profile.dart index 1bee9d9..6317b02 100644 --- a/lib/screens/posts/pub_profile.dart +++ b/lib/screens/posts/pub_profile.dart @@ -28,7 +28,7 @@ part 'pub_profile.g.dart'; @riverpod Future publisher(Ref ref, String uname) async { final apiClient = ref.watch(apiClientProvider); - final resp = await apiClient.get("/publishers/$uname"); + final resp = await apiClient.get("/sphere/publishers/$uname"); return SnPublisher.fromJson(resp.data); } @@ -37,7 +37,7 @@ Future> publisherBadges(Ref ref, String pubName) async { final pub = await ref.watch(publisherProvider(pubName).future); if (pub.type != 0 || pub.account == null) return []; final apiClient = ref.watch(apiClientProvider); - final resp = await apiClient.get("/accounts/${pub.account!.name}/badges"); + final resp = await apiClient.get("/id/accounts/${pub.account!.name}/badges"); return List.from( resp.data.map((x) => SnAccountBadge.fromJson(x)), ); @@ -49,7 +49,7 @@ Future publisherSubscriptionStatus( String pubName, ) async { final apiClient = ref.watch(apiClientProvider); - final resp = await apiClient.get("/publishers/$pubName/subscription"); + final resp = await apiClient.get("/sphere/publishers/$pubName/subscription"); return SnSubscriptionStatus.fromJson(resp.data); } @@ -188,7 +188,10 @@ class PublisherProfileScreen extends HookConsumerWidget { onTap: () { Navigator.pop(context, true); if (data.account?.name != null) { - context.pushNamed('accountProfile', pathParameters: {'name': data.account!.name}); + context.pushNamed( + 'accountProfile', + pathParameters: {'name': data.account!.name}, + ); } }, ), diff --git a/lib/screens/realm/realm_detail.g.dart b/lib/screens/realm/realm_detail.g.dart index 992f841..535aa75 100644 --- a/lib/screens/realm/realm_detail.g.dart +++ b/lib/screens/realm/realm_detail.g.dart @@ -399,7 +399,7 @@ class _RealmChatRoomsProviderElement } String _$realmMemberListNotifierHash() => - r'b2e3eefc62a597f45df9470b2058fdda62f8853f'; + r'022bcef5a90cbae05ff23b937851afc3ef913d42'; abstract class _$RealmMemberListNotifier extends BuildlessAutoDisposeAsyncNotifier> { diff --git a/lib/screens/realm/realms.dart b/lib/screens/realm/realms.dart index 4568d37..3c50f4d 100644 --- a/lib/screens/realm/realms.dart +++ b/lib/screens/realm/realms.dart @@ -41,7 +41,6 @@ class RealmListScreen extends HookConsumerWidget { final realmInvites = ref.watch(realmInvitesProvider); return AppScaffold( - extendBody: false, // Prevent conflicts with tabs navigation noBackground: false, appBar: AppBar( title: const Text('realms').tr(), @@ -70,6 +69,7 @@ class RealmListScreen extends HookConsumerWidget { showModalBottomSheet( context: context, isScrollControlled: true, + useRootNavigator: true, builder: (_) => const _RealmInviteSheet(), ); }, @@ -279,128 +279,131 @@ class EditRealmScreen extends HookConsumerWidget { } return AppScaffold( + noBackground: false, appBar: AppBar( title: Text(slug == null ? 'createRealm'.tr() : 'editRealm'.tr()), leading: const PageBackButton(), ), - body: Column( - children: [ - AspectRatio( - aspectRatio: 16 / 7, - child: Stack( - clipBehavior: Clip.none, - fit: StackFit.expand, - children: [ - GestureDetector( - child: Container( - color: Theme.of(context).colorScheme.surfaceContainerHigh, - child: - background.value != null - ? CloudFileWidget( - item: background.value!, - fit: BoxFit.cover, - ) - : const SizedBox.shrink(), - ), - onTap: () { - setPicture('background'); - }, - ), - Positioned( - left: 20, - bottom: -32, - child: GestureDetector( - child: ProfilePictureWidget( - fileId: picture.value?.id, - radius: 40, - fallbackIcon: Symbols.group, + body: SingleChildScrollView( + child: Column( + children: [ + AspectRatio( + aspectRatio: 16 / 7, + child: Stack( + clipBehavior: Clip.none, + fit: StackFit.expand, + children: [ + GestureDetector( + child: Container( + color: Theme.of(context).colorScheme.surfaceContainerHigh, + child: + background.value != null + ? CloudFileWidget( + item: background.value!, + fit: BoxFit.cover, + ) + : const SizedBox.shrink(), ), onTap: () { - setPicture('picture'); + setPicture('background'); }, ), - ), - ], + Positioned( + left: 20, + bottom: -32, + child: GestureDetector( + child: ProfilePictureWidget( + fileId: picture.value?.id, + radius: 40, + fallbackIcon: Symbols.group, + ), + onTap: () { + setPicture('picture'); + }, + ), + ), + ], + ), + ).padding(bottom: 32), + Form( + key: formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextFormField( + controller: slugController, + decoration: InputDecoration( + labelText: 'slug'.tr(), + helperText: 'slugHint'.tr(), + ), + onTapOutside: + (_) => FocusManager.instance.primaryFocus?.unfocus(), + ), + const SizedBox(height: 16), + TextFormField( + controller: nameController, + decoration: InputDecoration(labelText: 'name'.tr()), + onTapOutside: + (_) => FocusManager.instance.primaryFocus?.unfocus(), + ), + const SizedBox(height: 16), + TextFormField( + controller: descriptionController, + decoration: InputDecoration( + labelText: 'description'.tr(), + alignLabelWithHint: true, + ), + minLines: 3, + maxLines: null, + onTapOutside: + (_) => FocusManager.instance.primaryFocus?.unfocus(), + ), + const SizedBox(height: 16), + Card( + margin: EdgeInsets.zero, + child: Column( + children: [ + CheckboxListTile( + secondary: const Icon(Symbols.public), + title: Text('publicRealm').tr(), + subtitle: Text('publicRealmDescription').tr(), + value: isPublic.value, + onChanged: (value) { + isPublic.value = value ?? true; + }, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + CheckboxListTile( + secondary: const Icon(Symbols.travel_explore), + title: Text('communityRealm').tr(), + subtitle: Text('communityRealmDescription').tr(), + value: isCommunity.value, + onChanged: (value) { + isCommunity.value = value ?? false; + }, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ], + ), + ), + const SizedBox(height: 16), + Align( + alignment: Alignment.centerRight, + child: TextButton.icon( + onPressed: submitting.value ? null : performAction, + label: Text('saveChanges'.tr()), + icon: const Icon(Symbols.save), + ), + ), + ], + ).padding(all: 24), ), - ).padding(bottom: 32), - Form( - key: formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextFormField( - controller: slugController, - decoration: InputDecoration( - labelText: 'slug'.tr(), - helperText: 'slugHint'.tr(), - ), - onTapOutside: - (_) => FocusManager.instance.primaryFocus?.unfocus(), - ), - const SizedBox(height: 16), - TextFormField( - controller: nameController, - decoration: InputDecoration(labelText: 'name'.tr()), - onTapOutside: - (_) => FocusManager.instance.primaryFocus?.unfocus(), - ), - const SizedBox(height: 16), - TextFormField( - controller: descriptionController, - decoration: InputDecoration( - labelText: 'description'.tr(), - alignLabelWithHint: true, - ), - minLines: 3, - maxLines: null, - onTapOutside: - (_) => FocusManager.instance.primaryFocus?.unfocus(), - ), - const SizedBox(height: 16), - Card( - margin: EdgeInsets.zero, - child: Column( - children: [ - CheckboxListTile( - secondary: const Icon(Symbols.public), - title: Text('publicRealm').tr(), - subtitle: Text('publicRealmDescription').tr(), - value: isPublic.value, - onChanged: (value) { - isPublic.value = value ?? true; - }, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - CheckboxListTile( - secondary: const Icon(Symbols.travel_explore), - title: Text('communityRealm').tr(), - subtitle: Text('communityRealmDescription').tr(), - value: isCommunity.value, - onChanged: (value) { - isCommunity.value = value ?? false; - }, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - ], - ), - ), - const SizedBox(height: 16), - Align( - alignment: Alignment.centerRight, - child: TextButton.icon( - onPressed: submitting.value ? null : performAction, - label: Text('saveChanges'.tr()), - icon: const Icon(Symbols.save), - ), - ), - ], - ).padding(all: 24), - ), - ], + ], + ), ), ); } diff --git a/lib/screens/tabs.dart b/lib/screens/tabs.dart index 70c366f..4f1148b 100644 --- a/lib/screens/tabs.dart +++ b/lib/screens/tabs.dart @@ -55,9 +55,9 @@ class TabsScreen extends HookConsumerWidget { final routes = ['/', '/chat', '/realms', '/account']; int getCurrentIndex() { - if (currentLocation.startsWith('/sphere/chat')) return 1; - if (currentLocation.startsWith('/sphere/realms')) return 2; - if (currentLocation.startsWith('/id/account')) return 3; + if (currentLocation.startsWith('/chat')) return 1; + if (currentLocation.startsWith('/realms')) return 2; + if (currentLocation.startsWith('/account')) return 3; return 0; // Default to explore } diff --git a/lib/screens/wallet.g.dart b/lib/screens/wallet.g.dart index 716a594..a24080b 100644 --- a/lib/screens/wallet.g.dart +++ b/lib/screens/wallet.g.dart @@ -25,7 +25,7 @@ final walletCurrentProvider = AutoDisposeFutureProvider.internal( // ignore: unused_element typedef WalletCurrentRef = AutoDisposeFutureProviderRef; String _$transactionListNotifierHash() => - r'148ffb0ee9e3be3b92de432f314d8ee2f09e9a24'; + r'7b777cd44f3351f68f7bd1dd76bfe8b388381bdb'; /// See also [TransactionListNotifier]. @ProviderFor(TransactionListNotifier) diff --git a/lib/services/abuse_report_service.dart b/lib/services/abuse_report_service.dart index 9ee7778..a7d825a 100644 --- a/lib/services/abuse_report_service.dart +++ b/lib/services/abuse_report_service.dart @@ -11,13 +11,16 @@ class AbuseReportService { AbuseReportService(this.ref); Future getReport(String id) async { - final response = - await ref.read(apiClientProvider).get('/safety/reports/me/$id'); + final response = await ref + .read(apiClientProvider) + .get('/id/safety/reports/me/$id'); return SnAbuseReport.fromJson(response.data); } Future> getReports() async { - final response = await ref.read(apiClientProvider).get('/safety/reports/me'); + final response = await ref + .read(apiClientProvider) + .get('/id/safety/reports/me'); return (response.data as List) .map((json) => SnAbuseReport.fromJson(json)) .toList(); diff --git a/lib/widgets/account/fortune_graph.dart b/lib/widgets/account/fortune_graph.dart index 30f8989..1e51e90 100644 --- a/lib/widgets/account/fortune_graph.dart +++ b/lib/widgets/account/fortune_graph.dart @@ -67,7 +67,8 @@ class FortuneGraphWidget extends HookConsumerWidget { constraints: const BoxConstraints(), onPressed: () { context.pushNamed( - '/account/$eventCalanderUser/calendar', + 'accountCalendar', + pathParameters: {'name': eventCalanderUser!}, ); }, ), diff --git a/lib/widgets/content/cloud_file_collection.dart b/lib/widgets/content/cloud_file_collection.dart index cb0b921..b8b7567 100644 --- a/lib/widgets/content/cloud_file_collection.dart +++ b/lib/widgets/content/cloud_file_collection.dart @@ -38,7 +38,8 @@ class CloudFileList extends HookConsumerWidget { double calculateAspectRatio() { double total = 0; for (var ratio in files.map((e) => e.fileMeta?['ratio'] ?? 1)) { - total += double.parse(ratio); + if (ratio is double) total += ratio; + if (ratio is String) total += double.parse(ratio); } if (total == 0) return 1; return total / files.length; @@ -78,6 +79,7 @@ class CloudFileList extends HookConsumerWidget { if (!disableZoomIn) { context.pushTransparentRoute( CloudFileZoomIn(item: files.first, heroTag: heroTags.first), + rootNavigator: true, ); } }, @@ -505,7 +507,7 @@ class _CloudFileListEntry extends StatelessWidget { if (isImage) Positioned.fill( child: - file.fileMeta?['blur'] != null + file.fileMeta?['blur'] is String ? BlurHash(hash: file.fileMeta?['blur']) : ImageFiltered( imageFilter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), diff --git a/lib/widgets/content/cloud_files.dart b/lib/widgets/content/cloud_files.dart index feb4e3e..d486d77 100644 --- a/lib/widgets/content/cloud_files.dart +++ b/lib/widgets/content/cloud_files.dart @@ -30,7 +30,9 @@ class CloudFileWidget extends ConsumerWidget { var ratio = item.fileMeta?['ratio'] is num ? item.fileMeta!['ratio'].toDouble() - : double.parse(item.fileMeta?['ratio'] ?? 1); + : item.fileMeta?['ratio'] is String + ? double.parse(item.fileMeta!['ratio']) + : 1.0; if (ratio == 0) ratio = 1.0; final content = switch (item.mimeType?.split('/').firstOrNull) { "image" => AspectRatio( diff --git a/lib/widgets/post/post_item.dart b/lib/widgets/post/post_item.dart index 4042793..3753228 100644 --- a/lib/widgets/post/post_item.dart +++ b/lib/widgets/post/post_item.dart @@ -72,7 +72,10 @@ class PostItem extends HookConsumerWidget { children: [ GestureDetector( onTap: () { - context.pushNamed('publisherProfile', pathParameters: {'name': item.publisher.name}); + context.pushNamed( + 'publisherProfile', + pathParameters: {'name': item.publisher.name}, + ); }, child: Row( crossAxisAlignment: CrossAxisAlignment.center, @@ -254,7 +257,10 @@ class PostItem extends HookConsumerWidget { GestureDetector( child: ProfilePictureWidget(file: item.publisher.picture), onTap: () { - context.pushNamed('publisherProfile', pathParameters: {'name': item.publisher.name}); + context.pushNamed( + 'publisherProfile', + pathParameters: {'name': item.publisher.name}, + ); }, ), Expanded( @@ -427,7 +433,10 @@ class PostItem extends HookConsumerWidget { ), onTap: () { if (isOpenable) { - context.pushNamed('postDetail', pathParameters: {'id': item.id}); + context.pushNamed( + 'postDetail', + pathParameters: {'id': item.id}, + ); } }, ), @@ -496,11 +505,13 @@ class PostItem extends HookConsumerWidget { title: 'edit'.tr(), image: MenuImage.icon(Symbols.edit), callback: () { - context.pushNamed('postEdit', pathParameters: {'id': item.id}).then((value) { - if (value != null) { - onRefresh?.call(); - } - }); + context + .pushNamed('postEdit', pathParameters: {'id': item.id}) + .then((value) { + if (value != null) { + onRefresh?.call(); + } + }); }, ), if (isAuthor) @@ -732,7 +743,13 @@ Widget _buildReferencePost(BuildContext context, SnPost item) { ), ], ), - ).gestures(onTap: () => context.pushNamed('postDetail', pathParameters: {'id': referencePost.id})); + ).gestures( + onTap: + () => context.pushNamed( + 'postDetail', + pathParameters: {'id': referencePost.id}, + ), + ); } class PostReactionList extends HookConsumerWidget { @@ -757,7 +774,7 @@ class PostReactionList extends HookConsumerWidget { submitting.value = true; await client .post( - '/posts/$parentId/reactions', + '/sphere/posts/$parentId/reactions', data: {'symbol': symbol, 'attitude': attitude}, ) .catchError((err) { diff --git a/lib/widgets/post/post_quick_reply.dart b/lib/widgets/post/post_quick_reply.dart index 0d5ea31..044693c 100644 --- a/lib/widgets/post/post_quick_reply.dart +++ b/lib/widgets/post/post_quick_reply.dart @@ -43,7 +43,7 @@ class PostQuickReply extends HookConsumerWidget { try { final client = ref.watch(apiClientProvider); await client.post( - '/posts', + '/sphere/posts', data: { 'content': contentController.text, 'replied_post_id': parent.id, diff --git a/lib/widgets/post/post_replies.dart b/lib/widgets/post/post_replies.dart index 0b100ba..1e01636 100644 --- a/lib/widgets/post/post_replies.dart +++ b/lib/widgets/post/post_replies.dart @@ -35,7 +35,7 @@ class PostRepliesNotifier extends _$PostRepliesNotifier final offset = cursor == null ? 0 : int.parse(cursor); final response = await client.get( - '/posts/$_postId/replies', + '/sphere/posts/$_postId/replies', queryParameters: {'offset': offset, 'take': _pageSize}, ); @@ -57,7 +57,11 @@ class PostRepliesNotifier extends _$PostRepliesNotifier class PostRepliesList extends HookConsumerWidget { final String postId; final Color? backgroundColor; - const PostRepliesList({super.key, required this.postId, this.backgroundColor}); + const PostRepliesList({ + super.key, + required this.postId, + this.backgroundColor, + }); @override Widget build(BuildContext context, WidgetRef ref) { @@ -93,7 +97,8 @@ class PostRepliesList extends HookConsumerWidget { children: [ PostItem( item: data.items[index], - backgroundColor: backgroundColor ?? (isWide ? Colors.transparent : null), + backgroundColor: + backgroundColor ?? (isWide ? Colors.transparent : null), showReferencePost: false, ), const Divider(height: 1), diff --git a/lib/widgets/post/post_replies.g.dart b/lib/widgets/post/post_replies.g.dart index 01a02eb..d315bb7 100644 --- a/lib/widgets/post/post_replies.g.dart +++ b/lib/widgets/post/post_replies.g.dart @@ -7,7 +7,7 @@ part of 'post_replies.dart'; // ************************************************************************** String _$postRepliesNotifierHash() => - r'49c178102ec0a4136974a0e9a8f090f511abd542'; + r'1cdda919249e3bf34459369e033ad5de8dbcf3f8'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/widgets/realm/realm_list.g.dart b/lib/widgets/realm/realm_list.g.dart index ca950aa..742497e 100644 --- a/lib/widgets/realm/realm_list.g.dart +++ b/lib/widgets/realm/realm_list.g.dart @@ -6,7 +6,7 @@ part of 'realm_list.dart'; // RiverpodGenerator // ************************************************************************** -String _$realmListNotifierHash() => r'02dee373a5609a5617b04ffec395d09dea7ae070'; +String _$realmListNotifierHash() => r'8ae5c3ae2837acae4c7bf5e44578518afc9ea1a6'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/widgets/safety/abuse_report_sheet.dart b/lib/widgets/safety/abuse_report_sheet.dart index 93ed69f..126417f 100644 --- a/lib/widgets/safety/abuse_report_sheet.dart +++ b/lib/widgets/safety/abuse_report_sheet.dart @@ -43,7 +43,7 @@ class AbuseReportSheet extends HookConsumerWidget { try { final client = ref.read(apiClientProvider); await client.post( - '/safety/reports', + '/id/safety/reports', data: { 'resource_identifier': resourceIdentifier, 'type': selectedType.value,