working save and load functionality with custom datastructures
This commit is contained in:
		| @@ -21,6 +21,7 @@ final class Landmark extends LinkedListEntry<Landmark>{ | ||||
|   // final Landmark? next; | ||||
|   final Duration? tripTime; | ||||
|  | ||||
|  | ||||
|   Landmark({ | ||||
|     required this.uuid, | ||||
|     required this.name, | ||||
| @@ -37,23 +38,28 @@ final class Landmark extends LinkedListEntry<Landmark>{ | ||||
|     this.tripTime, | ||||
|   }); | ||||
|  | ||||
|  | ||||
|   factory Landmark.fromJson(Map<String, dynamic> json) { | ||||
|     if (json | ||||
|       case { // automatically match all the non-optionals and cast them to the right type | ||||
|         'uuid': String uuid, | ||||
|         'name': String name, | ||||
|         'location': List<double> location, | ||||
|         'type': LandmarkType type, | ||||
|         'location': List<dynamic> location, | ||||
|         'type': String type, | ||||
|       }) { | ||||
|         // parse the rest separately, they could be missing | ||||
|         final isSecondary = json['is_secondary'] as bool?; | ||||
|         final imageURL = json['image_url'] as String?; | ||||
|         final description = json['description'] as String?; | ||||
|         final duration = json['duration'] as Duration?; | ||||
|         final visited = json['visited'] as bool?; | ||||
|          | ||||
|         return Landmark( | ||||
|           uuid: uuid, name: name, location: location, type: type, isSecondary: isSecondary, imageURL: imageURL, description: description, duration: duration, visited: visited); | ||||
|       // refine the parsing on a few | ||||
|       List<double> locationFixed = List<double>.from(location); | ||||
|       // parse the rest separately, they could be missing | ||||
|       LandmarkType typeFixed = LandmarkType(name: type); | ||||
|       final isSecondary = json['is_secondary'] as bool?; | ||||
|       final imageURL = json['image_url'] as String?; | ||||
|       final description = json['description'] as String?; | ||||
|       var duration = Duration(minutes: json['duration'] ?? 0) as Duration?; | ||||
|       if (duration == const Duration()) {duration = null;}; | ||||
|       final visited = json['visited'] as bool?; | ||||
|        | ||||
|       return Landmark( | ||||
|         uuid: uuid, name: name, location: locationFixed, type: typeFixed, isSecondary: isSecondary, imageURL: imageURL, description: description, duration: duration, visited: visited); | ||||
|     } else { | ||||
|       throw FormatException('Invalid JSON: $json'); | ||||
|     } | ||||
| @@ -64,6 +70,19 @@ final class Landmark extends LinkedListEntry<Landmark>{ | ||||
|   bool operator ==(Object other) { | ||||
|     return other is Landmark && uuid == other.uuid; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   Map<String, dynamic> toJson() => { | ||||
|     'uuid': uuid, | ||||
|     'name': name, | ||||
|     'location': location, | ||||
|     'type': type.name, | ||||
|     'is_secondary': isSecondary, | ||||
|     'image_url': imageURL, | ||||
|     'description': description, | ||||
|     'duration': duration?.inMinutes, | ||||
|     'visited': visited | ||||
|   }; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -80,8 +99,8 @@ class LandmarkType { | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| // Helper | ||||
| // Helpers | ||||
| // Handling the landmarks requires a little bit of special care because the linked list is not directly representable in json | ||||
| (Landmark, String?) getLandmarkFromPrefs(SharedPreferences prefs, String uuid) { | ||||
|   String? content = prefs.getString('landmark_$uuid'); | ||||
|   Map<String, dynamic> json = jsonDecode(content!); | ||||
| @@ -89,3 +108,9 @@ class LandmarkType { | ||||
|   return (Landmark.fromJson(json), nextUUID); | ||||
| } | ||||
|  | ||||
|  | ||||
| void landmarkToPrefs(SharedPreferences prefs, Landmark current, Landmark? next) { | ||||
|   Map<String, dynamic> json = current.toJson(); | ||||
|   json['next_uuid'] = next?.uuid; | ||||
|   prefs.setString('landmark_${current.uuid}', jsonEncode(json)); | ||||
| } | ||||
|   | ||||
| @@ -14,36 +14,62 @@ class Trip { | ||||
|   final LinkedList<Landmark> landmarks; | ||||
|   // could be empty as well | ||||
|  | ||||
|  | ||||
|   Trip({ | ||||
|     required this.uuid, | ||||
|     required this.cityName, | ||||
|     required this.landmarks, | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|  | ||||
|   factory Trip.fromJson(Map<String, dynamic> json) { | ||||
|     return Trip( | ||||
|       uuid: json['uuid'], | ||||
|       cityName: json['cityName'], | ||||
|       cityName: json['city_name'], | ||||
|       landmarks: LinkedList() | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   factory Trip.fromPrefs(SharedPreferences prefs, String uuid) { | ||||
|     String? content = prefs.getString('trip_$uuid'); | ||||
|     Map<String, dynamic> json = jsonDecode(content!); | ||||
|     Trip trip = Trip.fromJson(json); | ||||
|     String? firstUUID = json['entry_uuid']; | ||||
|     appendLandmarks(trip.landmarks, prefs, firstUUID); | ||||
|     readLandmarks(trip.landmarks, prefs, firstUUID); | ||||
|     return trip; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   Map<String, dynamic> toJson() => { | ||||
|     'uuid': uuid, | ||||
|     'city_name': cityName, | ||||
|     'entry_uuid': landmarks.first?.uuid ?? '' | ||||
|   }; | ||||
|  | ||||
|  | ||||
|   void toPrefs(SharedPreferences prefs){ | ||||
|     Map<String, dynamic> json = toJson(); | ||||
|     prefs.setString('trip_$uuid', jsonEncode(json)); | ||||
|     for (Landmark landmark in landmarks) { | ||||
|       landmarkToPrefs(prefs, landmark, landmark.next); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| // Helper | ||||
|  | ||||
| appendLandmarks(LinkedList<Landmark> landmarks, SharedPreferences prefs, String? firstUUID) { | ||||
| // Helper | ||||
| readLandmarks(LinkedList<Landmark> landmarks, SharedPreferences prefs, String? firstUUID) { | ||||
|   while (firstUUID != null) { | ||||
|     var (head, nextUUID) = getLandmarkFromPrefs(prefs, firstUUID); | ||||
|     landmarks.add(head); | ||||
|     firstUUID = nextUUID; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void removeAllTripsFromPrefs () async { | ||||
|   SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||
|   prefs.clear(); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user