✨ Able to see realm affiliated publishers on realm view
This commit is contained in:
		| @@ -128,6 +128,7 @@ | |||||||
|     "one": "{} social point", |     "one": "{} social point", | ||||||
|     "other": "{} social points" |     "other": "{} social points" | ||||||
|   }, |   }, | ||||||
|  |   "publisherAffiliatedBy": "Affiliated by {}", | ||||||
|   "publisherRunBy": "Run by {}", |   "publisherRunBy": "Run by {}", | ||||||
|   "fieldPublisherBelongToRealm": "Belongs to", |   "fieldPublisherBelongToRealm": "Belongs to", | ||||||
|   "fieldPublisherBelongToRealmUnset": "Unset Publisher Belongs to Realm", |   "fieldPublisherBelongToRealmUnset": "Unset Publisher Belongs to Realm", | ||||||
|   | |||||||
| @@ -112,6 +112,7 @@ | |||||||
|     "one": "{} 点社会信用点", |     "one": "{} 点社会信用点", | ||||||
|     "other": "{} 点社会信用点" |     "other": "{} 点社会信用点" | ||||||
|   }, |   }, | ||||||
|  |   "publisherAffiliatedBy": "隶属于 {}", | ||||||
|   "publisherRunBy": "由 {} 管理", |   "publisherRunBy": "由 {} 管理", | ||||||
|   "fieldPublisherBelongToRealm": "所属领域", |   "fieldPublisherBelongToRealm": "所属领域", | ||||||
|   "fieldPublisherBelongToRealmUnset": "未设置发布者所属领域", |   "fieldPublisherBelongToRealmUnset": "未设置发布者所属领域", | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ import 'package:surface/providers/sn_network.dart'; | |||||||
| import 'package:surface/providers/user_directory.dart'; | import 'package:surface/providers/user_directory.dart'; | ||||||
| import 'package:surface/types/account.dart'; | import 'package:surface/types/account.dart'; | ||||||
| import 'package:surface/types/post.dart'; | import 'package:surface/types/post.dart'; | ||||||
|  | import 'package:surface/types/realm.dart'; | ||||||
| import 'package:surface/widgets/account/account_image.dart'; | import 'package:surface/widgets/account/account_image.dart'; | ||||||
| import 'package:surface/widgets/dialog.dart'; | import 'package:surface/widgets/dialog.dart'; | ||||||
| import 'package:surface/widgets/post/post_item.dart'; | import 'package:surface/widgets/post/post_item.dart'; | ||||||
| @@ -22,19 +23,19 @@ import 'package:very_good_infinite_list/very_good_infinite_list.dart'; | |||||||
|  |  | ||||||
| class PostPublisherScreen extends StatefulWidget { | class PostPublisherScreen extends StatefulWidget { | ||||||
|   final String name; |   final String name; | ||||||
|  |  | ||||||
|   const PostPublisherScreen({super.key, required this.name}); |   const PostPublisherScreen({super.key, required this.name}); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   State<PostPublisherScreen> createState() => _PostPublisherScreenState(); |   State<PostPublisherScreen> createState() => _PostPublisherScreenState(); | ||||||
| } | } | ||||||
|  |  | ||||||
| class _PostPublisherScreenState extends State<PostPublisherScreen> | class _PostPublisherScreenState extends State<PostPublisherScreen> with SingleTickerProviderStateMixin { | ||||||
|     with SingleTickerProviderStateMixin { |  | ||||||
|   late final ScrollController _scrollController = ScrollController(); |   late final ScrollController _scrollController = ScrollController(); | ||||||
|   late final TabController _tabController = |   late final TabController _tabController = TabController(length: 3, vsync: this); | ||||||
|       TabController(length: 3, vsync: this); |  | ||||||
|  |  | ||||||
|   SnPublisher? _publisher; |   SnPublisher? _publisher; | ||||||
|  |   SnRealm? _realm; | ||||||
|   SnAccount? _account; |   SnAccount? _account; | ||||||
|  |  | ||||||
|   Future<void> _fetchPublisher() async { |   Future<void> _fetchPublisher() async { | ||||||
| @@ -45,11 +46,16 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|       if (!mounted) return; |       if (!mounted) return; | ||||||
|       _publisher = SnPublisher.fromJson(resp.data); |       _publisher = SnPublisher.fromJson(resp.data); | ||||||
|       _account = await ud.getAccount(_publisher?.accountId); |       _account = await ud.getAccount(_publisher?.accountId); | ||||||
|  |       if (_publisher?.realmId != null) { | ||||||
|  |         final resp = await sn.client.get('/cgi/id/realms/${_publisher!.realmId}'); | ||||||
|  |         _realm = SnRealm.fromJson(resp.data); | ||||||
|  |       } | ||||||
|     } catch (err) { |     } catch (err) { | ||||||
|       if (!mounted) return; |       if (!mounted) return; | ||||||
|       context.showErrorDialog(err).then((_) { |       context.showErrorDialog(err).then((_) { | ||||||
|         if (mounted) Navigator.pop(context); |         if (mounted) Navigator.pop(context); | ||||||
|       }); |       }); | ||||||
|  |       rethrow; | ||||||
|     } finally { |     } finally { | ||||||
|       setState(() {}); |       setState(() {}); | ||||||
|     } |     } | ||||||
| @@ -114,14 +120,12 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|   double _appBarBlur = 0.0; |   double _appBarBlur = 0.0; | ||||||
|  |  | ||||||
|   late final _appBarWidth = MediaQuery.of(context).size.width; |   late final _appBarWidth = MediaQuery.of(context).size.width; | ||||||
|   late final _appBarHeight = |   late final _appBarHeight = (_appBarWidth * kBannerAspectRatio).roundToDouble(); | ||||||
|       (_appBarWidth * kBannerAspectRatio).roundToDouble(); |  | ||||||
|  |  | ||||||
|   void _updateAppBarBlur() { |   void _updateAppBarBlur() { | ||||||
|     if (_scrollController.offset > _appBarHeight) return; |     if (_scrollController.offset > _appBarHeight) return; | ||||||
|     setState(() { |     setState(() { | ||||||
|       _appBarBlur = |       _appBarBlur = (_scrollController.offset / _appBarHeight * 10).clamp(0.0, 10.0); | ||||||
|           (_scrollController.offset / _appBarHeight * 10).clamp(0.0, 10.0); |  | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -215,10 +219,7 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|                             text: TextSpan(children: [ |                             text: TextSpan(children: [ | ||||||
|                               TextSpan( |                               TextSpan( | ||||||
|                                 text: _publisher!.nick, |                                 text: _publisher!.nick, | ||||||
|                                 style: Theme.of(context) |                                 style: Theme.of(context).textTheme.titleLarge!.copyWith( | ||||||
|                                     .textTheme |  | ||||||
|                                     .titleLarge! |  | ||||||
|                                     .copyWith( |  | ||||||
|                                       color: Colors.white, |                                       color: Colors.white, | ||||||
|                                       shadows: labelShadows, |                                       shadows: labelShadows, | ||||||
|                                     ), |                                     ), | ||||||
| @@ -226,10 +227,7 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|                               const TextSpan(text: '\n'), |                               const TextSpan(text: '\n'), | ||||||
|                               TextSpan( |                               TextSpan( | ||||||
|                                 text: '@${_publisher!.name}', |                                 text: '@${_publisher!.name}', | ||||||
|                                 style: Theme.of(context) |                                 style: Theme.of(context).textTheme.bodySmall!.copyWith( | ||||||
|                                     .textTheme |  | ||||||
|                                     .bodySmall! |  | ||||||
|                                     .copyWith( |  | ||||||
|                                       color: Colors.white, |                                       color: Colors.white, | ||||||
|                                       shadows: labelShadows, |                                       shadows: labelShadows, | ||||||
|                                     ), |                                     ), | ||||||
| @@ -241,6 +239,7 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|                         ? Stack( |                         ? Stack( | ||||||
|                             fit: StackFit.expand, |                             fit: StackFit.expand, | ||||||
|                             children: [ |                             children: [ | ||||||
|  |                               if (_publisher!.banner.isNotEmpty) | ||||||
|                                 UniversalImage( |                                 UniversalImage( | ||||||
|                                   sn.getAttachmentUrl(_publisher!.banner), |                                   sn.getAttachmentUrl(_publisher!.banner), | ||||||
|                                   fit: BoxFit.cover, |                                   fit: BoxFit.cover, | ||||||
| @@ -248,6 +247,10 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|                                   width: _appBarWidth, |                                   width: _appBarWidth, | ||||||
|                                   cacheHeight: imageHeight, |                                   cacheHeight: imageHeight, | ||||||
|                                   cacheWidth: _appBarWidth, |                                   cacheWidth: _appBarWidth, | ||||||
|  |                                 ) | ||||||
|  |                               else | ||||||
|  |                                 Container( | ||||||
|  |                                   color: Theme.of(context).colorScheme.surfaceContainer, | ||||||
|                                 ), |                                 ), | ||||||
|                               Positioned( |                               Positioned( | ||||||
|                                 top: 0, |                                 top: 0, | ||||||
| @@ -288,14 +291,11 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|                                 const Gap(16), |                                 const Gap(16), | ||||||
|                                 Expanded( |                                 Expanded( | ||||||
|                                   child: Column( |                                   child: Column( | ||||||
|                                     crossAxisAlignment: |                                     crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                                         CrossAxisAlignment.start, |  | ||||||
|                                     children: [ |                                     children: [ | ||||||
|                                       Text( |                                       Text( | ||||||
|                                         _publisher!.nick, |                                         _publisher!.nick, | ||||||
|                                         style: Theme.of(context) |                                         style: Theme.of(context).textTheme.titleMedium, | ||||||
|                                             .textTheme |  | ||||||
|                                             .titleMedium, |  | ||||||
|                                       ).bold(), |                                       ).bold(), | ||||||
|                                       Text('@${_publisher!.name}').fontSize(13), |                                       Text('@${_publisher!.name}').fontSize(13), | ||||||
|                                     ], |                                     ], | ||||||
| @@ -306,9 +306,7 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|                                     style: ButtonStyle( |                                     style: ButtonStyle( | ||||||
|                                       elevation: WidgetStatePropertyAll(0), |                                       elevation: WidgetStatePropertyAll(0), | ||||||
|                                     ), |                                     ), | ||||||
|                                     onPressed: _isSubscribing |                                     onPressed: _isSubscribing ? null : _toggleSubscription, | ||||||
|                                         ? null |  | ||||||
|                                         : _toggleSubscription, |  | ||||||
|                                     label: Text('subscribe').tr(), |                                     label: Text('subscribe').tr(), | ||||||
|                                     icon: const Icon(Symbols.add), |                                     icon: const Icon(Symbols.add), | ||||||
|                                   ) |                                   ) | ||||||
| @@ -317,17 +315,14 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|                                     style: ButtonStyle( |                                     style: ButtonStyle( | ||||||
|                                       elevation: WidgetStatePropertyAll(0), |                                       elevation: WidgetStatePropertyAll(0), | ||||||
|                                     ), |                                     ), | ||||||
|                                     onPressed: _isSubscribing |                                     onPressed: _isSubscribing ? null : _toggleSubscription, | ||||||
|                                         ? null |  | ||||||
|                                         : _toggleSubscription, |  | ||||||
|                                     label: Text('unsubscribe').tr(), |                                     label: Text('unsubscribe').tr(), | ||||||
|                                     icon: const Icon(Symbols.remove), |                                     icon: const Icon(Symbols.remove), | ||||||
|                                   ), |                                   ), | ||||||
|                               ], |                               ], | ||||||
|                             ).padding(right: 8), |                             ).padding(right: 8), | ||||||
|                             const Gap(12), |                             const Gap(12), | ||||||
|                             Text(_publisher!.description) |                             Text(_publisher!.description).padding(horizontal: 8), | ||||||
|                                 .padding(horizontal: 8), |  | ||||||
|                             const Gap(12), |                             const Gap(12), | ||||||
|                             Column( |                             Column( | ||||||
|                               children: [ |                               children: [ | ||||||
| @@ -335,10 +330,8 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|                                   children: [ |                                   children: [ | ||||||
|                                     const Icon(Symbols.calendar_add_on), |                                     const Icon(Symbols.calendar_add_on), | ||||||
|                                     const Gap(8), |                                     const Gap(8), | ||||||
|                                     Text('publisherJoinedAt').tr(args: [ |                                     Text('publisherJoinedAt') | ||||||
|                                       DateFormat('y/M/d') |                                         .tr(args: [DateFormat('y/M/d').format(_publisher!.createdAt)]), | ||||||
|                                           .format(_publisher!.createdAt) |  | ||||||
|                                     ]), |  | ||||||
|                                   ], |                                   ], | ||||||
|                                 ), |                                 ), | ||||||
|                                 Row( |                                 Row( | ||||||
| @@ -346,11 +339,30 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|                                     const Icon(Symbols.trending_up), |                                     const Icon(Symbols.trending_up), | ||||||
|                                     const Gap(8), |                                     const Gap(8), | ||||||
|                                     Text('publisherSocialPointTotal').plural( |                                     Text('publisherSocialPointTotal').plural( | ||||||
|                                       _publisher!.totalUpvote - |                                       _publisher!.totalUpvote - _publisher!.totalDownvote, | ||||||
|                                           _publisher!.totalDownvote, |  | ||||||
|                                     ), |                                     ), | ||||||
|                                   ], |                                   ], | ||||||
|                                 ), |                                 ), | ||||||
|  |                                 if (_realm != null) | ||||||
|  |                                   Row( | ||||||
|  |                                     children: [ | ||||||
|  |                                       const Icon(Symbols.group_work), | ||||||
|  |                                       const Gap(8), | ||||||
|  |                                       InkWell( | ||||||
|  |                                         child: Text('publisherAffiliatedBy').tr(args: [ | ||||||
|  |                                           '@${_realm?.alias ?? 'unknown'}', | ||||||
|  |                                         ]), | ||||||
|  |                                         onTap: () { | ||||||
|  |                                           GoRouter.of(context).pushNamed( | ||||||
|  |                                             'realmDetail', | ||||||
|  |                                             pathParameters: {'alias': _realm!.alias}, | ||||||
|  |                                           ); | ||||||
|  |                                         }, | ||||||
|  |                                       ), | ||||||
|  |                                       const Gap(8), | ||||||
|  |                                       AccountImage(content: _realm?.avatar, radius: 8), | ||||||
|  |                                     ], | ||||||
|  |                                   ), | ||||||
|                                 Row( |                                 Row( | ||||||
|                                   children: [ |                                   children: [ | ||||||
|                                     const Icon(Symbols.tools_wrench), |                                     const Icon(Symbols.tools_wrench), | ||||||
| @@ -369,8 +381,7 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> | |||||||
|                                       }, |                                       }, | ||||||
|                                     ), |                                     ), | ||||||
|                                     const Gap(8), |                                     const Gap(8), | ||||||
|                                     AccountImage( |                                     AccountImage(content: _account?.avatar, radius: 8), | ||||||
|                                         content: _account?.avatar, radius: 8), |  | ||||||
|                                   ], |                                   ], | ||||||
|                                 ), |                                 ), | ||||||
|                               ], |                               ], | ||||||
| @@ -447,6 +458,7 @@ class _PublisherPostList extends StatelessWidget { | |||||||
|   final void Function() fetchPosts; |   final void Function() fetchPosts; | ||||||
|   final void Function(int index, SnPost data) onChanged; |   final void Function(int index, SnPost data) onChanged; | ||||||
|   final void Function() onDeleted; |   final void Function() onDeleted; | ||||||
|  |  | ||||||
|   const _PublisherPostList({ |   const _PublisherPostList({ | ||||||
|     super.key, |     super.key, | ||||||
|     required this.isBusy, |     required this.isBusy, | ||||||
|   | |||||||
| @@ -6,16 +6,15 @@ import 'package:material_symbols_icons/symbols.dart'; | |||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
| import 'package:styled_widget/styled_widget.dart'; | import 'package:styled_widget/styled_widget.dart'; | ||||||
| import 'package:surface/providers/sn_network.dart'; | import 'package:surface/providers/sn_network.dart'; | ||||||
|  | import 'package:surface/providers/userinfo.dart'; | ||||||
| import 'package:surface/types/realm.dart'; | import 'package:surface/types/realm.dart'; | ||||||
| import 'package:surface/widgets/account/account_image.dart'; | import 'package:surface/widgets/account/account_image.dart'; | ||||||
| import 'package:surface/widgets/app_bar_leading.dart'; | import 'package:surface/widgets/app_bar_leading.dart'; | ||||||
| import 'package:surface/widgets/dialog.dart'; | import 'package:surface/widgets/dialog.dart'; | ||||||
| import 'package:surface/widgets/loading_indicator.dart'; | import 'package:surface/widgets/loading_indicator.dart'; | ||||||
|  | import 'package:surface/widgets/unauthorized_hint.dart'; | ||||||
| import 'package:surface/widgets/universal_image.dart'; | import 'package:surface/widgets/universal_image.dart'; | ||||||
|  |  | ||||||
| import '../providers/userinfo.dart'; |  | ||||||
| import '../widgets/unauthorized_hint.dart'; |  | ||||||
|  |  | ||||||
| class RealmScreen extends StatefulWidget { | class RealmScreen extends StatefulWidget { | ||||||
|   const RealmScreen({super.key}); |   const RealmScreen({super.key}); | ||||||
|  |  | ||||||
| @@ -101,9 +100,7 @@ class _RealmScreenState extends State<RealmScreen> { | |||||||
|         title: Text('screenRealm').tr(), |         title: Text('screenRealm').tr(), | ||||||
|         actions: [ |         actions: [ | ||||||
|           IconButton( |           IconButton( | ||||||
|             icon: !_isCompactView |             icon: !_isCompactView ? const Icon(Symbols.view_list) : const Icon(Symbols.view_module), | ||||||
|                 ? const Icon(Symbols.view_list) |  | ||||||
|                 : const Icon(Symbols.view_module), |  | ||||||
|             onPressed: () { |             onPressed: () { | ||||||
|               setState(() => _isCompactView = !_isCompactView); |               setState(() => _isCompactView = !_isCompactView); | ||||||
|             }, |             }, | ||||||
| @@ -129,8 +126,7 @@ class _RealmScreenState extends State<RealmScreen> { | |||||||
|                   final realm = _realms![idx]; |                   final realm = _realms![idx]; | ||||||
|                   if (_isCompactView) { |                   if (_isCompactView) { | ||||||
|                     return ListTile( |                     return ListTile( | ||||||
|                       contentPadding: |                       contentPadding: const EdgeInsets.symmetric(horizontal: 16), | ||||||
|                           const EdgeInsets.symmetric(horizontal: 16), |  | ||||||
|                       leading: AccountImage( |                       leading: AccountImage( | ||||||
|                         content: realm.avatar, |                         content: realm.avatar, | ||||||
|                         fallbackWidget: const Icon(Symbols.group, size: 20), |                         fallbackWidget: const Icon(Symbols.group, size: 20), | ||||||
| @@ -201,9 +197,7 @@ class _RealmScreenState extends State<RealmScreen> { | |||||||
|                                 fit: StackFit.expand, |                                 fit: StackFit.expand, | ||||||
|                                 children: [ |                                 children: [ | ||||||
|                                   Container( |                                   Container( | ||||||
|                                     color: Theme.of(context) |                                     color: Theme.of(context).colorScheme.surfaceContainer, | ||||||
|                                         .colorScheme |  | ||||||
|                                         .surfaceContainer, |  | ||||||
|                                     child: (realm.banner?.isEmpty ?? true) |                                     child: (realm.banner?.isEmpty ?? true) | ||||||
|                                         ? const SizedBox.shrink() |                                         ? const SizedBox.shrink() | ||||||
|                                         : AutoResizeUniversalImage( |                                         : AutoResizeUniversalImage( | ||||||
| @@ -217,8 +211,7 @@ class _RealmScreenState extends State<RealmScreen> { | |||||||
|                                     child: AccountImage( |                                     child: AccountImage( | ||||||
|                                       content: realm.avatar, |                                       content: realm.avatar, | ||||||
|                                       radius: 24, |                                       radius: 24, | ||||||
|                                       fallbackWidget: |                                       fallbackWidget: const Icon(Symbols.group, size: 24), | ||||||
|                                           const Icon(Symbols.group, size: 24), |  | ||||||
|                                     ), |                                     ), | ||||||
|                                   ), |                                   ), | ||||||
|                                 ], |                                 ], | ||||||
| @@ -228,10 +221,8 @@ class _RealmScreenState extends State<RealmScreen> { | |||||||
|                             Column( |                             Column( | ||||||
|                               crossAxisAlignment: CrossAxisAlignment.start, |                               crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                               children: [ |                               children: [ | ||||||
|                                 Text(realm.name).textStyle( |                                 Text(realm.name).textStyle(Theme.of(context).textTheme.titleMedium!), | ||||||
|                                     Theme.of(context).textTheme.titleMedium!), |                                 Text(realm.description).textStyle(Theme.of(context).textTheme.bodySmall!), | ||||||
|                                 Text(realm.description).textStyle( |  | ||||||
|                                     Theme.of(context).textTheme.bodySmall!), |  | ||||||
|                               ], |                               ], | ||||||
|                             ).padding(horizontal: 24, bottom: 14), |                             ).padding(horizontal: 24, bottom: 14), | ||||||
|                           ], |                           ], | ||||||
|   | |||||||
| @@ -13,8 +13,11 @@ import 'package:surface/widgets/account/account_image.dart'; | |||||||
| import 'package:surface/widgets/dialog.dart'; | import 'package:surface/widgets/dialog.dart'; | ||||||
| import 'package:very_good_infinite_list/very_good_infinite_list.dart'; | import 'package:very_good_infinite_list/very_good_infinite_list.dart'; | ||||||
|  |  | ||||||
|  | import '../../types/post.dart'; | ||||||
|  |  | ||||||
| class RealmDetailScreen extends StatefulWidget { | class RealmDetailScreen extends StatefulWidget { | ||||||
|   final String alias; |   final String alias; | ||||||
|  |  | ||||||
|   const RealmDetailScreen({super.key, required this.alias}); |   const RealmDetailScreen({super.key, required this.alias}); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -32,6 +35,24 @@ class _RealmDetailScreenState extends State<RealmDetailScreen> { | |||||||
|     } catch (err) { |     } catch (err) { | ||||||
|       if (!mounted) return; |       if (!mounted) return; | ||||||
|       context.showErrorDialog(err); |       context.showErrorDialog(err); | ||||||
|  |       rethrow; | ||||||
|  |     } finally { | ||||||
|  |       setState(() {}); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   List<SnPublisher>? _publishers; | ||||||
|  |  | ||||||
|  |   Future<void> _fetchPublishers() async { | ||||||
|  |     try { | ||||||
|  |       final sn = context.read<SnNetworkProvider>(); | ||||||
|  |       final resp = await sn.client.get('/cgi/co/publishers?realm=${widget.alias}'); | ||||||
|  |       _publishers = List<SnPublisher>.from( | ||||||
|  |         resp.data?.map((e) => SnPublisher.fromJson(e)) ?? [], | ||||||
|  |       ); | ||||||
|  |     } catch (err) { | ||||||
|  |       if (mounted) context.showErrorDialog(err); | ||||||
|  |       rethrow; | ||||||
|     } finally { |     } finally { | ||||||
|       setState(() {}); |       setState(() {}); | ||||||
|     } |     } | ||||||
| @@ -40,7 +61,9 @@ class _RealmDetailScreenState extends State<RealmDetailScreen> { | |||||||
|   @override |   @override | ||||||
|   void initState() { |   void initState() { | ||||||
|     super.initState(); |     super.initState(); | ||||||
|     _fetchRealm(); |     _fetchRealm().then((_) { | ||||||
|  |       _fetchPublishers(); | ||||||
|  |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -60,8 +83,7 @@ class _RealmDetailScreenState extends State<RealmDetailScreen> { | |||||||
|                 // scroll view thinks it has not been scrolled. |                 // scroll view thinks it has not been scrolled. | ||||||
|                 // This is not necessary if the "headerSliverBuilder" only builds |                 // This is not necessary if the "headerSliverBuilder" only builds | ||||||
|                 // widgets that do not overlap the next sliver. |                 // widgets that do not overlap the next sliver. | ||||||
|                 handle: |                 handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), | ||||||
|                     NestedScrollView.sliverOverlapAbsorberHandleFor(context), |  | ||||||
|                 sliver: SliverAppBar( |                 sliver: SliverAppBar( | ||||||
|                   title: Text(_realm?.name ?? 'loading'.tr()), |                   title: Text(_realm?.name ?? 'loading'.tr()), | ||||||
|                   bottom: TabBar( |                   bottom: TabBar( | ||||||
| @@ -77,7 +99,7 @@ class _RealmDetailScreenState extends State<RealmDetailScreen> { | |||||||
|           }, |           }, | ||||||
|           body: TabBarView( |           body: TabBarView( | ||||||
|             children: [ |             children: [ | ||||||
|               _RealmDetailHomeWidget(realm: _realm), |               _RealmDetailHomeWidget(realm: _realm, publishers: _publishers), | ||||||
|               _RealmMemberListWidget(realm: _realm), |               _RealmMemberListWidget(realm: _realm), | ||||||
|               _RealmSettingsWidget( |               _RealmSettingsWidget( | ||||||
|                 realm: _realm, |                 realm: _realm, | ||||||
| @@ -95,7 +117,9 @@ class _RealmDetailScreenState extends State<RealmDetailScreen> { | |||||||
|  |  | ||||||
| class _RealmDetailHomeWidget extends StatelessWidget { | class _RealmDetailHomeWidget extends StatelessWidget { | ||||||
|   final SnRealm? realm; |   final SnRealm? realm; | ||||||
|   const _RealmDetailHomeWidget({super.key, required this.realm}); |   final List<SnPublisher>? publishers; | ||||||
|  |  | ||||||
|  |   const _RealmDetailHomeWidget({super.key, required this.realm, this.publishers}); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
| @@ -118,6 +142,31 @@ class _RealmDetailHomeWidget extends StatelessWidget { | |||||||
|           ).padding(horizontal: 24), |           ).padding(horizontal: 24), | ||||||
|         const Gap(16), |         const Gap(16), | ||||||
|         const Divider(), |         const Divider(), | ||||||
|  |         Expanded( | ||||||
|  |           child: ListView.builder( | ||||||
|  |             padding: EdgeInsets.zero, | ||||||
|  |             itemCount: publishers?.length ?? 0, | ||||||
|  |             itemBuilder: (context, idx) { | ||||||
|  |               final ele = publishers![idx]; | ||||||
|  |               return ListTile( | ||||||
|  |                 contentPadding: const EdgeInsets.symmetric(horizontal: 24), | ||||||
|  |                 leading: AccountImage( | ||||||
|  |                   content: ele.avatar, | ||||||
|  |                   fallbackWidget: const Icon(Symbols.group, size: 24), | ||||||
|  |                 ), | ||||||
|  |                 title: Text(ele.nick), | ||||||
|  |                 subtitle: Text('@${ele.name}'), | ||||||
|  |                 trailing: const Icon(Symbols.chevron_right), | ||||||
|  |                 onTap: () { | ||||||
|  |                   GoRouter.of(context).pushNamed( | ||||||
|  |                     'postPublisher', | ||||||
|  |                     pathParameters: {'name': ele.name}, | ||||||
|  |                   ); | ||||||
|  |                 }, | ||||||
|  |               ); | ||||||
|  |             }, | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|       ], |       ], | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| @@ -125,6 +174,7 @@ class _RealmDetailHomeWidget extends StatelessWidget { | |||||||
|  |  | ||||||
| class _RealmMemberListWidget extends StatefulWidget { | class _RealmMemberListWidget extends StatefulWidget { | ||||||
|   final SnRealm? realm; |   final SnRealm? realm; | ||||||
|  |  | ||||||
|   const _RealmMemberListWidget({super.key, this.realm}); |   const _RealmMemberListWidget({super.key, this.realm}); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -143,9 +193,7 @@ class _RealmMemberListWidgetState extends State<_RealmMemberListWidget> { | |||||||
|     try { |     try { | ||||||
|       final ud = context.read<UserDirectoryProvider>(); |       final ud = context.read<UserDirectoryProvider>(); | ||||||
|       final sn = context.read<SnNetworkProvider>(); |       final sn = context.read<SnNetworkProvider>(); | ||||||
|       final resp = await sn.client.get( |       final resp = await sn.client.get('/cgi/id/realms/${widget.realm!.alias}/members', queryParameters: { | ||||||
|           '/cgi/id/realms/${widget.realm!.alias}/members', |  | ||||||
|           queryParameters: { |  | ||||||
|         'take': 10, |         'take': 10, | ||||||
|         'offset': 0, |         'offset': 0, | ||||||
|       }); |       }); | ||||||
| @@ -236,12 +284,10 @@ class _RealmMemberListWidgetState extends State<_RealmMemberListWidget> { | |||||||
|                 fallbackWidget: const Icon(Symbols.group, size: 24), |                 fallbackWidget: const Icon(Symbols.group, size: 24), | ||||||
|               ), |               ), | ||||||
|               title: Text( |               title: Text( | ||||||
|                 ud.getAccountFromCache(member.accountId)?.nick ?? |                 ud.getAccountFromCache(member.accountId)?.nick ?? 'unknown'.tr(), | ||||||
|                     'unknown'.tr(), |  | ||||||
|               ), |               ), | ||||||
|               subtitle: Text( |               subtitle: Text( | ||||||
|                 ud.getAccountFromCache(member.accountId)?.name ?? |                 ud.getAccountFromCache(member.accountId)?.name ?? 'unknown'.tr(), | ||||||
|                     'unknown'.tr(), |  | ||||||
|               ), |               ), | ||||||
|               trailing: IconButton( |               trailing: IconButton( | ||||||
|                 icon: const Icon(Symbols.person_remove), |                 icon: const Icon(Symbols.person_remove), | ||||||
| @@ -257,6 +303,7 @@ class _RealmMemberListWidgetState extends State<_RealmMemberListWidget> { | |||||||
|  |  | ||||||
| class _NewRealmMemberWidget extends StatefulWidget { | class _NewRealmMemberWidget extends StatefulWidget { | ||||||
|   final SnRealm realm; |   final SnRealm realm; | ||||||
|  |  | ||||||
|   const _NewRealmMemberWidget({super.key, required this.realm}); |   const _NewRealmMemberWidget({super.key, required this.realm}); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -321,8 +368,7 @@ class _NewRealmMemberWidgetState extends State<_NewRealmMemberWidget> { | |||||||
|               child: IconButton( |               child: IconButton( | ||||||
|                 onPressed: _isBusy ? null : () => _performAction(), |                 onPressed: _isBusy ? null : () => _performAction(), | ||||||
|                 icon: Icon(Symbols.send), |                 icon: Icon(Symbols.send), | ||||||
|                 visualDensity: |                 visualDensity: const VisualDensity(horizontal: -4, vertical: -4), | ||||||
|                     const VisualDensity(horizontal: -4, vertical: -4), |  | ||||||
|                 padding: EdgeInsets.zero, |                 padding: EdgeInsets.zero, | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
| @@ -337,8 +383,8 @@ class _NewRealmMemberWidgetState extends State<_NewRealmMemberWidget> { | |||||||
| class _RealmSettingsWidget extends StatefulWidget { | class _RealmSettingsWidget extends StatefulWidget { | ||||||
|   final SnRealm? realm; |   final SnRealm? realm; | ||||||
|   final Function() onUpdate; |   final Function() onUpdate; | ||||||
|   const _RealmSettingsWidget( |  | ||||||
|       {super.key, required this.realm, required this.onUpdate}); |   const _RealmSettingsWidget({super.key, required this.realm, required this.onUpdate}); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   State<_RealmSettingsWidget> createState() => _RealmSettingsWidgetState(); |   State<_RealmSettingsWidget> createState() => _RealmSettingsWidgetState(); | ||||||
| @@ -382,6 +428,7 @@ class _RealmSettingsWidgetState extends State<_RealmSettingsWidget> { | |||||||
|  |  | ||||||
|     return Column( |     return Column( | ||||||
|       children: [ |       children: [ | ||||||
|  |         const Gap(16), | ||||||
|         ListTile( |         ListTile( | ||||||
|           leading: const Icon(Symbols.edit), |           leading: const Icon(Symbols.edit), | ||||||
|           trailing: const Icon(Symbols.chevron_right), |           trailing: const Icon(Symbols.chevron_right), | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user