fix(pwa): mirror thread-ripper in-app install trigger, direct links in head, and simplified manifest
This commit is contained in:
1 parent
369a6a6e04
commit
94fb793f99
3 files changed
+65
-16
No files matched your search
+14
-4
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "Everclone — Notes & Knowledge Base",
|
||||
"name": "Everclone",
|
||||
"short_name": "Everclone",
|
||||
"description": "Self-hosted Evernote clone for rich notes, web clips, and attachments",
|
||||
"id": "/",
|
||||
@@ -8,7 +8,7 @@
|
||||
"display": "standalone",
|
||||
"background_color": "#18181b",
|
||||
"theme_color": "#00a82d",
|
||||
"orientation": "any",
|
||||
"orientation": "portrait-primary",
|
||||
"categories": ["productivity", "utilities", "notes"],
|
||||
"icons": [
|
||||
{
|
||||
@@ -62,14 +62,24 @@
|
||||
"short_name": "New Note",
|
||||
"description": "Create a new note in Everclone",
|
||||
"url": "/?action=new-note",
|
||||
"icons": [{ "src": "/icon-192.png", "sizes": "192x192" }]
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icon-192.png",
|
||||
"sizes": "192x192"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Search Notes",
|
||||
"short_name": "Search",
|
||||
"description": "Search notes across your library",
|
||||
"url": "/?action=search",
|
||||
"icons": [{ "src": "/icon-192.png", "sizes": "192x192" }]
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icon-192.png",
|
||||
"sizes": "192x192"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
+41
-12
@@ -42,29 +42,58 @@ export default function RootLayout({
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="/icon-192.png" />
|
||||
<link rel="icon" type="image/png" sizes="512x512" href="/icon-512.png" />
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/sw.js', { scope: '/' })
|
||||
.then(function(reg) {
|
||||
console.log('[Everclone PWA] Early SW registered, scope:', reg.scope);
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.warn('[Everclone PWA] Early SW registration failed:', err);
|
||||
});
|
||||
}
|
||||
window.__everclone_install_prompt = null;
|
||||
if ('serviceWorker' in navigator) {
|
||||
var registerSW = function() {
|
||||
navigator.serviceWorker.register('/sw.js', { scope: '/' })
|
||||
.then(function(reg) {
|
||||
console.log('[Everclone PWA] Early SW registered, scope:', reg.scope);
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.warn('[Everclone PWA] Early SW registration failed:', err);
|
||||
});
|
||||
};
|
||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||
registerSW();
|
||||
} else {
|
||||
window.addEventListener('load', registerSW);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('beforeinstallprompt', function(e) {
|
||||
e.preventDefault();
|
||||
window.__everclone_install_prompt = e;
|
||||
window.dispatchEvent(new CustomEvent('everclone:installable', { detail: true }));
|
||||
console.log('[Everclone PWA] Early beforeinstallprompt captured!');
|
||||
console.log('[Everclone PWA] beforeinstallprompt captured!');
|
||||
var btns = document.querySelectorAll('.pwa-install-trigger');
|
||||
btns.forEach(function(b) { b.classList.remove('hidden'); });
|
||||
});
|
||||
|
||||
window.addEventListener('appinstalled', function() {
|
||||
window.__everclone_install_prompt = null;
|
||||
window.dispatchEvent(new CustomEvent('everclone:installable', { detail: false }));
|
||||
var btns = document.querySelectorAll('.pwa-install-trigger');
|
||||
btns.forEach(function(b) { b.classList.add('hidden'); });
|
||||
});
|
||||
|
||||
window.__triggerEvercloneInstall = async function() {
|
||||
var prompt = window.__everclone_install_prompt;
|
||||
if (prompt) {
|
||||
prompt.prompt();
|
||||
var res = await prompt.userChoice;
|
||||
if (res && res.outcome === 'accepted') {
|
||||
window.__everclone_install_prompt = null;
|
||||
var btns = document.querySelectorAll('.pwa-install-trigger');
|
||||
btns.forEach(function(b) { b.classList.add('hidden'); });
|
||||
}
|
||||
} else {
|
||||
alert("Install prompt is not available or app is already installed.\\n\\nIf Everclone is already on your phone, uninstall the existing app first so Android allows re-installation.");
|
||||
}
|
||||
};
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -160,6 +160,16 @@ export default function EvercloneWorkspace() {
|
||||
}, []);
|
||||
|
||||
const handleInstallPwa = async () => {
|
||||
if (
|
||||
typeof window !== 'undefined' &&
|
||||
typeof (window as unknown as { __triggerEvercloneInstall?: () => void })
|
||||
.__triggerEvercloneInstall === 'function'
|
||||
) {
|
||||
(
|
||||
window as unknown as { __triggerEvercloneInstall: () => void }
|
||||
).__triggerEvercloneInstall();
|
||||
return;
|
||||
}
|
||||
const promptEvent = window.__everclone_install_prompt;
|
||||
if (promptEvent) {
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user