@panoramax/web-viewer 3.2.2-develop-e0cee138 → 3.2.2-develop-5c3f5e00

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@panoramax/web-viewer",
3
- "version": "3.2.2-develop-e0cee138",
3
+ "version": "3.2.2-develop-5c3f5e00",
4
4
  "description": "Panoramax web viewer for geolocated pictures",
5
5
  "main": "build/index.js",
6
6
  "author": "Panoramax team",
@@ -84,7 +84,7 @@ class StandaloneMap extends CoreView {
84
84
 
85
85
  this.map = new MyMap(this, this.mapContainer, this._options);
86
86
  this.map.addControl(new NavigationControl({ showCompass: false }));
87
- this.map.on("load", () => {
87
+ this.map.waitForEnoughMapLoaded().then(() => {
88
88
  this.map.reloadLayersStyles();
89
89
  this._loader.dismiss();
90
90
  });
@@ -22,7 +22,7 @@
22
22
  display: flex;
23
23
  flex-direction: column;
24
24
  justify-content: center;
25
- gap: 40px;
25
+ gap: 20px;
26
26
  align-items: center;
27
27
  background: #37474F;
28
28
  z-index: 9000;
@@ -53,4 +53,22 @@
53
53
  @keyframes rotating {
54
54
  from { transform: rotate(0deg); }
55
55
  to { transform: rotate(360deg); }
56
+ }
57
+
58
+ /* Call to action button */
59
+ .gvs .gvs-loader .gvs-loader-cta {
60
+ border: none;
61
+ border-radius: 7px;
62
+ font-weight: 500;
63
+ font-size: 1.0em;
64
+ color: white;
65
+ background-color: #EF6C00;
66
+ cursor: pointer;
67
+ margin: 10px;
68
+ padding: 5px 30px;
69
+ box-shadow: 2px 2px 2px rgba(0,0,0,0.3);
70
+ }
71
+
72
+ .gvs .gvs-loader .gvs-loader-cta:hover {
73
+ background-color: #F57C00;
56
74
  }
@@ -83,7 +83,15 @@ export default class Loader {
83
83
  this.container.children[0].src = LogoDead;
84
84
  this.container.children[0].style.width = "200px";
85
85
  this.container.children[0].style.animation = "unset";
86
- let errHtml = `<small>${next ? this._parent._t.gvs.error_click : this._parent._t.gvs.error_retry}</small>`;
86
+
87
+ let errHtml;
88
+ if(next) {
89
+ errHtml = `<button class="gvs-loader-cta">${this._parent._t.gvs.error_click}</button>`;
90
+ }
91
+ else {
92
+ errHtml = `<small>${this._parent._t.gvs.error_retry}</small>`;
93
+ }
94
+
87
95
  if(errMeaningful) { errHtml = errMeaningful + "<br />" + errHtml; }
88
96
  this.container.children[1].innerHTML = `${this._parent._t.gvs.error}<br />${errHtml}`;
89
97
  if(next) {
@@ -110,11 +110,16 @@ export default class Map extends maplibregl.Map {
110
110
  }
111
111
  }, 15000);
112
112
 
113
- this.on("load", async () => {
114
- await this.setVisibleUsers(this._parent._options.users);
115
- this.reloadLayersStyles();
116
- this.resize();
117
- });
113
+ this.waitForEnoughMapLoaded().then(async () => await this._postLoad());
114
+ }
115
+
116
+ /**
117
+ * @private
118
+ */
119
+ async _postLoad() {
120
+ this.resize();
121
+ await this.setVisibleUsers(this._parent._options.users);
122
+ this.reloadLayersStyles();
118
123
  }
119
124
 
120
125
  /**
@@ -132,6 +137,54 @@ export default class Map extends maplibregl.Map {
132
137
  delete this._userLayers;
133
138
  }
134
139
 
140
+ /**
141
+ * Helper to know when enough map background and Panoramax tiles are loaded for a proper display.
142
+ * @returns {Promise} Resolves when enough is loaded
143
+ */
144
+ waitForEnoughMapLoaded() {
145
+ return new Promise((resolve) => {
146
+ let nbBgTiles = 0;
147
+ let nbFgTiles = 0;
148
+ let nbLoadedBgTiles = 0;
149
+ let nbLoadedFgTiles = 0;
150
+
151
+ const onSourceDataLoading = e => {
152
+ if(e.dataType === "source" && e.tile) {
153
+ if(e.sourceId.startsWith("geovisio")) {
154
+ nbFgTiles++;
155
+ }
156
+ else {
157
+ nbBgTiles++;
158
+ }
159
+ }
160
+ };
161
+ const onSourceData = e => {
162
+ if(e.dataType === "source" && e.tile) {
163
+ if(e.sourceId.startsWith("geovisio")) {
164
+ nbLoadedFgTiles++;
165
+ if(e.isSourceLoaded) { nbLoadedFgTiles = nbFgTiles; }
166
+ }
167
+ else {
168
+ nbLoadedBgTiles++;
169
+ if(e.isSourceLoaded) { nbLoadedBgTiles = nbBgTiles; }
170
+ }
171
+ }
172
+ checkEnoughLoaded();
173
+ };
174
+
175
+ const checkEnoughLoaded = () => {
176
+ if(nbLoadedBgTiles / nbBgTiles >= 0.75 && nbLoadedFgTiles / nbFgTiles >= 0.75) {
177
+ this.off("sourcedata", onSourceData);
178
+ this.off("sourcedataloading", onSourceDataLoading);
179
+ resolve();
180
+ }
181
+ };
182
+
183
+ this.on("sourcedataloading", onSourceDataLoading);
184
+ this.on("sourcedata", onSourceData);
185
+ });
186
+ }
187
+
135
188
  /**
136
189
  * Sets map view based on returned API bbox (if no precise option given by user).
137
190
  * @private
@@ -148,7 +201,7 @@ export default class Map extends maplibregl.Map {
148
201
  try {
149
202
  bbox = new maplibregl.LngLatBounds(bbox);
150
203
  if(this.loaded()) { this.fitBounds(bbox, { "animate": false }); }
151
- else { this.on("load", () => this.fitBounds(bbox, { "animate": false })); }
204
+ else { this.waitForEnoughMapLoaded().then(() => this.fitBounds(bbox, { "animate": false })); }
152
205
  }
153
206
  catch(e) {
154
207
  console.warn("Received invalid bbox: "+bbox);
@@ -42,7 +42,7 @@
42
42
  "copy": "Copy",
43
43
  "copied": "Copied",
44
44
  "error": "We have a problem…",
45
- "error_click": "Click to continue",
45
+ "error_click": "Continue",
46
46
  "error_retry": "Please retry later",
47
47
  "sequence_next": "Next picture in sequence",
48
48
  "sequence_play": "Play along this sequence",
@@ -95,7 +95,7 @@
95
95
  "sequence_play": "Reproducir esta secuencia",
96
96
  "sequence_pause": "Pausar la secuencia",
97
97
  "sequence_prev": "Imagen anterior de la secuencia",
98
- "error_click": "Haz click para continuar",
98
+ "error_click": "Continuar",
99
99
  "error_retry": "Por favor, inténtalo más tarde",
100
100
  "error_psv": "El visor de fotos esféricas no se carga correctamente",
101
101
  "error_pic": "No se encuentra la imagen que queríamos",
@@ -42,7 +42,7 @@
42
42
  "copy": "Copier",
43
43
  "copied": "Copié",
44
44
  "error": "On a un problème…",
45
- "error_click": "Cliquez pour continuer",
45
+ "error_click": "Continuer",
46
46
  "error_retry": "Merci de réessayer plus tard",
47
47
  "sequence_next": "Photo suivante dans la séquence",
48
48
  "sequence_play": "Parcourir cette séquence",
@@ -26,7 +26,7 @@
26
26
  "copy": "Copia",
27
27
  "copied": "Copiato",
28
28
  "error": "Abbiamo un problema…",
29
- "error_click": "Clicca per continuare",
29
+ "error_click": "Continuare",
30
30
  "error_retry": "Riprovare più tardi",
31
31
  "sequence_play": "Riproduci questa sequenza",
32
32
  "sequence_pause": "Pausa la sequenza",
@@ -143,13 +143,13 @@ describe("setBackground", () => {
143
143
  });
144
144
 
145
145
  describe("getVisibleUsers", () => {
146
- it("works", () => {
146
+ it("works", async () => {
147
147
  const p = createParent();
148
148
  const c = document.createElement("div");
149
149
  const m = new Map(p, c);
150
150
  m.getSource = () => true;
151
151
  m.setPaintProperty = jest.fn();
152
- m._fire("load");
152
+ await m._postLoad();
153
153
  m.getLayoutProperty = () => "visible";
154
154
  expect(m.getVisibleUsers()).toStrictEqual(["geovisio"]);
155
155
  });
@@ -177,14 +177,14 @@ describe("setVisibleUsers", () => {
177
177
  m.getLayer = () => true;
178
178
  let cptlCount = 0;
179
179
  let deCalls = [];
180
- return new Promise(resolve => {
180
+ return new Promise(async (resolve) => {
181
181
  p.dispatchEvent = (e) => {
182
182
  deCalls.push(e);
183
183
  if(e.type == "map:users-changed") {
184
184
  resolve();
185
185
  }
186
186
  };
187
- m._fire("load");
187
+ await m._postLoad();
188
188
  }).then(() => {
189
189
  m.setLayoutProperty = jest.fn();
190
190
  m._createPicturesTilesLayer = () => { cptlCount++; return Promise.resolve(); };
@@ -199,7 +199,7 @@ describe("setVisibleUsers", () => {
199
199
  });
200
200
 
201
201
  describe("filterUserLayersContent", () => {
202
- it("works", () => {
202
+ it("works", async () => {
203
203
  const p = createParent();
204
204
  p._options.users = ["blabla", "geovisio"];
205
205
  const c = document.createElement("div");
@@ -207,7 +207,7 @@ describe("filterUserLayersContent", () => {
207
207
  m.getSource = () => true;
208
208
  m.setPaintProperty = jest.fn();
209
209
  m.getLayer = () => true;
210
- m._fire("load");
210
+ await m._postLoad();
211
211
  m.setFilter = jest.fn();
212
212
  m.filterUserLayersContent("pictures", [["test", "true"]]);
213
213
  expect(m.setFilter.mock.calls).toMatchSnapshot();
@@ -215,14 +215,14 @@ describe("filterUserLayersContent", () => {
215
215
  });
216
216
 
217
217
  describe("reloadLayersStyles", () => {
218
- it("works", () => {
218
+ it("works", async () => {
219
219
  const p = createParent();
220
220
  p._options.users = ["blabla", "geovisio"];
221
221
  const c = document.createElement("div");
222
222
  const m = new Map(p, c);
223
223
  m.getSource = () => true;
224
224
  m.setPaintProperty = jest.fn();
225
- m._fire("load");
225
+ await m._postLoad();
226
226
  m.setLayoutProperty = jest.fn();
227
227
  m.setPaintProperty = jest.fn();
228
228
  m.reloadLayersStyles();