mirror of
https://github.com/immich-app/immich
synced 2026-08-22 13:13:05 +00:00
Rewrote map options notifier to be more Riverpody
This commit is contained in:
parent
758259cfd6
commit
292adc5ae2
8 changed files with 41 additions and 43 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:immich_mobile/domain/models/time_range.model.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
|
||||
part 'map.model.freezed.dart';
|
||||
|
|
@ -7,3 +8,17 @@ part 'map.model.freezed.dart';
|
|||
abstract class Marker with _$Marker {
|
||||
const factory Marker({required LatLng location, required String assetId}) = _Marker;
|
||||
}
|
||||
|
||||
@Freezed(fromJson: false, toJson: false)
|
||||
abstract class TimelineMapOptions with _$TimelineMapOptions {
|
||||
const factory TimelineMapOptions({
|
||||
required LatLngBounds bounds,
|
||||
|
||||
@Default(false) bool onlyFavorites,
|
||||
@Default(false) bool includeArchived,
|
||||
@Default(false) bool withPartners,
|
||||
@Default(0) int relativeDays,
|
||||
|
||||
@Default(TimeRange()) TimeRange timeRange,
|
||||
}) = _TimelineMapOptions;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:immich_mobile/utils/option.dart';
|
||||
|
||||
class TimeRange {
|
||||
final DateTime? from;
|
||||
final DateTime? to;
|
||||
part 'time_range.model.freezed.dart';
|
||||
|
||||
const TimeRange({this.from, this.to});
|
||||
// copyWith is hand-written so that fields can be cleared via optionals
|
||||
@Freezed(copyWith: false, fromJson: false, toJson: false)
|
||||
abstract class TimeRange with _$TimeRange {
|
||||
const TimeRange._();
|
||||
|
||||
const factory TimeRange({DateTime? from, DateTime? to}) = _TimeRange;
|
||||
|
||||
TimeRange copyWith({Option<DateTime>? from, Option<DateTime>? to}) {
|
||||
return TimeRange(from: from.patch(this.from), to: to.patch(this.to));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:immich_mobile/domain/models/map.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/map.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
|
||||
typedef MapMarkerSource = Future<List<Marker>> Function(LatLngBounds? bounds);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:collection/collection.dart';
|
|||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/events.model.dart';
|
||||
import 'package:immich_mobile/domain/models/map.model.dart';
|
||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart';
|
|||
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/map.repository.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
|
||||
@DriftAccessor()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import 'package:drift/drift.dart';
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/time_range.model.dart';
|
||||
import 'package:immich_mobile/domain/models/map.model.dart';
|
||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
||||
|
|
@ -13,27 +13,8 @@ import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.
|
|||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/map.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.drift.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
import 'package:stream_transform/stream_transform.dart';
|
||||
|
||||
class TimelineMapOptions {
|
||||
final LatLngBounds bounds;
|
||||
final bool onlyFavorites;
|
||||
final bool includeArchived;
|
||||
final bool withPartners;
|
||||
final int relativeDays;
|
||||
final TimeRange timeRange;
|
||||
|
||||
const TimelineMapOptions({
|
||||
required this.bounds,
|
||||
this.onlyFavorites = false,
|
||||
this.includeArchived = false,
|
||||
this.withPartners = false,
|
||||
this.relativeDays = 0,
|
||||
this.timeRange = const TimeRange(),
|
||||
});
|
||||
}
|
||||
|
||||
@DriftAccessor()
|
||||
class TimelineRepository extends DatabaseAccessor<Drift> with $TimelineRepositoryMixin {
|
||||
TimelineRepository(super.attachedDatabase);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/map.model.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart';
|
||||
|
|
@ -46,14 +49,21 @@ class _ScopedMapTimeline extends StatelessWidget {
|
|||
final withPartners = ref.watch(mapStateProvider.select((s) => s.withPartners));
|
||||
final users = withPartners ? ref.watch(timelineUsersProvider).valueOrNull ?? [user.id] : [user.id];
|
||||
|
||||
final optionsController = StreamController<TimelineMapOptions>.broadcast();
|
||||
ref.onDispose(optionsController.close);
|
||||
|
||||
var currentOptions = ref.read(mapStateProvider).toOptions();
|
||||
|
||||
ref.listen(mapStateProvider.select((state) => state.toOptions()), (_, newOptions) {
|
||||
currentOptions = newOptions;
|
||||
optionsController.add(newOptions);
|
||||
});
|
||||
|
||||
final timelineService = ref
|
||||
.watch(timelineFactoryProvider)
|
||||
.geographicMap(
|
||||
users,
|
||||
() => ref.read(mapStateProvider).toOptions(),
|
||||
ref.read(mapStateProvider.notifier).optionsStream,
|
||||
);
|
||||
.geographicMap(users, () => currentOptions, optionsController.stream);
|
||||
ref.onDispose(timelineService.dispose);
|
||||
|
||||
return timelineService;
|
||||
}),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/events.model.dart';
|
||||
import 'package:immich_mobile/domain/models/map.model.dart';
|
||||
import 'package:immich_mobile/domain/models/time_range.model.dart';
|
||||
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/map.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
||||
import 'package:immich_mobile/providers/map/map_state.provider.dart';
|
||||
|
|
@ -72,17 +72,11 @@ class MapState {
|
|||
class MapStateNotifier extends Notifier<MapState> {
|
||||
MapStateNotifier();
|
||||
|
||||
final StreamController<TimelineMapOptions> _optionsController = StreamController.broadcast();
|
||||
|
||||
// ignore: avoid-public-notifier-properties
|
||||
Stream<TimelineMapOptions> get optionsStream => _optionsController.stream;
|
||||
|
||||
bool setBounds(LatLngBounds bounds) {
|
||||
if (state.bounds == bounds) {
|
||||
return false;
|
||||
}
|
||||
state = state.copyWith(bounds: bounds);
|
||||
_optionsController.add(state.toOptions());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -97,14 +91,12 @@ class MapStateNotifier extends Notifier<MapState> {
|
|||
void switchFavoriteOnly(bool isFavoriteOnly) {
|
||||
unawaited(ref.read(settingsProvider).write(.mapShowFavoriteOnly, isFavoriteOnly));
|
||||
state = state.copyWith(onlyFavorites: isFavoriteOnly);
|
||||
_optionsController.add(state.toOptions());
|
||||
EventStream.shared.emit(const MapMarkerReloadEvent());
|
||||
}
|
||||
|
||||
void switchIncludeArchived(bool isIncludeArchived) {
|
||||
unawaited(ref.read(settingsProvider).write(.mapIncludeArchived, isIncludeArchived));
|
||||
state = state.copyWith(includeArchived: isIncludeArchived);
|
||||
_optionsController.add(state.toOptions());
|
||||
EventStream.shared.emit(const MapMarkerReloadEvent());
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +109,6 @@ class MapStateNotifier extends Notifier<MapState> {
|
|||
void setRelativeTime(int relativeDays) {
|
||||
unawaited(ref.read(settingsProvider).write(.mapRelativeDate, relativeDays));
|
||||
state = state.copyWith(relativeDays: relativeDays);
|
||||
_optionsController.add(state.toOptions());
|
||||
EventStream.shared.emit(const MapMarkerReloadEvent());
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +116,6 @@ class MapStateNotifier extends Notifier<MapState> {
|
|||
unawaited(ref.read(settingsProvider).write(.mapCustomFrom, range.from));
|
||||
unawaited(ref.read(settingsProvider).write(.mapCustomTo, range.to));
|
||||
state = state.copyWith(timeRange: range);
|
||||
_optionsController.add(state.toOptions());
|
||||
EventStream.shared.emit(const MapMarkerReloadEvent());
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +132,6 @@ class MapStateNotifier extends Notifier<MapState> {
|
|||
|
||||
@override
|
||||
MapState build() {
|
||||
ref.onDispose(_optionsController.close);
|
||||
final mapConfig = ref.read(appConfigProvider.select((config) => config.map));
|
||||
return MapState(
|
||||
themeMode: mapConfig.themeMode,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue