From c46ed27a36c692fa40e600ec4d161581a3d5d5bb Mon Sep 17 00:00:00 2001 From: Christian Fiebrig <fiebrig@bitidee.de> Date: Thu, 23 Jan 2025 09:33:36 +0100 Subject: [PATCH] apply door to use cache --- lib/app/services/converters.dart | 4 + .../converters/campaign_action_parsing.dart | 18 +- .../converters/door_create_model_parsing.dart | 23 ++ .../converters/door_update_model_parsing.dart | 21 ++ .../map_string_dynamic_converter.dart | 4 +- lib/app/services/converters/poi_parsing.dart | 1 + .../converters/poi_service_type_parsing.dart | 33 +++ .../poster_create_model_parsing.dart | 4 +- .../poster_update_model_parsing.dart | 2 +- .../gruene_api_campaigns_service.dart | 49 +---- lib/app/services/gruene_api_door_service.dart | 45 ++++ .../services/gruene_api_poster_service.dart | 10 + .../helper/campaign_action_cache.dart | 208 ++++++++++++++---- .../models/doors/door_create_model.dart | 10 + .../models/doors/door_detail_model.dart | 37 ++++ .../models/doors/door_update_model.dart | 24 +- .../models/flyer/flyer_detail_model.dart | 5 +- lib/features/campaigns/screens/door_edit.dart | 2 + .../campaigns/screens/doors_screen.dart | 31 ++- .../campaigns/screens/flyer_screen.dart | 9 +- .../campaigns/screens/map_consumer.dart | 19 +- .../campaigns/screens/posters_screen.dart | 29 +-- lib/main.dart | 6 +- 23 files changed, 443 insertions(+), 151 deletions(-) create mode 100644 lib/app/services/converters/door_create_model_parsing.dart create mode 100644 lib/app/services/converters/door_update_model_parsing.dart create mode 100644 lib/app/services/gruene_api_door_service.dart diff --git a/lib/app/services/converters.dart b/lib/app/services/converters.dart index 754e0682..c137a578 100644 --- a/lib/app/services/converters.dart +++ b/lib/app/services/converters.dart @@ -3,7 +3,9 @@ import 'dart:convert'; import 'package:gruene_app/app/services/enums.dart'; import 'package:gruene_app/app/services/nominatim_service.dart'; import 'package:gruene_app/features/campaigns/helper/campaign_action.dart'; +import 'package:gruene_app/features/campaigns/models/doors/door_create_model.dart'; import 'package:gruene_app/features/campaigns/models/doors/door_detail_model.dart'; +import 'package:gruene_app/features/campaigns/models/doors/door_update_model.dart'; import 'package:gruene_app/features/campaigns/models/flyer/flyer_detail_model.dart'; import 'package:gruene_app/features/campaigns/models/map_layer_model.dart'; import 'package:gruene_app/features/campaigns/models/marker_item_model.dart'; @@ -36,3 +38,5 @@ part 'converters/poster_update_model_parsing.dart'; part 'converters/campaign_action_parsing.dart'; part 'converters/map_string_dynamic_converter.dart'; part 'converters/string_extension.dart'; +part 'converters/door_update_model_parsing.dart'; +part 'converters/door_create_model_parsing.dart'; diff --git a/lib/app/services/converters/campaign_action_parsing.dart b/lib/app/services/converters/campaign_action_parsing.dart index 3e0a154e..727f6e20 100644 --- a/lib/app/services/converters/campaign_action_parsing.dart +++ b/lib/app/services/converters/campaign_action_parsing.dart @@ -14,8 +14,22 @@ extension CampaignActionParsing on CampaignAction { return model; } + DoorCreateModel getAsDoorCreate() { + var data = jsonDecode(serialized!) as Map<String, dynamic>; + var model = DoorCreateModel.fromJson(data.convertLatLongField()); + + return model; + } + + DoorUpdateModel getAsDoorUpdate() { + var data = jsonDecode(serialized!) as Map<String, dynamic>; + var model = DoorUpdateModel.fromJson(data.updateIdField(poiId!).convertLatLongField()); + + return model; + } + PosterListItemModel getPosterUpdateAsPosterListItem(DateTime originalCreatedAt) { - var updateModel = getAsPosterUpdate().transformToPosterDetailModel(poiId!); + var updateModel = getAsPosterUpdate().transformToPosterDetailModel(); return PosterListItemModel( id: updateModel.id, thumbnailUrl: updateModel.thumbnailUrl, @@ -30,7 +44,7 @@ extension CampaignActionParsing on CampaignAction { } PosterListItemModel getPosterCreateAsPosterListItem() { - var createModel = getAsPosterCreate().transformToPosterDetailModel(poiTempId); + var createModel = getAsPosterCreate().transformToPosterDetailModel(poiTempId.toString()); return PosterListItemModel( id: createModel.id, thumbnailUrl: createModel.thumbnailUrl, diff --git a/lib/app/services/converters/door_create_model_parsing.dart b/lib/app/services/converters/door_create_model_parsing.dart new file mode 100644 index 00000000..234e7367 --- /dev/null +++ b/lib/app/services/converters/door_create_model_parsing.dart @@ -0,0 +1,23 @@ +part of '../converters.dart'; + +extension DoorCreateModelParsing on DoorCreateModel { + DoorDetailModel transformToDoorDetailModel(String temporaryId) { + return DoorDetailModel( + id: temporaryId, + address: address, + closedDoors: closedDoors, + openedDoors: openedDoors, + location: location, + createdAt: '${DateTime.now().getAsLocalDateTimeString()}*', // should mark this as preliminary + isCached: true, + ); + } + + MarkerItemModel transformToVirtualMarkerItem(int temporaryId) { + return MarkerItemModel.virtual( + id: temporaryId, + status: PoiServiceType.door.name, + location: location, + ); + } +} diff --git a/lib/app/services/converters/door_update_model_parsing.dart b/lib/app/services/converters/door_update_model_parsing.dart new file mode 100644 index 00000000..c28ce7a5 --- /dev/null +++ b/lib/app/services/converters/door_update_model_parsing.dart @@ -0,0 +1,21 @@ +part of '../converters.dart'; + +extension DoorUpdateModelParsing on DoorUpdateModel { + DoorDetailModel transformToDoorDetailModel() { + var newDoorDetail = oldDoorDetail.copyWith( + address: address, + closedDoors: closedDoors, + openedDoors: openedDoors, + isCached: true, + ); + return newDoorDetail; + } + + MarkerItemModel transformToVirtualMarkerItem() { + return MarkerItemModel.virtual( + id: int.parse(id), + status: PoiServiceType.door.name, + location: location, + ); + } +} diff --git a/lib/app/services/converters/map_string_dynamic_converter.dart b/lib/app/services/converters/map_string_dynamic_converter.dart index 839286d9..7e40a2b9 100644 --- a/lib/app/services/converters/map_string_dynamic_converter.dart +++ b/lib/app/services/converters/map_string_dynamic_converter.dart @@ -2,7 +2,9 @@ part of '../converters.dart'; extension MapStringDynamicConverter on Map<String, dynamic> { Map<String, dynamic> convertLatLongField({String fieldName = 'location'}) { - this[fieldName] = (this[fieldName] as List<dynamic>).cast<double>(); + if (containsKey(fieldName) && this[fieldName] is List<dynamic>) { + this[fieldName] = (this[fieldName] as List<dynamic>).cast<double>().toList(); + } return this; } diff --git a/lib/app/services/converters/poi_parsing.dart b/lib/app/services/converters/poi_parsing.dart index 56b33fcb..6f8aafdc 100644 --- a/lib/app/services/converters/poi_parsing.dart +++ b/lib/app/services/converters/poi_parsing.dart @@ -22,6 +22,7 @@ extension PoiParsing on Poi { address: poi.address.transformToAddressModel(), openedDoors: poi.house!.countOpenedDoors.toInt(), closedDoors: poi.house!.countClosedDoors.toInt(), + location: poi.coords.transformToLatLng(), createdAt: poi.createdAt.getAsLocalDateTimeString(), ); } diff --git a/lib/app/services/converters/poi_service_type_parsing.dart b/lib/app/services/converters/poi_service_type_parsing.dart index 1fcc0cdb..233804b1 100644 --- a/lib/app/services/converters/poi_service_type_parsing.dart +++ b/lib/app/services/converters/poi_service_type_parsing.dart @@ -46,4 +46,37 @@ extension PoiServiceTypeParsing on PoiServiceType { return typeName; } } + + CampaignActionType getCacheDeleteAction() { + switch (this) { + case PoiServiceType.poster: + return CampaignActionType.deletePoster; + case PoiServiceType.door: + return CampaignActionType.deleteDoor; + case PoiServiceType.flyer: + return CampaignActionType.deleteFlyer; + } + } + + CampaignActionType getCacheEditAction() { + switch (this) { + case PoiServiceType.poster: + return CampaignActionType.editPoster; + case PoiServiceType.door: + return CampaignActionType.editDoor; + case PoiServiceType.flyer: + return CampaignActionType.editFlyer; + } + } + + CampaignActionType getCacheAddAction() { + switch (this) { + case PoiServiceType.poster: + return CampaignActionType.addPoster; + case PoiServiceType.door: + return CampaignActionType.addDoor; + case PoiServiceType.flyer: + return CampaignActionType.addFlyer; + } + } } diff --git a/lib/app/services/converters/poster_create_model_parsing.dart b/lib/app/services/converters/poster_create_model_parsing.dart index 7f2314a0..00e08c31 100644 --- a/lib/app/services/converters/poster_create_model_parsing.dart +++ b/lib/app/services/converters/poster_create_model_parsing.dart @@ -9,9 +9,9 @@ extension PosterCreateModelParsing on PosterCreateModel { ); } - PosterDetailModel transformToPosterDetailModel(int temporaryId) { + PosterDetailModel transformToPosterDetailModel(String temporaryId) { return PosterDetailModel( - id: temporaryId.toString(), + id: temporaryId, status: PosterStatus.ok, address: address, thumbnailUrl: imageFileLocation, diff --git a/lib/app/services/converters/poster_update_model_parsing.dart b/lib/app/services/converters/poster_update_model_parsing.dart index 83243e7b..95d5e866 100644 --- a/lib/app/services/converters/poster_update_model_parsing.dart +++ b/lib/app/services/converters/poster_update_model_parsing.dart @@ -9,7 +9,7 @@ extension PosterUpdateModelParsing on PosterUpdateModel { ); } - PosterDetailModel transformToPosterDetailModel(int temporaryId) { + PosterDetailModel transformToPosterDetailModel() { var newPosterDetail = oldPosterDetail.copyWith( status: status, address: address, diff --git a/lib/app/services/gruene_api_campaigns_service.dart b/lib/app/services/gruene_api_campaigns_service.dart index ddaa79c1..780227d9 100644 --- a/lib/app/services/gruene_api_campaigns_service.dart +++ b/lib/app/services/gruene_api_campaigns_service.dart @@ -4,15 +4,11 @@ import 'package:flutter/foundation.dart'; import 'package:get_it/get_it.dart'; import 'package:gruene_app/app/services/converters.dart'; import 'package:gruene_app/app/services/enums.dart'; -import 'package:gruene_app/features/campaigns/models/doors/door_create_model.dart'; -import 'package:gruene_app/features/campaigns/models/doors/door_detail_model.dart'; -import 'package:gruene_app/features/campaigns/models/doors/door_update_model.dart'; import 'package:gruene_app/features/campaigns/models/flyer/flyer_create_model.dart'; import 'package:gruene_app/features/campaigns/models/flyer/flyer_detail_model.dart'; import 'package:gruene_app/features/campaigns/models/flyer/flyer_update_model.dart'; import 'package:gruene_app/features/campaigns/models/map_layer_model.dart'; import 'package:gruene_app/features/campaigns/models/marker_item_model.dart'; -import 'package:gruene_app/features/campaigns/models/posters/poster_detail_model.dart'; import 'package:gruene_app/features/campaigns/models/posters/poster_list_item_model.dart'; import 'package:gruene_app/swagger_generated_code/gruene_api.swagger.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; @@ -46,22 +42,6 @@ class GrueneApiCampaignsService { return getPoisResult.body!.data.map((layerItem) => layerItem.transformToMapLayer()).toList(); } - Future<MarkerItemModel> createNewDoor(DoorCreateModel newDoor) async { - final requestParam = CreatePoi( - coords: newDoor.location.transformToGeoJsonCoords(), - type: poiType.transformToApiCreateType(), - address: newDoor.address.transformToPoiAddress(), - house: PoiHouse( - countOpenedDoors: newDoor.openedDoors.toDouble(), - countClosedDoors: newDoor.closedDoors.toDouble(), - ), - ); - // saving POI - final newPoiResponse = await grueneApi.v1CampaignsPoisPost(body: requestParam); - - return newPoiResponse.body!.transformToMarkerItem(); - } - Future<MarkerItemModel> createNewFlyer(FlyerCreateModel newFlyer) async { final requestParam = CreatePoi( coords: newFlyer.location.transformToGeoJsonCoords(), @@ -77,23 +57,11 @@ class GrueneApiCampaignsService { return newPoiResponse.body!.transformToMarkerItem(); } - Future<PosterDetailModel> getPoiAsPosterDetail(String poiId) async { - return _getPoi(poiId, (p) => p.transformPoiToPosterDetail()); - } - - Future<PosterListItemModel> getPoiAsPosterListItem(String poiId) { - return _getPoi(poiId, (p) => p.transformToPosterListItem()); - } - - Future<DoorDetailModel> getPoiAsDoorDetail(String poiId) { - return _getPoi(poiId, (p) => p.transformPoiToDoorDetail()); - } - Future<FlyerDetailModel> getPoiAsFlyerDetail(String poiId) { - return _getPoi(poiId, (p) => p.transformPoiToFlyerDetail()); + return getPoi(poiId, (p) => p.transformPoiToFlyerDetail()); } - Future<T> _getPoi<T>(String poiId, T Function(Poi) transform) async { + Future<T> getPoi<T>(String poiId, T Function(Poi) transform) async { final poiResponse = await grueneApi.v1CampaignsPoisPoiIdGet(poiId: poiId); return transform(poiResponse.body!); } @@ -103,19 +71,6 @@ class GrueneApiCampaignsService { final deletePoiResponse = await grueneApi.v1CampaignsPoisPoiIdDelete(poiId: poiId); } - Future<MarkerItemModel> updateDoor(DoorUpdateModel doorUpdate) async { - var dtoUpdate = UpdatePoi( - address: doorUpdate.address.transformToPoiAddress(), - house: PoiHouse( - countOpenedDoors: doorUpdate.openedDoors.toDouble(), - countClosedDoors: doorUpdate.closedDoors.toDouble(), - ), - ); - var updatePoiResponse = await grueneApi.v1CampaignsPoisPoiIdPut(poiId: doorUpdate.id, body: dtoUpdate); - - return updatePoiResponse.body!.transformToMarkerItem(); - } - Future<MarkerItemModel> updateFlyer(FlyerUpdateModel flyerUpdate) async { var dtoUpdate = UpdatePoi( address: flyerUpdate.address.transformToPoiAddress(), diff --git a/lib/app/services/gruene_api_door_service.dart b/lib/app/services/gruene_api_door_service.dart new file mode 100644 index 00000000..bb30084d --- /dev/null +++ b/lib/app/services/gruene_api_door_service.dart @@ -0,0 +1,45 @@ +import 'package:gruene_app/app/services/converters.dart'; +import 'package:gruene_app/app/services/enums.dart'; +import 'package:gruene_app/app/services/gruene_api_campaigns_service.dart'; +import 'package:gruene_app/features/campaigns/models/doors/door_create_model.dart'; +import 'package:gruene_app/features/campaigns/models/doors/door_detail_model.dart'; +import 'package:gruene_app/features/campaigns/models/doors/door_update_model.dart'; +import 'package:gruene_app/features/campaigns/models/marker_item_model.dart'; +import 'package:gruene_app/swagger_generated_code/gruene_api.swagger.dart'; + +class GrueneApiDoorService extends GrueneApiCampaignsService { + GrueneApiDoorService() : super(poiType: PoiServiceType.door); + + Future<MarkerItemModel> createNewDoor(DoorCreateModel newDoor) async { + final requestParam = CreatePoi( + coords: newDoor.location.transformToGeoJsonCoords(), + type: poiType.transformToApiCreateType(), + address: newDoor.address.transformToPoiAddress(), + house: PoiHouse( + countOpenedDoors: newDoor.openedDoors.toDouble(), + countClosedDoors: newDoor.closedDoors.toDouble(), + ), + ); + // saving POI + final newPoiResponse = await grueneApi.v1CampaignsPoisPost(body: requestParam); + + return newPoiResponse.body!.transformToMarkerItem(); + } + + Future<MarkerItemModel> updateDoor(DoorUpdateModel doorUpdate) async { + var dtoUpdate = UpdatePoi( + address: doorUpdate.address.transformToPoiAddress(), + house: PoiHouse( + countOpenedDoors: doorUpdate.openedDoors.toDouble(), + countClosedDoors: doorUpdate.closedDoors.toDouble(), + ), + ); + var updatePoiResponse = await grueneApi.v1CampaignsPoisPoiIdPut(poiId: doorUpdate.id, body: dtoUpdate); + + return updatePoiResponse.body!.transformToMarkerItem(); + } + + Future<DoorDetailModel> getPoiAsDoorDetail(String poiId) { + return getPoi(poiId, (p) => p.transformPoiToDoorDetail()); + } +} diff --git a/lib/app/services/gruene_api_poster_service.dart b/lib/app/services/gruene_api_poster_service.dart index 83033a58..ce5a9129 100644 --- a/lib/app/services/gruene_api_poster_service.dart +++ b/lib/app/services/gruene_api_poster_service.dart @@ -6,6 +6,8 @@ import 'package:gruene_app/app/services/gruene_api_campaigns_service.dart'; import 'package:gruene_app/features/campaigns/helper/file_cache_manager.dart'; import 'package:gruene_app/features/campaigns/models/marker_item_model.dart'; import 'package:gruene_app/features/campaigns/models/posters/poster_create_model.dart'; +import 'package:gruene_app/features/campaigns/models/posters/poster_detail_model.dart'; +import 'package:gruene_app/features/campaigns/models/posters/poster_list_item_model.dart'; import 'package:gruene_app/features/campaigns/models/posters/poster_update_model.dart'; import 'package:gruene_app/swagger_generated_code/gruene_api.swagger.dart'; import 'package:http/http.dart' as http; @@ -76,4 +78,12 @@ class GrueneApiPosterService extends GrueneApiCampaignsService { fileManager.deleteFile(imageFileLocation); return savePoiPhotoResponse; } + + Future<PosterDetailModel> getPoiAsPosterDetail(String poiId) async { + return getPoi(poiId, (p) => p.transformPoiToPosterDetail()); + } + + Future<PosterListItemModel> getPoiAsPosterListItem(String poiId) { + return getPoi(poiId, (p) => p.transformToPosterListItem()); + } } diff --git a/lib/features/campaigns/helper/campaign_action_cache.dart b/lib/features/campaigns/helper/campaign_action_cache.dart index 39b677ba..56a61cd8 100644 --- a/lib/features/campaigns/helper/campaign_action_cache.dart +++ b/lib/features/campaigns/helper/campaign_action_cache.dart @@ -4,9 +4,14 @@ import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'package:gruene_app/app/services/campaign_action_database.dart'; import 'package:gruene_app/app/services/converters.dart'; +import 'package:gruene_app/app/services/enums.dart'; +import 'package:gruene_app/app/services/gruene_api_door_service.dart'; import 'package:gruene_app/app/services/gruene_api_poster_service.dart'; import 'package:gruene_app/features/campaigns/helper/campaign_action.dart'; import 'package:gruene_app/features/campaigns/helper/media_helper.dart'; +import 'package:gruene_app/features/campaigns/models/doors/door_create_model.dart'; +import 'package:gruene_app/features/campaigns/models/doors/door_detail_model.dart'; +import 'package:gruene_app/features/campaigns/models/doors/door_update_model.dart'; import 'package:gruene_app/features/campaigns/models/marker_item_model.dart'; import 'package:gruene_app/features/campaigns/models/posters/poster_create_model.dart'; import 'package:gruene_app/features/campaigns/models/posters/poster_detail_model.dart'; @@ -29,7 +34,7 @@ class CampaignActionCache extends ChangeNotifier { return campaignActionDatabase.actionsWithPoiIdExists(poiId); } - Future<void> _addAction(CampaignAction action) async { + Future<void> _appendActionToCache(CampaignAction action) async { await campaignActionDatabase.create(action); notifyListeners(); } @@ -42,71 +47,127 @@ class CampaignActionCache extends ChangeNotifier { return campaignActionDatabase.getCount(); } - Future<MarkerItemModel> addPosterCreate(PosterCreateModel posterCreate) async { + Future<MarkerItemModel> addCreateAction(PoiServiceType poiType, dynamic poiCreate) async { + switch (poiType) { + case PoiServiceType.poster: + return await _addCreateAction<PosterCreateModel>( + poiType: poiType, + poi: poiCreate as PosterCreateModel, + getJson: (poi) => poi.toJson(), + getMarker: (poi, tempId) => poi.transformToVirtualMarkerItem(tempId), + ); + case PoiServiceType.door: + return await _addCreateAction<DoorCreateModel>( + poiType: poiType, + poi: poiCreate as DoorCreateModel, + getJson: (poi) => poi.toJson(), + getMarker: (poi, tempId) => poi.transformToVirtualMarkerItem(tempId), + ); + case PoiServiceType.flyer: + throw UnimplementedError(); + } + } + + Future<MarkerItemModel> _addCreateAction<T>({ + required PoiServiceType poiType, + required T poi, + required Map<String, dynamic> Function(T) getJson, + required MarkerItemModel Function(T, int) getMarker, + }) async { final action = CampaignAction( - actionType: CampaignActionType.addPoster, - serialized: jsonEncode(posterCreate.toJson()), + actionType: poiType.getCacheAddAction(), + serialized: jsonEncode(getJson(poi)), ); - await _addAction(action); - return posterCreate.transformToVirtualMarkerItem(action.poiTempId); + await _appendActionToCache(action); + return getMarker(poi, action.poiTempId); } - Future<MarkerItemModel> addPosterDelete(String posterId) async { + Future<MarkerItemModel> addDeleteAction(PoiServiceType poiType, String poiId) async { final action = CampaignAction( - poiId: int.parse(posterId), - actionType: CampaignActionType.deletePoster, + poiId: int.parse(poiId), + actionType: poiType.getCacheDeleteAction(), ); - var posterCacheList = await _findActionsByPoiId(posterId); - var addPosterActions = posterCacheList.where((p) => p.actionType == CampaignActionType.addPoster).toList(); - if (addPosterActions.isNotEmpty) { + var poiCacheList = await _findActionsByPoiId(poiId); + var addActions = poiCacheList.where((p) => p.actionType == poiType.getCacheAddAction()).toList(); + if (addActions.isNotEmpty) { // create_action is in cache - for (var action in posterCacheList) { + for (var action in poiCacheList) { campaignActionDatabase.delete(action.id!); } notifyListeners(); } else { - await _addAction(action); + await _appendActionToCache(action); } - return _getDeletePosterMarkerModel(action.poiId!); + return _getDeleteMarkerModel(poiType, action.poiId!); } - Future<MarkerItemModel> addPosterUpdate(PosterUpdateModel posterUpdate) async { - var actions = - (await _findActionsByPoiId(posterUpdate.id)).where((x) => x.actionType == CampaignActionType.editPoster); + Future<MarkerItemModel> addUpdateAction(PoiServiceType poiType, dynamic poi) async { + switch (poiType) { + case PoiServiceType.poster: + return await _addUpdateAction<PosterUpdateModel>( + poiType: poiType, + poi: poi as PosterUpdateModel, + getId: (poi) => poi.id, + getJson: (poi) => poi.toJson(), + mergeUpdates: (action, poiUpdate) => action.getAsPosterUpdate().mergeWith(poiUpdate), + getMarker: (poi) => poi.transformToVirtualMarkerItem(), + ); + case PoiServiceType.door: + return await _addUpdateAction<DoorUpdateModel>( + poiType: poiType, + poi: poi as DoorUpdateModel, + getId: (poi) => poi.id, + getJson: (poi) => poi.toJson(), + mergeUpdates: (action, poiUpdate) => poiUpdate, + getMarker: (poi) => poi.transformToVirtualMarkerItem(), + ); + case PoiServiceType.flyer: + throw UnimplementedError(); + } + } + + Future<MarkerItemModel> _addUpdateAction<T>({ + required PoiServiceType poiType, + required T poi, + required String Function(T) getId, + required Map<String, dynamic> Function(T) getJson, + required T Function(CampaignAction, T) mergeUpdates, + required MarkerItemModel Function(T) getMarker, + }) async { + var actions = (await _findActionsByPoiId(getId(poi))).where((x) => x.actionType == poiType.getCacheEditAction()); var action = actions.singleOrNull; if (action == null) { action = CampaignAction( - poiId: int.parse(posterUpdate.id), - actionType: CampaignActionType.editPoster, - serialized: jsonEncode(posterUpdate.toJson()), + poiId: int.parse(getId(poi)), + actionType: poiType.getCacheEditAction(), + serialized: jsonEncode(getJson(poi)), ); - await _addAction(action); + await _appendActionToCache(action); } else { // update previous edit action - var oldUpdate = action.getAsPosterUpdate(); - var newPosterUpdate = oldUpdate.mergeWith(posterUpdate); - action.serialized = jsonEncode(newPosterUpdate.toJson()); + var newPoiUpdate = mergeUpdates(action, poi); + action.serialized = jsonEncode(getJson(newPoiUpdate)); await _updateAction(action); } - return posterUpdate.transformToVirtualMarkerItem(); + return getMarker(poi); } - MarkerItemModel _getDeletePosterMarkerModel(int id) { + MarkerItemModel _getDeleteMarkerModel(PoiServiceType poiType, int id) { return MarkerItemModel.virtual( id: id, - status: 'poster_deleted', + status: '${poiType.name}_deleted', location: LatLng(0, 0), ); } - Future<List<MarkerItemModel>> getPosterMarkerItems() async { + Future<List<MarkerItemModel>> getMarkerItems(PoiServiceType poiType) async { List<MarkerItemModel> markerItems = []; var posterActions = [ - CampaignActionType.addPoster.index, - CampaignActionType.editPoster.index, - CampaignActionType.deletePoster.index, + poiType.getCacheAddAction().index, + poiType.getCacheEditAction().index, + poiType.getCacheDeleteAction().index, ]; final posterCacheList = await campaignActionDatabase.readAllByActionType(posterActions); for (var action in posterCacheList) { @@ -119,15 +180,23 @@ class CampaignActionCache extends ChangeNotifier { var model = action.getAsPosterUpdate(); markerItems.add(model.transformToVirtualMarkerItem()); case CampaignActionType.deletePoster: - var model = _getDeletePosterMarkerModel(action.poiId!); + var model = _getDeleteMarkerModel(PoiServiceType.poster, action.poiId!); markerItems.add(model); - case CampaignActionType.unknown: case CampaignActionType.addDoor: + var model = action.getAsDoorCreate(); + markerItems.add(model.transformToVirtualMarkerItem(action.poiTempId)); case CampaignActionType.editDoor: + var model = action.getAsDoorUpdate(); + markerItems.add(model.transformToVirtualMarkerItem()); case CampaignActionType.deleteDoor: + var model = _getDeleteMarkerModel(PoiServiceType.door, action.poiId!); + markerItems.add(model); case CampaignActionType.addFlyer: case CampaignActionType.editFlyer: case CampaignActionType.deleteFlyer: + // var model = _getDeleteMarkerModel(PoiServiceType.door, action.poiId!); + // markerItems.add(model); + case CampaignActionType.unknown: case null: throw UnimplementedError(); } @@ -137,18 +206,43 @@ class CampaignActionCache extends ChangeNotifier { } Future<PosterDetailModel> getPoiAsPosterDetail(String poiId) async { - var posterCacheList = await _findActionsByPoiId(poiId); - var addPosterActions = posterCacheList.where((p) => p.actionType == CampaignActionType.addPoster).toList(); - var editPosterActions = posterCacheList.where((p) => p.actionType == CampaignActionType.editPoster).toList(); - if (editPosterActions.isNotEmpty) { - var editPosterAction = editPosterActions.single; - var model = editPosterAction.getAsPosterUpdate(); - return model.transformToPosterDetailModel(int.parse(poiId)); - } else { - var addPosterAction = addPosterActions.single; + var detailModel = await getPoiDetail<PosterDetailModel>( + poiId: poiId, + addActionFilter: CampaignActionType.addDoor, + editActionFilter: CampaignActionType.editDoor, + transformEditAction: (action) => action.getAsPosterUpdate().transformToPosterDetailModel(), + transformAddAction: (action) => action.getAsPosterCreate().transformToPosterDetailModel(poiId), + ); + return detailModel; + } - var model = addPosterAction.getAsPosterCreate(); - return model.transformToPosterDetailModel(int.parse(poiId)); + Future<DoorDetailModel> getPoiAsDoorDetail(String poiId) async { + var detailModel = await getPoiDetail<DoorDetailModel>( + poiId: poiId, + addActionFilter: CampaignActionType.addDoor, + editActionFilter: CampaignActionType.editDoor, + transformEditAction: (action) => action.getAsDoorUpdate().transformToDoorDetailModel(), + transformAddAction: (action) => action.getAsDoorCreate().transformToDoorDetailModel(poiId), + ); + return detailModel; + } + + Future<T> getPoiDetail<T>({ + required String poiId, + required CampaignActionType addActionFilter, + required CampaignActionType editActionFilter, + required T Function(CampaignAction) transformEditAction, + required T Function(CampaignAction) transformAddAction, + }) async { + var cacheList = await _findActionsByPoiId(poiId); + var addActions = cacheList.where((p) => p.actionType == addActionFilter).toList(); + var editActions = cacheList.where((p) => p.actionType == editActionFilter).toList(); + if (editActions.isNotEmpty) { + var editAction = editActions.single; + return transformEditAction(editAction); + } else { + var addAction = addActions.single; + return transformAddAction(addAction); } } @@ -160,6 +254,7 @@ class CampaignActionCache extends ChangeNotifier { void flushCachedItems() async { try { var posterApiService = GetIt.I<GrueneApiPosterService>(); + var doorApiService = GetIt.I<GrueneApiDoorService>(); final allActions = await campaignActionDatabase.readAll(); for (int i = 0; i < allActions.length; i++) { @@ -175,16 +270,33 @@ class CampaignActionCache extends ChangeNotifier { allActions: allActions, ); campaignActionDatabase.delete(action.id!); + case CampaignActionType.editPoster: var model = action.getAsPosterUpdate(); await posterApiService.updatePoster(model); campaignActionDatabase.delete(action.id!); - case CampaignActionType.deletePoster: - await posterApiService.deletePoi(action.poiId!.toString()); - campaignActionDatabase.delete(action.id!); + case CampaignActionType.addDoor: + var model = action.getAsDoorCreate(); + var newDoorMarker = await doorApiService.createNewDoor(model); + await updateIds( + oldId: action.poiTempId, + newId: newDoorMarker.id!, + startIndex: i + 1, + allActions: allActions, + ); + campaignActionDatabase.delete(action.id!); + case CampaignActionType.editDoor: + var model = action.getAsDoorUpdate(); + await doorApiService.updateDoor(model); + campaignActionDatabase.delete(action.id!); + case CampaignActionType.deleteDoor: + case CampaignActionType.deletePoster: + await posterApiService.deletePoi(action.poiId!.toString()); + campaignActionDatabase.delete(action.id!); + case CampaignActionType.addFlyer: case CampaignActionType.editFlyer: case CampaignActionType.deleteFlyer: diff --git a/lib/features/campaigns/models/doors/door_create_model.dart b/lib/features/campaigns/models/doors/door_create_model.dart index 1cce9bea..53898941 100644 --- a/lib/features/campaigns/models/doors/door_create_model.dart +++ b/lib/features/campaigns/models/doors/door_create_model.dart @@ -1,7 +1,13 @@ import 'package:gruene_app/app/services/nominatim_service.dart'; +import 'package:gruene_app/features/campaigns/models/posters/poster_create_model.dart'; +import 'package:json_annotation/json_annotation.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; +part 'door_create_model.g.dart'; + +@JsonSerializable() class DoorCreateModel { + @LatLongConverter() final LatLng location; final AddressModel address; final int openedDoors; @@ -13,4 +19,8 @@ class DoorCreateModel { required this.openedDoors, required this.closedDoors, }); + + factory DoorCreateModel.fromJson(Map<String, dynamic> json) => _$DoorCreateModelFromJson(json); + + Map<String, dynamic> toJson() => _$DoorCreateModelToJson(this); } diff --git a/lib/features/campaigns/models/doors/door_detail_model.dart b/lib/features/campaigns/models/doors/door_detail_model.dart index ca4bfe0e..ad15754a 100644 --- a/lib/features/campaigns/models/doors/door_detail_model.dart +++ b/lib/features/campaigns/models/doors/door_detail_model.dart @@ -1,5 +1,13 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first +import 'package:gruene_app/app/services/converters.dart'; import 'package:gruene_app/app/services/nominatim_service.dart'; +import 'package:gruene_app/features/campaigns/models/posters/poster_create_model.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +part 'door_detail_model.g.dart'; + +@JsonSerializable() class DoorDetailModel { String id; @@ -7,6 +15,9 @@ class DoorDetailModel { final int openedDoors; final int closedDoors; final String createdAt; + @LatLongConverter() + final LatLng location; + final bool isCached; DoorDetailModel({ required this.id, @@ -14,5 +25,31 @@ class DoorDetailModel { required this.openedDoors, required this.closedDoors, required this.createdAt, + required this.location, + this.isCached = false, }); + + factory DoorDetailModel.fromJson(Map<String, dynamic> json) => _$DoorDetailModelFromJson(json.convertLatLongField()); + + Map<String, dynamic> toJson() => _$DoorDetailModelToJson(this); + + DoorDetailModel copyWith({ + String? id, + AddressModel? address, + int? openedDoors, + int? closedDoors, + String? createdAt, + LatLng? location, + bool? isCached, + }) { + return DoorDetailModel( + id: id ?? this.id, + address: address ?? this.address, + openedDoors: openedDoors ?? this.openedDoors, + closedDoors: closedDoors ?? this.closedDoors, + createdAt: createdAt ?? this.createdAt, + location: location ?? this.location, + isCached: isCached ?? this.isCached, + ); + } } diff --git a/lib/features/campaigns/models/doors/door_update_model.dart b/lib/features/campaigns/models/doors/door_update_model.dart index 1b3e712f..b6bf5c6d 100644 --- a/lib/features/campaigns/models/doors/door_update_model.dart +++ b/lib/features/campaigns/models/doors/door_update_model.dart @@ -1,15 +1,31 @@ import 'package:gruene_app/app/services/nominatim_service.dart'; +import 'package:gruene_app/features/campaigns/models/doors/door_detail_model.dart'; +import 'package:gruene_app/features/campaigns/models/posters/poster_create_model.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +part 'door_update_model.g.dart'; + +@JsonSerializable() class DoorUpdateModel { - int openedDoors; - int closedDoors; - String id; - AddressModel address; + final int openedDoors; + final int closedDoors; + final String id; + final AddressModel address; + @LatLongConverter() + final LatLng location; + final DoorDetailModel oldDoorDetail; DoorUpdateModel({ required this.id, required this.address, required this.openedDoors, required this.closedDoors, + required this.oldDoorDetail, + required this.location, }); + + factory DoorUpdateModel.fromJson(Map<String, dynamic> json) => _$DoorUpdateModelFromJson(json); + + Map<String, dynamic> toJson() => _$DoorUpdateModelToJson(this); } diff --git a/lib/features/campaigns/models/flyer/flyer_detail_model.dart b/lib/features/campaigns/models/flyer/flyer_detail_model.dart index 5b5fb644..68e23ffa 100644 --- a/lib/features/campaigns/models/flyer/flyer_detail_model.dart +++ b/lib/features/campaigns/models/flyer/flyer_detail_model.dart @@ -2,17 +2,16 @@ import 'package:gruene_app/app/services/nominatim_service.dart'; class FlyerDetailModel { final String id; - final AddressModel address; - final int flyerCount; - final String createdAt; + final bool isCached; FlyerDetailModel({ required this.id, required this.address, required this.flyerCount, required this.createdAt, + this.isCached = false, }); } diff --git a/lib/features/campaigns/screens/door_edit.dart b/lib/features/campaigns/screens/door_edit.dart index 2c2174c3..ae854214 100644 --- a/lib/features/campaigns/screens/door_edit.dart +++ b/lib/features/campaigns/screens/door_edit.dart @@ -153,6 +153,8 @@ class _DoorEditState extends State<DoorEdit> with AddressExtension, DoorValidato address: getAddress(), openedDoors: validationResult.openedDoors, closedDoors: validationResult.closedDoors, + location: widget.door.location, + oldDoorDetail: widget.door, ); await widget.onSave(updateModel); _closeDialog(); diff --git a/lib/features/campaigns/screens/doors_screen.dart b/lib/features/campaigns/screens/doors_screen.dart index 59952db3..137703d8 100644 --- a/lib/features/campaigns/screens/doors_screen.dart +++ b/lib/features/campaigns/screens/doors_screen.dart @@ -1,10 +1,12 @@ import 'dart:math'; import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; import 'package:gruene_app/app/services/enums.dart'; -import 'package:gruene_app/app/services/gruene_api_campaigns_service.dart'; +import 'package:gruene_app/app/services/gruene_api_door_service.dart'; import 'package:gruene_app/app/services/nominatim_service.dart'; import 'package:gruene_app/features/campaigns/helper/campaign_constants.dart'; +import 'package:gruene_app/features/campaigns/helper/map_helper.dart'; import 'package:gruene_app/features/campaigns/models/doors/door_create_model.dart'; import 'package:gruene_app/features/campaigns/models/doors/door_detail_model.dart'; import 'package:gruene_app/features/campaigns/models/doors/door_update_model.dart'; @@ -26,6 +28,7 @@ class DoorsScreen extends StatefulWidget { } class _DoorsScreenState extends MapConsumer<DoorsScreen> { + static const _poiType = PoiServiceType.door; final Map<String, List<String>> doorsExclusions = <String, List<String>>{ t.campaigns.filters.focusAreas: [t.campaigns.filters.visited_areas], t.campaigns.filters.visited_areas: [t.campaigns.filters.focusAreas], @@ -33,12 +36,12 @@ class _DoorsScreenState extends MapConsumer<DoorsScreen> { late List<FilterChipModel> doorsFilter; - final GrueneApiCampaignsService _grueneApiService = GrueneApiCampaignsService(poiType: PoiServiceType.door); + final _grueneApiService = GetIt.I<GrueneApiDoorService>(); - _DoorsScreenState() : super(NominatimService()); + _DoorsScreenState() : super(NominatimService(), _poiType); @override - GrueneApiCampaignsService get campaignService => _grueneApiService; + GrueneApiDoorService get campaignService => _grueneApiService; @override void initState() { @@ -70,7 +73,7 @@ class _DoorsScreenState extends MapConsumer<DoorsScreen> { onMapCreated: onMapCreated, addPOIClicked: _addPOIClicked, loadVisibleItems: loadVisibleItems, - loadCachedItems: _loadCachedItems, + loadCachedItems: loadCachedItems, getMarkerImages: _getMarkerImages, onFeatureClick: _onFeatureClick, onNoFeatureClick: _onNoFeatureClick, @@ -105,11 +108,21 @@ class _DoorsScreenState extends MapConsumer<DoorsScreen> { } void _onFeatureClick(dynamic rawFeature) async { + final feature = rawFeature as Map<String, dynamic>; + final isCached = MapHelper.extractIsCachedFromFeature(feature); + getPoi(String poiId) async { final door = await campaignService.getPoiAsDoorDetail(poiId); return door; } + getCachedPoi(String poiId) async { + final door = await campaignActionCache.getPoiAsDoorDetail(poiId); + return door; + } + + var getPoiFromCacheOrApi = isCached ? getCachedPoi : getPoi; + getPoiDetail(DoorDetailModel door) { return DoorsDetail( poi: door, @@ -122,7 +135,7 @@ class _DoorsScreenState extends MapConsumer<DoorsScreen> { super.onFeatureClick<DoorDetailModel>( rawFeature, - getPoi, + getPoiFromCacheOrApi, getPoiDetail, getEditPoiWidget, desiredSize: Size(145, 110), @@ -134,7 +147,7 @@ class _DoorsScreenState extends MapConsumer<DoorsScreen> { } Future<void> _saveDoor(DoorUpdateModel doorUpdate) async { - final updatedMarker = await campaignService.updateDoor(doorUpdate); + final updatedMarker = await campaignActionCache.addUpdateAction(_poiType, doorUpdate); mapController.setMarkerSource([updatedMarker]); } @@ -146,7 +159,5 @@ class _DoorsScreenState extends MapConsumer<DoorsScreen> { } Future<MarkerItemModel> _saveNewAndGetMarkerItem(DoorCreateModel newDoor) async => - await _grueneApiService.createNewDoor(newDoor); - - void _loadCachedItems() {} + await campaignActionCache.addCreateAction(_poiType, newDoor); } diff --git a/lib/features/campaigns/screens/flyer_screen.dart b/lib/features/campaigns/screens/flyer_screen.dart index 76181ee8..6cdae708 100644 --- a/lib/features/campaigns/screens/flyer_screen.dart +++ b/lib/features/campaigns/screens/flyer_screen.dart @@ -26,11 +26,12 @@ class FlyerScreen extends StatefulWidget { } class _FlyerScreenState extends MapConsumer<FlyerScreen> { - final GrueneApiCampaignsService _grueneApiService = GrueneApiCampaignsService(poiType: PoiServiceType.flyer); + static const _poiType = PoiServiceType.door; + final GrueneApiCampaignsService _grueneApiService = GrueneApiCampaignsService(poiType: _poiType); late List<FilterChipModel> flyerFilter; - _FlyerScreenState() : super(NominatimService()); + _FlyerScreenState() : super(NominatimService(), _poiType); @override void initState() { @@ -62,7 +63,7 @@ class _FlyerScreenState extends MapConsumer<FlyerScreen> { onMapCreated: onMapCreated, addPOIClicked: _addPOIClicked, loadVisibleItems: loadVisibleItems, - loadCachedItems: _loadCachedItems, + loadCachedItems: loadCachedItems, getMarkerImages: _getMarkerImages, onFeatureClick: _onFeatureClick, onNoFeatureClick: _onNoFeatureClick, @@ -143,6 +144,4 @@ class _FlyerScreenState extends MapConsumer<FlyerScreen> { final updatedMarker = await campaignService.updateFlyer(flyerUpdate); mapController.setMarkerSource([updatedMarker]); } - - void _loadCachedItems() {} } diff --git a/lib/features/campaigns/screens/map_consumer.dart b/lib/features/campaigns/screens/map_consumer.dart index fea94672..37311b3a 100644 --- a/lib/features/campaigns/screens/map_consumer.dart +++ b/lib/features/campaigns/screens/map_consumer.dart @@ -1,10 +1,13 @@ import 'dart:math'; import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; import 'package:go_router/go_router.dart'; +import 'package:gruene_app/app/services/enums.dart'; import 'package:gruene_app/app/services/gruene_api_campaigns_service.dart'; import 'package:gruene_app/app/services/nominatim_service.dart'; import 'package:gruene_app/app/theme/theme.dart'; +import 'package:gruene_app/features/campaigns/helper/campaign_action_cache.dart'; import 'package:gruene_app/features/campaigns/helper/campaign_constants.dart'; import 'package:gruene_app/features/campaigns/helper/enums.dart'; import 'package:gruene_app/features/campaigns/helper/map_helper.dart'; @@ -24,7 +27,7 @@ typedef SaveNewAndGetMarkerCallback<T> = Future<MarkerItemModel> Function(T); typedef GetPoiCallback<T> = Future<T> Function(String); typedef GetPoiDetailWidgetCallback<T> = Widget Function(T); typedef GetPoiEditWidgetCallback<T> = Widget Function(T); -typedef OnDeletePoiCallback = Future<void> Function(String posterId); +typedef OnDeletePoiCallback = Future<void> Function(String poiId); abstract class MapConsumer<T extends StatefulWidget> extends State<T> with FocusAreaInfo { late MapController mapController; @@ -35,8 +38,10 @@ abstract class MapConsumer<T extends StatefulWidget> extends State<T> with Focus final _minZoomFocusAreaLayer = 11.0; ScaffoldFeatureController<SnackBar, SnackBarClosedReason>? _lastInfoSnackBar; String? _lastFocusAreaId; + final campaignActionCache = GetIt.I<CampaignActionCache>(); + final PoiServiceType poiType; - MapConsumer(this._nominatimService); + MapConsumer(this._nominatimService, this.poiType); GrueneApiCampaignsService get campaignService; @@ -147,9 +152,8 @@ abstract class MapConsumer<T extends StatefulWidget> extends State<T> with Focus } Future<void> deletePoi(String poiId) async { - final id = int.parse(poiId); - await campaignService.deletePoi(poiId); - mapController.removeMarkerItem(id); + var markerItem = await campaignActionCache.addDeleteAction(poiType, poiId); + mapController.setMarkerSource([markerItem]); } void addMapLayersForContext(MapLibreMapController mapLibreController) async { @@ -326,4 +330,9 @@ abstract class MapConsumer<T extends StatefulWidget> extends State<T> with Focus toast.show(context); } + + void loadCachedItems() async { + var markerItems = await campaignActionCache.getMarkerItems(poiType); + mapController.setMarkerSource(markerItems); + } } diff --git a/lib/features/campaigns/screens/posters_screen.dart b/lib/features/campaigns/screens/posters_screen.dart index 892e9bbb..ca1ab81c 100644 --- a/lib/features/campaigns/screens/posters_screen.dart +++ b/lib/features/campaigns/screens/posters_screen.dart @@ -4,10 +4,9 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'package:gruene_app/app/services/enums.dart'; -import 'package:gruene_app/app/services/gruene_api_campaigns_service.dart'; +import 'package:gruene_app/app/services/gruene_api_poster_service.dart'; import 'package:gruene_app/app/services/nominatim_service.dart'; import 'package:gruene_app/app/theme/theme.dart'; -import 'package:gruene_app/features/campaigns/helper/campaign_action_cache.dart'; import 'package:gruene_app/features/campaigns/helper/campaign_constants.dart'; import 'package:gruene_app/features/campaigns/helper/map_helper.dart'; import 'package:gruene_app/features/campaigns/helper/media_helper.dart'; @@ -36,15 +35,15 @@ class PostersScreen extends StatefulWidget { } class _PostersScreenState extends MapConsumer<PostersScreen> { - final GrueneApiCampaignsService _grueneApiService = GrueneApiCampaignsService(poiType: PoiServiceType.poster); - final campaignActionCache = GetIt.I<CampaignActionCache>(); + static const _poiType = PoiServiceType.poster; + final _grueneApiService = GetIt.I<GrueneApiPosterService>(); late List<FilterChipModel> postersFilter; - _PostersScreenState() : super(NominatimService()); + _PostersScreenState() : super(NominatimService(), _poiType); @override - GrueneApiCampaignsService get campaignService => _grueneApiService; + GrueneApiPosterService get campaignService => _grueneApiService; @override void initState() { @@ -77,7 +76,7 @@ class _PostersScreenState extends MapConsumer<PostersScreen> { onMapCreated: onMapCreated, addPOIClicked: _addPOIClicked, loadVisibleItems: loadVisibleItems, - loadCachedItems: _loadCachedItems, + loadCachedItems: loadCachedItems, getMarkerImages: _getMarkerImages, onFeatureClick: _onFeatureClick, onNoFeatureClick: _onNoFeatureClick, @@ -141,7 +140,7 @@ class _PostersScreenState extends MapConsumer<PostersScreen> { } Future<MarkerItemModel> saveNewAndGetMarkerItem(PosterCreateModel newPoster) async { - return await campaignActionCache.addPosterCreate(newPoster); + return await campaignActionCache.addCreateAction(_poiType, newPoster); } void _addPOIClicked(LatLng location) async { @@ -181,7 +180,7 @@ class _PostersScreenState extends MapConsumer<PostersScreen> { } Widget _getEditPosterWidget(PosterDetailModel poster) { - return PosterEdit(poster: poster, onSave: _savePoster, onDelete: _deletePoster); + return PosterEdit(poster: poster, onSave: _savePoster, onDelete: deletePoi); } void _onFeatureClick(dynamic rawFeature) async { @@ -210,7 +209,7 @@ class _PostersScreenState extends MapConsumer<PostersScreen> { } Future<void> _savePoster(PosterUpdateModel posterUpdate) async { - final updatedMarker = await campaignActionCache.addPosterUpdate(posterUpdate); + final updatedMarker = await campaignActionCache.addUpdateAction(_poiType, posterUpdate); mapController.setMarkerSource([updatedMarker]); } @@ -247,16 +246,6 @@ class _PostersScreenState extends MapConsumer<PostersScreen> { return myPosters; } - void _loadCachedItems() async { - var markerItems = await campaignActionCache.getPosterMarkerItems(); - mapController.setMarkerSource(markerItems); - } - - Future<void> _deletePoster(String posterId) async { - var markerItem = await campaignActionCache.addPosterDelete(posterId); - mapController.setMarkerSource([markerItem]); - } - Future<PosterListItemModel> _getPosterListItem(String id) async { return await campaignActionCache.isCached(id) ? campaignActionCache.getPoiAsPosterListItem(id) diff --git a/lib/main.dart b/lib/main.dart index 61004e53..7ded799e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,6 +9,7 @@ import 'package:gruene_app/app/auth/bloc/auth_bloc.dart'; import 'package:gruene_app/app/auth/repository/auth_repository.dart'; import 'package:gruene_app/app/router.dart'; import 'package:gruene_app/app/services/gruene_api_core.dart'; +import 'package:gruene_app/app/services/gruene_api_door_service.dart'; import 'package:gruene_app/app/services/gruene_api_poster_service.dart'; import 'package:gruene_app/app/theme/theme.dart'; import 'package:gruene_app/app/widgets/clean_layout.dart'; @@ -41,13 +42,12 @@ Future<void> main() async { GetIt.I.registerSingleton<GrueneApi>(await createGrueneApiClient()); GetIt.I.registerSingleton<CampaignSessionSettings>(CampaignSessionSettings()); GetIt.I.registerSingleton<CampaignActionCache>(CampaignActionCache()); - // GetIt.I.registerSingleton<CacheManager>(FileCacheManager.instance); GetIt.I.registerSingleton<FileManager>(FileManager()); GetIt.I.registerFactory<AuthenticatorService>(MfaFactory.create); GetIt.I.registerFactory<GrueneApiPosterService>(() => GrueneApiPosterService()); - // This is required so ObjectBox can get the application directory - // to store the database in. + GetIt.I.registerFactory<GrueneApiDoorService>(() => GrueneApiDoorService()); + WidgetsFlutterBinding.ensureInitialized(); runApp(TranslationProvider(child: const MyApp()));