diff --git a/lib/provider/api/tag_users_provider.dart b/lib/provider/api/tag_users_provider.dart new file mode 100644 index 000000000..414b77e72 --- /dev/null +++ b/lib/provider/api/tag_users_provider.dart @@ -0,0 +1,25 @@ +import 'package:misskey_dart/misskey_dart.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +import '../../model/account.dart'; +import 'misskey_provider.dart'; + +part 'tag_users_provider.g.dart'; + +@riverpod +FutureOr> tagUsers( + TagUsersRef ref, + Account account, + String tag, { + UsersSortType sort = UsersSortType.followerDescendant, + Origin? userOrigin, +}) async { + final response = await ref.read(misskeyProvider(account)).hashtags.users( + HashtagsUsersRequest( + tag: tag, + sort: sort, + origin: userOrigin, + ), + ); + return response.toList(); +} diff --git a/lib/provider/api/tag_users_provider.g.dart b/lib/provider/api/tag_users_provider.g.dart new file mode 100644 index 000000000..fdd650d49 --- /dev/null +++ b/lib/provider/api/tag_users_provider.g.dart @@ -0,0 +1,207 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'tag_users_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$tagUsersHash() => r'55e6e7821a3b59551f880d82d7bb34871351223f'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// See also [tagUsers]. +@ProviderFor(tagUsers) +const tagUsersProvider = TagUsersFamily(); + +/// See also [tagUsers]. +class TagUsersFamily extends Family>> { + /// See also [tagUsers]. + const TagUsersFamily(); + + /// See also [tagUsers]. + TagUsersProvider call( + Account account, + String tag, { + UsersSortType sort = UsersSortType.followerDescendant, + Origin? userOrigin, + }) { + return TagUsersProvider( + account, + tag, + sort: sort, + userOrigin: userOrigin, + ); + } + + @override + TagUsersProvider getProviderOverride( + covariant TagUsersProvider provider, + ) { + return call( + provider.account, + provider.tag, + sort: provider.sort, + userOrigin: provider.userOrigin, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'tagUsersProvider'; +} + +/// See also [tagUsers]. +class TagUsersProvider extends AutoDisposeFutureProvider> { + /// See also [tagUsers]. + TagUsersProvider( + Account account, + String tag, { + UsersSortType sort = UsersSortType.followerDescendant, + Origin? userOrigin, + }) : this._internal( + (ref) => tagUsers( + ref as TagUsersRef, + account, + tag, + sort: sort, + userOrigin: userOrigin, + ), + from: tagUsersProvider, + name: r'tagUsersProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$tagUsersHash, + dependencies: TagUsersFamily._dependencies, + allTransitiveDependencies: TagUsersFamily._allTransitiveDependencies, + account: account, + tag: tag, + sort: sort, + userOrigin: userOrigin, + ); + + TagUsersProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.account, + required this.tag, + required this.sort, + required this.userOrigin, + }) : super.internal(); + + final Account account; + final String tag; + final UsersSortType sort; + final Origin? userOrigin; + + @override + Override overrideWith( + FutureOr> Function(TagUsersRef provider) create, + ) { + return ProviderOverride( + origin: this, + override: TagUsersProvider._internal( + (ref) => create(ref as TagUsersRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + account: account, + tag: tag, + sort: sort, + userOrigin: userOrigin, + ), + ); + } + + @override + AutoDisposeFutureProviderElement> createElement() { + return _TagUsersProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is TagUsersProvider && + other.account == account && + other.tag == tag && + other.sort == sort && + other.userOrigin == userOrigin; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, account.hashCode); + hash = _SystemHash.combine(hash, tag.hashCode); + hash = _SystemHash.combine(hash, sort.hashCode); + hash = _SystemHash.combine(hash, userOrigin.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin TagUsersRef on AutoDisposeFutureProviderRef> { + /// The parameter `account` of this provider. + Account get account; + + /// The parameter `tag` of this provider. + String get tag; + + /// The parameter `sort` of this provider. + UsersSortType get sort; + + /// The parameter `userOrigin` of this provider. + Origin? get userOrigin; +} + +class _TagUsersProviderElement + extends AutoDisposeFutureProviderElement> + with TagUsersRef { + _TagUsersProviderElement(super.provider); + + @override + Account get account => (origin as TagUsersProvider).account; + @override + String get tag => (origin as TagUsersProvider).tag; + @override + UsersSortType get sort => (origin as TagUsersProvider).sort; + @override + Origin? get userOrigin => (origin as TagUsersProvider).userOrigin; +} +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/router/router.dart b/lib/router/router.dart index 5421a4d59..11fec5a17 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -72,7 +72,7 @@ import '../view/page/settings/theme_manage_page.dart'; import '../view/page/settings/theme_page.dart'; import '../view/page/share_page.dart'; import '../view/page/splash_page.dart'; -import '../view/page/tag_page.dart'; +import '../view/page/tag/tag_page.dart'; import '../view/page/timeline_page.dart'; import '../view/page/timelines_page.dart'; import '../view/page/token_login_page.dart'; @@ -592,6 +592,7 @@ GoRouter router(RouterRef ref) { builder: (_, state) => TagPage( account: Account.fromString(state.pathParameters['acct']!), tag: state.pathParameters['tag']!, + initialIndex: state.uri.fragment == 'users' ? 1 : 0, ), ), GoRoute( diff --git a/lib/router/router.g.dart b/lib/router/router.g.dart index e6a155642..c9c35d599 100644 --- a/lib/router/router.g.dart +++ b/lib/router/router.g.dart @@ -6,7 +6,7 @@ part of 'router.dart'; // RiverpodGenerator // ************************************************************************** -String _$routerHash() => r'44eb3b71196e6339fa106b03a3950f7f51650e0c'; +String _$routerHash() => r'78ec8f098d73703df414cb80fff35db35172a595'; /// See also [router]. @ProviderFor(router) diff --git a/lib/view/page/explore/explore_users.dart b/lib/view/page/explore/explore_users.dart index f4615b366..7fed0093b 100644 --- a/lib/view/page/explore/explore_users.dart +++ b/lib/view/page/explore/explore_users.dart @@ -12,6 +12,7 @@ import '../../widget/error_message.dart'; import '../../widget/misskey_server_autocomplete.dart'; import '../../widget/paginated_list_view.dart'; import '../../widget/user_info.dart'; +import '../../widget/users_sort_type_widget.dart'; enum _UserType { pinned, local, remote } @@ -99,44 +100,14 @@ class ExploreUsers extends HookConsumerWidget { flex: 3, child: DropdownButton( isExpanded: true, - items: [ - DropdownMenuItem( - value: UsersSortType.followerAscendant, - child: Text( - '${t.misskey.followersCount} (${t.misskey.ascendingOrder})', - ), - ), - DropdownMenuItem( - value: UsersSortType.followerDescendant, - child: Text( - '${t.misskey.followersCount} (${t.misskey.descendingOrder})', - ), - ), - DropdownMenuItem( - value: UsersSortType.createdAtAscendant, - child: Text( - '${t.misskey.createdAt} (${t.misskey.ascendingOrder})', - ), - ), - DropdownMenuItem( - value: UsersSortType.createdAtDescendant, - child: Text( - '${t.misskey.createdAt} (${t.misskey.descendingOrder})', - ), - ), - DropdownMenuItem( - value: UsersSortType.updateAtAscendant, - child: Text( - '${t.misskey.updatedAt} (${t.misskey.ascendingOrder})', - ), - ), - DropdownMenuItem( - value: UsersSortType.updateAtDescendant, - child: Text( - '${t.misskey.updatedAt} (${t.misskey.descendingOrder})', - ), - ), - ], + items: UsersSortType.values + .map( + (sort) => DropdownMenuItem( + value: sort, + child: UsersSortTypeWidget(sort: sort), + ), + ) + .toList(), value: sort.value, onChanged: (value) { if (value != null) { diff --git a/lib/view/page/tag/tag_notes.dart b/lib/view/page/tag/tag_notes.dart new file mode 100644 index 000000000..6231dc75c --- /dev/null +++ b/lib/view/page/tag/tag_notes.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +import '../../../i18n/strings.g.dart'; +import '../../../model/account.dart'; +import '../../../provider/api/tag_notes_notifier_provider.dart'; +import '../../widget/note_widget.dart'; +import '../../widget/paginated_list_view.dart'; + +class TagNotes extends ConsumerWidget { + const TagNotes({ + super.key, + required this.account, + required this.tag, + }); + + final Account account; + final String tag; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final notes = ref.watch(tagNotesNotifierProvider(account, tag)); + + return PaginatedListView( + paginationState: notes, + itemBuilder: (context, note) => + NoteWidget(account: account, noteId: note.id), + footer: const SliverToBoxAdapter(child: SizedBox(height: 80.0)), + onRefresh: () => + ref.refresh(tagNotesNotifierProvider(account, tag).future), + loadMore: (skipError) => ref + .read(tagNotesNotifierProvider(account, tag).notifier) + .loadMore(skipError: skipError), + noItemsLabel: t.misskey.noNotes, + ); + } +} diff --git a/lib/view/page/tag/tag_page.dart b/lib/view/page/tag/tag_page.dart new file mode 100644 index 000000000..3f2be80ce --- /dev/null +++ b/lib/view/page/tag/tag_page.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +import '../../../i18n/strings.g.dart'; +import '../../../model/account.dart'; +import '../../../provider/api/post_notifier_provider.dart'; +import 'tag_notes.dart'; +import 'tag_users.dart'; + +class TagPage extends ConsumerWidget { + const TagPage({ + super.key, + required this.account, + required this.tag, + this.initialIndex = 0, + }); + + final Account account; + final String tag; + final int initialIndex; + + @override + Widget build(BuildContext context, WidgetRef ref) { + return DefaultTabController( + length: 2, + initialIndex: initialIndex, + child: Scaffold( + appBar: AppBar( + title: Text('#$tag'), + bottom: TabBar( + tabs: [ + Tab(text: t.misskey.notes), + Tab(text: t.misskey.users), + ], + ), + ), + body: TabBarView( + children: [ + TagNotes(account: account, tag: tag), + TagUsers(account: account, tag: tag), + ], + ), + floatingActionButton: account.isGuest + ? null + : FloatingActionButton.extended( + onPressed: () { + ref + .read(postNotifierProvider(account).notifier) + .setText('#$tag '); + context.push('/$account/post'); + }, + label: Text(t.misskey.postToHashtag), + icon: const Icon(Icons.edit), + ), + ), + ); + } +} diff --git a/lib/view/page/tag/tag_users.dart b/lib/view/page/tag/tag_users.dart new file mode 100644 index 000000000..d4a48feed --- /dev/null +++ b/lib/view/page/tag/tag_users.dart @@ -0,0 +1,93 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:misskey_dart/misskey_dart.dart'; + +import '../../../i18n/strings.g.dart'; +import '../../../model/account.dart'; +import '../../../provider/api/tag_users_provider.dart'; +import '../../dialog/radio_dialog.dart'; +import '../../widget/error_message.dart'; +import '../../widget/user_info.dart'; +import '../../widget/users_sort_type_widget.dart'; + +class TagUsers extends HookConsumerWidget { + const TagUsers({ + super.key, + required this.account, + required this.tag, + }); + + final Account account; + final String tag; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final sort = useState(UsersSortType.followerDescendant); + final localOnly = useState(false); + final users = ref.watch( + tagUsersProvider( + account, + tag, + sort: sort.value, + userOrigin: localOnly.value ? Origin.local : Origin.combined, + ), + ); + + return RefreshIndicator( + onRefresh: () => ref.refresh(tagUsersProvider(account, tag).future), + child: Center( + child: Container( + width: 800.0, + margin: const EdgeInsets.symmetric(horizontal: 8.0), + child: ListView( + children: [ + ExpansionTile( + title: Text(t.misskey.options), + children: [ + ListTile( + title: Text(t.misskey.sort), + subtitle: UsersSortTypeWidget(sort: sort.value), + onTap: () async { + final result = await showRadioDialog( + context, + title: Text(t.misskey.sort), + values: UsersSortType.values, + initialValue: sort.value, + itemBuilder: (context, sort) => + UsersSortTypeWidget(sort: sort), + ); + if (!context.mounted) return; + if (result != null) { + sort.value = result; + } + }, + ), + SwitchListTile( + title: Text(t.misskey.localOnly), + value: localOnly.value, + onChanged: (value) => localOnly.value = value, + ), + ], + ), + ...switch (users) { + AsyncValue(valueOrNull: final users?) => users.isEmpty + ? [Center(child: Text(t.misskey.noUsers))] + : [ + ...users.map( + (user) => UserInfo(account: account, user: user), + ), + const SizedBox(height: 80.0), + ], + AsyncValue(:final error?, :final stackTrace) => [ + ErrorMessage(error: error, stackTrace: stackTrace), + ], + _ => const [Center(child: CircularProgressIndicator())], + }, + ], + ), + ), + ), + ); + } +} diff --git a/lib/view/page/tag_page.dart b/lib/view/page/tag_page.dart deleted file mode 100644 index 682a1d4b7..000000000 --- a/lib/view/page/tag_page.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -import '../../i18n/strings.g.dart'; -import '../../model/account.dart'; -import '../../provider/api/post_notifier_provider.dart'; -import '../../provider/api/tag_notes_notifier_provider.dart'; -import '../widget/note_widget.dart'; -import '../widget/paginated_list_view.dart'; - -class TagPage extends ConsumerWidget { - const TagPage({ - super.key, - required this.account, - required this.tag, - }); - - final Account account; - final String tag; - - @override - Widget build(BuildContext context, WidgetRef ref) { - final notes = ref.watch(tagNotesNotifierProvider(account, tag)); - - return Scaffold( - appBar: AppBar(title: Text('#$tag')), - body: PaginatedListView( - paginationState: notes, - itemBuilder: (context, note) => - NoteWidget(account: account, noteId: note.id), - onRefresh: () => - ref.refresh(tagNotesNotifierProvider(account, tag).future), - loadMore: (skipError) => ref - .read(tagNotesNotifierProvider(account, tag).notifier) - .loadMore(skipError: skipError), - noItemsLabel: t.misskey.noNotes, - ), - floatingActionButton: account.isGuest - ? null - : FloatingActionButton.extended( - onPressed: () { - ref - .read(postNotifierProvider(account).notifier) - .setText('#$tag '); - context.push('/$account/post'); - }, - label: Text(t.misskey.postToHashtag), - icon: const Icon(Icons.edit), - ), - ); - } -} diff --git a/lib/view/page/user/user_home.dart b/lib/view/page/user/user_home.dart index 16dc4df36..94e9f3e16 100644 --- a/lib/view/page/user/user_home.dart +++ b/lib/view/page/user/user_home.dart @@ -386,6 +386,7 @@ class _UserHome extends ConsumerWidget { text: user.description, emojis: user.emojis, author: user, + isUserDescription: true, textAlign: TextAlign.center, ) : Text( diff --git a/lib/view/widget/mfm.dart b/lib/view/widget/mfm.dart index fff3a72d4..fc49f1e5b 100644 --- a/lib/view/widget/mfm.dart +++ b/lib/view/widget/mfm.dart @@ -25,8 +25,8 @@ List buildMfm( Map? emojis, User? author, bool nyaize = false, + bool isUserDescription = false, void Function(String emoji)? onTapEmoji, - void Function(String link)? onLinkTap, void Function(String clickEv)? onClickEv, TextAlign? textAlign, TextOverflow? overflow, @@ -81,12 +81,13 @@ List buildMfm( ); }, onTapEmoji: onTapEmoji, - onLinkTap: onLinkTap, + onLinkTap: (link) => navigate(ref, account, link), onLinkLongPress: (url) => showModalBottomSheet( context: ref.context, builder: (context) => UrlSheet(url: url), ), - onHashtagTap: (hashtag) => ref.context.push('/$account/tags/$hashtag'), + onHashtagTap: (hashtag) => ref.context + .push('/$account/tags/$hashtag${isUserDescription ? '#users' : ''}'), onClickEv: onClickEv, shouldNyaize: nyaize && (author?.isCat ?? false), useAdvanced: useAdvanced, @@ -116,6 +117,7 @@ class Mfm extends HookConsumerWidget { this.emojis, this.author, this.nyaize = false, + this.isUserDescription = false, this.selectable = false, this.onTapEmoji, this.onClickEv, @@ -132,6 +134,7 @@ class Mfm extends HookConsumerWidget { final Map? emojis; final User? author; final bool nyaize; + final bool isUserDescription; final bool selectable; final void Function(String emoji)? onTapEmoji; final void Function(String clickEv)? onClickEv; @@ -154,7 +157,8 @@ class Mfm extends HookConsumerWidget { style: style, emojis: emojis, author: author, - onLinkTap: (link) => navigate(ref, account, link), + nyaize: nyaize, + isUserDescription: isUserDescription, onClickEv: onClickEv, textAlign: textAlign, overflow: overflow, diff --git a/lib/view/widget/note_detailed_widget.dart b/lib/view/widget/note_detailed_widget.dart index 8934fda88..f1e7de2f9 100644 --- a/lib/view/widget/note_detailed_widget.dart +++ b/lib/view/widget/note_detailed_widget.dart @@ -22,7 +22,6 @@ import '../../provider/parsed_mfm_provider.dart'; import '../../util/extract_url.dart'; import '../../util/format_datetime.dart'; import '../../util/get_note_action.dart'; -import '../../util/navigate.dart'; import 'acct_widget.dart'; import 'bot_badge.dart'; import 'channel_color_bar_box.dart'; @@ -395,8 +394,6 @@ class NoteDetailedWidget extends HookConsumerWidget { targetNote: appearNote, ), ), - onLinkTap: (link) => - navigate(ref, account, link), ), [ account, diff --git a/lib/view/widget/note_widget.dart b/lib/view/widget/note_widget.dart index d6562db9d..44900838a 100644 --- a/lib/view/widget/note_widget.dart +++ b/lib/view/widget/note_widget.dart @@ -20,7 +20,6 @@ import '../../provider/note_provider.dart'; import '../../provider/parsed_mfm_provider.dart'; import '../../util/extract_url.dart'; import '../../util/get_note_action.dart'; -import '../../util/navigate.dart'; import 'channel_color_bar_box.dart'; import 'cw_button.dart'; import 'emoji_sheet.dart'; @@ -440,8 +439,6 @@ class NoteWidget extends HookConsumerWidget { targetNote: appearNote, ), ), - onLinkTap: (link) => - navigate(ref, account, link), maxLines: isCollapsed.value ? 10 : null, ), diff --git a/lib/view/widget/paginated_list_view.dart b/lib/view/widget/paginated_list_view.dart index 031408e8f..38927fc77 100644 --- a/lib/view/widget/paginated_list_view.dart +++ b/lib/view/widget/paginated_list_view.dart @@ -13,6 +13,7 @@ class PaginatedListView extends HookConsumerWidget { this.header, required this.paginationState, required this.itemBuilder, + this.footer, this.onRefresh, this.loadMore, this.panel = true, @@ -23,6 +24,7 @@ class PaginatedListView extends HookConsumerWidget { final Widget? header; final AsyncValue>? paginationState; final Widget Function(BuildContext context, T item) itemBuilder; + final Widget? footer; final Future Function()? onRefresh; final void Function(bool skipError)? loadMore; final bool panel; @@ -60,7 +62,7 @@ class PaginatedListView extends HookConsumerWidget { child: CustomScrollView( controller: controller, slivers: [ - if (header != null) header!, + if (header case final header?) header, if (paginationState != null) ...[ if (paginationState?.valueOrNull case PaginationState(:final items)) @@ -114,6 +116,7 @@ class PaginatedListView extends HookConsumerWidget { ), ), ], + if (footer case final footer?) footer, ], ), ), diff --git a/lib/view/widget/sub_note_content.dart b/lib/view/widget/sub_note_content.dart index 0404944ca..b41802567 100644 --- a/lib/view/widget/sub_note_content.dart +++ b/lib/view/widget/sub_note_content.dart @@ -11,7 +11,6 @@ import '../../provider/misskey_colors_provider.dart'; import '../../provider/note_is_long_provider.dart'; import '../../provider/note_provider.dart'; import '../../provider/parsed_mfm_provider.dart'; -import '../../util/navigate.dart'; import 'emoji_sheet.dart'; import 'media_list.dart'; import 'mfm.dart'; @@ -102,7 +101,6 @@ class SubNoteContent extends HookConsumerWidget { targetNote: note, ), ), - onLinkTap: (link) => navigate(ref, account, link), maxLines: isCollapsed.value ? 10 : null, ), [account, parsed, colors, note.user, note.emojis], diff --git a/lib/view/widget/timeline_drawer.dart b/lib/view/widget/timeline_drawer.dart index ee4d9f77c..ffc58672a 100644 --- a/lib/view/widget/timeline_drawer.dart +++ b/lib/view/widget/timeline_drawer.dart @@ -185,7 +185,8 @@ class TimelineDrawer extends HookConsumerWidget { if (query.startsWith('@') && !query.contains(' ')) { await context.push('/$account/$query'); } else if (query.startsWith('#')) { - await context.push('/$account/tags/$query'); + await context + .push('/$account/tags/${query.substring(1)}'); } else if (query.startsWith('https://')) { final url = Uri.tryParse(query); if (url == null) return; diff --git a/lib/view/widget/user_info.dart b/lib/view/widget/user_info.dart index b65d19d33..b323bb789 100644 --- a/lib/view/widget/user_info.dart +++ b/lib/view/widget/user_info.dart @@ -98,6 +98,7 @@ class UserInfo extends ConsumerWidget { text: description, emojis: user.emojis, author: user, + isUserDescription: true, overflow: TextOverflow.ellipsis, maxLines: 3, ), diff --git a/lib/view/widget/users_sort_type_widget.dart b/lib/view/widget/users_sort_type_widget.dart new file mode 100644 index 000000000..22a80da77 --- /dev/null +++ b/lib/view/widget/users_sort_type_widget.dart @@ -0,0 +1,30 @@ +import 'package:flutter/widgets.dart'; +import 'package:misskey_dart/misskey_dart.dart'; + +import '../../i18n/strings.g.dart'; + +class UsersSortTypeWidget extends StatelessWidget { + const UsersSortTypeWidget({super.key, required this.sort}); + + final UsersSortType sort; + + @override + Widget build(BuildContext context) { + return Text( + switch (sort) { + UsersSortType.followerAscendant => + '${t.misskey.followersCount} (${t.misskey.ascendingOrder})', + UsersSortType.followerDescendant => + '${t.misskey.followersCount} (${t.misskey.descendingOrder})', + UsersSortType.createdAtAscendant => + '${t.misskey.createdAt} (${t.misskey.ascendingOrder})', + UsersSortType.createdAtDescendant => + '${t.misskey.createdAt} (${t.misskey.descendingOrder})', + UsersSortType.updateAtAscendant => + '${t.misskey.updatedAt} (${t.misskey.ascendingOrder})', + UsersSortType.updateAtDescendant => + '${t.misskey.updatedAt} (${t.misskey.descendingOrder})', + }, + ); + } +}