Skip to content

Commit

Permalink
feat(neon_framework): Only search in active app first
Browse files Browse the repository at this point in the history
Signed-off-by: provokateurin <[email protected]>
  • Loading branch information
provokateurin committed Apr 4, 2024
1 parent 7cc6efd commit b92e713
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 15 deletions.
1 change: 1 addition & 0 deletions packages/neon_framework/lib/l10n/en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
}
},
"searchNoResults": "No search results",
"searchEverywhere": "Search everywhere",
"settings": "Settings",
"settingsApps": "Apps",
"settingsAccount": "Account",
Expand Down
6 changes: 6 additions & 0 deletions packages/neon_framework/lib/l10n/localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,12 @@ abstract class NeonLocalizations {
/// **'No search results'**
String get searchNoResults;

/// No description provided for @searchEverywhere.
///
/// In en, this message translates to:
/// **'Search everywhere'**
String get searchEverywhere;

/// No description provided for @settings.
///
/// In en, this message translates to:
Expand Down
3 changes: 3 additions & 0 deletions packages/neon_framework/lib/l10n/localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ class NeonLocalizationsEn extends NeonLocalizations {
@override
String get searchNoResults => 'No search results';

@override
String get searchEverywhere => 'Search everywhere';

@override
String get settings => 'Settings';

Expand Down
37 changes: 36 additions & 1 deletion packages/neon_framework/lib/src/blocs/unified_search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ sealed class UnifiedSearchBloc implements InteractiveBloc {
/// Search for a [term].
void search(String term);

/// Enables searching in all providers.
void enableExtendedSearch();

/// Whether the search happens only in the providers of the active app or of all apps.
BehaviorSubject<bool?> get isExtendedSearch;

/// The available search providers.
BehaviorSubject<Result<BuiltList<core.UnifiedSearchProvider>?>> get providers;

Expand All @@ -38,6 +44,7 @@ class _UnifiedSearchBloc extends InteractiveBloc implements UnifiedSearchBloc {
}) {
appsBloc.activeApp.listen((_) {
term = '';
extendedSearchEnabled = false;
results.add(BuiltMap());
});
}
Expand All @@ -48,6 +55,10 @@ class _UnifiedSearchBloc extends InteractiveBloc implements UnifiedSearchBloc {
final AppsBloc appsBloc;
final Account account;
String term = '';
bool extendedSearchEnabled = false;

@override
final isExtendedSearch = BehaviorSubject.seeded(null);

@override
final providers = BehaviorSubject.seeded(Result.success(null));
Expand All @@ -57,6 +68,7 @@ class _UnifiedSearchBloc extends InteractiveBloc implements UnifiedSearchBloc {

@override
void dispose() {
unawaited(isExtendedSearch.close());
unawaited(providers.close());
unawaited(results.close());
super.dispose();
Expand All @@ -77,11 +89,28 @@ class _UnifiedSearchBloc extends InteractiveBloc implements UnifiedSearchBloc {

if (term.isEmpty) {
results.add(BuiltMap());
isExtendedSearch.add(null);
extendedSearchEnabled = false;
return;
}

if (providers.value.hasData) {
await searchProviders(providers.value.requireData!.map((provider) => provider.id).toList());
final activeApp = appsBloc.activeApp.value;

var providerIDs = providers.value.requireData!.map((provider) => provider.id);
if (!extendedSearchEnabled) {
final matchingProviderIDs = providerIDs.where((id) => providerMatchesApp(id, activeApp));

if (matchingProviderIDs.isNotEmpty) {
providerIDs = matchingProviderIDs;
}

isExtendedSearch.add(matchingProviderIDs.isEmpty);
} else {
isExtendedSearch.add(true);
}

await searchProviders(providerIDs.toList());
}
}

Expand All @@ -91,6 +120,12 @@ class _UnifiedSearchBloc extends InteractiveBloc implements UnifiedSearchBloc {
await refresh();
}

@override
Future<void> enableExtendedSearch() async {
extendedSearchEnabled = true;
await refresh();
}

Future<void> searchProviders(List<String> providerIDs) async {
results.add(
BuiltMap.build((b) {
Expand Down
53 changes: 39 additions & 14 deletions packages/neon_framework/lib/src/widgets/unified_search_results.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,45 @@ class NeonUnifiedSearchResults extends StatelessWidget {
Widget build(BuildContext context) {
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final bloc = accountsBloc.activeUnifiedSearchBloc;
return ResultBuilder.behaviorSubject(
subject: bloc.providers,
builder: (context, providers) => NeonListView(
scrollKey: 'unified-search',
isLoading: providers.isLoading,
error: providers.error,
onRefresh: bloc.refresh,
itemCount: providers.data?.length ?? 0,
itemBuilder: (context, index) {
final provider = providers.data![index];

return NeonUnifiedSearchProvider(
provider: provider,
onSelected: onSelected,
return StreamBuilder(
stream: bloc.isExtendedSearch,
builder: (context, isExtendedSearchSnapshot) => ResultBuilder.behaviorSubject(
subject: bloc.providers,
builder: (context, providers) {
final isExtendedSearch = isExtendedSearchSnapshot.data ?? true;

var itemCount = providers.data?.length ?? 0;
if (!isExtendedSearch) {
itemCount++;
}

return NeonListView(
scrollKey: 'unified-search',
isLoading: providers.isLoading,
error: providers.error,
onRefresh: bloc.refresh,
itemCount: itemCount,
itemBuilder: (context, index) {
if (!isExtendedSearch && index == itemCount - 1) {
return Padding(
padding: const EdgeInsets.only(top: 10),
child: Align(
child: ElevatedButton.icon(
onPressed: bloc.enableExtendedSearch,
label: Text(NeonLocalizations.of(context).searchEverywhere),
icon: Icon(AdaptiveIcons.search),
),
),
);
}

final provider = providers.data![index];

return NeonUnifiedSearchProvider(
provider: provider,
onSelected: onSelected,
);
},
);
},
),
Expand Down

0 comments on commit b92e713

Please sign in to comment.