powergrid-viewer 2.0.6 → 2.0.7

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": "powergrid-viewer",
3
- "version": "2.0.6",
3
+ "version": "2.0.7",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/boardgamers/powergrid.git",
@@ -2024,6 +2024,10 @@ export default class Game extends Vue {
2024
2024
  * the choice would disappear along with the layout.
2025
2025
  */
2026
2026
  portraitViewport = false;
2027
+
2028
+ /** Viewport the board was last laid out against, as `WxH` — see onViewportResize. */
2029
+ private lastViewport = '';
2030
+ private viewportObserver: ResizeObserver | null = null;
2027
2031
  /** Height of the stacked canvas, in scene units. */
2028
2032
  stackHeight = STACK_WIDTH;
2029
2033
  /** Wrapper transform per slot; empty means "render as authored". */
@@ -2062,6 +2066,16 @@ export default class Game extends Vue {
2062
2066
  return window.innerWidth < 900 && window.innerHeight > window.innerWidth * 1.1;
2063
2067
  }
2064
2068
 
2069
+ /**
2070
+ * The platform mounts the viewer in an iframe that is `display: none` until the
2071
+ * game state arrives, so the first measurement here is 0x0 — which is not a
2072
+ * landscape phone, it is nothing at all. Answering then would settle the layout
2073
+ * against a viewport that does not exist yet.
2074
+ */
2075
+ private viewportIsMeasurable(): boolean {
2076
+ return window.innerWidth > 0 && window.innerHeight > 0;
2077
+ }
2078
+
2065
2079
  private shouldStack(): boolean {
2066
2080
  return this.isPortraitViewport() && this.preferences.stackOnPortrait !== false;
2067
2081
  }
@@ -2075,6 +2089,11 @@ export default class Game extends Vue {
2075
2089
  }
2076
2090
 
2077
2091
  relayout() {
2092
+ if (!this.viewportIsMeasurable()) {
2093
+ // Still hidden. Whoever reveals us triggers the observer below.
2094
+ return;
2095
+ }
2096
+
2078
2097
  this.portraitViewport = this.isPortraitViewport();
2079
2098
 
2080
2099
  if (!this.shouldStack()) {
@@ -2189,17 +2208,57 @@ export default class Game extends Vue {
2189
2208
  this.$nextTick(() => this.relayout());
2190
2209
  }
2191
2210
 
2192
- private onViewportResize = () => this.scheduleRelayout();
2211
+ /**
2212
+ * Re-lay out only when the viewport itself changed size. The observer below also
2213
+ * fires for our OWN output — laying out the board changes the document's box — and
2214
+ * without this that would be a loop.
2215
+ */
2216
+ private onViewportResize = () => {
2217
+ const size = `${window.innerWidth}x${window.innerHeight}`;
2218
+
2219
+ if (size === this.lastViewport) {
2220
+ return;
2221
+ }
2222
+
2223
+ this.lastViewport = size;
2224
+ this.scheduleRelayout();
2225
+ };
2193
2226
 
2194
2227
  mounted() {
2195
2228
  window.addEventListener('resize', this.onViewportResize);
2196
2229
  window.addEventListener('orientationchange', this.onViewportResize);
2230
+ window.addEventListener('load', this.onViewportResize);
2231
+
2232
+ if (window.visualViewport) {
2233
+ window.visualViewport.addEventListener('resize', this.onViewportResize);
2234
+ }
2235
+
2236
+ // The one signal that does not depend on the browser dispatching an event:
2237
+ // being revealed changes the document's own box. Safari does not reliably fire
2238
+ // `resize` inside an iframe going from `display: none` to visible, and the
2239
+ // board then stays in the landscape layout with no toggle to escape it — the
2240
+ // measurement was taken at 0x0 and nothing ever asked again.
2241
+ if (typeof ResizeObserver !== 'undefined') {
2242
+ this.viewportObserver = new ResizeObserver(this.onViewportResize);
2243
+ this.viewportObserver.observe(document.documentElement);
2244
+ }
2245
+
2197
2246
  this.scheduleRelayout();
2198
2247
  }
2199
2248
 
2200
2249
  beforeDestroy() {
2201
2250
  window.removeEventListener('resize', this.onViewportResize);
2202
2251
  window.removeEventListener('orientationchange', this.onViewportResize);
2252
+ window.removeEventListener('load', this.onViewportResize);
2253
+
2254
+ if (window.visualViewport) {
2255
+ window.visualViewport.removeEventListener('resize', this.onViewportResize);
2256
+ }
2257
+
2258
+ if (this.viewportObserver) {
2259
+ this.viewportObserver.disconnect();
2260
+ this.viewportObserver = null;
2261
+ }
2203
2262
  }
2204
2263
 
2205
2264
  // Boards grow as players buy plants, so the row heights are re-derived on