mirror of
https://github.com/immich-app/immich.git
synced 2026-03-26 20:00:44 +03:00
Search results are replaced with a spinner when loading the next page, which is quite jarring. Search results now remain visible when loading the next page with a spinner at the bottom. The next page also loads sooner, which makes it feel a lot smoother. Co-authored-by: Alex <alex.tran1502@gmail.com>
75 lines
2.2 KiB
Dart
75 lines
2.2 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|
import 'package:immich_mobile/domain/services/search.service.dart';
|
|
import 'package:immich_mobile/models/search/search_filter.model.dart';
|
|
import 'package:immich_mobile/providers/infrastructure/search.provider.dart';
|
|
|
|
final searchPreFilterProvider = NotifierProvider<SearchFilterProvider, SearchFilter?>(SearchFilterProvider.new);
|
|
|
|
class SearchFilterProvider extends Notifier<SearchFilter?> {
|
|
@override
|
|
SearchFilter? build() {
|
|
return null;
|
|
}
|
|
|
|
void setFilter(SearchFilter? filter) {
|
|
state = filter;
|
|
}
|
|
|
|
void clear() {
|
|
state = null;
|
|
}
|
|
}
|
|
|
|
class SearchState {
|
|
final List<BaseAsset> assets;
|
|
final int? nextPage;
|
|
final bool isLoading;
|
|
|
|
const SearchState({this.assets = const [], this.nextPage = 1, this.isLoading = false});
|
|
}
|
|
|
|
final paginatedSearchProvider = StateNotifierProvider<PaginatedSearchNotifier, SearchState>(
|
|
(ref) => PaginatedSearchNotifier(ref.watch(searchServiceProvider)),
|
|
);
|
|
|
|
class PaginatedSearchNotifier extends StateNotifier<SearchState> {
|
|
final SearchService _searchService;
|
|
final _assetCountController = StreamController<int>.broadcast();
|
|
|
|
PaginatedSearchNotifier(this._searchService) : super(const SearchState());
|
|
|
|
Stream<int> get assetCount => _assetCountController.stream;
|
|
|
|
Future<void> search(SearchFilter filter) async {
|
|
if (state.nextPage == null || state.isLoading) return;
|
|
|
|
state = SearchState(assets: state.assets, nextPage: state.nextPage, isLoading: true);
|
|
|
|
final result = await _searchService.search(filter, state.nextPage!);
|
|
|
|
if (result == null) {
|
|
state = SearchState(assets: state.assets, nextPage: state.nextPage);
|
|
return;
|
|
}
|
|
|
|
final assets = [...state.assets, ...result.assets];
|
|
state = SearchState(assets: assets, nextPage: result.nextPage);
|
|
|
|
_assetCountController.add(assets.length);
|
|
}
|
|
|
|
void clear() {
|
|
state = const SearchState();
|
|
_assetCountController.add(0);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_assetCountController.close();
|
|
super.dispose();
|
|
}
|
|
}
|