A strip along the top that leads to the other apps of the same system. It is served by HoneyOS; InkNote only says where to find it, through INKNOTE_HONEYBAR_ORIGIN. Empty means no bar and no change at all. The origin is served by the API rather than built into the page, because an image is pulled ready-made and a service worker keeps whole responses: anything frozen into index.html would outlive the setting. Layout follows the bar through --honeybar-h. The body has overflow:hidden, so the surplus height would not have scrolled but been cut off at the bottom; and #root padded itself around the notch that the bar now covers, which would have counted that gap twice. Unit 263/263, all fourteen browser suites green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
70 lines
4.1 KiB
HTML
70 lines
4.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
|
<meta name="theme-color" content="#0d1117" media="(prefers-color-scheme: dark)" />
|
|
<meta name="theme-color" content="#f6f8fa" media="(prefers-color-scheme: light)" />
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
<meta name="apple-mobile-web-app-title" content="InkNote" />
|
|
<meta name="description" content="Write & draw — notes that sync everywhere" />
|
|
<meta name="mobile-web-app-capable" content="yes" />
|
|
<!-- `use-credentials` because the manifest is otherwise fetched with
|
|
credentials omitted, cookies and all. Behind an authenticating reverse
|
|
proxy that request comes back as the proxy's login page, the browser
|
|
reads it as an invalid manifest, and no install is ever offered — while
|
|
the app itself works perfectly, because its own requests do carry the
|
|
cookie. Harmless without a proxy. -->
|
|
<link rel="manifest" href="./manifest.json" crossorigin="use-credentials" />
|
|
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
|
|
<link rel="icon" type="image/png" sizes="192x192" href="./icon-192.png" />
|
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>✏️</text></svg>" />
|
|
<title>InkNote</title>
|
|
<script>
|
|
/* Catch the browser's install offer before anything else runs.
|
|
*
|
|
* `beforeinstallprompt` is fired once, early — usually before React has
|
|
* mounted — and is never fired again. Listening for it from inside a
|
|
* component meant it was simply missed, and the install button never
|
|
* appeared however correctly the site was served. It is stashed here, at
|
|
* the top of the document, and the app picks it up when it is ready. */
|
|
window.__inknoteInstallPrompt = null;
|
|
window.addEventListener("beforeinstallprompt", function (e) {
|
|
e.preventDefault();
|
|
window.__inknoteInstallPrompt = e;
|
|
window.dispatchEvent(new Event("inknote:installable"));
|
|
});
|
|
</script>
|
|
<style>
|
|
body { margin: 0; padding: 0; overflow: hidden; overscroll-behavior: none; }
|
|
/* --honeybar-h is set by the HoneyOS bar while it is on the page, and is
|
|
0 when it is not. The bar sits above the app and pushes it down, so the
|
|
app has that much less room; body has overflow:hidden, which means the
|
|
difference would not scroll but simply be cut off at the bottom.
|
|
|
|
It also covers the notch itself, so the padding above must give way —
|
|
otherwise the gap is counted twice. max() keeps that from going
|
|
negative when there is no bar. */
|
|
#root {
|
|
box-sizing: border-box;
|
|
padding: max(0px, calc(env(safe-area-inset-top) - var(--honeybar-h, 0px)))
|
|
env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
|
|
height: calc(100vh - var(--honeybar-h, 0px));
|
|
}
|
|
#splash { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 16px; background: #0d1117; z-index: 9999; transition: opacity 0.3s; }
|
|
#splash.hide { opacity: 0; pointer-events: none; }
|
|
#splash .logo { width: 64px; height: 64px; border-radius: 18px; background: linear-gradient(135deg, #388bfd, #a855f7); display: flex; align-items: center; justify-content: center; font-size: 32px; animation: pulse 1.5s infinite; }
|
|
#splash .text { color: #e6edf3; font-family: Georgia, serif; font-size: 22px; font-weight: 700; }
|
|
@keyframes pulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.05); } }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="splash">
|
|
<div class="logo">✏️</div>
|
|
<div class="text">InkNote</div>
|
|
</div>
|
|
<div id="root"></div>
|
|
<script type="module" src="/src/main.jsx"></script>
|
|
</body>
|
|
</html> |