fix(mobile): show places in Search page on mobile (#9085)

* fix(mobile): show map on mobile

* remove ununsed code
This commit is contained in:
Alex 2024-04-26 00:49:31 -05:00 committed by GitHub
parent d52ed51aab
commit 52bcb46b42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 40 additions and 191 deletions

View File

@ -1,81 +0,0 @@
import 'dart:convert';
import 'package:collection/collection.dart';
class SearchPageState {
final String searchTerm;
final bool isSearchEnabled;
final List<String> searchSuggestion;
final List<String> userSuggestedSearchTerms;
SearchPageState({
required this.searchTerm,
required this.isSearchEnabled,
required this.searchSuggestion,
required this.userSuggestedSearchTerms,
});
SearchPageState copyWith({
String? searchTerm,
bool? isSearchEnabled,
List<String>? searchSuggestion,
List<String>? userSuggestedSearchTerms,
}) {
return SearchPageState(
searchTerm: searchTerm ?? this.searchTerm,
isSearchEnabled: isSearchEnabled ?? this.isSearchEnabled,
searchSuggestion: searchSuggestion ?? this.searchSuggestion,
userSuggestedSearchTerms:
userSuggestedSearchTerms ?? this.userSuggestedSearchTerms,
);
}
Map<String, dynamic> toMap() {
return {
'searchTerm': searchTerm,
'isSearchEnabled': isSearchEnabled,
'searchSuggestion': searchSuggestion,
'userSuggestedSearchTerms': userSuggestedSearchTerms,
};
}
factory SearchPageState.fromMap(Map<String, dynamic> map) {
return SearchPageState(
searchTerm: map['searchTerm'] ?? '',
isSearchEnabled: map['isSearchEnabled'] ?? false,
searchSuggestion: List<String>.from(map['searchSuggestion']),
userSuggestedSearchTerms:
List<String>.from(map['userSuggestedSearchTerms']),
);
}
String toJson() => json.encode(toMap());
factory SearchPageState.fromJson(String source) =>
SearchPageState.fromMap(json.decode(source));
@override
String toString() {
return 'SearchPageState(searchTerm: $searchTerm, isSearchEnabled: $isSearchEnabled, searchSuggestion: $searchSuggestion, userSuggestedSearchTerms: $userSuggestedSearchTerms)';
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
final listEquals = const DeepCollectionEquality().equals;
return other is SearchPageState &&
other.searchTerm == searchTerm &&
other.isSearchEnabled == isSearchEnabled &&
listEquals(other.searchSuggestion, searchSuggestion) &&
listEquals(other.userSuggestedSearchTerms, userSuggestedSearchTerms);
}
@override
int get hashCode {
return searchTerm.hashCode ^
isSearchEnabled.hashCode ^
searchSuggestion.hashCode ^
userSuggestedSearchTerms.hashCode;
}
}

View File

@ -1,65 +1,29 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/search/models/search_page_state.model.dart';
import 'package:immich_mobile/modules/search/models/curated_content.dart';
import 'package:immich_mobile/modules/search/services/search.service.dart';
import 'package:openapi/api.dart';
class SearchPageStateNotifier extends StateNotifier<SearchPageState> {
SearchPageStateNotifier(this._searchService)
: super(
SearchPageState(
searchTerm: "",
isSearchEnabled: false,
searchSuggestion: [],
userSuggestedSearchTerms: [],
),
);
final SearchService _searchService;
void enableSearch() {
state = state.copyWith(isSearchEnabled: true);
}
void disableSearch() {
state = state.copyWith(isSearchEnabled: false);
}
void setSearchTerm(String value) {
state = state.copyWith(searchTerm: value);
_getSearchSuggestion(state.searchTerm);
}
void _getSearchSuggestion(String searchTerm) {
var searchList = state.userSuggestedSearchTerms;
var newList = searchList.where((e) => e.toLowerCase().contains(searchTerm));
state = state.copyWith(searchSuggestion: [...newList]);
if (searchTerm.isEmpty) {
state = state.copyWith(searchSuggestion: []);
}
}
void getSuggestedSearchTerms() async {
var userSuggestedSearchTerms =
await _searchService.getUserSuggestedSearchTerms();
state = state.copyWith(userSuggestedSearchTerms: userSuggestedSearchTerms);
}
}
final searchPageStateProvider =
StateNotifierProvider<SearchPageStateNotifier, SearchPageState>((ref) {
return SearchPageStateNotifier(ref.watch(searchServiceProvider));
});
final getCuratedLocationProvider =
FutureProvider.autoDispose<List<CuratedLocationsResponseDto>>((ref) async {
final getPlacesProvider =
FutureProvider.autoDispose<List<CuratedContent>>((ref) async {
final SearchService searchService = ref.watch(searchServiceProvider);
var curatedLocation = await searchService.getCuratedLocation();
return curatedLocation ?? [];
final exploreData = await searchService.getExploreData();
if (exploreData == null) {
return [];
}
final locations =
exploreData.firstWhere((data) => data.fieldName == "exifInfo.city").items;
final curatedContent = locations
.map(
(l) => CuratedContent(
label: l.value,
id: l.data.id,
),
)
.toList();
return curatedContent;
});

View File

@ -6,6 +6,7 @@ import 'package:immich_mobile/shared/providers/api.provider.dart';
import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:immich_mobile/shared/services/api.service.dart';
import 'package:isar/isar.dart';
import 'package:logging/logging.dart';
import 'package:openapi/api.dart';
final searchServiceProvider = Provider(
@ -19,17 +20,9 @@ class SearchService {
final ApiService _apiService;
final Isar _db;
final _log = Logger("SearchService");
SearchService(this._apiService, this._db);
Future<List<String>?> getUserSuggestedSearchTerms() async {
try {
return await _apiService.assetApi.getAssetSearchTerms();
} catch (e) {
debugPrint("[ERROR] [getUserSuggestedSearchTerms] ${e.toString()}");
return [];
}
}
Future<List<String>?> getSearchSuggestions(
SearchSuggestionType type, {
String? country,
@ -112,29 +105,18 @@ class SearchService {
return _db.assets
.getAllByRemoteId(response.assets.items.map((e) => e.id));
} catch (error) {
debugPrint("Error [search] $error");
} catch (error, stackTrace) {
_log.severe("Failed to search for assets", error, stackTrace);
}
return null;
}
Future<List<CuratedLocationsResponseDto>?> getCuratedLocation() async {
Future<List<SearchExploreResponseDto>?> getExploreData() async {
try {
var locations = await _apiService.assetApi.getCuratedLocations();
return locations;
} catch (e) {
debugPrint("Error [getCuratedLocation] ${e.toString()}");
return [];
}
}
Future<List<CuratedObjectsResponseDto>?> getCuratedObjects() async {
try {
return await _apiService.assetApi.getCuratedObjects();
} catch (e) {
debugPrint("Error [getCuratedObjects] ${e.toString()}");
return [];
return await _apiService.searchApi.getExploreData();
} catch (error, stackTrace) {
_log.severe("Failed to getExploreData", error, stackTrace);
}
return null;
}
}

View File

@ -6,7 +6,6 @@ import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
import 'package:immich_mobile/modules/search/models/curated_content.dart';
import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart';
import 'package:immich_mobile/modules/search/ui/explore_grid.dart';
import 'package:openapi/api.dart';
@RoutePage()
class CuratedLocationPage extends HookConsumerWidget {
@ -14,8 +13,7 @@ class CuratedLocationPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
AsyncValue<List<CuratedLocationsResponseDto>> curatedLocation =
ref.watch(getCuratedLocationProvider);
AsyncValue<List<CuratedContent>> places = ref.watch(getPlacesProvider);
return Scaffold(
appBar: AppBar(
@ -27,16 +25,9 @@ class CuratedLocationPage extends HookConsumerWidget {
icon: const Icon(Icons.arrow_back_ios_rounded),
),
),
body: curatedLocation.widgetWhen(
onData: (curatedLocations) => ExploreGrid(
curatedContent: curatedLocations
.map(
(l) => CuratedContent(
label: l.city,
id: l.id,
),
)
.toList(),
body: places.widgetWhen(
onData: (data) => ExploreGrid(
curatedContent: data,
),
),
);

View File

@ -27,7 +27,7 @@ class SearchPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final curatedLocation = ref.watch(getCuratedLocationProvider);
final places = ref.watch(getPlacesProvider);
final curatedPeople = ref.watch(getAllPeopleProvider);
final isMapEnabled =
ref.watch(serverInfoProvider.select((v) => v.serverFeatures.map));
@ -87,18 +87,11 @@ class SearchPage extends HookConsumerWidget {
buildPlaces() {
return SizedBox(
height: imageSize,
child: curatedLocation.widgetWhen(
child: places.widgetWhen(
onError: (error, stack) => const ScaffoldErrorBody(withIcon: false),
onData: (locations) => CuratedPlacesRow(
onData: (data) => CuratedPlacesRow(
isMapEnabled: isMapEnabled,
content: locations
.map(
(o) => CuratedContent(
id: o.id,
label: o.city,
),
)
.toList(),
content: data,
imageSize: imageSize,
onTap: (content, index) {
context.pushRoute(

View File

@ -37,7 +37,7 @@ class TabNavigationObserver extends AutoRouterObserver {
// Perform tasks on re-visit to SearchRoute
if (route.name == 'SearchRoute') {
// Refresh Location State
ref.invalidate(getCuratedLocationProvider);
ref.invalidate(getPlacesProvider);
ref.invalidate(getAllPeopleProvider);
}