feat(wip): implement trip persistence through a local repository. Include loaded trips in the start page UI
This commit is contained in:
@@ -1,16 +1,86 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:anyway/domain/entities/preferences.dart';
|
||||
import 'package:anyway/domain/entities/trip.dart';
|
||||
import 'package:anyway/domain/repositories/trip_repository.dart';
|
||||
import 'package:anyway/presentation/providers/landmark_providers.dart';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:anyway/presentation/providers/core_providers.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
// Provides a function that creates a trip given preferences.
|
||||
final createTripProvider = Provider<Future<Trip> Function(Preferences)>((ref) {
|
||||
return (Preferences prefs) async {
|
||||
final repo = ref.read(tripRepositoryProvider);
|
||||
final landmarks = await repo.searchLandmarks(prefs);
|
||||
ref.read(intermediateLandmarksProvider.notifier).setLandmarks(landmarks);
|
||||
return repo.getTrip(preferences: prefs, landmarks: landmarks);
|
||||
};
|
||||
return (Preferences prefs) async {
|
||||
final repo = ref.read(tripRepositoryProvider);
|
||||
final landmarks = await repo.searchLandmarks(prefs);
|
||||
ref.read(intermediateLandmarksProvider.notifier).setLandmarks(landmarks);
|
||||
final trip = await repo.getTrip(preferences: prefs, landmarks: landmarks);
|
||||
await ref.read(currentTripsProvider.notifier).saveTrip(trip);
|
||||
return trip;
|
||||
};
|
||||
});
|
||||
|
||||
class CurrentTripsNotifier extends AsyncNotifier<List<Trip>> {
|
||||
TripRepository get _repository => ref.read(tripRepositoryProvider);
|
||||
Future<List<Trip>>? _pendingLoad;
|
||||
|
||||
List<Trip> _currentTrips() => state.asData?.value ?? const <Trip>[];
|
||||
|
||||
@override
|
||||
Future<List<Trip>> build() async {
|
||||
final load = _repository.getSavedTrips();
|
||||
_pendingLoad = load;
|
||||
try {
|
||||
final trips = await load;
|
||||
return List.unmodifiable(trips);
|
||||
} finally {
|
||||
if (identical(_pendingLoad, load)) {
|
||||
_pendingLoad = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> refresh() async {
|
||||
state = const AsyncValue.loading();
|
||||
final load = _repository.getSavedTrips();
|
||||
_pendingLoad = load;
|
||||
state = await AsyncValue.guard(() async {
|
||||
final trips = await load;
|
||||
return List.unmodifiable(trips);
|
||||
});
|
||||
if (identical(_pendingLoad, load)) {
|
||||
_pendingLoad = null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> saveTrip(Trip trip) async {
|
||||
final previous = state;
|
||||
final updatedTrips = [..._currentTrips()]
|
||||
..removeWhere((t) => t.uuid == trip.uuid)
|
||||
..insert(0, trip);
|
||||
state = AsyncValue.data(List.unmodifiable(updatedTrips));
|
||||
|
||||
try {
|
||||
await _repository.saveTrip(trip);
|
||||
} catch (error) {
|
||||
state = previous;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteTrip(String uuid) async {
|
||||
final previous = state;
|
||||
final updatedTrips = _currentTrips()
|
||||
.where((trip) => trip.uuid != uuid)
|
||||
.toList(growable: false);
|
||||
state = AsyncValue.data(List.unmodifiable(updatedTrips));
|
||||
|
||||
try {
|
||||
await _repository.deleteSavedTrip(uuid);
|
||||
} catch (error) {
|
||||
state = previous;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final currentTripsProvider = AsyncNotifierProvider<CurrentTripsNotifier, List<Trip>>(CurrentTripsNotifier.new);
|
||||
|
||||
Reference in New Issue
Block a user