🐛 Finish bug fixes
This commit is contained in:
		| @@ -890,5 +890,11 @@ | ||||
|   }, | ||||
|   "settingsHideBottomNav": "Hide Bottom Navigation", | ||||
|   "settingsHideBottomNavDescription": "Hide the bottom navigation bar, and show the navigation buttons in the drawer.", | ||||
|   "reCaptcha": "reCaptcha" | ||||
|   "reCaptcha": "reCaptcha", | ||||
|   "friends": "Friends", | ||||
|   "friendsDescription": "Manage your friendships.", | ||||
|   "album": "Album", | ||||
|   "albumDescription": "View albums and manage attachments.", | ||||
|   "stickers": "Stickers", | ||||
|   "stickersDescription": "View sticker packs and manage stickers." | ||||
| } | ||||
|   | ||||
| @@ -888,5 +888,11 @@ | ||||
|   }, | ||||
|   "settingsHideBottomNav": "隐藏底部导航栏", | ||||
|   "settingsHideBottomNavDescription": "隐藏底部导航栏,在侧边栏抽屉显示导航按钮。", | ||||
|   "reCaptcha": "人机验证" | ||||
|   "reCaptcha": "人机验证", | ||||
|   "friends": "好友", | ||||
|   "friendsDescription": "管理好友关系。", | ||||
|   "album": "相册", | ||||
|   "albumDescription": "查看相册与管理上传附件。", | ||||
|   "stickers": "贴图", | ||||
|   "stickersDescription": "查看贴图包与管理贴图。" | ||||
| } | ||||
|   | ||||
| @@ -888,5 +888,11 @@ | ||||
|   }, | ||||
|   "settingsHideBottomNav": "隱藏底部導航欄", | ||||
|   "settingsHideBottomNavDescription": "隱藏底部導航欄,在側邊欄抽屜顯示導航按鈕。", | ||||
|   "reCaptcha": "人機驗證" | ||||
|   "reCaptcha": "人機驗證", | ||||
|   "friends": "好友", | ||||
|   "friendsDescription": "管理好友關係。", | ||||
|   "album": "相冊", | ||||
|   "albumDescription": "查看相冊與管理上傳附件。", | ||||
|   "stickers": "貼圖", | ||||
|   "stickersDescription": "查看貼圖包與管理貼圖。" | ||||
| } | ||||
|   | ||||
| @@ -888,5 +888,11 @@ | ||||
|   }, | ||||
|   "settingsHideBottomNav": "隱藏底部導航欄", | ||||
|   "settingsHideBottomNavDescription": "隱藏底部導航欄,在側邊欄抽屜顯示導航按鈕。", | ||||
|   "reCaptcha": "人機驗證" | ||||
|   "reCaptcha": "人機驗證", | ||||
|   "friends": "好友", | ||||
|   "friendsDescription": "管理好友關係。", | ||||
|   "album": "相冊", | ||||
|   "albumDescription": "查看相冊與管理上傳附件。", | ||||
|   "stickers": "貼圖", | ||||
|   "stickersDescription": "查看貼圖包與管理貼圖。" | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| import 'dart:async'; | ||||
| import 'dart:developer'; | ||||
| import 'dart:io'; | ||||
| import 'dart:math' hide log; | ||||
| import 'dart:ui'; | ||||
|  | ||||
| import 'package:bitsdojo_window/bitsdojo_window.dart'; | ||||
| @@ -161,7 +160,7 @@ class SolianApp extends StatelessWidget { | ||||
|             Provider(create: (ctx) => SnNetworkProvider(ctx)), | ||||
|             Provider(create: (ctx) => UserDirectoryProvider(ctx)), | ||||
|             Provider(create: (ctx) => SnAttachmentProvider(ctx)), | ||||
|             Provider(create: (ctx) => SnRealmProvider(ctx)), | ||||
|             ChangeNotifierProvider(create: (ctx) => SnRealmProvider(ctx)), | ||||
|             Provider(create: (ctx) => SnPostContentProvider(ctx)), | ||||
|             Provider(create: (ctx) => SnRelationshipProvider(ctx)), | ||||
|             Provider(create: (ctx) => SnLinkPreviewProvider(ctx)), | ||||
| @@ -331,25 +330,29 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener { | ||||
|       if (!mounted) return; | ||||
|       _setPhaseText('keyPair'); | ||||
|       final kp = context.read<KeyPairProvider>(); | ||||
|       await kp.reloadActive(); | ||||
|       kp.listen(); | ||||
|       if (!mounted) return; | ||||
|       _setPhaseText('stickers'); | ||||
|       final sticker = context.read<SnStickerProvider>(); | ||||
|       await sticker.listSticker(); | ||||
|       if (!mounted) return; | ||||
|       _setPhaseText('userDirectory'); | ||||
|       final ud = context.read<UserDirectoryProvider>(); | ||||
|       await ud.loadAccountCache(); | ||||
|       if (!mounted) return; | ||||
|       _setPhaseText('realm'); | ||||
|       final rm = context.read<SnRealmProvider>(); | ||||
|       await rm.refreshAvailableRealms(); | ||||
|       if (!mounted) return; | ||||
|       _setPhaseText('chat'); | ||||
|       final ct = context.read<ChatChannelProvider>(); | ||||
|       await ct.refreshAvailableChannels(); | ||||
|       _setPhaseText('done'); | ||||
|       try { | ||||
|         await kp.reloadActive(); | ||||
|         kp.listen(); | ||||
|       } catch (_) {} | ||||
|       if (ua.isAuthorized) { | ||||
|         if (!mounted) return; | ||||
|         _setPhaseText('stickers'); | ||||
|         final sticker = context.read<SnStickerProvider>(); | ||||
|         await sticker.listSticker(); | ||||
|         if (!mounted) return; | ||||
|         _setPhaseText('userDirectory'); | ||||
|         final ud = context.read<UserDirectoryProvider>(); | ||||
|         await ud.loadAccountCache(); | ||||
|         if (!mounted) return; | ||||
|         _setPhaseText('realm'); | ||||
|         final rm = context.read<SnRealmProvider>(); | ||||
|         await rm.refreshAvailableRealms(); | ||||
|         if (!mounted) return; | ||||
|         _setPhaseText('chat'); | ||||
|         final ct = context.read<ChatChannelProvider>(); | ||||
|         await ct.refreshAvailableChannels(); | ||||
|         _setPhaseText('done'); | ||||
|       } | ||||
|     } catch (err) { | ||||
|       if (!mounted) return; | ||||
|       await context.showErrorDialog(err); | ||||
| @@ -534,7 +537,6 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener { | ||||
|                       key: Key('app-splash-screen-$_isBusy'), | ||||
|                       child: Stack( | ||||
|                         children: [ | ||||
|                           CustomPaint(painter: GraphPainter()), | ||||
|                           Center( | ||||
|                             child: Container( | ||||
|                               constraints: const BoxConstraints( | ||||
| @@ -574,44 +576,3 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener { | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| class GraphPainter extends CustomPainter { | ||||
|   final Random random = Random(); | ||||
|   final int numNodes = 20; | ||||
|   final double maxDistance = 100; // Max distance to draw a line | ||||
|  | ||||
|   @override | ||||
|   void paint(Canvas canvas, Size size) { | ||||
|     final paintNode = Paint()..color = Colors.white; | ||||
|     final paintEdge = Paint() | ||||
|       ..color = Colors.white.withOpacity(0.3) | ||||
|       ..strokeWidth = 1; | ||||
|  | ||||
|     // Generate random points | ||||
|     List<Offset> nodes = List.generate( | ||||
|       numNodes, | ||||
|       (_) => Offset( | ||||
|         random.nextDouble() * size.width, | ||||
|         random.nextDouble() * size.height, | ||||
|       ), | ||||
|     ); | ||||
|  | ||||
|     // Draw edges between close nodes | ||||
|     for (var i = 0; i < nodes.length; i++) { | ||||
|       for (var j = i + 1; j < nodes.length; j++) { | ||||
|         double distance = (nodes[i] - nodes[j]).distance; | ||||
|         if (distance < maxDistance) { | ||||
|           canvas.drawLine(nodes[i], nodes[j], paintEdge); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Draw nodes | ||||
|     for (var node in nodes) { | ||||
|       canvas.drawCircle(node, 4, paintNode); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   bool shouldRepaint(CustomPainter oldDelegate) => false; | ||||
| } | ||||
|   | ||||
| @@ -41,6 +41,11 @@ class ChatChannelProvider extends ChangeNotifier { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   void addAvailableChannel(SnChannel channel) { | ||||
|     _availableChannels.add(channel); | ||||
|     notifyListeners(); | ||||
|   } | ||||
|  | ||||
|   Future<void> _saveChannelToLocal(Iterable<SnChannel> channels) async { | ||||
|     await Future.wait( | ||||
|       channels.map( | ||||
|   | ||||
| @@ -61,26 +61,6 @@ class NavigationProvider extends ChangeNotifier { | ||||
|       screen: 'news', | ||||
|       label: 'screenNews', | ||||
|     ), | ||||
|     AppNavDestination( | ||||
|       icon: Icon(Symbols.emoji_emotions, weight: 400, opticalSize: 20), | ||||
|       screen: 'stickers', | ||||
|       label: 'screenStickers', | ||||
|     ), | ||||
|     AppNavDestination( | ||||
|       icon: Icon(Symbols.photo_library, weight: 400, opticalSize: 20), | ||||
|       screen: 'album', | ||||
|       label: 'screenAlbum', | ||||
|     ), | ||||
|     AppNavDestination( | ||||
|       icon: Icon(Symbols.diversity_4, weight: 400, opticalSize: 20), | ||||
|       screen: 'friend', | ||||
|       label: 'screenFriend', | ||||
|     ), | ||||
|     AppNavDestination( | ||||
|       icon: Icon(Symbols.notifications, weight: 400, opticalSize: 20), | ||||
|       screen: 'notification', | ||||
|       label: 'screenNotification', | ||||
|     ), | ||||
|   ]; | ||||
|   static const List<String> kDefaultPinnedDestination = [ | ||||
|     'home', | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import 'package:surface/providers/database.dart'; | ||||
| import 'package:surface/providers/sn_network.dart'; | ||||
| import 'package:surface/types/realm.dart'; | ||||
|  | ||||
| class SnRealmProvider { | ||||
| class SnRealmProvider extends ChangeNotifier { | ||||
|   late final SnNetworkProvider _sn; | ||||
|   late final DatabaseProvider _dt; | ||||
|  | ||||
| @@ -39,6 +39,11 @@ class SnRealmProvider { | ||||
|     return out; | ||||
|   } | ||||
|  | ||||
|   void addAvailableRealm(SnRealm realm) { | ||||
|     _availableRealms.add(realm); | ||||
|     notifyListeners(); | ||||
|   } | ||||
|  | ||||
|   Future<SnRealm> getRealm(dynamic aliasOrId) async { | ||||
|     if (_cache.containsKey(aliasOrId.toString())) { | ||||
|       return _cache[aliasOrId.toString()]!; | ||||
|   | ||||
| @@ -64,6 +64,7 @@ class UserProvider extends ChangeNotifier { | ||||
|   } | ||||
|  | ||||
|   Future<SnAccount?> refreshUser() async { | ||||
|     if (!isAuthorized) return null; | ||||
|     final resp = await _sn.client.get('/cgi/id/users/me'); | ||||
|     final out = SnAccount.fromJson(resp.data); | ||||
|  | ||||
|   | ||||
| @@ -158,23 +158,33 @@ class _AuthorizedAccountScreen extends StatelessWidget { | ||||
|           }, | ||||
|         ), | ||||
|         ListTile( | ||||
|           title: Text('abuseReport').tr(), | ||||
|           subtitle: Text('abuseReportActionDescription').tr(), | ||||
|           title: Text('friends').tr(), | ||||
|           subtitle: Text('friendsDescription').tr(), | ||||
|           contentPadding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|           leading: const Icon(Symbols.flag), | ||||
|           leading: const Icon(Symbols.person), | ||||
|           trailing: const Icon(Symbols.chevron_right), | ||||
|           onTap: () { | ||||
|             GoRouter.of(context).pushNamed('abuseReport'); | ||||
|             GoRouter.of(context).pushNamed('friend'); | ||||
|           }, | ||||
|         ), | ||||
|         ListTile( | ||||
|           title: Text('factorSettings').tr(), | ||||
|           subtitle: Text('factorSettingsSubtitle').tr(), | ||||
|           title: Text('album').tr(), | ||||
|           subtitle: Text('albumDescription').tr(), | ||||
|           contentPadding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|           leading: const Icon(Symbols.lock), | ||||
|           leading: const Icon(Symbols.photo_library), | ||||
|           trailing: const Icon(Symbols.chevron_right), | ||||
|           onTap: () { | ||||
|             GoRouter.of(context).pushNamed('factorSettings'); | ||||
|             GoRouter.of(context).pushNamed('album'); | ||||
|           }, | ||||
|         ), | ||||
|         ListTile( | ||||
|           title: Text('stickers').tr(), | ||||
|           subtitle: Text('stickersDescription').tr(), | ||||
|           contentPadding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|           leading: const Icon(Symbols.emoji_emotions), | ||||
|           trailing: const Icon(Symbols.chevron_right), | ||||
|           onTap: () { | ||||
|             GoRouter.of(context).pushNamed('stickers'); | ||||
|           }, | ||||
|         ), | ||||
|         ListTile( | ||||
| @@ -237,6 +247,16 @@ class _AuthorizedAccountScreen extends StatelessWidget { | ||||
|             GoRouter.of(context).pushNamed('accountSettings'); | ||||
|           }, | ||||
|         ), | ||||
|         ListTile( | ||||
|           title: Text('abuseReport').tr(), | ||||
|           subtitle: Text('abuseReportActionDescription').tr(), | ||||
|           contentPadding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|           leading: const Icon(Symbols.flag), | ||||
|           trailing: const Icon(Symbols.chevron_right), | ||||
|           onTap: () { | ||||
|             GoRouter.of(context).pushNamed('abuseReport'); | ||||
|           }, | ||||
|         ), | ||||
|         ListTile( | ||||
|           title: Text('accountLogout').tr(), | ||||
|           subtitle: Text('accountLogoutSubtitle').tr(), | ||||
|   | ||||
| @@ -117,6 +117,16 @@ class AccountSettingsScreen extends StatelessWidget { | ||||
|                 GoRouter.of(context).pushNamed('accountSettingsSecurity'); | ||||
|               }, | ||||
|             ), | ||||
|             ListTile( | ||||
|               title: Text('factorSettings').tr(), | ||||
|               subtitle: Text('factorSettingsSubtitle').tr(), | ||||
|               contentPadding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|               leading: const Icon(Symbols.lock), | ||||
|               trailing: const Icon(Symbols.chevron_right), | ||||
|               onTap: () { | ||||
|                 GoRouter.of(context).pushNamed('factorSettings'); | ||||
|               }, | ||||
|             ), | ||||
|             ListTile( | ||||
|               title: Text('accountProfileEdit').tr(), | ||||
|               subtitle: Text('accountProfileEditSubtitle').tr(), | ||||
|   | ||||
| @@ -10,7 +10,6 @@ import 'package:styled_widget/styled_widget.dart'; | ||||
| import 'package:surface/providers/sn_network.dart'; | ||||
| import 'package:surface/providers/user_directory.dart'; | ||||
| import 'package:surface/types/attachment.dart'; | ||||
| import 'package:surface/widgets/app_bar_leading.dart'; | ||||
| import 'package:surface/widgets/attachment/attachment_zoom.dart'; | ||||
| import 'package:surface/widgets/attachment/attachment_item.dart'; | ||||
| import 'package:surface/widgets/dialog.dart'; | ||||
| @@ -106,7 +105,7 @@ class _AlbumScreenState extends State<AlbumScreen> { | ||||
|         controller: _scrollController, | ||||
|         slivers: [ | ||||
|           SliverAppBar( | ||||
|             leading: AutoAppBarLeading(), | ||||
|             leading: PageBackButton(), | ||||
|             title: Text('screenAlbum').tr(), | ||||
|           ), | ||||
|           SliverToBoxAdapter( | ||||
| @@ -119,7 +118,8 @@ class _AlbumScreenState extends State<AlbumScreen> { | ||||
|                     child: CircularProgressIndicator( | ||||
|                       value: _billing?.includedRatio ?? 0, | ||||
|                       strokeWidth: 8, | ||||
|                       backgroundColor: Theme.of(context).colorScheme.surfaceContainerHigh, | ||||
|                       backgroundColor: | ||||
|                           Theme.of(context).colorScheme.surfaceContainerHigh, | ||||
|                     ), | ||||
|                   ).padding(all: 12), | ||||
|                   const Gap(24), | ||||
| @@ -129,7 +129,8 @@ class _AlbumScreenState extends State<AlbumScreen> { | ||||
|                       children: [ | ||||
|                         Text('attachmentBillingUploaded').tr().bold(), | ||||
|                         Text( | ||||
|                           (_billing?.currentBytes ?? 0).formatBytes(decimals: 4), | ||||
|                           (_billing?.currentBytes ?? 0) | ||||
|                               .formatBytes(decimals: 4), | ||||
|                           style: GoogleFonts.robotoMono(), | ||||
|                         ), | ||||
|                         Text('attachmentBillingDiscount').tr().bold(), | ||||
|   | ||||
| @@ -201,7 +201,7 @@ class _FriendScreenState extends State<FriendScreen> { | ||||
|     if (!ua.isAuthorized) { | ||||
|       return AppScaffold( | ||||
|         appBar: AppBar( | ||||
|           leading: AutoAppBarLeading(), | ||||
|           leading: PageBackButton(), | ||||
|           title: Text('screenFriend').tr(), | ||||
|         ), | ||||
|         body: Center( | ||||
| @@ -254,7 +254,8 @@ class _FriendScreenState extends State<FriendScreen> { | ||||
|               trailing: const Icon(Symbols.chevron_right), | ||||
|               onTap: _showBlocks, | ||||
|             ), | ||||
|           if (_requests.isNotEmpty || _blocks.isNotEmpty) const Divider(height: 1), | ||||
|           if (_requests.isNotEmpty || _blocks.isNotEmpty) | ||||
|             const Divider(height: 1), | ||||
|           Expanded( | ||||
|             child: MediaQuery.removePadding( | ||||
|               context: context, | ||||
| @@ -270,7 +271,8 @@ class _FriendScreenState extends State<FriendScreen> { | ||||
|                     final relation = _relations[index]; | ||||
|                     final other = relation.related; | ||||
|                     return ListTile( | ||||
|                       contentPadding: const EdgeInsets.only(right: 24, left: 16), | ||||
|                       contentPadding: | ||||
|                           const EdgeInsets.only(right: 24, left: 16), | ||||
|                       leading: AccountImage(content: other?.avatar), | ||||
|                       title: Text(other?.nick ?? 'unknown'), | ||||
|                       subtitle: Text(other?.nick ?? 'unknown'), | ||||
| @@ -286,12 +288,16 @@ class _FriendScreenState extends State<FriendScreen> { | ||||
|                               mainAxisAlignment: MainAxisAlignment.end, | ||||
|                               children: [ | ||||
|                                 InkWell( | ||||
|                                   onTap: _isUpdating ? null : () => _changeRelation(relation, 2), | ||||
|                                   onTap: _isUpdating | ||||
|                                       ? null | ||||
|                                       : () => _changeRelation(relation, 2), | ||||
|                                   child: Text('friendBlock').tr(), | ||||
|                                 ), | ||||
|                                 const Gap(8), | ||||
|                                 InkWell( | ||||
|                                   onTap: _isUpdating ? null : () => _deleteRelation(relation), | ||||
|                                   onTap: _isUpdating | ||||
|                                       ? null | ||||
|                                       : () => _deleteRelation(relation), | ||||
|                                   child: Text('friendDeleteAction').tr(), | ||||
|                                 ), | ||||
|                               ], | ||||
| @@ -420,7 +426,9 @@ class _FriendshipListWidgetState extends State<_FriendshipListWidget> { | ||||
|               mainAxisAlignment: MainAxisAlignment.center, | ||||
|               crossAxisAlignment: CrossAxisAlignment.end, | ||||
|               children: [ | ||||
|                 Text(kFriendStatus[relation.status] ?? 'unknown').tr().opacity(0.75), | ||||
|                 Text(kFriendStatus[relation.status] ?? 'unknown') | ||||
|                     .tr() | ||||
|                     .opacity(0.75), | ||||
|                 if (relation.status == 0) | ||||
|                   Row( | ||||
|                     mainAxisAlignment: MainAxisAlignment.end, | ||||
| @@ -441,7 +449,8 @@ class _FriendshipListWidgetState extends State<_FriendshipListWidget> { | ||||
|                     mainAxisAlignment: MainAxisAlignment.end, | ||||
|                     children: [ | ||||
|                       InkWell( | ||||
|                         onTap: _isBusy ? null : () => _changeRelation(relation, 1), | ||||
|                         onTap: | ||||
|                             _isBusy ? null : () => _changeRelation(relation, 1), | ||||
|                         child: Text('friendUnblock').tr(), | ||||
|                       ), | ||||
|                       const Gap(8), | ||||
|   | ||||
| @@ -806,7 +806,7 @@ class _HomeDashNotificationWidgetState | ||||
|               child: IconButton( | ||||
|                 icon: const Icon(Symbols.arrow_right_alt), | ||||
|                 onPressed: () { | ||||
|                   GoRouter.of(context).goNamed('notification'); | ||||
|                   GoRouter.of(context).pushNamed('notification'); | ||||
|                 }, | ||||
|               ), | ||||
|             ), | ||||
|   | ||||
| @@ -149,8 +149,9 @@ class _NotificationScreenState extends State<NotificationScreen> { | ||||
|     if (!ua.isAuthorized) { | ||||
|       return AppScaffold( | ||||
|         appBar: AppBar( | ||||
|             leading: AutoAppBarLeading(), | ||||
|             title: Text('screenNotification').tr()), | ||||
|           leading: PageBackButton(), | ||||
|           title: Text('screenNotification').tr(), | ||||
|         ), | ||||
|         body: Center(child: UnauthorizedHint()), | ||||
|       ); | ||||
|     } | ||||
|   | ||||
| @@ -4,8 +4,10 @@ import 'package:gap/gap.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
| import 'package:surface/providers/channel.dart'; | ||||
| import 'package:surface/providers/config.dart'; | ||||
| import 'package:surface/providers/sn_network.dart'; | ||||
| import 'package:surface/providers/sn_realm.dart'; | ||||
| import 'package:surface/providers/userinfo.dart'; | ||||
| import 'package:surface/types/chat.dart'; | ||||
| import 'package:surface/types/realm.dart'; | ||||
| @@ -57,7 +59,9 @@ class _RealmDiscoveryScreenState extends State<RealmDiscoveryScreen> { | ||||
|         title: Text('screenRealmDiscovery').tr(), | ||||
|         actions: [ | ||||
|           IconButton( | ||||
|             icon: _isCompactView ? const Icon(Symbols.view_list) : const Icon(Symbols.view_module), | ||||
|             icon: _isCompactView | ||||
|                 ? const Icon(Symbols.view_list) | ||||
|                 : const Icon(Symbols.view_module), | ||||
|             onPressed: () { | ||||
|               setState(() => _isCompactView = !_isCompactView); | ||||
|               context.read<ConfigProvider>().realmCompactView = _isCompactView; | ||||
| @@ -117,7 +121,8 @@ class _RealmJoinPopupState extends State<_RealmJoinPopup> { | ||||
|     try { | ||||
|       setState(() => _isBusy = true); | ||||
|       final sn = context.read<SnNetworkProvider>(); | ||||
|       final resp = await sn.client.get('/cgi/im/channels/${widget.realm.alias}/public'); | ||||
|       final resp = | ||||
|           await sn.client.get('/cgi/im/channels/${widget.realm.alias}/public'); | ||||
|       final out = List<SnChannel>.from( | ||||
|         resp.data.map((e) => SnChannel.fromJson(e)).cast<SnChannel>(), | ||||
|       ); | ||||
| @@ -135,10 +140,13 @@ class _RealmJoinPopupState extends State<_RealmJoinPopup> { | ||||
|       setState(() => _isJoining = true); | ||||
|       final sn = context.read<SnNetworkProvider>(); | ||||
|       final ua = context.read<UserProvider>(); | ||||
|       await sn.client.post('/cgi/id/realms/${widget.realm.alias}/members', data: { | ||||
|       final rel = context.read<SnRealmProvider>(); | ||||
|       await sn.client | ||||
|           .post('/cgi/id/realms/${widget.realm.alias}/members', data: { | ||||
|         'related': ua.user?.name, | ||||
|       }); | ||||
|       await _joinSelectedChannels(); | ||||
|       rel.addAvailableRealm(widget.realm); | ||||
|       if (!mounted) return; | ||||
|       context.showSnackbar('realmJoined'.tr(args: [widget.realm.name])); | ||||
|       Navigator.pop(context); | ||||
| @@ -156,13 +164,20 @@ class _RealmJoinPopupState extends State<_RealmJoinPopup> { | ||||
|       try { | ||||
|         final sn = context.read<SnNetworkProvider>(); | ||||
|         final ua = context.read<UserProvider>(); | ||||
|         await sn.client.post('/cgi/im/channels/${widget.realm.alias}/$channel/members', data: { | ||||
|           'related': ua.user?.name, | ||||
|         }); | ||||
|         await sn.client.post( | ||||
|             '/cgi/im/channels/${widget.realm.alias}/$channel/members', | ||||
|             data: { | ||||
|               'related': ua.user?.name, | ||||
|             }); | ||||
|       } catch (err) { | ||||
|         if (!mounted) return; | ||||
|         context.showErrorDialog(err); | ||||
|       } | ||||
|       final ct = context.read<ChatChannelProvider>(); | ||||
|       for (final channel | ||||
|           in _channels!.where((ele) => _planJoinChannels.contains(ele.alias))) { | ||||
|         ct.addAvailableChannel(channel); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -182,7 +197,8 @@ class _RealmJoinPopupState extends State<_RealmJoinPopup> { | ||||
|           children: [ | ||||
|             const Icon(Symbols.group_add, size: 24), | ||||
|             const Gap(16), | ||||
|             Text('realmJoin', style: Theme.of(context).textTheme.titleLarge).tr(), | ||||
|             Text('realmJoin', style: Theme.of(context).textTheme.titleLarge) | ||||
|                 .tr(), | ||||
|           ], | ||||
|         ).padding(horizontal: 20, top: 16, bottom: 12), | ||||
|         Row( | ||||
| @@ -216,7 +232,8 @@ class _RealmJoinPopupState extends State<_RealmJoinPopup> { | ||||
|         Container( | ||||
|           width: double.infinity, | ||||
|           color: Theme.of(context).colorScheme.surfaceContainerHigh, | ||||
|           child: Text('realmCommunityPublicChannelsHint'.tr(), style: Theme.of(context).textTheme.bodyMedium) | ||||
|           child: Text('realmCommunityPublicChannelsHint'.tr(), | ||||
|                   style: Theme.of(context).textTheme.bodyMedium) | ||||
|               .padding(horizontal: 24, vertical: 8), | ||||
|         ), | ||||
|         Expanded( | ||||
|   | ||||
| @@ -9,7 +9,6 @@ import 'package:surface/providers/sn_network.dart'; | ||||
| import 'package:surface/providers/sn_sticker.dart'; | ||||
| import 'package:surface/providers/userinfo.dart'; | ||||
| import 'package:surface/types/attachment.dart'; | ||||
| import 'package:surface/widgets/app_bar_leading.dart'; | ||||
| import 'package:surface/widgets/attachment/attachment_item.dart'; | ||||
| import 'package:surface/widgets/dialog.dart'; | ||||
| import 'package:surface/widgets/loading_indicator.dart'; | ||||
| @@ -134,7 +133,7 @@ class _StickerScreenState extends State<StickerScreen> | ||||
|   Widget build(BuildContext context) { | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar( | ||||
|         leading: AutoAppBarLeading(), | ||||
|         leading: PageBackButton(), | ||||
|         title: Text('screenStickers').tr(), | ||||
|         actions: [ | ||||
|           IconButton( | ||||
|   | ||||
| @@ -155,7 +155,7 @@ class _DrawerContentList extends StatelessWidget { | ||||
|     final ct = context.read<ChatChannelProvider>(); | ||||
|     final sn = context.read<SnNetworkProvider>(); | ||||
|     final nav = context.watch<NavigationProvider>(); | ||||
|     final rel = context.read<SnRealmProvider>(); | ||||
|     final rel = context.watch<SnRealmProvider>(); | ||||
|  | ||||
|     return PageTransitionSwitcher( | ||||
|       duration: const Duration(milliseconds: 300), | ||||
| @@ -188,13 +188,14 @@ class _DrawerContentList extends StatelessWidget { | ||||
|                 ListTile( | ||||
|                   minTileHeight: 48, | ||||
|                   contentPadding: EdgeInsets.only(left: 28, right: 16), | ||||
|                   leading: const Icon(Symbols.home), | ||||
|                   leading: const Icon(Symbols.home).padding(right: 4), | ||||
|                   title: Text('screenHome').tr(), | ||||
|                   onTap: () { | ||||
|                     GoRouter.of(context).goNamed('home'); | ||||
|                     Scaffold.of(context).closeDrawer(); | ||||
|                   }, | ||||
|                 ), | ||||
|                 const Divider(height: 1).padding(vertical: 4), | ||||
|                 ...rel.availableRealms.map((ele) { | ||||
|                   return ListTile( | ||||
|                     minTileHeight: 48, | ||||
| @@ -209,6 +210,16 @@ class _DrawerContentList extends StatelessWidget { | ||||
|                     }, | ||||
|                   ); | ||||
|                 }), | ||||
|                 ListTile( | ||||
|                   minTileHeight: 48, | ||||
|                   contentPadding: EdgeInsets.only(left: 28, right: 16), | ||||
|                   leading: const Icon(Symbols.globe).padding(right: 4), | ||||
|                   title: Text('screenRealmDiscovery').tr(), | ||||
|                   onTap: () { | ||||
|                     GoRouter.of(context).pushNamed('realmDiscovery'); | ||||
|                     Scaffold.of(context).closeDrawer(); | ||||
|                   }, | ||||
|                 ), | ||||
|               ], | ||||
|             ) | ||||
|           : ListView( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user