Преглед на файлове

Extend Office splash to Sheets and Slides

Bring the shared Office start-up splash to Sheets and Slides, including preloaded app icons, splash-first loading order, and smaller initial float-window sizes that expand to the full working size when the document is ready. The shared splash logic now recenters windows on the desktop and avoids stacking new windows directly on top of existing ones, and the Office docs/contracts were updated to describe the behavior across Docs, Sheets, and Slides.
Toby Chui преди 2 седмици
родител
ревизия
0c3feb0075

+ 9 - 8
src/web/Office/README.md

@@ -635,17 +635,18 @@ payload to `user:/.appdata/Office/tmp/` through the system upload endpoint
 low-memory boards) and passes `dataFile` to the backend script, which reads
 and deletes it. Raising the server-side form limit is *not* an option here.
 
-### Docs: start-up splash
+### Start-up splash
 
 Opening a large document takes a moment (fetching and unpacking it, a server
-or WebAssembly conversion for `.docx`, laying out every page), so Docs starts
-behind a splash that says what is happening — [`common/splash.js`](common/splash.js),
+or WebAssembly conversion for `.docx` / `.xlsx` / `.pptx`, laying out every
+page), so Docs, Sheets and Slides start behind a splash that says what is
+happening — [`common/splash.js`](common/splash.js),
 contract in `CONTRACT.md`. In a desktop float window it is the classic office
-splash (the window opens small, `InitFWSize` 400x240, and grows to 1080x700
-around its centre once the document is on screen); in a browser tab it is a
-white page with the Docs icon and the status under it. `docs/index.html` loads
-its stylesheets and scripts in `<body>`, after the splash, so the splash paints
-while they arrive.
+splash (the window opens small, `InitFWSize` 400x240, and grows to 1080x700,
+both centred on the desktop, once the document is on screen); in a browser tab it is a
+white page with the app's icon and the status under it. Sheets grows to
+1180x720 and Slides to 1220x740. Each `index.html` loads its stylesheets and
+scripts in `<body>`, after the splash, so the splash paints while they arrive.
 
 ### Header / footer
 

+ 2 - 2
src/web/Office/common/CONTRACT.md

@@ -739,12 +739,12 @@ downstream has to know about them.
 
 ## Start-up splash (common/splash.js)
 
-An app can show a splash while it starts and opens its document (Docs does):
+An app can show a splash while it starts and opens its document (all three do):
 `<script src="../common/splash.js" data-app="Docs" data-icon="../img/docs.svg"
 data-size="1080x700"></script>` as the **first element of `<body>`**, with the
 app's stylesheets and scripts after it rather than in `<head>` (they would hold
 the first paint back). Inside a web desktop float window it is a coloured card
-in a small window that grows to `data-size` about its own centre when ready
+in a small window that grows to `data-size` when ready, both centred on the desktop
 (register the app with an `InitFWSize` of 400x240 so the window opens at that
 size); in a full tab it is a plain page with the icon and a status line. It
 styles itself. `OfficeApp` drives it: `setStatus` / `showBusy` text becomes its

+ 42 - 13
src/web/Office/common/splash.js

@@ -7,10 +7,11 @@
 
     Two looks, chosen by where the app runs:
 
-      window    inside a web desktop float window: the window starts small,
-                a coloured card with the app name, moving dots and the
-                status line in the corner - and grows to its working size,
-                about its own centre, once the document is ready
+      window    inside a web desktop float window: the window starts small
+                in the middle of the desktop, a coloured card with the app
+                name, moving dots and the status line in the corner - and
+                grows to its working size, still centred on the desktop,
+                once the document is ready
       page      a full browser tab (or the mobile desktop, whose windows
                 fill the screen): a plain page with the app icon in the
                 middle and the status under it
@@ -272,10 +273,11 @@ var OfficeSplash = (function () {
             root.appendChild(mid);
             statusEl = el("div", "of-splash-status", "Loading...");
             root.appendChild(statusEl);
-            // start small, like a splash; grown back in done()
+            // start small, like a splash, in the middle of the desktop;
+            // grown back in done()
             try {
                 setResizable(fw, false);
-                setWindowSize(fw, SPLASH_W, SPLASH_H);
+                placeCentred(fw, SPLASH_W, SPLASH_H);
             } catch (e) { }
         } else {
             var center = el("div", "of-splash-center");
@@ -313,17 +315,44 @@ var OfficeSplash = (function () {
             return;
         }
         try {
-            var pw = window.parent.innerWidth, ph = window.parent.innerHeight;
-            var w = Math.min(workW, pw), h = Math.min(workH, ph);
-            var left = parseFloat(fw.style.left) || 0, top = parseFloat(fw.style.top) || 0;
-            var cx = left + fw.offsetWidth / 2, cy = top + fw.offsetHeight / 2;
-            fw.style.left = Math.max(0, Math.min(pw - w, Math.round(cx - w / 2))) + "px";
-            fw.style.top = Math.max(0, Math.min(ph - h, Math.round(cy - h / 2))) + "px";
-            setWindowSize(fw, w, h);
+            placeCentred(fw, workW, workH);
             setResizable(fw, true);
         } catch (e) { }
     }
 
+    /* placeCentred sizes the window and puts its centre on the centre of the
+       desktop. A window of the same app opened a moment earlier sits exactly
+       there already, so like the desktop's own placement this one steps
+       30px down and right until the spot is free. */
+    function placeCentred(fw, width, height) {
+        var pw = window.parent.innerWidth, ph = window.parent.innerHeight;
+        var w = Math.min(width, pw), h = Math.min(height, ph);
+        var left = Math.max(0, Math.round((pw - w) / 2));
+        var top = Math.max(0, Math.round((ph - h) / 2));
+        var others = [];
+        try {
+            var all = window.parent.document.querySelectorAll(".floatWindow");
+            for (var i = 0; i < all.length; i++) {
+                if (all[i] !== fw) others.push(all[i]);
+            }
+        } catch (e) { }
+        var taken = function (x, y) {
+            for (var i = 0; i < others.length; i++) {
+                if (Math.abs((parseFloat(others[i].style.left) || 0) - x) < 3 &&
+                        Math.abs((parseFloat(others[i].style.top) || 0) - y) < 3) return true;
+            }
+            return false;
+        };
+        for (var step = 0; step < 20 && taken(left, top); step++) {
+            if (left + 30 + w > pw || top + 30 + h > ph) break;
+            left += 30;
+            top += 30;
+        }
+        fw.style.left = left + "px";
+        fw.style.top = top + "px";
+        setWindowSize(fw, w, h);
+    }
+
     function done() {
         if (finished || !root) return;
         finished = true;

+ 2 - 0
src/web/Office/docs/index.html

@@ -5,6 +5,8 @@
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Docs</title>
     <link rel="icon" type="image/png" href="docs.png">
+    <!-- fetched first: the start-up splash shows it -->
+    <link rel="preload" href="../img/docs.svg" as="image">
     <!-- Dynamic print stylesheet: docs.js writes the @page rule (size,
          orientation, margins, optional page-number margin box) in here
          whenever the page setup changes. Static print rules live in docs.css. -->

+ 6 - 4
src/web/Office/init.agi

@@ -43,8 +43,9 @@ registerModule(JSON.stringify({
     LaunchFWDir: "Office/sheets/index.html",
     SupportEmb: true,
     LaunchEmb: "Office/sheets/index.html",
-    InitFWSize: [1180, 720],
-    InitEmbSize: [1180, 720],
+    // splash-sized, grows to 1180x720 when ready (common/splash.js)
+    InitFWSize: [400, 240],
+    InitEmbSize: [400, 240],
     SupportedExt: [".xlsa", ".csv", ".tsv", ".xlsx"]
 }));
 
@@ -61,8 +62,9 @@ registerModule(JSON.stringify({
     LaunchFWDir: "Office/slides/index.html",
     SupportEmb: true,
     LaunchEmb: "Office/slides/index.html",
-    InitFWSize: [1220, 740],
-    InitEmbSize: [1220, 740],
+    // splash-sized, grows to 1220x740 when ready (common/splash.js)
+    InitFWSize: [400, 240],
+    InitEmbSize: [400, 240],
     SupportedExt: [".ppta", ".pptx"]
 }));
 

+ 8 - 2
src/web/Office/sheets/index.html

@@ -5,6 +5,14 @@
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Sheets</title>
     <link rel="icon" type="image/png" href="sheets.png">
+    <!-- fetched first: the start-up splash shows it -->
+    <link rel="preload" href="../img/sheets.svg" as="image">
+</head>
+<body data-officeapp="sheets">
+    <!-- start-up splash: first, so it covers the page before anything draws -->
+    <script src="../common/splash.js" data-app="Sheets" data-icon="../img/sheets.svg" data-size="1180x720"></script>
+    <!-- the app's stylesheets and scripts come after the splash, so it can
+         paint while they load -->
     <link rel="stylesheet" href="../../script/semantic/semantic.min.css">
     <link rel="stylesheet" href="../common/office.css">
     <link rel="stylesheet" href="../common/fonts/fonts.css">
@@ -23,8 +31,6 @@
     <script src="../common/clipboard.js"></script>
     <script src="../common/charts.js"></script>
     <script src="formula.js"></script>
-</head>
-<body data-officeapp="sheets">
     <div class="of-toolbar of-noprint" id="toolbar"></div>
     <div id="shFxBar" class="of-noprint">
         <input id="shNameBox" spellcheck="false" title="Cell reference (type a ref and press Enter to jump)">

+ 7 - 4
src/web/Office/sheets/sheets_io.js

@@ -523,10 +523,13 @@ var SheetsIO = (function () {
                 OfficeApp.toast("Import failed: unexpected response", "error");
                 return;
             }
-            Core.setBody(b);
-            // the framework kept us attached to the source file, so Save
-            // writes straight back to it in its own format
-            OfficeApp.setStatus("Opened " + fn);
+            OfficeApp.splashStep("Preparing the sheets...", function () {
+                Core.setBody(b);
+                // the framework kept us attached to the source file, so Save
+                // writes straight back to it in its own format
+                OfficeApp.setStatus("Opened " + fn);
+                OfficeApp.documentLoaded();
+            });
         }, function (msg) {
             OfficeApp.hideBusy();
             OfficeApp.toast("Import failed: " + msg, "error");

+ 8 - 2
src/web/Office/slides/index.html

@@ -5,6 +5,14 @@
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Slides</title>
     <link rel="icon" type="image/png" href="slides.png">
+    <!-- fetched first: the start-up splash shows it -->
+    <link rel="preload" href="../img/slides.svg" as="image">
+</head>
+<body data-officeapp="slides">
+    <!-- start-up splash: first, so it covers the page before anything draws -->
+    <script src="../common/splash.js" data-app="Slides" data-icon="../img/slides.svg" data-size="1220x740"></script>
+    <!-- the app's stylesheets and scripts come after the splash, so it can
+         paint while they load -->
     <link rel="stylesheet" href="../../script/semantic/semantic.min.css">
     <link rel="stylesheet" href="../common/office.css">
     <link rel="stylesheet" href="../common/fonts/fonts.css">
@@ -25,8 +33,6 @@
     <script src="../common/charts.js"></script>
     <script src="../common/lib/html2canvas.min.js"></script>
     <script src="../common/lib/pdf-lib.min.js"></script>
-</head>
-<body data-officeapp="slides">
     <div class="of-toolbar of-noprint" id="toolbar"></div>
     <div class="of-workspace" id="workspace">
         <div id="slRail" class="of-noprint">

+ 12 - 9
src/web/Office/slides/slides.js

@@ -3467,15 +3467,18 @@ var SlidesApp = (function () {
                 OfficeApp.toast("Import failed: unexpected response", "error");
                 return;
             }
-            body = normalizeBody(b);
-            cur = 0;
-            sel = [];
-            editingId = null;
-            renderAll();
-            undo.init(snap());
-            // the framework kept us attached to the source file, so Save
-            // writes straight back to it in its own format
-            OfficeApp.setStatus("Opened " + fn);
+            OfficeApp.splashStep("Preparing the slides...", function () {
+                body = normalizeBody(b);
+                cur = 0;
+                sel = [];
+                editingId = null;
+                renderAll();
+                undo.init(snap());
+                // the framework kept us attached to the source file, so Save
+                // writes straight back to it in its own format
+                OfficeApp.setStatus("Opened " + fn);
+                OfficeApp.documentLoaded();
+            });
         }, function (msg) {
             OfficeApp.hideBusy();
             OfficeApp.toast("Import failed: " + msg, "error");