diff --git a/IsraelHiking.Web/src/application/components/application-state.component.ts b/IsraelHiking.Web/src/application/components/application-state.component.ts index cf914ea5e..1d0bba195 100644 --- a/IsraelHiking.Web/src/application/components/application-state.component.ts +++ b/IsraelHiking.Web/src/application/components/application-state.component.ts @@ -1,7 +1,5 @@ -import { Component, OnInit, OnDestroy } from "@angular/core"; - +import { Component, DestroyRef, OnInit } from "@angular/core"; import { Router, ActivatedRoute } from "@angular/router"; -import { Subscription } from "rxjs"; import { Store } from "@ngxs/store"; import { RouteStrings } from "../services/hash.service"; @@ -9,26 +7,24 @@ import { SidebarService } from "../services/sidebar.service"; import { DataContainerService } from "../services/data-container.service"; import { FitBoundsService } from "../services/fit-bounds.service"; import { SetFileUrlAndBaseLayerAction, SetShareUrlAction } from "../reducers/in-memory.reducer"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; @Component({ selector: "application-state", template: "
" }) -export class ApplicationStateComponent implements OnInit, OnDestroy { - - private subscription: Subscription; - +export class ApplicationStateComponent implements OnInit { constructor(private readonly router: Router, private readonly route: ActivatedRoute, private readonly sidebarService: SidebarService, private readonly dataContainerService: DataContainerService, private readonly fitBoundsService: FitBoundsService, - private readonly store: Store) { - this.subscription = null; + private readonly store: Store, + private readonly destroyRef: DestroyRef) { } public ngOnInit() { - this.subscription = this.route.params.subscribe(params => { + this.route.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(params => { if (this.router.url.startsWith(RouteStrings.ROUTE_MAP)) { this.fitBoundsService.flyTo({ lng: +params[RouteStrings.LON], @@ -46,10 +42,4 @@ export class ApplicationStateComponent implements OnInit, OnDestroy { } }); } - - public ngOnDestroy() { - if (this.subscription) { - this.subscription.unsubscribe(); - } - } } diff --git a/IsraelHiking.Web/src/application/components/background-text.component.ts b/IsraelHiking.Web/src/application/components/background-text.component.ts index 0365af07f..f3de6b576 100644 --- a/IsraelHiking.Web/src/application/components/background-text.component.ts +++ b/IsraelHiking.Web/src/application/components/background-text.component.ts @@ -1,11 +1,10 @@ import { Component } from "@angular/core"; -import { Observable } from "rxjs"; -import { Store, Select } from "@ngxs/store"; -import type { Immutable } from "immer"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; +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 +13,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 +20,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).pipe(takeUntilDestroyed()).subscribe(() => this.updateText()); + this.store.select((state: ApplicationState) => state.offlineState.lastModifiedDate).pipe(takeUntilDestroyed()).subscribe(() => this.updateText()); + this.store.select((state: ApplicationState) => state.configuration.language).pipe(takeUntilDestroyed()).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..a73f8158d 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..10238da1a 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 { MatDialogRef } from "@angular/material/dialog"; 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"; @@ -22,14 +22,9 @@ import type { ApplicationState, BatteryOptimizationType } from "../../models/mod }) export class ConfigurationDialogComponent extends BaseMapComponent { - @Select((state: ApplicationState) => state.configuration.batteryOptimizationType) - public batteryOptimizationType: Observable; - - @Select((state: ApplicationState) => state.configuration.isAutomaticRecordingUpload) - public isAutomaticRecordingUpload: Observable; - - @Select((state: ApplicationState) => state.configuration.isGotLostWarnings) - public isGotLostWarnings: Observable; + public batteryOptimizationType$: Observable; + public isAutomaticRecordingUpload$: Observable; + public isGotLostWarnings$: Observable; constructor(resources: ResourcesService, private readonly dialogRef: MatDialogRef, @@ -38,6 +33,9 @@ export class ConfigurationDialogComponent extends BaseMapComponent { private readonly logginService: LoggingService, private readonly store: Store) { super(resources); + this.batteryOptimizationType$ = this.store.select((state: ApplicationState) => state.configuration.batteryOptimizationType); + this.isAutomaticRecordingUpload$ = this.store.select((state: ApplicationState) => state.configuration.isAutomaticRecordingUpload); + this.isGotLostWarnings$ = this.store.select((state: ApplicationState) => state.configuration.isGotLostWarnings); } 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..31b9a304e 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 { Observable, firstValueFrom } from "rxjs"; +import { Store } from "@ngxs/store"; import { BaseMapComponent } from "../../base-map.component"; import { ResourcesService } from "../../../services/resources.service"; @@ -14,18 +14,15 @@ export abstract class LayerBaseDialogComponent extends BaseMapComponent { public title: string; public isNew: boolean; public isOverlay: boolean; - public layerData: EditableLayer; - - @Select((state: ApplicationState) => state.locationState) - public location: Observable>; + public location$: Observable>; 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 +34,8 @@ export abstract class LayerBaseDialogComponent extends BaseMapComponent { isOfflineAvailable: false, isOfflineOn: true } as EditableLayer; + + this.location$ = this.store.select((state: ApplicationState) => state.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..f70662122 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 @@
; public shareUrlInEditMode: ShareUrl; 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>; private sessionSearchTerm = ""; private page: number; - private subscriptions: Subscription[]; constructor(resources: ResourcesService, private readonly dialog: MatDialog, @@ -56,17 +51,17 @@ export class SharesDialogComponent extends BaseMapComponent implements OnInit, O this.shareUrlInEditMode = null; this.selectedShareUrlId = null; this.page = 1; - this.subscriptions = []; this.searchTerm = new FormControl(""); - this.subscriptions.push(this.searchTerm.valueChanges.subscribe((searchTerm: string) => { + this.searchTerm.valueChanges.pipe(takeUntilDestroyed()).subscribe((searchTerm: string) => { this.updateFilteredLists(searchTerm); - })); + }); this.searchTerm.setValue(this.sessionSearchTerm); - this.subscriptions.push(this.shareUrls$.subscribe(() => { + this.store.select((state: ApplicationState) => state.shareUrlsState.shareUrls).pipe(takeUntilDestroyed()).subscribe(() => { if (!this.loadingShareUrls) { this.updateFilteredLists(this.searchTerm.value); } - })); + }); + this.shownShareUrl$ = this.store.select((state: ApplicationState) => state.inMemoryState.shareUrl).pipe(takeUntilDestroyed()); } public async ngOnInit() { @@ -76,12 +71,6 @@ export class SharesDialogComponent extends BaseMapComponent implements OnInit, O this.updateFilteredLists(this.searchTerm.value); } - public ngOnDestroy() { - for (const subscription of this.subscriptions) { - subscription.unsubscribe(); - } - } - public isApp(): boolean { return this.runningContextService.isCapacitor; } 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..f3c91ad36 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 { Component, OnInit, ViewEncapsulation, Inject } from "@angular/core"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { FormControl } from "@angular/forms"; import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; -import { Subscription, Observable } 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"; @@ -26,7 +26,7 @@ import type { ApplicationState, Trace, TraceVisibility } from "../../models/mode styleUrls: ["./traces-dialog.component.scss"], encapsulation: ViewEncapsulation.None }) -export class TracesDialogComponent extends BaseMapComponent implements OnInit, OnDestroy { +export class TracesDialogComponent extends BaseMapComponent implements OnInit { public filteredTraces: Immutable; public selectedTraceId: string; @@ -35,12 +35,8 @@ 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; private specificIds: string[]; constructor(resources: ResourcesService, @@ -68,11 +64,11 @@ export class TracesDialogComponent extends BaseMapComponent implements OnInit, O this.specificIds = []; } - this.searchTerm.valueChanges.subscribe((searchTerm: string) => { + this.searchTerm.valueChanges.pipe(takeUntilDestroyed()).subscribe((searchTerm: string) => { this.updateFilteredLists(searchTerm); }); this.searchTerm.setValue(this.sessionSearchTerm); - this.tracesChangedSubscription = this.traces$.subscribe(() => { + this.store.select((state: ApplicationState) => state.tracesState.traces).pipe(takeUntilDestroyed()).subscribe(() => { if (!this.loadingTraces) { this.updateFilteredLists(this.searchTerm.value); } @@ -86,10 +82,6 @@ export class TracesDialogComponent extends BaseMapComponent implements OnInit, O this.updateFilteredLists(this.searchTerm.value); } - public ngOnDestroy() { - this.tracesChangedSubscription.unsubscribe(); - } - public async addTraceToRoutes() { const trace = await this.tracesService.getTraceById(this.selectedTraceId); this.dataContainerService.setData(trace.dataContainer, true); diff --git a/IsraelHiking.Web/src/application/components/drawing.component.html b/IsraelHiking.Web/src/application/components/drawing.component.html index c6906a44c..5e51b8dca 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..493520617 100644 --- a/IsraelHiking.Web/src/application/components/drawing.component.ts +++ b/IsraelHiking.Web/src/application/components/drawing.component.ts @@ -1,6 +1,6 @@ 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 +25,14 @@ import type { RoutingType, ApplicationState } from "../models/models"; }) export class DrawingComponent extends BaseMapComponent { - @Select((state: ApplicationState) => state.routes.past.length) - public undoQueueLength: Observable; + public undoQueueLength$: Observable; constructor(resources: ResourcesService, private readonly selectedRouteService: SelectedRouteService, private readonly toastService: ToastService, private readonly store: Store) { super(resources); + this.undoQueueLength$ = this.store.select((state: ApplicationState) => state.routes.past.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..468491d3b 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 { Component, DestroyRef } from "@angular/core"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; 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,6 @@ 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; @@ -53,6 +43,7 @@ export class LocationComponent extends BaseMapComponent { private readonly fitBoundsService: FitBoundsService, private readonly deviceOrientationService: DeviceOrientationService, private readonly store: Store, + private readonly destroyRef: DestroyRef, private readonly mapComponent: MapComponent) { super(resources); @@ -62,12 +53,12 @@ export class LocationComponent extends BaseMapComponent { this.lastSpeedTime = null; this.clearLocationFeatureCollection(); - this.distance$.subscribe(distance => { + this.store.select((state: ApplicationState) => state.inMemoryState.distance).pipe(takeUntilDestroyed()).subscribe(distance => { this.showDistance = distance; this.updateDistanceFeatureCollection(); }); - this.pannedTimestamp$.subscribe(pannedTimestamp => { + this.store.select((state: ApplicationState) => state.inMemoryState.pannedTimestamp).pipe(takeUntilDestroyed()).subscribe(pannedTimestamp => { this.isPanned = pannedTimestamp != null; if (this.isPanned) { return; @@ -98,13 +89,13 @@ export class LocationComponent extends BaseMapComponent { } }); - this.currentPosition$.subscribe((position: GeolocationPosition) => { + this.store.select((state: ApplicationState) => state.gpsState.currentPosition).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(position => { if (position != null) { this.handlePositionChange(position); } }); - this.deviceOrientationService.orientationChanged.subscribe((bearing: number) => { + this.deviceOrientationService.orientationChanged.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((bearing: number) => { if (!this.isActive() || this.locationFeatures.features.length === 0) { return; } diff --git a/IsraelHiking.Web/src/application/components/main-menu.component.ts b/IsraelHiking.Web/src/application/components/main-menu.component.ts index 4855a549a..b5da322ce 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 { Component } from "@angular/core"; import { MatDialog, MatDialogConfig } from "@angular/material/dialog"; -import { Subscription, Observable, timer } from "rxjs"; +import { 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"; @@ -31,30 +30,20 @@ import { SendReportDialogComponent } from "./dialogs/send-report-dialog.componen import { SetUIComponentVisibilityAction } from "../reducers/ui-components.reducer"; import { SetAgreeToTermsAction } from "../reducers/user.reducer"; import type { UserInfo, ApplicationState } from "../models/models"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; @Component({ selector: "main-menu", templateUrl: "./main-menu.component.html", styleUrls: ["./main-menu.component.scss"] }) -export class MainMenuComponent extends BaseMapComponent implements OnDestroy { - - private subscriptions: Subscription[]; +export class MainMenuComponent extends BaseMapComponent { public userInfo: UserInfo; public drawingVisible: boolean; 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, @@ -72,10 +61,9 @@ export class MainMenuComponent extends BaseMapComponent implements OnDestroy { super(resources); 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.store.select((state: ApplicationState) => state.userState.userInfo).pipe(takeUntilDestroyed()).subscribe(userInfo => this.userInfo = userInfo); + this.store.select((state: ApplicationState) => state.uiComponentsState.drawingVisible).pipe(takeUntilDestroyed()).subscribe(v => this.drawingVisible = v); + this.store.select((state: ApplicationState) => state.uiComponentsState.statisticsVisible).pipe(takeUntilDestroyed()).subscribe(v => this.statisticsVisible = v); if (this.runningContextService.isCapacitor) { App.getInfo().then((info) => { this.loggingService.info(`App version: ${info.version}`); @@ -83,12 +71,6 @@ export class MainMenuComponent extends BaseMapComponent implements OnDestroy { } } - public ngOnDestroy(): void { - for (const subscription of this.subscriptions) { - subscription.unsubscribe(); - } - } - public isLoggedIn() { return this.userInfo != null; } @@ -141,14 +123,14 @@ export class MainMenuComponent extends BaseMapComponent implements OnDestroy { public selectDrawing() { this.store.dispatch(new SetUIComponentVisibilityAction( "drawing", - !this.store.selectSnapshot((s: ApplicationState) => s.uiComponentsState).drawingVisible + !this.drawingVisible )); } public selectStatistics() { this.store.dispatch(new SetUIComponentVisibilityAction( "statistics", - !this.store.selectSnapshot((s: ApplicationState) => s.uiComponentsState).statisticsVisible + !this.statisticsVisible )); } 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..93d74abd9 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); } @@ -244,4 +240,4 @@ export class AutomaticLayerPresentationComponent extends BaseMapComponent implem } }); } -} +} \ No newline at end of file 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..86b3b37e2 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$: Observable>; constructor(resources: ResourcesService, private readonly router: Router, @@ -45,7 +41,8 @@ export class LayersViewComponent extends BaseMapComponent implements OnInit { private readonly poiService: PoiService, private readonly selectedRouteService: SelectedRouteService, private readonly navigateHereService: NavigateHereService, - private readonly store: Store + private readonly store: Store, + private readonly destroyRef: DestroyRef ) { super(resources); this.selectedCluster = null; @@ -56,6 +53,7 @@ export class LayersViewComponent extends BaseMapComponent implements OnInit { type: "FeatureCollection", features: [] }; + this.overlays$ = this.store.select((state: ApplicationState) => state.layersState.overlays); } public getBaseLayer() { @@ -64,10 +62,10 @@ export class LayersViewComponent extends BaseMapComponent implements OnInit { public ngOnInit() { this.poiGeoJsonData = this.poiService.poiGeojsonFiltered; - this.poiService.poisChanged.subscribe(() => { + this.poiService.poisChanged.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { this.poiGeoJsonData = this.poiService.poiGeojsonFiltered; }); - this.selectedPoi$.subscribe((poi) => this.onSelectedPoiChanged(poi)); + this.store.select((state: ApplicationState) => state.poiState.selectedPointOfInterest).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(poi => this.onSelectedPoiChanged(poi)); } private onSelectedPoiChanged(poi: Immutable) { 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..acaa3819c 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,7 @@ import { Component } from "@angular/core"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; 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 +18,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 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 +42,14 @@ 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 })) + combineLatest([this.recordedRoute$, this.currentPosition$]).pipe(throttleTime(50, undefined, { trailing: true }), takeUntilDestroyed()) .subscribe(() => this.handleRecordingChanges()); + + this.isAddingPoi$ = this.store.select((state: ApplicationState) => state.recordedRouteState.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, @@ -77,17 +66,17 @@ export class RoutesComponent extends BaseMapComponent implements AfterViewInit { features: [] }; 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.routeEditRouteInteraction.onRoutePointClick.pipe(takeUntilDestroyed()).subscribe(this.handleRoutePointClick); + this.store.select((state: ApplicationState) => state.routes.present).pipe(takeUntilDestroyed()).subscribe(routes => this.handleRoutesChanges(routes)); + this.store.select((state: ApplicationState) => state.routeEditingState.selectedRouteId).pipe(takeUntilDestroyed()).subscribe(() => this.handleRoutesChanges(this.routes)); + this.store.select((state: ApplicationState) => state.recordedRouteState.isAddingPoi).pipe(takeUntilDestroyed()).subscribe(() => this.setInteractionAccordingToState()); } - private handleRoutesChanges = (routes: Immutable) => { + private handleRoutesChanges(routes: Immutable) { this.routes = routes; this.setInteractionAccordingToState(); this.buildFeatureCollections(); - }; + } private buildFeatureCollections() { let features = [] as GeoJSON.Feature[]; diff --git a/IsraelHiking.Web/src/application/components/map/traces.component.ts b/IsraelHiking.Web/src/application/components/map/traces.component.ts index 6825fa1e2..7cf6e4b2b 100644 --- a/IsraelHiking.Web/src/application/components/map/traces.component.ts +++ b/IsraelHiking.Web/src/application/components/map/traces.component.ts @@ -1,7 +1,6 @@ import { Component } from "@angular/core"; -import { Observable } from "rxjs"; -import { Store, Select } from "@ngxs/store"; -import type { Immutable } from "immer"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; +import { Store } from "@ngxs/store"; import type { LngLatLike } from "maplibre-gl"; import { BaseMapComponent } from "../base-map.component"; @@ -28,12 +27,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 +41,7 @@ export class TracesComponent extends BaseMapComponent { type: "FeatureCollection", features: [] }; - this.visibleTraceId$.subscribe(async (id) => { + this.store.select((state: ApplicationState) => state.tracesState.visibleTraceId).pipe(takeUntilDestroyed()).subscribe(async (id) => { if (id == null) { this.clearTraceSource(); @@ -94,7 +87,7 @@ export class TracesComponent extends BaseMapComponent { this.selectedTraceStart = traceCoordinates[0]; }); - this.missingParts$.subscribe(m => { + this.store.select((state: ApplicationState) => state.tracesState.missingParts).pipe(takeUntilDestroyed()).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.ts b/IsraelHiking.Web/src/application/components/overlays/gps-location-overlay.component.ts index 21dfa403a..61f672cb4 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 @@ -2,7 +2,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 +29,7 @@ export class GpsLocationOverlayComponent extends BaseMapComponent { @Output() public closed = new EventEmitter(); - @Select((state: ApplicationState) => state.inMemoryState.distance) public distance$: Observable; - public hideCoordinates: boolean; constructor(resources: ResourcesService, @@ -44,6 +42,7 @@ export class GpsLocationOverlayComponent extends BaseMapComponent { private readonly store: Store) { super(resources); this.hideCoordinates = true; + this.distance$ = this.store.select((state: ApplicationState) => state.inMemoryState.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..5c603a618 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..7d786cc2b 100644 --- a/IsraelHiking.Web/src/application/components/route-statistics.component.ts +++ b/IsraelHiking.Web/src/application/components/route-statistics.component.ts @@ -1,9 +1,10 @@ -import { Component, ViewEncapsulation, OnInit, OnDestroy, ViewChild, ElementRef, ChangeDetectorRef } from "@angular/core"; +import { Component, ViewEncapsulation, OnInit, ViewChild, ElementRef, ChangeDetectorRef, DestroyRef } from "@angular/core"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { trigger, style, transition, animate } from "@angular/animations"; -import { Subscription, Observable, interval } from "rxjs"; +import { Observable, 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 +19,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"; @@ -72,7 +73,7 @@ interface IChartElements { ) ], }) -export class RouteStatisticsComponent extends BaseMapComponent implements OnInit, OnDestroy { +export class RouteStatisticsComponent extends BaseMapComponent implements OnInit { private static readonly HOVER_BOX_WIDTH = 160; private static readonly MAX_SLOPE = 20; @@ -97,37 +98,13 @@ export class RouteStatisticsComponent extends BaseMapComponent implements OnInit public slopeRouteSource: GeoJSON.FeatureCollection; public subRouteRange: IChartSubRouteRange; public slopeRoutePaint: LineLayerSpecification["paint"]; + public statisticsVisible$: Observable; @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[]; private zoom: number; private routeColor: string; private audioPlayer: IAudioPlayer; @@ -140,7 +117,8 @@ export class RouteStatisticsComponent extends BaseMapComponent implements OnInit private readonly cancelableTimeoutService: CancelableTimeoutService, private readonly sidebarService: SidebarService, private readonly audioPlayerFactory: AudioPlayerFactory, - private readonly store: Store + private readonly store: Store, + private readonly destroyRef: DestroyRef, ) { super(resources); this.isExpanded = false; @@ -151,7 +129,6 @@ export class RouteStatisticsComponent extends BaseMapComponent implements OnInit this.subRouteRange = null; this.heading = null; this.setViewStatisticsValues(null); - this.componentSubscriptions = []; this.kmMarkersSource = { type: "FeatureCollection", features: [] @@ -169,14 +146,15 @@ 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).pipe(takeUntilDestroyed()).subscribe((zoom) => { this.zoom = zoom; this.updateKmMarkers(); }); - this.componentSubscriptions.push(this.sidebarService.sideBarStateChanged.subscribe(() => { + this.sidebarService.sideBarStateChanged.pipe(takeUntilDestroyed()).subscribe(() => { this.redrawChart(); - })); - this.componentSubscriptions.push(this.selectedRouteService.selectedRouteHover.subscribe(this.onSelectedRouteHover)); + }); + this.selectedRouteService.selectedRouteHover.pipe(takeUntilDestroyed()).subscribe(this.onSelectedRouteHover); + this.statisticsVisible$ = this.store.select((state: ApplicationState) => state.uiComponentsState.statisticsVisible); } private setViewStatisticsValues(statistics: RouteStatistics): void { @@ -248,44 +226,38 @@ export class RouteStatisticsComponent extends BaseMapComponent implements OnInit } public async ngOnInit() { - this.componentSubscriptions.push(this.routes$.subscribe(() => { + this.store.select((state: ApplicationState) => state.routes.present).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { this.routeChanged(); - })); - this.componentSubscriptions.push(this.selectedRouteId$.subscribe(() => { + }); + this.store.select((state: ApplicationState) => state.routeEditingState.selectedRouteId).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { this.routeChanged(); - })); - this.componentSubscriptions.push(this.language$.subscribe(() => { + }); + this.store.select((state: ApplicationState) => state.configuration.language).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { this.redrawChart(); - })); - this.componentSubscriptions.push(this.currentPosition$.subscribe(p => { + }); + this.store.select((state: ApplicationState) => state.gpsState.currentPosition).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(p => { this.onGeolocationChanged(p); - })); - this.componentSubscriptions.push(this.isShowSlope$.subscribe(showSlope => { + }); + this.store.select((state: ApplicationState) => state.configuration.isShowSlope).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(showSlope => { this.isSlopeOn = showSlope; this.redrawChart(); this.updateSlopeRoute(); - })); - this.componentSubscriptions.push(this.isShowKmMarkers$.subscribe(showKmMarkers => { + }); + this.store.select((state: ApplicationState) => state.configuration.isShowKmMarker).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(showKmMarkers => { this.isKmMarkersOn = showKmMarkers; this.updateKmMarkers(); - })); + }); this.routeChanged(); - this.componentSubscriptions.push(interval(1000).subscribe(() => { + interval(1000).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { const recordedRouteState = this.store.selectSnapshot((s: ApplicationState) => s.recordedRouteState); if (recordedRouteState.isRecording) { const recordingStartTime = new Date(recordedRouteState.route.latlngs[0].timestamp).getTime(); this.updateDurationString((new Date().getTime() - recordingStartTime) / 1000); } - })); + }); this.audioPlayer = await this.audioPlayerFactory.create(); } - public ngOnDestroy() { - for (const subscription of this.componentSubscriptions) { - subscription.unsubscribe(); - } - } - public changeState(state: string) { switch (state) { case "table": 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..08222090e 100644 --- a/IsraelHiking.Web/src/application/components/sidebar/info-sidebar.component.ts +++ b/IsraelHiking.Web/src/application/components/sidebar/info-sidebar.component.ts @@ -1,10 +1,9 @@ import { Component } from "@angular/core"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; 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"; @@ -14,7 +13,7 @@ import { ResourcesService } from "../../services/resources.service"; import { LayersService } from "../../services/layers.service"; import { RunningContextService } from "../../services/running-context.service"; import { ISRAEL_MTB_MAP, ISRAEL_HIKING_MAP } from "../../reducers/initial-state"; -import type { ApplicationState, Language } from "../../models/models"; +import type { ApplicationState } from "../../models/models"; import legendSectionsJson from "../../../content/legend/legend.json"; export type LegendSection = { @@ -33,22 +32,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).pipe(takeUntilDestroyed()).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..abfc3a174 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$ | async | 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..99699a828 100644 --- a/IsraelHiking.Web/src/application/components/sidebar/layers-sidebar.component.ts +++ b/IsraelHiking.Web/src/application/components/sidebar/layers-sidebar.component.ts @@ -2,7 +2,7 @@ import { Component, ViewEncapsulation } 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 { Store } from "@ngxs/store"; import type { Immutable } from "immer"; import { BaseMapComponent } from "../base-map.component"; @@ -33,20 +33,11 @@ import type { ApplicationState, RouteData, EditableLayer, Overlay, CategoriesGro }) export class LayersSidebarComponent extends BaseMapComponent { - @Select((state: ApplicationState) => state.layersState.baseLayers) - public baseLayers: Observable>; - - @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 baseLayers$: Observable>; + public overlays$: Observable>; + public categoriesGroups$: Observable>; + public routes$: Observable>; + public lastModified$: Observable; public manageSubscriptions: string; @@ -64,6 +55,11 @@ export class LayersSidebarComponent extends BaseMapComponent { this.manageSubscriptions = this.runningContextService.isIos ? "https://apps.apple.com/account/subscriptions" : "https://play.google.com/store/account/subscriptions"; + this.lastModified$ = this.store.select((state: ApplicationState) => state.offlineState.lastModifiedDate); + this.baseLayers$ = this.store.select((state: ApplicationState) => state.layersState.baseLayers); + this.overlays$ = this.store.select((state: ApplicationState) => state.layersState.overlays); + this.categoriesGroups$ = this.store.select((state: ApplicationState) => state.layersState.categoriesGroups); + this.routes$ = this.store.select((state: ApplicationState) => state.routes.present); } 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..84055cfd3 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 @@ -