feat(mobile): hide search by context/OCR if disabled on server (#25472) (#26063)

* feat(mobile): hide search by context/OCR if disabled on server (#25472)

* revert(mobile): remove changes to old search page

---------

Co-authored-by: Nicolas <nicolasroy@MacBookPro>
This commit is contained in:
Nicolas
2026-02-16 03:41:56 +01:00
committed by GitHub
parent f6e10afe2b
commit c9dd8e0a79
2 changed files with 49 additions and 21 deletions

View File

@@ -6,6 +6,7 @@ class ServerFeatures {
final bool oauthEnabled; final bool oauthEnabled;
final bool passwordLogin; final bool passwordLogin;
final bool ocr; final bool ocr;
final bool smartSearch;
const ServerFeatures({ const ServerFeatures({
required this.trash, required this.trash,
@@ -13,21 +14,30 @@ class ServerFeatures {
required this.oauthEnabled, required this.oauthEnabled,
required this.passwordLogin, required this.passwordLogin,
this.ocr = false, this.ocr = false,
this.smartSearch = false,
}); });
ServerFeatures copyWith({bool? trash, bool? map, bool? oauthEnabled, bool? passwordLogin, bool? ocr}) { ServerFeatures copyWith({
bool? trash,
bool? map,
bool? oauthEnabled,
bool? passwordLogin,
bool? ocr,
bool? smartSearch,
}) {
return ServerFeatures( return ServerFeatures(
trash: trash ?? this.trash, trash: trash ?? this.trash,
map: map ?? this.map, map: map ?? this.map,
oauthEnabled: oauthEnabled ?? this.oauthEnabled, oauthEnabled: oauthEnabled ?? this.oauthEnabled,
passwordLogin: passwordLogin ?? this.passwordLogin, passwordLogin: passwordLogin ?? this.passwordLogin,
ocr: ocr ?? this.ocr, ocr: ocr ?? this.ocr,
smartSearch: smartSearch ?? this.smartSearch,
); );
} }
@override @override
String toString() { String toString() {
return 'ServerFeatures(trash: $trash, map: $map, oauthEnabled: $oauthEnabled, passwordLogin: $passwordLogin, ocr: $ocr)'; return 'ServerFeatures(trash: $trash, map: $map, oauthEnabled: $oauthEnabled, passwordLogin: $passwordLogin, ocr: $ocr, smartSearch: $smartSearch)';
} }
ServerFeatures.fromDto(ServerFeaturesDto dto) ServerFeatures.fromDto(ServerFeaturesDto dto)
@@ -35,7 +45,8 @@ class ServerFeatures {
map = dto.map, map = dto.map,
oauthEnabled = dto.oauth, oauthEnabled = dto.oauth,
passwordLogin = dto.passwordLogin, passwordLogin = dto.passwordLogin,
ocr = dto.ocr; ocr = dto.ocr,
smartSearch = dto.smartSearch;
@override @override
bool operator ==(covariant ServerFeatures other) { bool operator ==(covariant ServerFeatures other) {
@@ -45,11 +56,17 @@ class ServerFeatures {
other.map == map && other.map == map &&
other.oauthEnabled == oauthEnabled && other.oauthEnabled == oauthEnabled &&
other.passwordLogin == passwordLogin && other.passwordLogin == passwordLogin &&
other.ocr == ocr; other.ocr == ocr &&
other.smartSearch == smartSearch;
} }
@override @override
int get hashCode { int get hashCode {
return trash.hashCode ^ map.hashCode ^ oauthEnabled.hashCode ^ passwordLogin.hashCode ^ ocr.hashCode; return trash.hashCode ^
map.hashCode ^
oauthEnabled.hashCode ^
passwordLogin.hashCode ^
ocr.hashCode ^
smartSearch.hashCode;
} }
} }

View File

@@ -20,6 +20,7 @@ import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/providers/infrastructure/user_metadata.provider.dart'; import 'package:immich_mobile/providers/infrastructure/user_metadata.provider.dart';
import 'package:immich_mobile/providers/search/search_input_focus.provider.dart'; import 'package:immich_mobile/providers/search/search_input_focus.provider.dart';
import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/widgets/common/feature_check.dart'; import 'package:immich_mobile/widgets/common/feature_check.dart';
import 'package:immich_mobile/widgets/common/search_field.dart'; import 'package:immich_mobile/widgets/common/search_field.dart';
@@ -39,8 +40,15 @@ class DriftSearchPage extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final textSearchType = useState<TextSearchType>(TextSearchType.context); final serverFeatures = ref.watch(serverInfoProvider.select((v) => v.serverFeatures));
final searchHintText = useState<String>('sunrise_on_the_beach'.t(context: context)); final textSearchType = useState<TextSearchType>(
serverFeatures.smartSearch ? TextSearchType.context : TextSearchType.filename,
);
final searchHintText = useState<String>(
serverFeatures.smartSearch
? 'sunrise_on_the_beach'.t(context: context)
: 'file_name_or_extension'.t(context: context),
);
final textSearchController = useTextEditingController(); final textSearchController = useTextEditingController();
final preFilter = ref.watch(searchPreFilterProvider); final preFilter = ref.watch(searchPreFilterProvider);
final filter = useState<SearchFilter>( final filter = useState<SearchFilter>(
@@ -518,23 +526,26 @@ class DriftSearchPage extends HookConsumerWidget {
); );
}, },
menuChildren: [ menuChildren: [
MenuItemButton( FeatureCheck(
child: ListTile( feature: (features) => features.smartSearch,
leading: const Icon(Icons.image_search_rounded), child: MenuItemButton(
title: Text( child: ListTile(
'search_by_context'.t(context: context), leading: const Icon(Icons.image_search_rounded),
style: context.textTheme.bodyLarge?.copyWith( title: Text(
fontWeight: FontWeight.w500, 'search_by_context'.t(context: context),
color: textSearchType.value == TextSearchType.context ? context.colorScheme.primary : null, style: context.textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.w500,
color: textSearchType.value == TextSearchType.context ? context.colorScheme.primary : null,
),
), ),
selectedColor: context.colorScheme.primary,
selected: textSearchType.value == TextSearchType.context,
), ),
selectedColor: context.colorScheme.primary, onPressed: () {
selected: textSearchType.value == TextSearchType.context, textSearchType.value = TextSearchType.context;
searchHintText.value = 'sunrise_on_the_beach'.t(context: context);
},
), ),
onPressed: () {
textSearchType.value = TextSearchType.context;
searchHintText.value = 'sunrise_on_the_beach'.t(context: context);
},
), ),
MenuItemButton( MenuItemButton(
child: ListTile( child: ListTile(