Skip to content

Commit a219533

Browse files
committed
Move to signals and other refactoring.
1 parent 79d1818 commit a219533

18 files changed

Lines changed: 119 additions & 178 deletions

IsraelHiking.Web/src/application/components/drawing.component.ts

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,20 @@ export class DrawingComponent {
5151
private readonly presentRoutes = this.store.selectSignal((state: ApplicationState) => state.routes.present);
5252
private readonly selectedRoute = computed(() => this.presentRoutes().find(r => r.id === this.routeEditingState().selectedRouteId));
5353

54+
public readonly isPoiEditActive = computed(() => {
55+
const selectedRoute = this.selectedRoute();
56+
return selectedRoute && selectedRoute.state === "Poi";
57+
});
58+
59+
public readonly isRouteEditActive = computed(() => {
60+
const selectedRoute = this.selectedRoute();
61+
return selectedRoute != null && selectedRoute.state === "Route";
62+
});
63+
64+
public readonly canDeleteAllRoutes = computed(() => this.presentRoutes().length > 0);
65+
66+
public readonly hasMultipleRoutes = computed(() => this.presentRoutes().length > 1);
67+
5468
@HostListener("window:keydown", ["$event"])
5569
public onDrawingShortcutKeys($event: KeyboardEvent) {
5670
if (($event.ctrlKey && $event.code === "KeyY") ||
@@ -90,16 +104,6 @@ export class DrawingComponent {
90104
this.store.dispatch(new ClearPoisAndRouteAction(selectedRoute.id));
91105
}
92106

93-
public isPoiEditActive() {
94-
const selectedRoute = this.selectedRoute();
95-
return selectedRoute && selectedRoute.state === "Poi";
96-
}
97-
98-
public isRouteEditActive() {
99-
const selectedRoute = this.selectedRoute();
100-
return selectedRoute != null && selectedRoute.state === "Route";
101-
}
102-
103107
public isEditActive() {
104108
return this.isPoiEditActive() || this.isRouteEditActive();
105109
}
@@ -193,10 +197,6 @@ export class DrawingComponent {
193197
this.store.dispatch(new ClearHistoryAction());
194198
}
195199

196-
public canDeleteAllRoutes() {
197-
return this.presentRoutes().length > 0;
198-
}
199-
200200
public togglePrivateRoutes() {
201201
this.sidebarService.toggle("private-routes");
202202
}
@@ -233,10 +233,6 @@ export class DrawingComponent {
233233
}
234234
}
235235

236-
public hasMultipleRoutes() {
237-
return this.presentRoutes().length > 1;
238-
}
239-
240236
public allXRoutesText() {
241237
return this.resources.allXRoutes.replace("{{count}}", this.presentRoutes().length.toString());
242238
}

IsraelHiking.Web/src/application/components/legend-item.component.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import { Component, inject, input } from "@angular/core";
1+
import { Component, inject, input, computed } from "@angular/core";
22
import { NgClass } from "@angular/common";
33
import { Dir } from "@angular/cdk/bidi";
44
import { MatTooltip } from "@angular/material/tooltip";
55

66
import { AnalyticsDirective } from "../directives/analytics.directive";
77
import { LayersService } from "../services/layers.service";
8-
import { ResourcesService } from "../services/resources.service";
98
import { MapService } from "../services/map.service";
109
import { HIKING_MAP } from "../reducers/initial-state";
10+
import type { ResourcesService } from "../services/resources.service";
1111
import type { LatLngAltTime } from "../models";
1212

1313
type LegendItemType = "POI" | "Way";
@@ -34,23 +34,22 @@ export class LegendItemComponent {
3434

3535
public item = input<ILegendItem>();
3636

37-
public readonly resources = inject(ResourcesService);
3837

3938
private readonly mapService = inject(MapService);
4039
private readonly layersService = inject(LayersService);
4140

42-
public moveToLocation() {
43-
this.mapService.moveTo(this.item().latlng, this.item().zoom, 0);
44-
}
45-
46-
public getLink() {
41+
public readonly getLink = computed(() => {
4742
if (this.item().link === LegendItemComponent.OSM_KEY_LINK) {
4843
return `https://wiki.openstreetmap.org/wiki/Key:${this.item().osmTags[0].split("=")[0]}`;
4944
}
5045
if (this.item().link === LegendItemComponent.OSM_TAG_LINK) {
5146
return `https://wiki.openstreetmap.org/wiki/Tag:${this.item().osmTags[0].split(" ")[0]}`;
5247
}
5348
return this.item().link;
49+
});
50+
51+
public moveToLocation() {
52+
this.mapService.moveTo(this.item().latlng, this.item().zoom, 0);
5453
}
5554

5655
public getImageAddress() {

IsraelHiking.Web/src/application/components/location.component.ts

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, inject, signal } from "@angular/core";
1+
import { Component, inject, signal, computed } from "@angular/core";
22
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
33
import { MatButton } from "@angular/material/button";
44
import { MatTooltip } from "@angular/material/tooltip";
@@ -50,6 +50,18 @@ export class LocationComponent {
5050
private readonly recordedRouteState = this.store.selectSignal((s: ApplicationState) => s.recordedRouteState);
5151
private readonly mapComponent = inject(MapComponent);
5252

53+
public readonly isKeepNorthUp = computed(() => this.inMemoryState().keepNorthUp);
54+
55+
public readonly getRotationAngle = computed(() => `rotate(${-this.bearing()}deg)`);
56+
57+
public readonly isDisabled = computed(() => this.gpsState().tracking === "disabled");
58+
59+
public readonly isActive = computed(() => this.gpsState().tracking === "tracking");
60+
61+
public readonly isLoading = computed(() => this.gpsState().tracking === "searching");
62+
63+
public readonly isAddingRecordingPoi = computed(() => this.recordedRouteState().isAddingPoi);
64+
5365
constructor() {
5466
this.clearLocationFeatureCollection();
5567

@@ -105,21 +117,13 @@ export class LocationComponent {
105117
}
106118
}
107119

108-
public isKeepNorthUp() {
109-
return this.inMemoryState().keepNorthUp;
110-
}
111-
112120
public toggleKeepNorthUp() {
113121
this.store.dispatch(new ToggleKeepNorthUpAction());
114122
if (this.isKeepNorthUp()) {
115123
this.mapComponent.mapInstance.rotateTo(0);
116124
}
117125
}
118126

119-
public getRotationAngle() {
120-
return `rotate(${-this.bearing()}deg)`;
121-
}
122-
123127
public toggleTracking() {
124128
if (this.isLoading()) {
125129
this.locationService.disable();
@@ -196,22 +200,6 @@ export class LocationComponent {
196200
}
197201
}
198202

199-
public isDisabled() {
200-
return this.gpsState().tracking === "disabled";
201-
}
202-
203-
public isActive() {
204-
return this.gpsState().tracking === "tracking";
205-
}
206-
207-
public isLoading() {
208-
return this.gpsState().tracking === "searching";
209-
}
210-
211-
public isAddingRecordingPoi() {
212-
return this.recordedRouteState().isAddingPoi;
213-
}
214-
215203
public toggleAddRecordingPoi() {
216204
const selectedRoute = this.selectedRouteService.getSelectedRoute();
217205
if (selectedRoute && (selectedRoute.state === "Poi" || selectedRoute.state === "Route")) {

IsraelHiking.Web/src/application/components/main-menu.component.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, inject } from "@angular/core";
1+
import { Component, inject, computed } from "@angular/core";
22
import { RouterLink, RouterLinkActive } from "@angular/router";
33
import { MatButton } from "@angular/material/button";
44
import { MatMenuTrigger, MatMenu, MatMenuItem } from "@angular/material/menu";
@@ -51,6 +51,8 @@ export class MainMenuComponent {
5151
public userInfo = this.store.selectSignal((state: ApplicationState) => state.userState.userInfo);
5252
private readonly isSubscribed = this.store.selectSignal((state: ApplicationState) => state.offlineState.isSubscribed);
5353

54+
public readonly isLoggedIn = computed(() => this.userInfo() != null);
55+
5456
constructor() {
5557
if (this.runningContextService.isCapacitor) {
5658
App.getInfo().then((info) => {
@@ -59,10 +61,6 @@ export class MainMenuComponent {
5961
}
6062
}
6163

62-
public isLoggedIn() {
63-
return this.userInfo() != null;
64-
}
65-
6664
public isApp() {
6765
return this.runningContextService.isCapacitor;
6866
}

IsraelHiking.Web/src/application/components/map/automatic-layer-presentation.component.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { Subject, mergeMap } from "rxjs";
44
import { Store } from "@ngxs/store";
55
import type { SourceSpecification, LayerSpecification } from "maplibre-gl";
66

7-
import { ResourcesService } from "../../services/resources.service";
87
import { DefaultStyleService } from "../../services/default-style.service";
98
import type { ApplicationState, EditableLayer, LanguageCode, LayerData } from "../../models";
109

@@ -26,7 +25,6 @@ export class AutomaticLayerPresentationComponent implements OnInit, OnChanges, O
2625
private currentLanguageCode: LanguageCode;
2726
private readonly recreateQueue = new Subject<() => Promise<void>>();
2827

29-
public readonly resources = inject(ResourcesService);
3028

3129
private readonly mapComponent = inject(MapComponent);
3230
private readonly defaultStyleService = inject(DefaultStyleService);

IsraelHiking.Web/src/application/components/map/public-pois.component.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, DestroyRef, inject, OnInit, signal } from "@angular/core";
1+
import { Component, DestroyRef, inject, OnInit, signal, computed } from "@angular/core";
22

33
import { Dir } from "@angular/cdk/bidi";
44
import { MatButton } from "@angular/material/button";
@@ -25,7 +25,7 @@ import { SetSelectedPoiAction } from "../../reducers/poi.reducer";
2525
import { AddPrivatePoiAction } from "../../reducers/routes.reducer";
2626
import { GeoJSONUtils } from "../../services/geojson-utils";
2727
import { Urls } from "../../urls";
28-
import type { ApplicationState, LatLngAltTime, LinkData, MarkerData } from "../../models";
28+
import type { ApplicationState, LinkData, MarkerData } from "../../models";
2929
import { skip } from "rxjs";
3030

3131
@Component({
@@ -62,6 +62,8 @@ export class PublicPoisComponent implements OnInit {
6262
private readonly destroyRef = inject(DestroyRef);
6363
private readonly mapComponent = inject(MapComponent);
6464

65+
public readonly getSelectedFeatureLatlng = computed(() => SpatialService.toLatLng(this.selectedPoiFeature().geometry.coordinates as [number, number]));
66+
6567
public ngOnInit() {
6668
this.poiGeoJsonData.set(this.poiService.getPoisGeoJson());
6769
this.store.select((state: ApplicationState) => state.configuration.language).pipe(takeUntilDestroyed(this.destroyRef), skip(1)).subscribe(() => {
@@ -188,10 +190,6 @@ export class PublicPoisComponent implements OnInit {
188190
this.hoverFeature.set(null);
189191
}
190192

191-
public getSelectedFeatureLatlng(): LatLngAltTime {
192-
return SpatialService.toLatLng(this.selectedPoiFeature().geometry.coordinates as [number, number]);
193-
}
194-
195193
public navigateHere() {
196194
this.navigateHereService.addNavigationSegment(this.getSelectedFeatureLatlng());
197195
this.clearSelected();

IsraelHiking.Web/src/application/components/overlays/missing-part-overlay.component.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, ViewEncapsulation, inject, input, model, output, signal } from "@angular/core";
1+
import { Component, ViewEncapsulation, inject, input, model, output, signal, computed } from "@angular/core";
22
import { HttpClient } from "@angular/common/http";
33
import { Dir } from "@angular/cdk/bidi";
44
import { MatButton } from "@angular/material/button";
@@ -35,18 +35,14 @@ export class MissingPartOverlayComponent {
3535
private readonly httpClient = inject(HttpClient);
3636
private readonly toastService = inject(ToastService);
3737

38-
public getHighwayType(): string {
39-
return this.feature().properties.highway || "track";
40-
}
38+
public readonly getHighwayType = computed(() => this.feature().properties.highway || "track");
39+
40+
public readonly getColor = computed(() => this.feature().properties.colour || "none");
4141

4242
public setHighwayType(highwayType: string) {
4343
this.feature.update(feature => ({ ...feature, properties: { ...feature.properties, highway: highwayType } }));
4444
}
4545

46-
public getColor(): string {
47-
return this.feature().properties.colour || "none";
48-
}
49-
5046
public setColor(color: string) {
5147
this.feature.update(feature => {
5248
const properties = { ...feature.properties, colour: color };

IsraelHiking.Web/src/application/components/photoswipe.component.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Component, ElementRef, AfterViewInit, InjectionToken, ViewEncapsulation, EventEmitter, viewChild, inject } from "@angular/core";
22
import PhotoSwipe from "photoswipe";
33

4-
import { ResourcesService } from "../services/resources.service";
54

65
export const PHOTO_SWIPE_DATA = new InjectionToken<PhotoSwipeData>("PHOTO_SWIPE_DATA");
76

@@ -18,7 +17,6 @@ export type PhotoSwipeData = {
1817
})
1918
export class PhotoSwpieComponent implements AfterViewInit {
2019

21-
public readonly resources = inject(ResourcesService);
2220
public photoswipe = viewChild<ElementRef>("photoswipe");
2321
public readonly closed = new EventEmitter();
2422
private readonly data = inject(PHOTO_SWIPE_DATA);

IsraelHiking.Web/src/application/components/public-routes-filter.component.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, DestroyRef, inject, signal } from "@angular/core";
1+
import { Component, DestroyRef, inject, signal, computed } from "@angular/core";
22
import { MatCheckbox } from "@angular/material/checkbox";
33
import { MatMenu, MatMenuItem, MatMenuTrigger } from "@angular/material/menu";
44
import { MatButton } from "@angular/material/button";
@@ -31,6 +31,12 @@ export class PublicRoutesFilterComponent {
3131

3232
private readonly publicRoutesFilter = this.store.selectSignal((s: ApplicationState) => s.inMemoryState.publicRoutesFilter);
3333

34+
public readonly isCategoryFiltered = computed(() => this.publicRoutesFilter().categories.length !== initialState.inMemoryState.publicRoutesFilter.categories.length);
35+
36+
public readonly isDifficultyFiltered = computed(() => this.publicRoutesFilter().difficulty.length !== initialState.inMemoryState.publicRoutesFilter.difficulty.length);
37+
38+
public readonly isLengthFiltered = computed(() => this.filterLengthStart() > 0 || this.filterLengthEnd() < 50);
39+
3440
constructor() {
3541
this.store.select((state: ApplicationState) => state.configuration.units).pipe(takeUntilDestroyed(this.destroyRef)).subscribe((units) => {
3642
this.unitString.set(this.resources.getLongDistanceUnitString(units));
@@ -66,14 +72,6 @@ export class PublicRoutesFilterComponent {
6672
return this.publicRoutesFilter().categories.includes(category);
6773
}
6874

69-
public isCategoryFiltered() {
70-
return this.publicRoutesFilter().categories.length !== initialState.inMemoryState.publicRoutesFilter.categories.length;
71-
}
72-
73-
public isDifficultyFiltered() {
74-
return this.publicRoutesFilter().difficulty.length !== initialState.inMemoryState.publicRoutesFilter.difficulty.length;
75-
}
76-
7775
public isDificultySelected(difficulty: Difficulty) {
7876
return this.publicRoutesFilter().difficulty.includes(difficulty);
7977
}
@@ -92,10 +90,6 @@ export class PublicRoutesFilterComponent {
9290
this.store.dispatch(new SetPublicRoutesFilterAction(filters));
9391
}
9492

95-
public isLengthFiltered() {
96-
return this.filterLengthStart() > 0 || this.filterLengthEnd() < 50
97-
}
98-
9993
public hasUserFilter() {
10094
return this.store.selectSnapshot((s: ApplicationState) => s.inMemoryState.publicRoutesFilter.userId) != null;
10195
}

IsraelHiking.Web/src/application/components/screens/offline-management.component.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, inject, signal } from "@angular/core";
1+
import { Component, inject, signal, computed } from "@angular/core";
22
import { Store } from "@ngxs/store";
33
import { GeoJSONSourceComponent, LayerComponent, MapComponent } from "@maplibre/ngx-maplibre-gl";
44
import { type Map, type MapMouseEvent, MercatorCoordinate, type StyleSpecification } from "maplibre-gl";
@@ -40,6 +40,14 @@ export class OfflineManagementComponent {
4040
private readonly downloadedTilesState = this.store.selectSignal((s: ApplicationState) => s.offlineState.downloadedTiles);
4141
public readonly resources = inject(ResourcesService);
4242

43+
public readonly isSelectedAvailableForOffline = computed(() => {
44+
if (!this.selectedTileXY()) {
45+
return false;
46+
}
47+
const downloadedTiles = this.downloadedTilesState();
48+
return downloadedTiles != null && downloadedTiles[`${this.selectedTileXY().tileX}-${this.selectedTileXY().tileY}`] != null;
49+
});
50+
4351
constructor() {
4452
this.offlineMapStyle = this.defaultStyleService.getStyleWithPlaceholders();
4553
this.baseLayerData = this.layersService.selectedBaseLayer();
@@ -246,14 +254,6 @@ export class OfflineManagementComponent {
246254
this.initializeCenterAndZoomFromDownloadingTile();
247255
}
248256

249-
public isSelectedAvailableForOffline(): boolean {
250-
if (!this.selectedTileXY()) {
251-
return false;
252-
}
253-
const downloadedTiles = this.downloadedTilesState();
254-
return downloadedTiles != null && downloadedTiles[`${this.selectedTileXY().tileX}-${this.selectedTileXY().tileY}`] != null;
255-
}
256-
257257
public async deleteSelected() {
258258
if (!this.selectedTileXY()) {
259259
return;

0 commit comments

Comments
 (0)