diff --git a/IsraelHiking.Web/android/app/capacitor.build.gradle b/IsraelHiking.Web/android/app/capacitor.build.gradle index ccca2c6ea..74edc4a43 100644 --- a/IsraelHiking.Web/android/app/capacitor.build.gradle +++ b/IsraelHiking.Web/android/app/capacitor.build.gradle @@ -15,6 +15,7 @@ dependencies { implementation project(':capacitor-camera') implementation project(':capacitor-device') implementation project(':capacitor-text-zoom') + implementation project(':capawesome-capacitor-app-update') implementation project(':capgo-native-audio') implementation "com.google.android.gms:play-services-location:17+" implementation "androidx.core:core:1.1.0" diff --git a/IsraelHiking.Web/android/app/src/main/assets/capacitor.plugins.json b/IsraelHiking.Web/android/app/src/main/assets/capacitor.plugins.json index 14b950d52..d3bb3c0c1 100644 --- a/IsraelHiking.Web/android/app/src/main/assets/capacitor.plugins.json +++ b/IsraelHiking.Web/android/app/src/main/assets/capacitor.plugins.json @@ -23,6 +23,10 @@ "pkg": "@capacitor/text-zoom", "classpath": "com.capacitorjs.plugins.textzoom.TextZoomPlugin" }, + { + "pkg": "@capawesome/capacitor-app-update", + "classpath": "io.capawesome.capacitorjs.plugins.appupdate.AppUpdatePlugin" + }, { "pkg": "@capgo/native-audio", "classpath": "ee.forgr.audio.NativeAudio" diff --git a/IsraelHiking.Web/android/capacitor.settings.gradle b/IsraelHiking.Web/android/capacitor.settings.gradle index a39995538..f920167c9 100644 --- a/IsraelHiking.Web/android/capacitor.settings.gradle +++ b/IsraelHiking.Web/android/capacitor.settings.gradle @@ -20,5 +20,8 @@ project(':capacitor-device').projectDir = new File('../node_modules/@capacitor/d include ':capacitor-text-zoom' project(':capacitor-text-zoom').projectDir = new File('../node_modules/@capacitor/text-zoom/android') +include ':capawesome-capacitor-app-update' +project(':capawesome-capacitor-app-update').projectDir = new File('../node_modules/@capawesome/capacitor-app-update/android') + include ':capgo-native-audio' project(':capgo-native-audio').projectDir = new File('../node_modules/@capgo/native-audio/android') diff --git a/IsraelHiking.Web/ios/App/App/capacitor.config.json b/IsraelHiking.Web/ios/App/App/capacitor.config.json index 427ce35b1..2a5dc2b04 100644 --- a/IsraelHiking.Web/ios/App/App/capacitor.config.json +++ b/IsraelHiking.Web/ios/App/App/capacitor.config.json @@ -28,6 +28,8 @@ "CAPCameraPlugin", "DevicePlugin", "TextZoomPlugin", + "AppUpdatePlugin", + "AppUpdatePlugin", "NativeAudio", "NativeAudio", "CDVPlugin" diff --git a/IsraelHiking.Web/ios/App/Podfile b/IsraelHiking.Web/ios/App/Podfile index b763dec8a..b3d097611 100644 --- a/IsraelHiking.Web/ios/App/Podfile +++ b/IsraelHiking.Web/ios/App/Podfile @@ -17,6 +17,7 @@ def capacitor_pods pod 'CapacitorCamera', :path => '../../node_modules/@capacitor/camera' pod 'CapacitorDevice', :path => '../../node_modules/@capacitor/device' pod 'CapacitorTextZoom', :path => '../../node_modules/@capacitor/text-zoom' + pod 'CapawesomeCapacitorAppUpdate', :path => '../../node_modules/@capawesome/capacitor-app-update' pod 'CapgoNativeAudio', :path => '../../node_modules/@capgo/native-audio' pod 'CordovaPlugins', :path => '../capacitor-cordova-ios-plugins' end diff --git a/IsraelHiking.Web/ios/App/Podfile.lock b/IsraelHiking.Web/ios/App/Podfile.lock index 24de57b77..ce2bc80c2 100644 --- a/IsraelHiking.Web/ios/App/Podfile.lock +++ b/IsraelHiking.Web/ios/App/Podfile.lock @@ -14,6 +14,8 @@ PODS: - Capacitor - CapacitorTextZoom (6.0.0): - Capacitor + - CapawesomeCapacitorAppUpdate (6.0.0): + - Capacitor - CapgoNativeAudio (6.4.3): - Capacitor - CordovaPlugins (6.0.0): @@ -28,6 +30,7 @@ DEPENDENCIES: - "CapacitorCordova (from `../../node_modules/@capacitor/ios`)" - "CapacitorDevice (from `../../node_modules/@capacitor/device`)" - "CapacitorTextZoom (from `../../node_modules/@capacitor/text-zoom`)" + - "CapawesomeCapacitorAppUpdate (from `../../node_modules/@capawesome/capacitor-app-update`)" - "CapgoNativeAudio (from `../../node_modules/@capgo/native-audio`)" - CordovaPlugins (from `../capacitor-cordova-ios-plugins`) @@ -48,6 +51,8 @@ EXTERNAL SOURCES: :path: "../../node_modules/@capacitor/device" CapacitorTextZoom: :path: "../../node_modules/@capacitor/text-zoom" + CapawesomeCapacitorAppUpdate: + :path: "../../node_modules/@capawesome/capacitor-app-update" CapgoNativeAudio: :path: "../../node_modules/@capgo/native-audio" CordovaPlugins: @@ -62,9 +67,10 @@ SPEC CHECKSUMS: CapacitorCordova: 8c4bfdf69368512e85b1d8b724dd7546abeb30af CapacitorDevice: f8fd88f9edd1261c55a109f32015b09bbbfdc4a0 CapacitorTextZoom: 696722e5c479b364f2429584f11ad386d609bd1a + CapawesomeCapacitorAppUpdate: 3c05b5c8e42f9c6a88d666093406e9336d9bfdb1 CapgoNativeAudio: 569bfe2955e4bc58d9c44f14590ea985854f7f9b CordovaPlugins: 1f2794134a8c57f6b5112e89cc7afd07dc0f7bef -PODFILE CHECKSUM: 0c32ad6bc2ae562b3fa0cf7a399eddd792459d18 +PODFILE CHECKSUM: 6ae88e6f813ac1f24c30d9c87142329696a5d43d -COCOAPODS: 1.12.1 +COCOAPODS: 1.15.2 diff --git a/IsraelHiking.Web/package-lock.json b/IsraelHiking.Web/package-lock.json index 7e619b477..f5ca8bc37 100644 --- a/IsraelHiking.Web/package-lock.json +++ b/IsraelHiking.Web/package-lock.json @@ -32,6 +32,7 @@ "@capacitor/device": "^6.0.0", "@capacitor/ios": "^6.0.0", "@capacitor/text-zoom": "^6.0.0", + "@capawesome/capacitor-app-update": "^6.0.0", "@capgo/native-audio": "^6.4.3", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mapbox/polyline": "^1.2.1", @@ -2809,6 +2810,24 @@ "@capacitor/core": "^6.0.0" } }, + "node_modules/@capawesome/capacitor-app-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@capawesome/capacitor-app-update/-/capacitor-app-update-6.0.0.tgz", + "integrity": "sha512-T4k0dC3XoJDgtX1QOQx0Rr5eMi3NhJn93QawQ6ZYYMmssnqCoRPpo2rg3VKVKMUZgAmIUN5Rwons9T4QkjTOzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/capawesome-team/" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/capawesome" + } + ], + "peerDependencies": { + "@capacitor/core": "^6.0.0" + } + }, "node_modules/@capgo/native-audio": { "version": "6.4.3", "resolved": "https://registry.npmjs.org/@capgo/native-audio/-/native-audio-6.4.3.tgz", diff --git a/IsraelHiking.Web/package.json b/IsraelHiking.Web/package.json index b51ccde68..b6e490b67 100644 --- a/IsraelHiking.Web/package.json +++ b/IsraelHiking.Web/package.json @@ -23,6 +23,7 @@ "@capacitor/device": "^6.0.0", "@capacitor/ios": "^6.0.0", "@capacitor/text-zoom": "^6.0.0", + "@capawesome/capacitor-app-update": "^6.0.0", "@capgo/native-audio": "^6.4.3", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mapbox/polyline": "^1.2.1", diff --git a/IsraelHiking.Web/src/application/application.module.ts b/IsraelHiking.Web/src/application/application.module.ts index 5c0c9d11f..6fa3e4047 100644 --- a/IsraelHiking.Web/src/application/application.module.ts +++ b/IsraelHiking.Web/src/application/application.module.ts @@ -96,6 +96,7 @@ import { GlobalErrorHandler } from "./services/global-error.handler"; import { OverpassTurboService } from "./services/overpass-turbo.service"; import { ImageAttributionService } from "./services/image-attribution.service"; import { PmTilesService } from "./services/pmtiles.service"; +import { ApplicationUpdateService } from "./services/application-update.service"; // interactions import { RouteEditPoiInteraction } from "./components/intercations/route-edit-poi.interaction"; import { RouteEditRouteInteraction } from "./components/intercations/route-edit-route.interaction"; @@ -309,6 +310,7 @@ const initializeApplication = (injector: Injector) => async () => { OverpassTurboService, ImageAttributionService, PmTilesService, + ApplicationUpdateService, AudioPlayerFactory, FileSystemWrapper, // eslint-disable-next-line diff --git a/IsraelHiking.Web/src/application/services/application-initialize.service.ts b/IsraelHiking.Web/src/application/services/application-initialize.service.ts index 5724d39f5..7a00fb1e7 100644 --- a/IsraelHiking.Web/src/application/services/application-initialize.service.ts +++ b/IsraelHiking.Web/src/application/services/application-initialize.service.ts @@ -24,6 +24,7 @@ import { GeoLocationService } from "./geo-location.service"; import { OverpassTurboService } from "./overpass-turbo.service"; import { AuthorizationService } from "./authorization.service"; import { ToastService } from "./toast.service"; +import { ApplicationUpdateService } from "./application-update.service"; import type { ApplicationState } from "../models/models"; @Injectable() @@ -47,6 +48,7 @@ export class ApplicationInitializeService { private readonly geoLocationService: GeoLocationService, private readonly overpassTurboService: OverpassTurboService, private readonly authorizationService: AuthorizationService, + private readonly applicationUpdateService: ApplicationUpdateService, private readonly toastService: ToastService, private readonly store: Store ) { @@ -62,6 +64,7 @@ export class ApplicationInitializeService { this.screenService.initialize(); await this.resources.initialize(); this.applicationExitService.initialize(); + await this.applicationUpdateService.initialize(); this.openWithService.initialize(); await this.purchaseService.initialize(); this.geoLocationService.initialize(); diff --git a/IsraelHiking.Web/src/application/services/application-update.service.ts b/IsraelHiking.Web/src/application/services/application-update.service.ts new file mode 100644 index 000000000..91fc70ef8 --- /dev/null +++ b/IsraelHiking.Web/src/application/services/application-update.service.ts @@ -0,0 +1,30 @@ +import { Injectable } from "@angular/core"; +import { AppUpdate, AppUpdateAvailability } from '@capawesome/capacitor-app-update'; + +import { RunningContextService } from "./running-context.service"; +import { ToastService } from "./toast.service"; +import { ResourcesService } from "./resources.service"; + +@Injectable() +export class ApplicationUpdateService { + constructor(private readonly resourcesService: ResourcesService, + private readonly runningContextSerive: RunningContextService, + private readonly toastService: ToastService) {} + + public async initialize() { + if (!this.runningContextSerive.isCapacitor) { + return; + } + const result = await AppUpdate.getAppUpdateInfo(); + if (result.updateAvailability !== AppUpdateAvailability.UPDATE_AVAILABLE) { + return; + } + this.toastService.confirm({ + type: "YesNo", + message: this.resourcesService.newVersionAvailable, + confirmAction: () => { + AppUpdate.openAppStore(); + } + }); + } +} \ No newline at end of file diff --git a/IsraelHiking.Web/src/application/services/resources.service.ts b/IsraelHiking.Web/src/application/services/resources.service.ts index f2768857a..34fbef369 100644 --- a/IsraelHiking.Web/src/application/services/resources.service.ts +++ b/IsraelHiking.Web/src/application/services/resources.service.ts @@ -309,6 +309,7 @@ export class ResourcesService { public editingRouteWhileTracking: string; public loginTokenExpiredPleaseLoginAgain: string; public jammedPositionReceived: string; + public newVersionAvailable: string; // Info public infoSubheader: string; public infoHelpfulLinks: string; @@ -484,7 +485,7 @@ export class ResourcesService { } private async setLanguageInternal(language: Language): Promise { - await this.gettextCatalog.loadRemote(Urls.translations + language.code + ".json?sign=1716145116367"); + await this.gettextCatalog.loadRemote(Urls.translations + language.code + ".json?sign=1722974337771"); this.about = this.gettextCatalog.getString("About"); this.legend = this.gettextCatalog.getString("Legend"); this.clear = this.gettextCatalog.getString("Clear"); @@ -796,6 +797,7 @@ export class ResourcesService { "in order to avoid map centering to current location please click the cross icon on the top left corner"); this.loginTokenExpiredPleaseLoginAgain = this.gettextCatalog.getString("Login token expired, please login again"); this.jammedPositionReceived = this.gettextCatalog.getString("Jammed position received..."); + this.newVersionAvailable = this.gettextCatalog.getString("New version available, do you want to update?"); // Info this.infoHelpfulLinks = this.gettextCatalog.getString("Helpful links:"); this.infoSubheader = this.gettextCatalog diff --git a/IsraelHiking.Web/src/translations/en-US.json b/IsraelHiking.Web/src/translations/en-US.json index 1ff0e3def..490f56ef7 100644 --- a/IsraelHiking.Web/src/translations/en-US.json +++ b/IsraelHiking.Web/src/translations/en-US.json @@ -230,6 +230,7 @@ "Nature Reserve, National Park": "Nature Reserve, National Park", "Navigate Here": "Navigate Here", "Navigate with Waze": "Navigate with Waze", + "New version available, do you want to update?": "A new app version is available. Do you want to update?", "Next": "Next", "No": "No", "No legend for this map...": "No legend for this map...", diff --git a/IsraelHiking.Web/src/translations/he.json b/IsraelHiking.Web/src/translations/he.json index ea500402a..1d92cd03c 100644 --- a/IsraelHiking.Web/src/translations/he.json +++ b/IsraelHiking.Web/src/translations/he.json @@ -230,6 +230,7 @@ "Nature Reserve, National Park": "שמורת טבע, גן לאומי", "Navigate Here": "נווט לכאן", "Navigate with Waze": "ניווט בעזרת וויז", + "New version available, do you want to update?": "שחררנו גרסה חדשה של האפליקציה. רוצים לעדכן?", "Next": "הבא", "No": "לא", "No legend for this map...": "אין מקרא עבור מפה זו...",