import 'dart:collection'; import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; final class Landmark extends LinkedListEntry{ // A linked node of a list of Landmarks final String uuid; final String name; final List location; final LandmarkType type; final bool? isSecondary; // description to be shown in the overview final String? imageURL; final String? description; final Duration? duration; final bool? visited; // Next node // final Landmark? next; final Duration? tripTime; Landmark({ required this.uuid, required this.name, required this.location, required this.type, this.isSecondary, this.imageURL, this.description, this.duration, this.visited, // this.next, this.tripTime, }); factory Landmark.fromJson(Map 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 location, 'type': String type, }) { // refine the parsing on a few List locationFixed = List.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'); } } @override bool operator ==(Object other) { return other is Landmark && uuid == other.uuid; } Map toJson() => { 'uuid': uuid, 'name': name, 'location': location, 'type': type.name, 'is_secondary': isSecondary, 'image_url': imageURL, 'description': description, 'duration': duration?.inMinutes, 'visited': visited }; } class LandmarkType { final String name; // final String description; // final Icon icon; const LandmarkType({ required this.name, // required this.description, // required this.icon, }); } // 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 json = jsonDecode(content!); String? nextUUID = json['next_uuid']; return (Landmark.fromJson(json), nextUUID); } void landmarkToPrefs(SharedPreferences prefs, Landmark current, Landmark? next) { Map json = current.toJson(); json['next_uuid'] = next?.uuid; prefs.setString('landmark_${current.uuid}', jsonEncode(json)); }