♻️ Optimize realm discovery
This commit is contained in:
@@ -233,7 +233,18 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'universalSearch',
|
name: 'universalSearch',
|
||||||
path: '/search',
|
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
|
// Main tabs with TabsScreen shell
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class RealmListScreen extends HookConsumerWidget {
|
|||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.travel_explore),
|
icon: const Icon(Symbols.travel_explore),
|
||||||
onPressed: () => context.pushNamed('discoveryRealms'),
|
onPressed: () => context.pushNamed('universalSearch', queryParameters: {'tab': 'realms'}),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Badge(
|
icon: Badge(
|
||||||
|
|||||||
@@ -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.dart';
|
||||||
import 'package:island/widgets/post/post_item_skeleton.dart';
|
import 'package:island/widgets/post/post_item_skeleton.dart';
|
||||||
import 'package:island/widgets/post/filters/post_filter.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:material_symbols_icons/symbols.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
const kSearchPostListId = 'search';
|
const kSearchPostListId = 'search';
|
||||||
|
|
||||||
enum SearchTab { posts, fediverse }
|
enum SearchTab { posts, fediverse, realms }
|
||||||
|
|
||||||
class UniversalSearchScreen extends HookConsumerWidget {
|
class UniversalSearchScreen extends HookConsumerWidget {
|
||||||
final SearchTab initialTab;
|
final SearchTab initialTab;
|
||||||
@@ -31,7 +32,7 @@ class UniversalSearchScreen extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final tabController = useTabController(
|
final tabController = useTabController(
|
||||||
initialLength: 2,
|
initialLength: 3,
|
||||||
initialIndex: initialTab.index,
|
initialIndex: initialTab.index,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -45,12 +46,13 @@ class UniversalSearchScreen extends HookConsumerWidget {
|
|||||||
tabs: [
|
tabs: [
|
||||||
Tab(text: 'posts'.tr()),
|
Tab(text: 'posts'.tr()),
|
||||||
Tab(text: 'fediverseUsers'.tr()),
|
Tab(text: 'fediverseUsers'.tr()),
|
||||||
|
Tab(text: 'realms'.tr()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TabBarView(
|
child: TabBarView(
|
||||||
controller: tabController,
|
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 {
|
class _PostsSearchTab extends HookConsumerWidget {
|
||||||
const _PostsSearchTab();
|
const _PostsSearchTab();
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import 'package:island/widgets/paging/pagination_list.dart';
|
|||||||
import 'package:island/widgets/realm/realm_list_tile.dart';
|
import 'package:island/widgets/realm/realm_list_tile.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
final realmListNotifierProvider = AsyncNotifierProvider.autoDispose
|
final realmListNotifierProvider = AsyncNotifierProvider.autoDispose.family(
|
||||||
.family<RealmListNotifier, PaginationState<SnRealm>, String?>(
|
|
||||||
RealmListNotifier.new,
|
RealmListNotifier.new,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -45,7 +44,7 @@ class RealmListNotifier extends AsyncNotifier<PaginationState<SnRealm>>
|
|||||||
};
|
};
|
||||||
|
|
||||||
final response = await client.get(
|
final response = await client.get(
|
||||||
'/sphere/discovery/realms',
|
'/pass/realms/public',
|
||||||
queryParameters: queryParams,
|
queryParameters: queryParams,
|
||||||
);
|
);
|
||||||
totalCount = int.parse(response.headers.value('X-Total') ?? '0');
|
totalCount = int.parse(response.headers.value('X-Total') ?? '0');
|
||||||
|
|||||||
Reference in New Issue
Block a user