♻️ Optimize realm discovery

This commit is contained in:
2026-02-02 13:30:33 +08:00
parent 5cdeb7bd22
commit cfd2a47064
4 changed files with 80 additions and 10 deletions

View File

@@ -233,7 +233,18 @@ final routerProvider = Provider<GoRouter>((ref) {
GoRoute(
name: 'universalSearch',
path: '/search',
builder: (context, state) => const UniversalSearchScreen(),
builder: (context, state) {
final initialTab = state.uri.queryParameters['tab'];
SearchTab tab;
if (initialTab == 'realms') {
tab = SearchTab.realms;
} else if (initialTab == 'fediverse') {
tab = SearchTab.fediverse;
} else {
tab = SearchTab.posts;
}
return UniversalSearchScreen(initialTab: tab);
},
),
// Main tabs with TabsScreen shell

View File

@@ -51,7 +51,7 @@ class RealmListScreen extends HookConsumerWidget {
actions: [
IconButton(
icon: const Icon(Symbols.travel_explore),
onPressed: () => context.pushNamed('discoveryRealms'),
onPressed: () => context.pushNamed('universalSearch', queryParameters: {'tab': 'realms'}),
),
IconButton(
icon: Badge(

View File

@@ -16,12 +16,13 @@ import 'package:island/widgets/paging/pagination_list.dart';
import 'package:island/widgets/post/post_item.dart';
import 'package:island/widgets/post/post_item_skeleton.dart';
import 'package:island/widgets/post/filters/post_filter.dart';
import 'package:island/widgets/realm/realm_list.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:styled_widget/styled_widget.dart';
const kSearchPostListId = 'search';
enum SearchTab { posts, fediverse }
enum SearchTab { posts, fediverse, realms }
class UniversalSearchScreen extends HookConsumerWidget {
final SearchTab initialTab;
@@ -31,7 +32,7 @@ class UniversalSearchScreen extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final tabController = useTabController(
initialLength: 2,
initialLength: 3,
initialIndex: initialTab.index,
);
@@ -45,12 +46,13 @@ class UniversalSearchScreen extends HookConsumerWidget {
tabs: [
Tab(text: 'posts'.tr()),
Tab(text: 'fediverseUsers'.tr()),
Tab(text: 'realms'.tr()),
],
),
Expanded(
child: TabBarView(
controller: tabController,
children: [_PostsSearchTab(), _FediverseSearchTab()],
children: [_PostsSearchTab(), _FediverseSearchTab(), _RealmsSearchTab()],
),
),
],
@@ -59,6 +61,64 @@ class UniversalSearchScreen extends HookConsumerWidget {
}
}
class _RealmsSearchTab extends HookConsumerWidget {
const _RealmsSearchTab();
@override
Widget build(BuildContext context, WidgetRef ref) {
Timer? debounceTimer;
final searchController = useTextEditingController();
final currentQuery = useState<String?>(null);
return Stack(
children: [
CustomScrollView(
slivers: [
const SliverGap(88),
SliverRealmList(
query: currentQuery.value,
key: ValueKey(currentQuery.value),
),
SliverGap(MediaQuery.of(context).padding.bottom + 16),
],
),
Positioned(
top: 0,
left: 0,
right: 0,
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 560),
child: Padding(
padding: const EdgeInsets.all(16),
child: SearchBar(
elevation: WidgetStateProperty.all(4),
controller: searchController,
hintText: 'search'.tr(),
leading: const Icon(Icons.search),
padding: WidgetStateProperty.all(
const EdgeInsets.symmetric(horizontal: 24),
),
onChanged: (value) {
if (debounceTimer?.isActive ?? false) {
debounceTimer?.cancel();
}
debounceTimer = Timer(const Duration(milliseconds: 300), () {
if (currentQuery.value != value) {
currentQuery.value = value;
}
});
},
),
),
),
),
),
],
);
}
}
class _PostsSearchTab extends HookConsumerWidget {
const _PostsSearchTab();

View File

@@ -9,10 +9,9 @@ import 'package:island/widgets/paging/pagination_list.dart';
import 'package:island/widgets/realm/realm_list_tile.dart';
import 'package:styled_widget/styled_widget.dart';
final realmListNotifierProvider = AsyncNotifierProvider.autoDispose
.family<RealmListNotifier, PaginationState<SnRealm>, String?>(
RealmListNotifier.new,
);
final realmListNotifierProvider = AsyncNotifierProvider.autoDispose.family(
RealmListNotifier.new,
);
class RealmListNotifier extends AsyncNotifier<PaginationState<SnRealm>>
with AsyncPaginationController<SnRealm> {
@@ -45,7 +44,7 @@ class RealmListNotifier extends AsyncNotifier<PaginationState<SnRealm>>
};
final response = await client.get(
'/sphere/discovery/realms',
'/pass/realms/public',
queryParameters: queryParams,
);
totalCount = int.parse(response.headers.value('X-Total') ?? '0');