diff --git a/IsraelHiking.Web/src/application/components/background-text.component.ts b/IsraelHiking.Web/src/application/components/background-text.component.ts index 0365af07f..62aff1c02 100644 --- a/IsraelHiking.Web/src/application/components/background-text.component.ts +++ b/IsraelHiking.Web/src/application/components/background-text.component.ts @@ -1,11 +1,9 @@ import { Component } from "@angular/core"; -import { Observable } from "rxjs"; -import { Store, Select } from "@ngxs/store"; -import type { Immutable } from "immer"; +import { Store } from "@ngxs/store"; import { BaseMapComponent } from "./base-map.component"; import { ResourcesService } from "../services/resources.service"; -import type { ApplicationState, Language } from "../models/models"; +import type { ApplicationState } from "../models/models"; @Component({ selector: "background-text", @@ -14,15 +12,6 @@ import type { ApplicationState, Language } from "../models/models"; }) export class BackgroundTextComponent extends BaseMapComponent { - @Select((state: ApplicationState) => state.offlineState.isOfflineAvailable) - public isOfflineAvailable$: Observable; - - @Select((state: ApplicationState) => state.offlineState.lastModifiedDate) - public lastModifiedDate$: Observable; - - @Select((state: ApplicationState) => state.configuration.language) - public language$: Observable>; - public text: string; constructor(resources: ResourcesService, @@ -30,9 +19,9 @@ export class BackgroundTextComponent extends BaseMapComponent { super(resources); this.text = ""; - this.isOfflineAvailable$.subscribe(() => this.updateText()); - this.lastModifiedDate$.subscribe(() => this.updateText()); - this.language$.subscribe(() => this.updateText()); + this.store.select((state: ApplicationState) => state.offlineState.isOfflineAvailable).subscribe(() => this.updateText()); + this.store.select((state: ApplicationState) => state.offlineState.lastModifiedDate).subscribe(() => this.updateText()); + this.store.select((state: ApplicationState) => state.configuration.language).subscribe(() => this.updateText()); } private updateText() { diff --git a/IsraelHiking.Web/src/application/components/dialogs/configuration-dialog.component.html b/IsraelHiking.Web/src/application/components/dialogs/configuration-dialog.component.html index 44a17ac65..642fecde1 100644 --- a/IsraelHiking.Web/src/application/components/dialogs/configuration-dialog.component.html +++ b/IsraelHiking.Web/src/application/components/dialogs/configuration-dialog.component.html @@ -8,7 +8,7 @@
- +
{{resources.screenOn}}
@@ -24,14 +24,14 @@
- {{resources.automaticRecordingUpload}} + {{resources.automaticRecordingUpload}}
{{resources.automaticRecordingUploadHint}}
- {{resources.gotLostWarnings}} + {{resources.gotLostWarnings}}
{{resources.gotLostWarningsHint}}
diff --git a/IsraelHiking.Web/src/application/components/dialogs/configuration-dialog.component.ts b/IsraelHiking.Web/src/application/components/dialogs/configuration-dialog.component.ts index 206f0689b..31e8dba22 100644 --- a/IsraelHiking.Web/src/application/components/dialogs/configuration-dialog.component.ts +++ b/IsraelHiking.Web/src/application/components/dialogs/configuration-dialog.component.ts @@ -1,7 +1,7 @@ -import { Component } from "@angular/core"; +import { Component, OnDestroy } from "@angular/core"; import { MatDialogRef } from "@angular/material/dialog"; -import { Observable } from "rxjs"; -import { Store, Select } from "@ngxs/store"; +import { Subscription } from "rxjs"; +import { Store } from "@ngxs/store"; import { BaseMapComponent } from "../base-map.component"; import { ResourcesService } from "../../services/resources.service"; @@ -20,16 +20,13 @@ import type { ApplicationState, BatteryOptimizationType } from "../../models/mod selector: "configuration-dialog", templateUrl: "./configuration-dialog.component.html" }) -export class ConfigurationDialogComponent extends BaseMapComponent { +export class ConfigurationDialogComponent extends BaseMapComponent implements OnDestroy { - @Select((state: ApplicationState) => state.configuration.batteryOptimizationType) - public batteryOptimizationType: Observable; + private subscriptions: Subscription[]; - @Select((state: ApplicationState) => state.configuration.isAutomaticRecordingUpload) - public isAutomaticRecordingUpload: Observable; - - @Select((state: ApplicationState) => state.configuration.isGotLostWarnings) - public isGotLostWarnings: Observable; + public batteryOptimizationType: BatteryOptimizationType; + public isAutomaticRecordingUpload: boolean; + public isGotLostWarnings: boolean; constructor(resources: ResourcesService, private readonly dialogRef: MatDialogRef, @@ -38,6 +35,22 @@ export class ConfigurationDialogComponent extends BaseMapComponent { private readonly logginService: LoggingService, private readonly store: Store) { super(resources); + this.subscriptions = []; + this.subscriptions.push(this.store.select((state: ApplicationState) => state.configuration.batteryOptimizationType).subscribe((batteryOptimizationType) => { + this.batteryOptimizationType = batteryOptimizationType; + })); + this.subscriptions.push(this.store.select((state: ApplicationState) => state.configuration.isAutomaticRecordingUpload).subscribe((isAutomaticRecordingUpload) => { + this.isAutomaticRecordingUpload = isAutomaticRecordingUpload; + })); + this.subscriptions.push(this.store.select((state: ApplicationState) => state.configuration.isGotLostWarnings).subscribe((isGotLostWarnings) => { + this.isGotLostWarnings = isGotLostWarnings; + })); + } + + public ngOnDestroy() { + for (const subscription of this.subscriptions) { + subscription.unsubscribe(); + } } public isApp() { diff --git a/IsraelHiking.Web/src/application/components/dialogs/layers/base-layer-add-dialog.component.ts b/IsraelHiking.Web/src/application/components/dialogs/layers/base-layer-add-dialog.component.ts index afc3d3595..d7d5e4f1c 100644 --- a/IsraelHiking.Web/src/application/components/dialogs/layers/base-layer-add-dialog.component.ts +++ b/IsraelHiking.Web/src/application/components/dialogs/layers/base-layer-add-dialog.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; import { HttpClient } from "@angular/common/http"; +import { Store } from "@ngxs/store"; import { LayerBaseDialogComponent } from "./layer-base-dialog.component"; import { ResourcesService } from "../../../services/resources.service"; @@ -17,9 +18,9 @@ export class BaseLayerAddDialogComponent extends LayerBaseDialogComponent { layersService: LayersService, mapService: MapService, toastService: ToastService, - http: HttpClient - ) { - super(resources, mapService, layersService, toastService, http); + http: HttpClient, + store: Store) { + super(resources, mapService, layersService, toastService, http, store); this.title = this.resources.addBaseLayer; this.isNew = true; this.isOverlay = false; diff --git a/IsraelHiking.Web/src/application/components/dialogs/layers/base-layer-edit-dialog.component.ts b/IsraelHiking.Web/src/application/components/dialogs/layers/base-layer-edit-dialog.component.ts index 0c12b95dd..d36453653 100644 --- a/IsraelHiking.Web/src/application/components/dialogs/layers/base-layer-edit-dialog.component.ts +++ b/IsraelHiking.Web/src/application/components/dialogs/layers/base-layer-edit-dialog.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; import { HttpClient } from "@angular/common/http"; +import { Store } from "@ngxs/store"; import { ResourcesService } from "../../../services/resources.service"; import { MapService } from "../../../services/map.service"; @@ -19,8 +20,9 @@ export class BaseLayerEditDialogComponent extends LayerBaseDialogComponent { mapService: MapService, layersService: LayersService, toastService: ToastService, - http: HttpClient) { - super(resources, mapService, layersService, toastService, http); + http: HttpClient, + store: Store) { + super(resources, mapService, layersService, toastService, http, store); this.title = this.resources.baseLayerProperties; this.isNew = false; this.isOverlay = false; diff --git a/IsraelHiking.Web/src/application/components/dialogs/layers/layer-base-dialog.component.ts b/IsraelHiking.Web/src/application/components/dialogs/layers/layer-base-dialog.component.ts index f9b11c617..c76a9549f 100644 --- a/IsraelHiking.Web/src/application/components/dialogs/layers/layer-base-dialog.component.ts +++ b/IsraelHiking.Web/src/application/components/dialogs/layers/layer-base-dialog.component.ts @@ -1,6 +1,6 @@ import { HttpClient } from "@angular/common/http"; -import { firstValueFrom, Observable } from "rxjs"; -import { Select } from "@ngxs/store"; +import { firstValueFrom } from "rxjs"; +import { Store } from "@ngxs/store"; import { BaseMapComponent } from "../../base-map.component"; import { ResourcesService } from "../../../services/resources.service"; @@ -17,15 +17,14 @@ export abstract class LayerBaseDialogComponent extends BaseMapComponent { public layerData: EditableLayer; - @Select((state: ApplicationState) => state.locationState) - public location: Observable>; + public location: Immutable; protected constructor(resources: ResourcesService, protected readonly mapService: MapService, protected readonly layersService: LayersService, protected readonly toastService: ToastService, - private readonly http: HttpClient - ) { + private readonly http: HttpClient, + private readonly store: Store) { super(resources); this.layerData = { minZoom: LayersService.MIN_ZOOM, @@ -37,6 +36,10 @@ export abstract class LayerBaseDialogComponent extends BaseMapComponent { isOfflineAvailable: false, isOfflineOn: true } as EditableLayer; + // HM TODO: unsubscribe + this.store.select((state: ApplicationState) => state.locationState).subscribe(locationState => { + this.location = locationState; + }); } public onAddressChanged(address: string) { diff --git a/IsraelHiking.Web/src/application/components/dialogs/layers/layer-properties-dialog.component.html b/IsraelHiking.Web/src/application/components/dialogs/layers/layer-properties-dialog.component.html index 2fdb6d7f3..ccdd2f8ff 100644 --- a/IsraelHiking.Web/src/application/components/dialogs/layers/layer-properties-dialog.component.html +++ b/IsraelHiking.Web/src/application/components/dialogs/layers/layer-properties-dialog.component.html @@ -39,7 +39,7 @@
-
+
{{shareUrl.title}}
{{shareUrl.description}}
{{shareUrl.creationDate | date:'dd/MM/yyyy'}} diff --git a/IsraelHiking.Web/src/application/components/dialogs/shares-dialog.component.ts b/IsraelHiking.Web/src/application/components/dialogs/shares-dialog.component.ts index 3931b52b9..b9b1c375f 100644 --- a/IsraelHiking.Web/src/application/components/dialogs/shares-dialog.component.ts +++ b/IsraelHiking.Web/src/application/components/dialogs/shares-dialog.component.ts @@ -3,8 +3,8 @@ import { MatDialog } from "@angular/material/dialog"; import { FormControl } from "@angular/forms"; import { SocialSharing } from "@awesome-cordova-plugins/social-sharing/ngx"; import { take, orderBy } from "lodash-es"; -import { Observable, Subscription } from "rxjs"; -import { Store, Select } from "@ngxs/store"; +import { Subscription } from "rxjs"; +import { Store } from "@ngxs/store"; import type { Immutable } from "immer"; import { BaseMapComponent } from "../base-map.component"; @@ -30,12 +30,7 @@ export class SharesDialogComponent extends BaseMapComponent implements OnInit, O public selectedShareUrlId: string; public loadingShareUrls: boolean; public searchTerm: FormControl; - - @Select((state: ApplicationState) => state.shareUrlsState.shareUrls) - public shareUrls$: Observable>; - - @Select((state: ApplicationState) => state.inMemoryState.shareUrl) - public shownShareUrl$: Observable>; + public shownShareUrl: Immutable; private sessionSearchTerm = ""; private page: number; @@ -62,11 +57,14 @@ export class SharesDialogComponent extends BaseMapComponent implements OnInit, O this.updateFilteredLists(searchTerm); })); this.searchTerm.setValue(this.sessionSearchTerm); - this.subscriptions.push(this.shareUrls$.subscribe(() => { + this.subscriptions.push(this.store.select((state: ApplicationState) => state.shareUrlsState.shareUrls).subscribe(() => { if (!this.loadingShareUrls) { this.updateFilteredLists(this.searchTerm.value); } })); + this.subscriptions.push(this.store.select((state: ApplicationState) => state.inMemoryState.shareUrl).subscribe((shareUrl) => { + this.shownShareUrl = shareUrl; + })); } public async ngOnInit() { diff --git a/IsraelHiking.Web/src/application/components/dialogs/traces-dialog.component.ts b/IsraelHiking.Web/src/application/components/dialogs/traces-dialog.component.ts index ee7d4edd5..f3cebb677 100644 --- a/IsraelHiking.Web/src/application/components/dialogs/traces-dialog.component.ts +++ b/IsraelHiking.Web/src/application/components/dialogs/traces-dialog.component.ts @@ -1,9 +1,9 @@ import { Component, OnInit, OnDestroy, ViewEncapsulation, Inject } from "@angular/core"; import { FormControl } from "@angular/forms"; import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; -import { Subscription, Observable } from "rxjs"; +import { Subscription } from "rxjs"; import { orderBy, take } from "lodash-es"; -import { Store, Select } from "@ngxs/store"; +import { Store } from "@ngxs/store"; import type { Immutable } from "immer"; import { BaseMapComponent } from "../base-map.component"; @@ -35,9 +35,6 @@ export class TracesDialogComponent extends BaseMapComponent implements OnInit, O public loadingTraces: boolean; public searchTerm: FormControl; - @Select((state: ApplicationState) => state.tracesState.traces) - public traces$: Observable>; - private sessionSearchTerm = ""; private page: number; private tracesChangedSubscription: Subscription; @@ -72,7 +69,7 @@ export class TracesDialogComponent extends BaseMapComponent implements OnInit, O this.updateFilteredLists(searchTerm); }); this.searchTerm.setValue(this.sessionSearchTerm); - this.tracesChangedSubscription = this.traces$.subscribe(() => { + this.tracesChangedSubscription = this.store.select((state: ApplicationState) => state.tracesState.traces).subscribe(() => { if (!this.loadingTraces) { this.updateFilteredLists(this.searchTerm.value); } diff --git a/IsraelHiking.Web/src/application/components/drawing.component.html b/IsraelHiking.Web/src/application/components/drawing.component.html index c6906a44c..857f2bc1c 100644 --- a/IsraelHiking.Web/src/application/components/drawing.component.html +++ b/IsraelHiking.Web/src/application/components/drawing.component.html @@ -5,7 +5,7 @@ - + diff --git a/IsraelHiking.Web/src/application/components/drawing.component.ts b/IsraelHiking.Web/src/application/components/drawing.component.ts index 219fc0f36..4074d96fd 100644 --- a/IsraelHiking.Web/src/application/components/drawing.component.ts +++ b/IsraelHiking.Web/src/application/components/drawing.component.ts @@ -1,6 +1,5 @@ import { Component, HostListener } from "@angular/core"; -import { Observable } from "rxjs"; -import { Store, Select } from "@ngxs/store"; +import { Store } from "@ngxs/store"; import { BaseMapComponent } from "./base-map.component"; import { ResourcesService } from "../services/resources.service"; @@ -25,14 +24,17 @@ import type { RoutingType, ApplicationState } from "../models/models"; }) export class DrawingComponent extends BaseMapComponent { - @Select((state: ApplicationState) => state.routes.past.length) - public undoQueueLength: Observable; + public undoQueueLength: number; constructor(resources: ResourcesService, private readonly selectedRouteService: SelectedRouteService, private readonly toastService: ToastService, private readonly store: Store) { super(resources); + this.undoQueueLength = 0; + this.store.select((state: ApplicationState) => state.routes.past.length).subscribe((length) => { + this.undoQueueLength = length; + }); } @HostListener("window:keydown", ["$event"]) diff --git a/IsraelHiking.Web/src/application/components/location.component.ts b/IsraelHiking.Web/src/application/components/location.component.ts index 48b936b89..8f24d333f 100644 --- a/IsraelHiking.Web/src/application/components/location.component.ts +++ b/IsraelHiking.Web/src/application/components/location.component.ts @@ -1,8 +1,7 @@ import { Component } from "@angular/core"; import { MapComponent } from "@maplibre/ngx-maplibre-gl"; import { Observable } from "rxjs"; -import { Store, Select } from "@ngxs/store"; -import type { Immutable } from "immer"; +import { Store } from "@ngxs/store"; import { BaseMapComponent } from "./base-map.component"; import { ResourcesService } from "../services/resources.service"; @@ -26,15 +25,8 @@ import type { LatLngAlt, ApplicationState } from "../models/models"; }) export class LocationComponent extends BaseMapComponent { - @Select((state: ApplicationState) => state.inMemoryState.distance) public distance$: Observable; - @Select((state: ApplicationState) => state.inMemoryState.pannedTimestamp) - public pannedTimestamp$: Observable; - - @Select((state: ApplicationState) => state.gpsState.currentPosition) - private currentPosition$: Observable>; - private lastSpeed: number; private lastSpeedTime: number; private isPanned: boolean; @@ -62,12 +54,13 @@ export class LocationComponent extends BaseMapComponent { this.lastSpeedTime = null; this.clearLocationFeatureCollection(); + this.distance$ = this.store.select((state: ApplicationState) => state.inMemoryState.distance); this.distance$.subscribe(distance => { this.showDistance = distance; this.updateDistanceFeatureCollection(); }); - this.pannedTimestamp$.subscribe(pannedTimestamp => { + this.store.select((state: ApplicationState) => state.inMemoryState.pannedTimestamp).subscribe(pannedTimestamp => { this.isPanned = pannedTimestamp != null; if (this.isPanned) { return; @@ -98,7 +91,7 @@ export class LocationComponent extends BaseMapComponent { } }); - this.currentPosition$.subscribe((position: GeolocationPosition) => { + this.store.select((state: ApplicationState) => state.gpsState.currentPosition).subscribe(position => { if (position != null) { this.handlePositionChange(position); } diff --git a/IsraelHiking.Web/src/application/components/main-menu.component.ts b/IsraelHiking.Web/src/application/components/main-menu.component.ts index 4855a549a..0c50d0521 100644 --- a/IsraelHiking.Web/src/application/components/main-menu.component.ts +++ b/IsraelHiking.Web/src/application/components/main-menu.component.ts @@ -1,13 +1,12 @@ import { Component, OnDestroy } from "@angular/core"; import { MatDialog, MatDialogConfig } from "@angular/material/dialog"; -import { Subscription, Observable, timer } from "rxjs"; +import { Subscription, timer } from "rxjs"; import { Device } from "@capacitor/device"; import { App } from "@capacitor/app"; import { SocialSharing } from "@awesome-cordova-plugins/social-sharing/ngx"; import { encode } from "base64-arraybuffer"; -import { Store, Select } from "@ngxs/store"; +import { Store } from "@ngxs/store"; import platform from "platform"; -import type { Immutable } from "immer"; import { BaseMapComponent } from "./base-map.component"; import { ResourcesService } from "../services/resources.service"; @@ -46,15 +45,6 @@ export class MainMenuComponent extends BaseMapComponent implements OnDestroy { public statisticsVisible: boolean; public isShowMore: boolean; - @Select((state: ApplicationState) => state.userState.userInfo) - public userInfo$: Observable>; - - @Select((state: ApplicationState) => state.uiComponentsState.drawingVisible) - public drawingVisible$: Observable; - - @Select((state: ApplicationState) => state.uiComponentsState.statisticsVisible) - public statisticsVisible$: Observable; - constructor(resources: ResourcesService, private readonly socialSharing: SocialSharing, private readonly authorizationService: AuthorizationService, @@ -73,9 +63,9 @@ export class MainMenuComponent extends BaseMapComponent implements OnDestroy { this.isShowMore = false; this.userInfo = null; this.subscriptions = []; - this.subscriptions.push(this.userInfo$.subscribe(userInfo => this.userInfo = userInfo)); - this.subscriptions.push(this.drawingVisible$.subscribe(v => this.drawingVisible = v)); - this.subscriptions.push(this.statisticsVisible$.subscribe(v => this.statisticsVisible = v)); + this.subscriptions.push(this.store.select((state: ApplicationState) => state.userState.userInfo).subscribe(userInfo => this.userInfo = userInfo)); + this.subscriptions.push(this.store.select((state: ApplicationState) => state.uiComponentsState.drawingVisible).subscribe(v => this.drawingVisible = v)); + this.subscriptions.push(this.store.select((state: ApplicationState) => state.uiComponentsState.statisticsVisible).subscribe(v => this.statisticsVisible = v)); if (this.runningContextService.isCapacitor) { App.getInfo().then((info) => { this.loggingService.info(`App version: ${info.version}`); diff --git a/IsraelHiking.Web/src/application/components/map/automatic-layer-presentation.component.ts b/IsraelHiking.Web/src/application/components/map/automatic-layer-presentation.component.ts index 743541fbd..21d599984 100644 --- a/IsraelHiking.Web/src/application/components/map/automatic-layer-presentation.component.ts +++ b/IsraelHiking.Web/src/application/components/map/automatic-layer-presentation.component.ts @@ -7,16 +7,15 @@ import { SourceSpecification, LayerSpecification } from "maplibre-gl"; -import { Observable, Subject, Subscription, mergeMap } from "rxjs"; -import { Store, Select } from "@ngxs/store"; -import type { Immutable } from "immer"; +import { Subject, Subscription, mergeMap } from "rxjs"; +import { Store } from "@ngxs/store"; import { BaseMapComponent } from "../base-map.component"; import { ResourcesService } from "../../services/resources.service"; import { FileService } from "../../services/file.service"; import { ConnectionService } from "../../services/connection.service"; import { MapService } from "../../services/map.service"; -import type { ApplicationState, EditableLayer, Language, LanguageCode, LayerData } from "../../models/models"; +import type { ApplicationState, EditableLayer, LanguageCode, LayerData } from "../../models/models"; @Component({ selector: "auto-layer", @@ -49,9 +48,6 @@ export class AutomaticLayerPresentationComponent extends BaseMapComponent implem private currentLanguageCode: LanguageCode; private recreateQueue: Subject<() => Promise>; - @Select((state: ApplicationState) => state.configuration.language) - private language$: Observable>; - constructor(resources: ResourcesService, private readonly mapComponent: MapComponent, private readonly fileService: FileService, @@ -79,7 +75,7 @@ export class AutomaticLayerPresentationComponent extends BaseMapComponent implem public ngOnInit() { this.addLayerRecreationQuqueItem(null, this.layerData); this.currentLanguageCode = this.store.selectSnapshot((s: ApplicationState) => s.configuration).language.code; - this.subscriptions.push(this.language$.subscribe((language) => { + this.subscriptions.push(this.store.select((state: ApplicationState) => state.configuration.language).subscribe((language) => { if (this.currentLanguageCode !== language.code) { this.addLayerRecreationQuqueItem(this.layerData, this.layerData); } diff --git a/IsraelHiking.Web/src/application/components/map/layers-view.component.html b/IsraelHiking.Web/src/application/components/map/layers-view.component.html index ae2c6459a..b49244bac 100644 --- a/IsraelHiking.Web/src/application/components/map/layers-view.component.html +++ b/IsraelHiking.Web/src/application/components/map/layers-view.component.html @@ -4,7 +4,7 @@ [isBaselayer]="true" [isMainMap]="true"> -
+
[]; public hoverFeature: GeoJSON.Feature; public isShowCoordinatesPopup: boolean; - - @Select((state: ApplicationState) => state.layersState.overlays) - public overlays: Observable>; - - @Select((state: ApplicationState) => state.poiState.selectedPointOfInterest) - public selectedPoi$: Observable>; + public overlays: Immutable; constructor(resources: ResourcesService, private readonly router: Router, @@ -67,7 +61,8 @@ export class LayersViewComponent extends BaseMapComponent implements OnInit { this.poiService.poisChanged.subscribe(() => { this.poiGeoJsonData = this.poiService.poiGeojsonFiltered; }); - this.selectedPoi$.subscribe((poi) => this.onSelectedPoiChanged(poi)); + this.store.select((state: ApplicationState) => state.poiState.selectedPointOfInterest).subscribe(poi => this.onSelectedPoiChanged(poi)); + this.store.select((state: ApplicationState) => state.layersState.overlays).subscribe(overlays => this.overlays = overlays); } private onSelectedPoiChanged(poi: Immutable) { diff --git a/IsraelHiking.Web/src/application/components/map/recorded-route.component.html b/IsraelHiking.Web/src/application/components/map/recorded-route.component.html index f4044f38e..3551f76e7 100644 --- a/IsraelHiking.Web/src/application/components/map/recorded-route.component.html +++ b/IsraelHiking.Web/src/application/components/map/recorded-route.component.html @@ -76,7 +76,7 @@
diff --git a/IsraelHiking.Web/src/application/components/map/recorded-route.component.ts b/IsraelHiking.Web/src/application/components/map/recorded-route.component.ts index f60322f20..7cabf60a5 100644 --- a/IsraelHiking.Web/src/application/components/map/recorded-route.component.ts +++ b/IsraelHiking.Web/src/application/components/map/recorded-route.component.ts @@ -1,6 +1,6 @@ import { Component } from "@angular/core"; import { Observable, combineLatest, throttleTime } from "rxjs"; -import { Store, Select } from "@ngxs/store"; +import { Store } from "@ngxs/store"; import type { Immutable } from "immer"; import { BaseMapComponent } from "../base-map.component"; @@ -17,19 +17,13 @@ export class RecordedRouteComponent extends BaseMapComponent { static readonly NUMBER_OF_POINTS_IN_ROUTE_SPLIT = 4000; - @Select((state: ApplicationState) => state.recordedRouteState.isAddingPoi) - public isAddingPoi$: Observable; - - @Select((state: ApplicationState) => state.recordedRouteState.route) - public recordedRoute$: Observable>; - - @Select((state: ApplicationState) => state.gpsState.currentPosition) - public currentPosition$: Observable>; - + public isAddingPoi: boolean; public recordedRouteSegments: GeoJSON.Feature[]; public lastRouteSegment: GeoJSON.Feature; public startPointGeoJson: GeoJSON.Feature; - + public recordedRoute$: Observable>; + + private currentPosition$: Observable>; private lastSplit: number; constructor(resources: ResourcesService, @@ -47,10 +41,16 @@ export class RecordedRouteComponent extends BaseMapComponent { }, properties: {} }; + this.recordedRoute$ = this.store.select((state: ApplicationState) => state.recordedRouteState.route); + this.currentPosition$ = this.store.select((state: ApplicationState) => state.gpsState.currentPosition); // Combine streams to work when both current location and recorded route changes, added throttle to avoid a double update of the UI combineLatest([this.recordedRoute$, this.currentPosition$]).pipe(throttleTime(50, undefined, { trailing: true })) .subscribe(() => this.handleRecordingChanges()); + + this.store.select((state: ApplicationState) => state.recordedRouteState.isAddingPoi).subscribe((isAddingPoi) => { + this.isAddingPoi = isAddingPoi; + }); } public isRecording() { diff --git a/IsraelHiking.Web/src/application/components/map/routes.component.html b/IsraelHiking.Web/src/application/components/map/routes.component.html index 9b72b4df4..f7a82bafa 100644 --- a/IsraelHiking.Web/src/application/components/map/routes.component.html +++ b/IsraelHiking.Web/src/application/components/map/routes.component.html @@ -116,7 +116,7 @@ -
+
state.routes.present) - public routes$: Observable>; - - @Select((state: ApplicationState) => state.routeEditingState.selectedRouteId) - public selectedRouteId$: Observable>; - - @Select((state: ApplicationState) => state.recordedRouteState.isAddingPoi) - public isAddingPoi$: Observable; - public routePointPopupData: RoutePointViewData; public nonEditRoutePointPopupData: { latlng: LatLngAlt; wazeAddress: string; routeId: string}; public editingRouteGeoJson: GeoJSON.FeatureCollection; public routesGeoJson: GeoJSON.FeatureCollection; - private routes: Immutable; + public routes: Immutable; constructor(resources: ResourcesService, private readonly selectedRouteService: SelectedRouteService, @@ -78,12 +68,12 @@ export class RoutesComponent extends BaseMapComponent implements AfterViewInit { }; this.routes = []; this.routeEditRouteInteraction.onRoutePointClick.subscribe(this.handleRoutePointClick); - this.routes$.subscribe(this.handleRoutesChanges); - this.selectedRouteId$.subscribe(() => this.handleRoutesChanges(this.routes)); - this.isAddingPoi$.subscribe(() => this.setInteractionAccordingToState()); + this.store.select((state: ApplicationState) => state.routes.present).subscribe(routes => this.handleRoutesChanges(routes)); + this.store.select((state: ApplicationState) => state.routeEditingState.selectedRouteId).subscribe(() => this.handleRoutesChanges(this.routes)); + this.store.select((state: ApplicationState) => state.recordedRouteState.isAddingPoi).subscribe(() => this.setInteractionAccordingToState()); } - private handleRoutesChanges = (routes: Immutable) => { + private handleRoutesChanges(routes: Immutable) { this.routes = routes; this.setInteractionAccordingToState(); this.buildFeatureCollections(); diff --git a/IsraelHiking.Web/src/application/components/map/traces.component.ts b/IsraelHiking.Web/src/application/components/map/traces.component.ts index 6825fa1e2..c2e20a76a 100644 --- a/IsraelHiking.Web/src/application/components/map/traces.component.ts +++ b/IsraelHiking.Web/src/application/components/map/traces.component.ts @@ -1,7 +1,5 @@ import { Component } from "@angular/core"; -import { Observable } from "rxjs"; -import { Store, Select } from "@ngxs/store"; -import type { Immutable } from "immer"; +import { Store } from "@ngxs/store"; import type { LngLatLike } from "maplibre-gl"; import { BaseMapComponent } from "../base-map.component"; @@ -28,12 +26,6 @@ export class TracesComponent extends BaseMapComponent { public selectedFeatureSource: GeoJSON.FeatureCollection; public isConfigOpen: boolean; - @Select((state: ApplicationState) => state.tracesState.visibleTraceId) - private visibleTraceId$: Observable; - - @Select((state: ApplicationState) => state.tracesState.missingParts) - private missingParts$: Observable>>; - constructor(resources: ResourcesService, private readonly routesFactory: RoutesFactory, private readonly tracesService: TracesService, @@ -48,7 +40,7 @@ export class TracesComponent extends BaseMapComponent { type: "FeatureCollection", features: [] }; - this.visibleTraceId$.subscribe(async (id) => { + this.store.select((state: ApplicationState) => state.tracesState.visibleTraceId).subscribe(async (id) => { if (id == null) { this.clearTraceSource(); @@ -94,7 +86,7 @@ export class TracesComponent extends BaseMapComponent { this.selectedTraceStart = traceCoordinates[0]; }); - this.missingParts$.subscribe(m => { + this.store.select((state: ApplicationState) => state.tracesState.missingParts).subscribe(m => { if (m != null) { this.missingParts = structuredClone(m) as GeoJSON.FeatureCollection; } else { diff --git a/IsraelHiking.Web/src/application/components/overlays/gps-location-overlay.component.html b/IsraelHiking.Web/src/application/components/overlays/gps-location-overlay.component.html index eafcad5fc..c70bae8b8 100644 --- a/IsraelHiking.Web/src/application/components/overlays/gps-location-overlay.component.html +++ b/IsraelHiking.Web/src/application/components/overlays/gps-location-overlay.component.html @@ -4,7 +4,7 @@
- +
diff --git a/IsraelHiking.Web/src/application/components/overlays/gps-location-overlay.component.ts b/IsraelHiking.Web/src/application/components/overlays/gps-location-overlay.component.ts index 21dfa403a..893a1823d 100644 --- a/IsraelHiking.Web/src/application/components/overlays/gps-location-overlay.component.ts +++ b/IsraelHiking.Web/src/application/components/overlays/gps-location-overlay.component.ts @@ -1,8 +1,7 @@ import { Component, Input, Output, EventEmitter } from "@angular/core"; import { MatDialog } from "@angular/material/dialog"; -import { Observable } from "rxjs"; import { SocialSharing } from "@awesome-cordova-plugins/social-sharing/ngx"; -import { Store, Select } from "@ngxs/store"; +import { Store } from "@ngxs/store"; import { BaseMapComponent } from "../base-map.component"; import { PrivatePoiEditDialogComponent } from "../dialogs/private-poi-edit-dialog.component"; @@ -29,9 +28,7 @@ export class GpsLocationOverlayComponent extends BaseMapComponent { @Output() public closed = new EventEmitter(); - @Select((state: ApplicationState) => state.inMemoryState.distance) - public distance$: Observable; - + public distance: boolean; public hideCoordinates: boolean; constructor(resources: ResourcesService, @@ -44,6 +41,9 @@ export class GpsLocationOverlayComponent extends BaseMapComponent { private readonly store: Store) { super(resources); this.hideCoordinates = true; + this.store.select((state: ApplicationState) => state.inMemoryState.distance).subscribe((distance) => { + this.distance = distance; + }); } public addPointToRoute() { diff --git a/IsraelHiking.Web/src/application/components/route-statistics.component.html b/IsraelHiking.Web/src/application/components/route-statistics.component.html index 86d228838..893adcff2 100644 --- a/IsraelHiking.Web/src/application/components/route-statistics.component.html +++ b/IsraelHiking.Web/src/application/components/route-statistics.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/IsraelHiking.Web/src/application/components/route-statistics.component.ts b/IsraelHiking.Web/src/application/components/route-statistics.component.ts index 5f1fdd891..26c973390 100644 --- a/IsraelHiking.Web/src/application/components/route-statistics.component.ts +++ b/IsraelHiking.Web/src/application/components/route-statistics.component.ts @@ -1,9 +1,9 @@ import { Component, ViewEncapsulation, OnInit, OnDestroy, ViewChild, ElementRef, ChangeDetectorRef } from "@angular/core"; import { trigger, style, transition, animate } from "@angular/animations"; -import { Subscription, Observable, interval } from "rxjs"; +import { Subscription, interval } from "rxjs"; import { regressionLoess } from "d3-regression"; import { LineLayerSpecification } from "maplibre-gl"; -import { Store, Select } from "@ngxs/store"; +import { Store } from "@ngxs/store"; import * as d3 from "d3"; import type { Selection, ScaleContinuousNumeric } from "d3"; import type { Immutable } from "immer"; @@ -18,7 +18,7 @@ import { SpatialService } from "../services/spatial.service"; import { GeoLocationService } from "../services/geo-location.service"; import { AudioPlayerFactory, IAudioPlayer } from "../services/audio-player.factory"; import { ToggleIsShowKmMarkersAction, ToggleIsShowSlopeAction } from "../reducers/configuration.reducer"; -import type { LatLngAlt, RouteData, ApplicationState, Language, LatLngAltTime } from "../models/models"; +import type { LatLngAlt, ApplicationState, LatLngAltTime } from "../models/models"; declare type DragState = "start" | "drag" | "none"; @@ -97,34 +97,11 @@ export class RouteStatisticsComponent extends BaseMapComponent implements OnInit public slopeRouteSource: GeoJSON.FeatureCollection; public subRouteRange: IChartSubRouteRange; public slopeRoutePaint: LineLayerSpecification["paint"]; + public statisticsVisible: boolean; @ViewChild("lineChartContainer") public lineChartContainer: ElementRef; - @Select((state: ApplicationState) => state.routes.present) - private routes$: Observable>; - - @Select((state: ApplicationState) => state.routeEditingState.selectedRouteId) - private selectedRouteId$: Observable; - - @Select((state: ApplicationState) => state.locationState.zoom) - private zoom$: Observable; - - @Select((state: ApplicationState) => state.gpsState.currentPosition) - private currentPosition$: Observable>; - - @Select((state: ApplicationState) => state.uiComponentsState.statisticsVisible) - public statisticsVisible$: Observable; - - @Select((state: ApplicationState) => state.configuration.language) - public language$: Observable>; - - @Select((state: ApplicationState) => state.configuration.isShowSlope) - public isShowSlope$: Observable; - - @Select((state: ApplicationState) => state.configuration.isShowKmMarker) - public isShowKmMarkers$: Observable; - private statistics: RouteStatistics; private chartElements: IChartElements; private componentSubscriptions: Subscription[]; @@ -147,6 +124,7 @@ export class RouteStatisticsComponent extends BaseMapComponent implements OnInit this.isOpen = false; this.isTable = false; this.isFollowing = false; + this.statisticsVisible = false; this.statistics = null; this.subRouteRange = null; this.heading = null; @@ -169,7 +147,7 @@ export class RouteStatisticsComponent extends BaseMapComponent implements OnInit margin: { top: 10, right: 10, bottom: 40, left: 40 }, } as IChartElements; this.zoom = 7; - this.zoom$.subscribe((zoom) => { + this.store.select((state: ApplicationState) => state.locationState.zoom).subscribe((zoom) => { this.zoom = zoom; this.updateKmMarkers(); }); @@ -248,27 +226,30 @@ export class RouteStatisticsComponent extends BaseMapComponent implements OnInit } public async ngOnInit() { - this.componentSubscriptions.push(this.routes$.subscribe(() => { + this.componentSubscriptions.push(this.store.select((state: ApplicationState) => state.routes.present).subscribe(() => { this.routeChanged(); })); - this.componentSubscriptions.push(this.selectedRouteId$.subscribe(() => { + this.componentSubscriptions.push(this.store.select((state: ApplicationState) => state.routeEditingState.selectedRouteId).subscribe(() => { this.routeChanged(); })); - this.componentSubscriptions.push(this.language$.subscribe(() => { + this.componentSubscriptions.push(this.store.select((state: ApplicationState) => state.configuration.language).subscribe(() => { this.redrawChart(); })); - this.componentSubscriptions.push(this.currentPosition$.subscribe(p => { + this.componentSubscriptions.push(this.store.select((state: ApplicationState) => state.gpsState.currentPosition).subscribe(p => { this.onGeolocationChanged(p); })); - this.componentSubscriptions.push(this.isShowSlope$.subscribe(showSlope => { + this.componentSubscriptions.push(this.store.select((state: ApplicationState) => state.configuration.isShowSlope).subscribe(showSlope => { this.isSlopeOn = showSlope; this.redrawChart(); this.updateSlopeRoute(); })); - this.componentSubscriptions.push(this.isShowKmMarkers$.subscribe(showKmMarkers => { + this.componentSubscriptions.push(this.store.select((state: ApplicationState) => state.configuration.isShowKmMarker).subscribe(showKmMarkers => { this.isKmMarkersOn = showKmMarkers; this.updateKmMarkers(); })); + this.componentSubscriptions.push(this.store.select((state: ApplicationState) => state.uiComponentsState.statisticsVisible).subscribe(visible => { + this.statisticsVisible = visible; + })); this.routeChanged(); this.componentSubscriptions.push(interval(1000).subscribe(() => { const recordedRouteState = this.store.selectSnapshot((s: ApplicationState) => s.recordedRouteState); diff --git a/IsraelHiking.Web/src/application/components/sidebar/info-sidebar.component.ts b/IsraelHiking.Web/src/application/components/sidebar/info-sidebar.component.ts index cc688b4e1..b061fd95e 100644 --- a/IsraelHiking.Web/src/application/components/sidebar/info-sidebar.component.ts +++ b/IsraelHiking.Web/src/application/components/sidebar/info-sidebar.component.ts @@ -2,9 +2,7 @@ import { Component } from "@angular/core"; import { MatDialog } from "@angular/material/dialog"; import { remove } from "lodash-es"; import { Angulartics2GoogleGlobalSiteTag } from "angulartics2"; -import { Observable } from "rxjs"; -import { Select } from "@ngxs/store"; -import type { Immutable } from "immer"; +import { Store } from "@ngxs/store"; import { BaseMapComponent } from "../base-map.component"; import { DownloadDialogComponent } from "../dialogs/download-dialog.component"; @@ -33,22 +31,20 @@ export class InfoSidebarComponent extends BaseMapComponent { public selectedTabIndex: number; private selectedSection: LegendSection; - @Select((state: ApplicationState) => state.configuration.language) - private language$: Observable>; - constructor(resources: ResourcesService, private readonly dialog: MatDialog, private readonly angulartics: Angulartics2GoogleGlobalSiteTag, private readonly sidebarService: SidebarService, private readonly layersService: LayersService, - private readonly runningContext: RunningContextService) { + private readonly runningContext: RunningContextService, + private readonly store: Store) { super(resources); this.selectedTabIndex = 0; this.selectedSection = null; this.legendSections = []; - this.language$.subscribe(() => { + this.store.select((state: ApplicationState) => state.configuration.language).subscribe(() => { this.initalizeLegendSections(); }); } diff --git a/IsraelHiking.Web/src/application/components/sidebar/layers-sidebar.component.html b/IsraelHiking.Web/src/application/components/sidebar/layers-sidebar.component.html index f9a52fdc4..38d17fbd0 100644 --- a/IsraelHiking.Web/src/application/components/sidebar/layers-sidebar.component.html +++ b/IsraelHiking.Web/src/application/components/sidebar/layers-sidebar.component.html @@ -17,7 +17,7 @@
-
+
-
+
- + @@ -75,7 +75,7 @@
-
+
-
-
{{resources.lastUpdatedOn}} {{lastModified | async | date:'dd/MM/yyyy'}}
+
+
{{resources.lastUpdatedOn}} {{lastModified | date:'dd/MM/yyyy'}}

{{resources.offlinePurchaseGraditude}}
diff --git a/IsraelHiking.Web/src/application/components/sidebar/layers-sidebar.component.ts b/IsraelHiking.Web/src/application/components/sidebar/layers-sidebar.component.ts index 1ca8bd14d..8d6f5e3a0 100644 --- a/IsraelHiking.Web/src/application/components/sidebar/layers-sidebar.component.ts +++ b/IsraelHiking.Web/src/application/components/sidebar/layers-sidebar.component.ts @@ -1,8 +1,8 @@ -import { Component, ViewEncapsulation } from "@angular/core"; +import { Component, ViewEncapsulation, OnDestroy } from "@angular/core"; import { MatDialog } from "@angular/material/dialog"; import { CdkDragDrop, moveItemInArray } from "@angular/cdk/drag-drop"; -import { Observable } from "rxjs"; -import { Store, Select } from "@ngxs/store"; +import { Subscription } from "rxjs"; +import { Store } from "@ngxs/store"; import type { Immutable } from "immer"; import { BaseMapComponent } from "../base-map.component"; @@ -31,24 +31,17 @@ import type { ApplicationState, RouteData, EditableLayer, Overlay, CategoriesGro styleUrls: ["./layers-sidebar.component.scss"], encapsulation: ViewEncapsulation.None }) -export class LayersSidebarComponent extends BaseMapComponent { +export class LayersSidebarComponent extends BaseMapComponent implements OnDestroy { - @Select((state: ApplicationState) => state.layersState.baseLayers) - public baseLayers: Observable>; + public baseLayers: Immutable; + public overlays: Immutable; + public categoriesGroups: Immutable; + public routes: Immutable; - @Select((state: ApplicationState) => state.layersState.overlays) - public overlays: Observable>; - - @Select((state: ApplicationState) => state.layersState.categoriesGroups) - public categoriesGroups: Observable>; - - @Select((state: ApplicationState) => state.routes.present) - public routes: Observable>; - - @Select((state: ApplicationState) => state.offlineState.lastModifiedDate) - public lastModified: Observable; + public lastModified: Date; public manageSubscriptions: string; + private subscriptions: Subscription[]; constructor(resources: ResourcesService, private readonly dialog: MatDialog, @@ -64,6 +57,28 @@ export class LayersSidebarComponent extends BaseMapComponent { this.manageSubscriptions = this.runningContextService.isIos ? "https://apps.apple.com/account/subscriptions" : "https://play.google.com/store/account/subscriptions"; + this.subscriptions = []; + this.subscriptions.push(this.store.select((state: ApplicationState) => state.offlineState.lastModifiedDate).subscribe((lastModifiedDate) => { + this.lastModified = lastModifiedDate; + })); + this.subscriptions.push(this.store.select((state: ApplicationState) => state.layersState.baseLayers).subscribe((baseLayers) => { + this.baseLayers = baseLayers; + })); + this.subscriptions.push(this.store.select((state: ApplicationState) => state.layersState.overlays).subscribe((overlays) => { + this.overlays = overlays; + })); + this.subscriptions.push(this.store.select((state: ApplicationState) => state.layersState.categoriesGroups).subscribe((categoriesGroups) => { + this.categoriesGroups = categoriesGroups; + })); + this.subscriptions.push(this.store.select((state: ApplicationState) => state.routes.present).subscribe((routes) => { + this.routes = routes; + })); + } + + public ngOnDestroy() { + for (const subscription of this.subscriptions) { + subscription.unsubscribe(); + } } public closeSidebar() { diff --git a/IsraelHiking.Web/src/application/components/sidebar/publicpoi/public-poi-sidebar.component.html b/IsraelHiking.Web/src/application/components/sidebar/publicpoi/public-poi-sidebar.component.html index e3aaf73ee..6a078b3f3 100644 --- a/IsraelHiking.Web/src/application/components/sidebar/publicpoi/public-poi-sidebar.component.html +++ b/IsraelHiking.Web/src/application/components/sidebar/publicpoi/public-poi-sidebar.component.html @@ -1,4 +1,4 @@ -