- commit
- 143080a91f7fced491a8d2d4ef75f25da1d08937
- parent
- d215c469a86aa922ef945f65fb96412fdfb774ca
- author
- Dami <dami.etoile@gmail.com>
| M | internal/ | 27 | +++++++++++++++++++++++++++ |
| M | internal/ | 2 | +- |
| M | internal/ | 3 | +++ |
| M | scripts/ | 1 | + |
@@ -74,6 +74,21 @@
7474 };7575 paintChrome();7676 matchMedia("(prefers-color-scheme: dark)").addEventListener("change", paintChrome);77+ // Browsers that can install the app announce it; the footer then offers78+ // a quiet link and nothing else changes until it is pressed.79+ let installPrompt = null;80+ const installButton = () => document.getElementById("install");81+ window.addEventListener("beforeinstallprompt", event => {82+ event.preventDefault();83+ installPrompt = event;84+ const button = installButton();85+ if (button) button.hidden = false;86+ });87+ window.addEventListener("appinstalled", () => {88+ installPrompt = null;89+ const button = installButton();90+ if (button) button.hidden = true;91+ });7792 const setMenu = open => {7893 const menu = document.getElementById("nav-menu");7994 if (menu) menu.open = open;@@ -86,6 +101,18 @@
86101 shellBindings.add(rail);87102 rail.addEventListener("click", event => { if (event.target.closest("a")) setMenu(false); });88103 }104+ const install = installButton();105+ if (install && !shellBindings.has(install)) {106+ shellBindings.add(install);107+ install.hidden = !installPrompt;108+ install.addEventListener("click", async () => {109+ if (!installPrompt) return;110+ const prompt = installPrompt;111+ installPrompt = null;112+ install.hidden = true;113+ try { await prompt.prompt(); } catch {}114+ });115+ }89116 if (themeButton && !shellBindings.has(themeButton)) {90117 shellBindings.add(themeButton);91118 const label = () => { themeButton.textContent = currentTheme() === "dark" ? "light" : "dark"; };@@ -61,7 +61,7 @@
6161 {{end}}</div></td>6262 <td id="aside"><div id="panel">{{template "panel" .}}</div></td>6363 </tr></tbody></table>64-<footer id="footer"><table><tr><td><span id="prompt"><b>{{.Slug}}</b> » {{prompt .Path .Query}}</span></td><td><span id="who">{{if .Private}}private relay{{else if .Actor}}signed in as {{template "nostrKey" .Actor}} (<button id="session-logout" type="button">sign out</button>){{else}}browsing as guest (<a href="/signin">Sign in</a>){{end}}</span> <span id="session-status" role="status"></span><span id="navigation-status" role="status" aria-live="polite"></span></td></tr></table></footer>64+<footer id="footer"><table><tr><td><span id="prompt"><b>{{.Slug}}</b> » {{prompt .Path .Query}}</span></td><td><span id="who">{{if .Private}}private relay{{else if .Actor}}signed in as {{template "nostrKey" .Actor}} (<button id="session-logout" type="button">sign out</button>){{else}}browsing as guest (<a href="/signin">Sign in</a>){{end}}</span> <span id="session-status" role="status"></span><span id="navigation-status" role="status" aria-live="polite"></span></td></tr></table><button id="install" type="button" hidden>install app</button></footer>6565 <script src="{{scriptURL "tiny.js"}}"></script>6666 <script src="{{scriptURL "bridge.js"}}"></script>6767 {{if or (eq .Tab "files") (eq .Tab "file")}}<script src="{{scriptURL "blossom-encryption.js"}}"></script>@@ -38,6 +38,8 @@ img{max-width:100%}
3838 #who button{border:0;background:none;padding:0;color:var(--accent);font:inherit}#who button:hover{text-decoration:underline}3939 #railbox{box-sizing:border-box;padding-bottom:44px}4040 #rail-tools{position:absolute;right:0;bottom:0;margin:0;padding:10px 2ch 10px 2.5ch}41+/* The install hint sits on the footer's centre line so it never moves the prompt or the session. */42+#install{position:absolute;left:50%;top:0;transform:translateX(-50%);border:0;background:none;padding:0;color:var(--muted);font:12px var(--mono);line-height:27px;cursor:pointer}#install:hover{color:var(--ink);text-decoration:underline}#install[hidden]{display:none}4143 share-link{display:inline-block}share-link:empty{display:none}4244 #theme{border:0;background:none;padding:0;color:var(--muted);font:12px var(--mono)}#theme:hover{color:var(--ink);text-decoration:underline}4345 @@ -210,6 +212,7 @@ html,body{overflow:auto}
210212 #content>section{padding:14px 2.5ch 20px}211213 #prompt{display:none}#footer td:last-child{text-align:left;white-space:nowrap}212214 #footer{padding:0 12px}#who{font-size:11px}215+#install{left:auto;right:12px;transform:none}213216 #navigation-status:not(:empty),#session-status:not(:empty){position:absolute;bottom:100%;left:0;right:0;padding:6px 12px;background:var(--rail);border-top:1px solid var(--line);white-space:normal}214217 #split,#split>tbody,#split>tbody>tr,#split>tbody>tr>td{display:block;width:auto}215218 #tree{border-right:0;border-bottom:1px solid var(--line)}@@ -24,6 +24,7 @@ async function page({signedIn = false, bunkerResult = null} = {}) {
2424 navigator: {clipboard: {writeText: async () => {} }},2525 getComputedStyle: () => ({getPropertyValue: () => ""}),2626 matchMedia: () => ({matches: false, addEventListener() {}}),27+ addEventListener() {},2728 localStorage: {getItem: () => null, setItem() {}, removeItem() {}},2829 sessionStorage: {getItem: key => saved.get(key), setItem: (key, value) => saved.set(key, value), removeItem: key => saved.delete(key)},2930 NostrSigner: {