Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(app): App installation is now configurable #929

Merged
merged 8 commits into from
Apr 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions docs/config_json.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,45 @@ Résumé

Important : Les propriétés en caractère gras suivies d'un * sont obligatoires.

***************
App
***************

.. line-block::

Permet d'activer des options pour l'application.

Exemples

.. code:: json

"app": {
"forceCoordsNA": false,
"install": {
enabled: true,
promote: false,
manifestPath: '../config/github.webmanifest'
},
"pwa": {
enable: true
}
}

Propriétés

.. line-block::

forceCoordsNA: true/false = force les coordonnées en Amérique du Nord
install: Object permettant de dire comment l'application sera installée.
install.enabled: true/false = Application installable ou non.
install.manifestPath: Identifie un chemin d'accès pour le manifest (info sur l'app).
Par défaut: 'manifest.webmanifest'
install.promote: true/false = Permet (Windows/Android) de faire afficher un message
incitant les utilisateurs a installer l'application
pwa: Object permettant de dire comment l'application sera mis en mémoire cache.
pwa.enabled: true/false = Identifie si l'application sera mis en mémoire cache.


***************
Analytics
***************
Expand Down
4 changes: 2 additions & 2 deletions docs/interactiveTour_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Lorsqu'une certaine configuration est détectée par l'application, le bouton re
configuré un tour pour un outil X, le bouton de présentation apparaitra dans l'entête de l'outil.

Une configuration pour ne pas avoir de tour interactif en mode mobile est aussi disponible dans le fichier config.json:
"interactiveTourInMobile": true
"tourInMobile": true
par défaut les tours interactifs seront présents en mode mobile.


Expand Down Expand Up @@ -265,7 +265,7 @@ Je ne vois pas le bouton de mon tour apparaitre.
- Vérifier que le fichier interactiveTour.json est bien présent dans le dossier config de votre application.
- Vérifier que le nom de l'outil est bien exact
- Vérifier que la syntaxe du tour est bien présentée de cette façon: global: {...} ou nomGénériqueDeOutil:{...}
- Si vous êtes en mode mobile vérifier la configuration dans le fichier config.json: "introInteractiveTourInMobile": true
- Si vous êtes en mode mobile vérifier la configuration dans le fichier config.json: "tourInMobile": true

L'élément de mon tour n'est pas mis en surbrillance.
Solution:
Expand Down
2,363 changes: 1,367 additions & 996 deletions package-lock.json

Large diffs are not rendered by default.

35 changes: 33 additions & 2 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class AppComponent {
private themeClass = 'blue-theme';
public hasHeader = true;
public hasFooter = true;

private promptEvent: any;
constructor(
protected languageService: LanguageService,
private configService: ConfigService,
Expand All @@ -29,7 +29,7 @@ export class AppComponent {
private titleService: Title,
private metaService: Meta,
private messageService: MessageService,
private pwaService: PwaService // let there to be handled (based on configs: app.pwa.enabled)
private pwaService: PwaService
) {
this.authConfig = this.configService.getConfig('auth');

Expand All @@ -46,6 +46,10 @@ export class AppComponent {

this.hasFooter = this.configService.getConfig('hasFooter') === undefined ? false :
this.configService.getConfig('hasFooter');

this.setManifest();
this.installPrompt();
this.pwaService.checkForUpdates();
}

private readTitleConfig() {
Expand All @@ -57,6 +61,33 @@ export class AppComponent {
});
}

private setManifest() {
const appConfig = this.configService.getConfig('app');
if (appConfig?.install?.enabled) {
const manifestPath = appConfig.install.manifestPath || 'manifest.webmanifest';
document.querySelector('#igoManifestByConfig').setAttribute('href', manifestPath);
}
}

private installPrompt() {
const appConfig = this.configService.getConfig('app');
if (appConfig?.install?.enabled && appConfig?.install?.promote) {
if (userAgent.getOSName() !== 'iOS') {
window.addEventListener('beforeinstallprompt', (event: any) => {
event.preventDefault();
this.promptEvent = event;
window.addEventListener('click', () => {
setTimeout(() => {
this.promptEvent.prompt();
this.promptEvent = undefined;
}, 750);
}, { once: true });
}, { once: true });
}
}
}


private readThemeConfig() {
const theme = this.configService.getConfig('theme') || this.themeClass;
if (theme) {
Expand Down
50 changes: 12 additions & 38 deletions src/app/services/pwa.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Injectable } from '@angular/core';
import { Platform } from '@angular/cdk/platform';
import { ConfigService, LanguageService } from '@igo2/core';
import { LanguageService } from '@igo2/core';
import { SwUpdate } from '@angular/service-worker';
import { interval } from 'rxjs';
import { ConfirmDialogService } from '@igo2/common';
Expand All @@ -10,21 +9,22 @@ import { skip, tap } from 'rxjs/operators';
providedIn: 'root'
})
export class PwaService {
promptEvent: any;
private confirmOpened: boolean = false;
constructor(
private platform: Platform,
public updates: SwUpdate,
public languageService: LanguageService,
private configService: ConfigService,
private updates: SwUpdate,
private languageService: LanguageService,
private confirmDialogService: ConfirmDialogService
) {
if (updates.isEnabled) {
this.checkForUpdates();
this.initPwaPrompt();
this.handleVersionUpdates();
}
}

checkForUpdates() {
if (this.updates.isEnabled) {
interval(60 * 1000 * 2).pipe(skip(1)).subscribe(async () => {
try {
const updateFound = await updates.checkForUpdate();
const updateFound = await this.updates.checkForUpdate();
console.log(updateFound ? 'A new version is available.' : 'Already on the latest version.');
} catch (err) {
console.error('Failed to check for updates:', err);
Expand Down Expand Up @@ -55,7 +55,7 @@ export class PwaService {
});
}

private checkForUpdates(): void {
private handleVersionUpdates(): void {
this.updates.versionUpdates.subscribe(evt => {
switch (evt.type) {
case 'VERSION_DETECTED':
Expand All @@ -64,38 +64,12 @@ export class PwaService {
case 'VERSION_READY':
console.log(`Current app version: ${evt.currentVersion.hash}`);
console.log(`New app version ready for use: ${evt.latestVersion.hash}`);
this.modalUpdatePWA();
this.modalUpdatePWA();
break;
case 'VERSION_INSTALLATION_FAILED':
console.error(`Failed to install app version '${evt.version.hash}': ${evt.error}`);
break;
}
});
}

private async initPwaPrompt() {
if (
this.configService.getConfig('app') &&
this.configService.getConfig('app.pwa') &&
this.configService.getConfig('app.pwa.enabled') &&
this.configService.getConfig('app.pwa.promote')) {
if (!this.platform.IOS) {
window.addEventListener('beforeinstallprompt', (event: any) => {
event.preventDefault();
this.promptEvent = event;
this.listenToUserAction();
}, { once: true });
}
}
}

private listenToUserAction() {
window.addEventListener('click', () => { this.showPrompt(); }, { once: true });
}

private async showPrompt() {
this.promptEvent.prompt();
const outcome = await this.promptEvent.userChoice;
this.promptEvent = undefined;
}
}
62 changes: 62 additions & 0 deletions src/config/github.webmanifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"id": "igo2DemoGitHub",
"name": "Demo Github - IGO2",
"short_name": "Demo Github - IGO",
"description": "Demo Github - IGO2 installable",
"theme_color": "#1976d2",
"background_color": "#fafafa",
"display": "standalone",
"scope": "../",
"start_url": "../",
"orientation": "any",
"icons": [
{
"src": "../assets/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "../assets/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "../assets/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "../assets/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "../assets/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "../assets/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "../assets/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "../assets/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable any"
}
]
}
17 changes: 8 additions & 9 deletions src/environments/environment.github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,17 @@ import {
CommonVectorStyleOptions
} from '@igo2/geo';

import { AppOptions, InteractiveTourConfigOptions } from './environnement.interface';
interface Environment {
production: boolean;
igo: {
app: {
forceCoordsNA: boolean;
pwa?: {
enabled?: boolean;
promote?: boolean;
}
};
app: AppOptions,
catalog?: CatalogServiceOptions;
importExport?: ImportExportServiceOptions;
language?: LanguageOptions;
searchSources?: { [key: string]: SearchSourceOptions };
projections?: Projection[];
interactiveTour?: { tourInMobile: boolean; pathToConfigFile: string };
interactiveTour?: InteractiveTourConfigOptions;
depot?: { url: string; trainingGuides?: string[]; };
queryOverlayStyle?: {
base?: CommonVectorStyleOptions,
Expand All @@ -42,9 +37,13 @@ export const environment: Environment = {
igo: {
app: {
forceCoordsNA: false,
install: {
enabled: true,
promote: true,
manifestPath: './config/github.webmanifest'
},
pwa: {
enabled: false,
promote: false
}
},
catalog: {
Expand Down
17 changes: 8 additions & 9 deletions src/environments/environment.prod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,19 @@ import {
CommonVectorStyleOptions
} from '@igo2/geo';

import { AppOptions, InteractiveTourConfigOptions } from './environnement.interface';

export interface Environment {
production: boolean;
igo: {
app: {
forceCoordsNA: boolean;
pwa?: {
enabled?: boolean;
promote?: boolean;
}
};
app: AppOptions;
importExport?: ImportExportServiceOptions;
language?: LanguageOptions;
searchSources?: { [key: string]: SearchSourceOptions };
optionsApi?: OptionsApiOptions;
projections?: Projection[];
spatialFilter?: SpatialFilterOptions;
interactiveTour?: { tourInMobile: boolean; pathToConfigFile: string };
interactiveTour?: InteractiveTourConfigOptions;
depot?: { url: string; trainingGuides?: string[]; };
queryOverlayStyle?: {
base?: CommonVectorStyleOptions,
Expand All @@ -44,9 +40,12 @@ export const environment: Environment = {
igo: {
app: {
forceCoordsNA: true,
pwa: {
install: {
enabled: false,
promote: false
},
pwa: {
enabled: false,
}
},
importExport: {
Expand Down
5 changes: 4 additions & 1 deletion src/environments/environment.pwa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ if (!prodEnv.igo.app.pwa) {
prodEnv.igo.app.pwa = {};
}
prodEnv.igo.app.pwa.enabled = true;
prodEnv.igo.app.pwa.promote = true;
prodEnv.igo.app.install.enabled = true;
prodEnv.igo.app.install.promote = true;
prodEnv.igo.app.install.manifestPath = undefined;

export const environment = prodEnv;
Loading