mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
refactor: implement suggestions
This commit is contained in:
@@ -27,19 +27,20 @@ class DriftMapRepository extends DriftDatabaseRepository {
|
|||||||
condition = condition & _db.remoteAssetEntity.isFavorite.equals(true);
|
condition = condition & _db.remoteAssetEntity.isFavorite.equals(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final from = options.timeRange.from;
|
final timeRange = options.timeRange;
|
||||||
final to = options.timeRange.to;
|
final hasCustomRange = timeRange.from.isSome || timeRange.to.isSome;
|
||||||
|
|
||||||
if (from != null || to != null) {
|
if (hasCustomRange) {
|
||||||
if (from != null) {
|
timeRange.from.ifSome((from) {
|
||||||
condition = condition & _db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(from);
|
condition = condition & _db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(from);
|
||||||
}
|
});
|
||||||
if (to != null) {
|
|
||||||
|
timeRange.to.ifSome((to) {
|
||||||
condition = condition & _db.remoteAssetEntity.createdAt.isSmallerOrEqualValue(to);
|
condition = condition & _db.remoteAssetEntity.createdAt.isSmallerOrEqualValue(to);
|
||||||
}
|
});
|
||||||
} else if (options.relativeDays > 0) {
|
} else if (options.relativeDays > 0) {
|
||||||
final fromDate = DateTime.now().subtract(Duration(days: options.relativeDays));
|
final cutoffDate = DateTime.now().toUtc().subtract(Duration(days: options.relativeDays));
|
||||||
condition = condition & _db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(fromDate);
|
condition = condition & _db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(cutoffDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
return condition;
|
return condition;
|
||||||
|
|||||||
@@ -552,20 +552,21 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
|||||||
query.where(_db.remoteAssetEntity.isFavorite.equals(true));
|
query.where(_db.remoteAssetEntity.isFavorite.equals(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
final from = options.timeRange.from;
|
final timeRange = options.timeRange;
|
||||||
final to = options.timeRange.to;
|
|
||||||
|
|
||||||
if (from != null || to != null) {
|
final hasCustomRange = timeRange.from.isSome || timeRange.to.isSome;
|
||||||
// Use custom from/to filters
|
|
||||||
if (from != null) {
|
if (hasCustomRange) {
|
||||||
|
timeRange.from.ifSome((from) {
|
||||||
query.where(_db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(from));
|
query.where(_db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(from));
|
||||||
}
|
});
|
||||||
if (to != null) {
|
|
||||||
|
timeRange.to.ifSome((to) {
|
||||||
query.where(_db.remoteAssetEntity.createdAt.isSmallerOrEqualValue(to));
|
query.where(_db.remoteAssetEntity.createdAt.isSmallerOrEqualValue(to));
|
||||||
}
|
});
|
||||||
} else if (options.relativeDays > 0) {
|
} else if (options.relativeDays > 0) {
|
||||||
// Use relative days
|
|
||||||
final cutoffDate = DateTime.now().toUtc().subtract(Duration(days: options.relativeDays));
|
final cutoffDate = DateTime.now().toUtc().subtract(Duration(days: options.relativeDays));
|
||||||
|
|
||||||
query.where(_db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(cutoffDate));
|
query.where(_db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(cutoffDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -606,20 +607,21 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
|||||||
query.where(_db.remoteAssetEntity.isFavorite.equals(true));
|
query.where(_db.remoteAssetEntity.isFavorite.equals(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
final from = options.timeRange.from;
|
final timeRange = options.timeRange;
|
||||||
final to = options.timeRange.to;
|
|
||||||
|
|
||||||
if (from != null || to != null) {
|
final hasCustomRange = timeRange.from.isSome || timeRange.to.isSome;
|
||||||
// Use custom from/to filters
|
|
||||||
if (from != null) {
|
if (hasCustomRange) {
|
||||||
|
timeRange.from.ifSome((from) {
|
||||||
query.where(_db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(from));
|
query.where(_db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(from));
|
||||||
}
|
});
|
||||||
if (to != null) {
|
|
||||||
|
timeRange.to.ifSome((to) {
|
||||||
query.where(_db.remoteAssetEntity.createdAt.isSmallerOrEqualValue(to));
|
query.where(_db.remoteAssetEntity.createdAt.isSmallerOrEqualValue(to));
|
||||||
}
|
});
|
||||||
} else if (options.relativeDays > 0) {
|
} else if (options.relativeDays > 0) {
|
||||||
// Use relative days
|
|
||||||
final cutoffDate = DateTime.now().toUtc().subtract(Duration(days: options.relativeDays));
|
final cutoffDate = DateTime.now().toUtc().subtract(Duration(days: options.relativeDays));
|
||||||
|
|
||||||
query.where(_db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(cutoffDate));
|
query.where(_db.remoteAssetEntity.createdAt.isBiggerOrEqualValue(cutoffDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,15 +7,16 @@ import 'package:immich_mobile/providers/app_settings.provider.dart';
|
|||||||
import 'package:immich_mobile/providers/infrastructure/map.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/map.provider.dart';
|
||||||
import 'package:immich_mobile/providers/map/map_state.provider.dart';
|
import 'package:immich_mobile/providers/map/map_state.provider.dart';
|
||||||
import 'package:immich_mobile/services/app_settings.service.dart';
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
|
import 'package:immich_mobile/utils/option.dart';
|
||||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||||
|
|
||||||
class TimeRange {
|
class TimeRange {
|
||||||
final DateTime? from;
|
final Option<DateTime> from;
|
||||||
final DateTime? to;
|
final Option<DateTime> to;
|
||||||
|
|
||||||
const TimeRange({this.from, this.to});
|
const TimeRange({this.from = const None(), this.to = const None()});
|
||||||
|
|
||||||
TimeRange copyWith({DateTime? from, DateTime? to}) {
|
TimeRange copyWith({Option<DateTime>? from, Option<DateTime>? to}) {
|
||||||
return TimeRange(from: from ?? this.from, to: to ?? this.to);
|
return TimeRange(from: from ?? this.from, to: to ?? this.to);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +76,7 @@ class MapState {
|
|||||||
onlyFavorites: onlyFavorites,
|
onlyFavorites: onlyFavorites,
|
||||||
includeArchived: includeArchived,
|
includeArchived: includeArchived,
|
||||||
withPartners: withPartners,
|
withPartners: withPartners,
|
||||||
|
relativeDays: relativeDays,
|
||||||
timeRange: timeRange,
|
timeRange: timeRange,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -123,31 +125,40 @@ class MapStateNotifier extends Notifier<MapState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setTimeRange(TimeRange range) {
|
void setTimeRange(TimeRange range) {
|
||||||
ref
|
final from = range.from.unwrapOrNull;
|
||||||
.read(appSettingsServiceProvider)
|
final to = range.to.unwrapOrNull;
|
||||||
.setSetting(AppSettingsEnum.mapCustomFrom, range.from == null ? "" : range.from!.toIso8601String());
|
|
||||||
ref
|
ref.read(appSettingsServiceProvider).setSetting(AppSettingsEnum.mapCustomFrom, from?.toIso8601String() ?? "");
|
||||||
.read(appSettingsServiceProvider)
|
ref.read(appSettingsServiceProvider).setSetting(AppSettingsEnum.mapCustomTo, to?.toIso8601String() ?? "");
|
||||||
.setSetting(AppSettingsEnum.mapCustomTo, range.to == null ? "" : range.to!.toIso8601String());
|
|
||||||
state = state.copyWith(timeRange: range);
|
state = state.copyWith(timeRange: range);
|
||||||
EventStream.shared.emit(const MapMarkerReloadEvent());
|
EventStream.shared.emit(const MapMarkerReloadEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Option<DateTime> parseDateOption(String s) {
|
||||||
|
try {
|
||||||
|
if (s.trim().isEmpty) return const Option.none();
|
||||||
|
return Option.some(DateTime.parse(s));
|
||||||
|
} catch (_) {
|
||||||
|
return const Option.none();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MapState build() {
|
MapState build() {
|
||||||
final appSettingsService = ref.read(appSettingsServiceProvider);
|
final appSettingsService = ref.read(appSettingsServiceProvider);
|
||||||
final customFrom = appSettingsService.getSetting(AppSettingsEnum.mapCustomFrom);
|
|
||||||
final customTo = appSettingsService.getSetting(AppSettingsEnum.mapCustomTo);
|
final customFrom = appSettingsService.getSetting(AppSettingsEnum.mapCustomFrom).toOption().flatMap(parseDateOption);
|
||||||
|
final customTo = appSettingsService.getSetting(AppSettingsEnum.mapCustomTo).toOption().flatMap(parseDateOption);
|
||||||
|
|
||||||
return MapState(
|
return MapState(
|
||||||
themeMode: ThemeMode.values[appSettingsService.getSetting(AppSettingsEnum.mapThemeMode)],
|
themeMode: ThemeMode.values[appSettingsService.getSetting(AppSettingsEnum.mapThemeMode)],
|
||||||
onlyFavorites: appSettingsService.getSetting(AppSettingsEnum.mapShowFavoriteOnly),
|
onlyFavorites: appSettingsService.getSetting(AppSettingsEnum.mapShowFavoriteOnly),
|
||||||
includeArchived: appSettingsService.getSetting(AppSettingsEnum.mapIncludeArchived),
|
includeArchived: appSettingsService.getSetting(AppSettingsEnum.mapIncludeArchived),
|
||||||
withPartners: appSettingsService.getSetting(AppSettingsEnum.mapwithPartners),
|
withPartners: appSettingsService.getSetting(AppSettingsEnum.mapwithPartners),
|
||||||
bounds: LatLngBounds(northeast: const LatLng(0, 0), southwest: const LatLng(0, 0)),
|
bounds: LatLngBounds(northeast: const LatLng(0, 0), southwest: const LatLng(0, 0)),
|
||||||
timeRange: TimeRange(
|
relativeDays: appSettingsService.getSetting(AppSettingsEnum.mapRelativeDate),
|
||||||
from: customFrom.isNotEmpty ? DateTime.parse(customFrom) : null,
|
timeRange: TimeRange(from: customFrom, to: customTo),
|
||||||
to: customTo.isNotEmpty ? DateTime.parse(customTo) : null,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
|
import 'package:immich_mobile/generated/translations.g.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/map/map.state.dart';
|
import 'package:immich_mobile/presentation/widgets/map/map.state.dart';
|
||||||
import 'package:immich_mobile/widgets/map/map_settings/map_custom_time_range.dart';
|
import 'package:immich_mobile/widgets/map/map_settings/map_custom_time_range.dart';
|
||||||
import 'package:immich_mobile/widgets/map/map_settings/map_settings_list_tile.dart';
|
import 'package:immich_mobile/widgets/map/map_settings/map_settings_list_tile.dart';
|
||||||
@@ -22,7 +23,7 @@ class _DriftMapSettingsSheetState extends ConsumerState<DriftMapSettingsSheet> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
final mapState = ref.read(mapStateProvider);
|
final mapState = ref.read(mapStateProvider);
|
||||||
final timeRange = mapState.timeRange;
|
final timeRange = mapState.timeRange;
|
||||||
useCustomRange = timeRange.from != null || timeRange.to != null;
|
useCustomRange = timeRange.from.isSome || timeRange.to.isSome;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -78,7 +79,7 @@ class _DriftMapSettingsSheetState extends ConsumerState<DriftMapSettingsSheet> {
|
|||||||
ref.read(mapStateProvider.notifier).setRelativeTime(0);
|
ref.read(mapStateProvider.notifier).setRelativeTime(0);
|
||||||
ref.read(mapStateProvider.notifier).setTimeRange(const TimeRange());
|
ref.read(mapStateProvider.notifier).setTimeRange(const TimeRange());
|
||||||
}),
|
}),
|
||||||
child: Text("remove_custom_date_range".t(context: context)),
|
child: Text(context.t.remove_custom_date_range),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
] else ...[
|
] else ...[
|
||||||
@@ -94,7 +95,7 @@ class _DriftMapSettingsSheetState extends ConsumerState<DriftMapSettingsSheet> {
|
|||||||
ref.read(mapStateProvider.notifier).setRelativeTime(0);
|
ref.read(mapStateProvider.notifier).setRelativeTime(0);
|
||||||
ref.read(mapStateProvider.notifier).setTimeRange(const TimeRange());
|
ref.read(mapStateProvider.notifier).setTimeRange(const TimeRange());
|
||||||
}),
|
}),
|
||||||
child: Text("use_custom_date_range".t(context: context)),
|
child: Text(context.t.use_custom_date_range),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -24,6 +24,21 @@ sealed class Option<T> {
|
|||||||
None() => onNone(),
|
None() => onNone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Option<U> flatMap<U>(Option<U> Function(T value) f) => switch (this) {
|
||||||
|
Some(:final value) => f(value),
|
||||||
|
None() => const Option.none(),
|
||||||
|
};
|
||||||
|
|
||||||
|
void ifSome(void Function(T value) action) {
|
||||||
|
switch (this) {
|
||||||
|
case Some(:final value):
|
||||||
|
action(value);
|
||||||
|
break;
|
||||||
|
case None():
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => switch (this) {
|
String toString() => switch (this) {
|
||||||
Some(:final value) => 'Some($value)',
|
Some(:final value) => 'Some($value)',
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/generated/translations.g.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/map/map.state.dart';
|
import 'package:immich_mobile/presentation/widgets/map/map.state.dart';
|
||||||
|
import 'package:immich_mobile/utils/option.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
class MapTimeRange extends StatelessWidget {
|
class MapTimeRange extends StatelessWidget {
|
||||||
@@ -15,44 +17,49 @@ class MapTimeRange extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text("date_after".t(context: context)),
|
title: Text(context.t.date_after),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
timeRange.from != null
|
timeRange.from.fold((from) => DateFormat.yMMMd().add_jm().format(from), () => context.t.not_set),
|
||||||
? DateFormat.yMMMd().add_jm().format(timeRange.from!)
|
|
||||||
: "not_set".t(context: context),
|
|
||||||
),
|
),
|
||||||
trailing: timeRange.from != null
|
trailing: timeRange.from.isSome
|
||||||
? IconButton(icon: const Icon(Icons.close), onPressed: () => onChanged(timeRange.clearFrom()))
|
? IconButton(icon: const Icon(Icons.close), onPressed: () => onChanged(timeRange.clearFrom()))
|
||||||
: null,
|
: null,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
final initial = timeRange.from.unwrapOrNull ?? DateTime.now();
|
||||||
|
|
||||||
final picked = await showDatePicker(
|
final picked = await showDatePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialDate: timeRange.from ?? DateTime.now(),
|
initialDate: initial,
|
||||||
firstDate: DateTime(1970),
|
firstDate: DateTime(1970),
|
||||||
lastDate: DateTime.now(),
|
lastDate: DateTime.now(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (picked != null) {
|
if (picked != null) {
|
||||||
onChanged(timeRange.copyWith(from: picked));
|
onChanged(timeRange.copyWith(from: Option.some(picked)));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text("date_before".t(context: context)),
|
title: Text(context.t.date_before),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
timeRange.to != null ? DateFormat.yMMMd().add_jm().format(timeRange.to!) : "not_set".t(context: context),
|
timeRange.to.fold<String>((to) => DateFormat.yMMMd().add_jm().format(to), () => context.t.not_set),
|
||||||
),
|
),
|
||||||
trailing: timeRange.to != null
|
trailing: timeRange.to.isSome
|
||||||
? IconButton(icon: const Icon(Icons.close), onPressed: () => onChanged(timeRange.clearTo()))
|
? IconButton(icon: const Icon(Icons.close), onPressed: () => onChanged(timeRange.clearTo()))
|
||||||
: null,
|
: null,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
final initial = timeRange.to.unwrapOrNull ?? DateTime.now();
|
||||||
|
|
||||||
final picked = await showDatePicker(
|
final picked = await showDatePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialDate: timeRange.to ?? DateTime.now(),
|
initialDate: initial,
|
||||||
firstDate: DateTime(1970),
|
firstDate: DateTime(1970),
|
||||||
lastDate: DateTime.now(),
|
lastDate: DateTime.now(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (picked != null) {
|
if (picked != null) {
|
||||||
onChanged(timeRange.copyWith(to: picked));
|
onChanged(timeRange.copyWith(to: Option.some(picked)));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user