@geogirafe/lib-geoportal 1.2.0-dev.2893241744 → 1.2.0-dev.2897830140

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  import Geolocation from 'ol/Geolocation.js';
2
2
  import GirafeHTMLElement from '../../base/GirafeHTMLElement.js';
3
3
  type GeolocationStatus = 'off' | 'error' | 'searching' | 'tracking' | 'headlock';
4
+ export type GeolocationIcons = Record<GeolocationStatus, string>;
4
5
  export default class GeolocationMobile extends GirafeHTMLElement {
5
6
  protected templateUrl: string | null;
6
7
  protected styleUrls: string[] | null;
@@ -8,6 +9,7 @@ export default class GeolocationMobile extends GirafeHTMLElement {
8
9
  geolocation: Geolocation | null;
9
10
  status: GeolocationStatus;
10
11
  statusBeforeError: GeolocationStatus;
12
+ icons: GeolocationIcons;
11
13
  private readonly positionFeature;
12
14
  private readonly accuracyFeature;
13
15
  private readonly headingFeature;
@@ -21,7 +23,7 @@ export default class GeolocationMobile extends GirafeHTMLElement {
21
23
  protected connectedCallback(): void;
22
24
  private pauseTracking;
23
25
  private updateIconIfTrackingOutside;
24
- getIconForStatus(): any;
26
+ getIconForStatus(): string | undefined;
25
27
  pointerUp(e: PointerEvent): void;
26
28
  pointerDown(e: PointerEvent): void;
27
29
  preventContextMenu(e: PointerEvent): boolean;
@@ -11,10 +11,6 @@ import Stroke from 'ol/style/Stroke.js';
11
11
  import Style from 'ol/style/Style.js';
12
12
  import { RegularShape } from 'ol/style.js';
13
13
  import GirafeHTMLElement from '../../base/GirafeHTMLElement.js';
14
- import locationDisabledIcon from '../../assets/icons/location_disabled.svg';
15
- import locationSearchingIcon from '../../assets/icons/location_searching.svg';
16
- import locationHeadingIcon from '../../assets/icons/location_heading.svg';
17
- import myLocationIcon from '../../assets/icons/my_location.svg';
18
14
  export default class GeolocationMobile extends GirafeHTMLElement {
19
15
  templateUrl = null;
20
16
  styleUrls = null;
@@ -31,6 +27,13 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
31
27
  geolocation = null;
32
28
  status = 'off';
33
29
  statusBeforeError = 'off';
30
+ icons = {
31
+ off: 'icons/location_disabled.svg',
32
+ error: 'icons/location_disabled.svg',
33
+ searching: 'icons/location_searching.svg',
34
+ tracking: 'icons/my_location.svg',
35
+ headlock: 'icons/location_heading.svg'
36
+ };
34
37
  positionFeature;
35
38
  accuracyFeature;
36
39
  headingFeature;
@@ -241,20 +244,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
241
244
  if (!this.geolocation) {
242
245
  return;
243
246
  }
244
- switch (this.status) {
245
- case 'searching':
246
- return locationSearchingIcon;
247
- case 'tracking':
248
- return myLocationIcon;
249
- case 'off':
250
- return locationDisabledIcon;
251
- case 'error':
252
- return locationDisabledIcon;
253
- case 'headlock':
254
- return locationHeadingIcon;
255
- default:
256
- return locationDisabledIcon;
257
- }
247
+ return this.icons[this.status] ?? this.icons.off;
258
248
  }
259
249
  pointerUp(e) {
260
250
  e.stopPropagation();
@@ -22,6 +22,7 @@ export { default as EditComponent } from './edit/component.js';
22
22
  export { default as EditFromComponent } from './edit/editform/component.js';
23
23
  export { default as ExternalLayersComponent } from './extlayers/component.js';
24
24
  export { default as FeedbackButtonComponent } from './feedbackbutton/component.js';
25
+ export type { GeolocationIcons } from './geolocation-mobile/component.js';
25
26
  export { default as GeolocationMobile } from './geolocation-mobile/component.js';
26
27
  export { default as GetDirectionsArtifact } from './getdirections/component.js';
27
28
  export { default as HeaderComponent } from './header/component.js';
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "GeoGirafe PSC",
6
6
  "url": "https://doc.geogirafe.org"
7
7
  },
8
- "version": "1.2.0-dev.2893241744",
8
+ "version": "1.2.0-dev.2897830140",
9
9
  "type": "module",
10
10
  "engines": {
11
11
  "node": ">=20.19.0"
@@ -1 +1 @@
1
- {"version":"1.2.0-dev.2893241744", "build":"2893241744", "date":"29/09/2026"}
1
+ {"version":"1.2.0-dev.2897830140", "build":"2897830140", "date":"30/09/2026"}
@@ -13,5 +13,5 @@ export default class GeoGirafeApp {
13
13
  protected addCustomSerializers(): void;
14
14
  protected defineCoreComponents(): void;
15
15
  private initializeServiceWorker;
16
- private waitForServiceWorkerActivation;
16
+ private waitForServiceWorkerControl;
17
17
  }
@@ -175,7 +175,7 @@ export default class GeoGirafeApp {
175
175
  }
176
176
  let sw;
177
177
  try {
178
- sw = await this.waitForServiceWorkerActivation();
178
+ sw = await this.waitForServiceWorkerControl();
179
179
  }
180
180
  catch (err) {
181
181
  throw new Error(`Service worker registration failed. ${err}`, { cause: err });
@@ -213,22 +213,36 @@ export default class GeoGirafeApp {
213
213
  this.context.stateManager.state.application.isAuthInitialized = true;
214
214
  }
215
215
  }
216
- async waitForServiceWorkerActivation() {
217
- const registration = await navigator.serviceWorker.register('service-worker.js', { type: 'module' });
218
- if (registration.active) {
219
- return registration.active;
216
+ async waitForServiceWorkerControl() {
217
+ const sw = navigator.serviceWorker;
218
+ const registration = await sw.register('service-worker.js', { type: 'module' });
219
+ // If a service worker already controls the current page, everything is ready.
220
+ // `registration.active` only tells us that a service worker is active for the registration;
221
+ // `sw.controller` tells us that it actually controls this page.
222
+ if (sw.controller) {
223
+ return sw.controller;
220
224
  }
221
- const sw = registration.installing || registration.waiting;
222
- if (!sw) {
223
- throw new Error('No service worker is installing or waiting.');
225
+ // The page is not currently controlled by a service worker.
226
+ // This can happen, for example, after a force refresh (Ctrl+F5), even though
227
+ // an active service worker already exists. In that case, the service worker's
228
+ // `activate` event is not triggered again, so the `clients.claim()` call from
229
+ // the activation phase cannot take control of this newly loaded page.
230
+ // If an active service worker already exists, explicitly ask it to claim the
231
+ // current page. The service worker handles this message by calling `clients.claim()`.
232
+ const active = registration.active;
233
+ if (active) {
234
+ active.postMessage({ type: 'claim' });
224
235
  }
236
+ // Wait until the service worker takes control of the current page.
237
+ // Once `clients.claim()` succeeds, the browser updates `sw.controller` and
238
+ // dispatches the `controllerchange` event.
225
239
  return new Promise((resolve) => {
226
- sw.addEventListener('statechange', function onStateChange() {
227
- if (sw.state === 'activated') {
228
- sw.removeEventListener('statechange', onStateChange);
229
- resolve(sw);
240
+ sw.addEventListener('controllerchange', () => {
241
+ const controller = navigator.serviceWorker.controller;
242
+ if (controller) {
243
+ resolve(controller);
230
244
  }
231
- });
245
+ }, { once: true });
232
246
  });
233
247
  }
234
248
  }
@@ -37,6 +37,10 @@ sw.addEventListener('fetch', (event) => {
37
37
  event.respondWith(handleFetchEvent(event));
38
38
  });
39
39
  function handleMessage(event) {
40
+ if (event.data?.type === 'claim') {
41
+ event.waitUntil(sw.clients.claim());
42
+ return;
43
+ }
40
44
  if (!swHelper.isOriginAllowed(self.location.origin, event.origin)) {
41
45
  console.warn(`Message ignored: origin not allowed (${event.origin})`);
42
46
  return;
@@ -64,11 +68,6 @@ function handleActivate(event) {
64
68
  if ('clients' in sw) {
65
69
  await swHelperReady;
66
70
  await sw.clients.claim();
67
- const clientsList = await sw.clients.matchAll({ type: 'window' });
68
- for (const client of clientsList) {
69
- client.navigate(client.url);
70
- log('Page reloaded by the service worker.');
71
- }
72
71
  }
73
72
  })());
74
73
  }