Make it a proper PWA.

This commit is contained in:
Chris McCormick 2026-01-05 16:14:39 +08:00
parent 30200ceb7b
commit a2359c41c4
2 changed files with 59 additions and 1 deletions

View file

@ -9,7 +9,6 @@
## TODO ## TODO
- [ ] Display sub-lines of the form `key: value` immediately after item - [ ] Display sub-lines of the form `key: value` immediately after item
- [ ] Make it a proper PWA with the minimal-pwa technique
## Bugs ## Bugs
@ -21,6 +20,7 @@
## Done ## Done
- [x] Make it a proper PWA with the minimal-pwa technique
- [x] Extract and consolidate indent detection functions - [x] Extract and consolidate indent detection functions
- [x] Reduce IndexedDB boilerplate with generic DB operation wrapper - [x] Reduce IndexedDB boilerplate with generic DB operation wrapper
- [x] Simplify drop indicator logic - [x] Simplify drop indicator logic

View file

@ -3,6 +3,13 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="A Kanban board for your Markdown TODO file">
<meta name="theme-color" content="#112">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="manifest" href="#" id="manifest-placeholder">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='192' height='192' viewBox='0 0 24 24'%3E%3Crect width='24' height='24' rx='4' fill='%23112'/%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M4 4l6 0' stroke='%23ffe' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3Cpath d='M14 4l6 0' stroke='%23ffe' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3Cpath d='M4 10a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -8' stroke='%23ffe' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3Cpath d='M14 10a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v2a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -2' stroke='%23ffe' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E" sizes="any" type="image/svg+xml">
<title>Kanban TODO</title> <title>Kanban TODO</title>
<style> <style>
:root { :root {
@ -2516,6 +2523,57 @@ chmod 755 kbtd
await confirmMove(); await confirmMove();
}; };
// PWA setup
function setupPWA() {
const iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" viewBox="0 0 24 24"><rect width="24" height="24" rx="4" fill="#112"/><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 4l6 0" stroke="#ffe" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M14 4l6 0" stroke="#ffe" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M4 10a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -8" stroke="#ffe" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M14 10a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v2a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -2" stroke="#ffe" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg>`;
const manifest = {
name: 'Kanban TODO',
short_name: 'Kanban TODO',
display: 'standalone',
theme_color: '#112',
background_color: '#112',
start_url: window.location.pathname,
icons: [{
src: 'data:image/svg+xml,' + encodeURIComponent(iconSvg),
sizes: 'any',
type: 'image/svg+xml'
}]
};
const manifestBlob = new Blob([JSON.stringify(manifest)], { type: 'application/json' });
const manifestURL = URL.createObjectURL(manifestBlob);
$('#manifest-placeholder').href = manifestURL;
if ('serviceWorker' in navigator) {
const swCode = `
self.addEventListener('install', (e) => {
console.log('Service Worker installed');
self.skipWaiting();
});
self.addEventListener('activate', (e) => {
console.log('Service Worker activated');
return self.clients.claim();
});
self.addEventListener('fetch', (e) => {
e.respondWith(fetch(e.request));
});
`;
const swBlob = new Blob([swCode], { type: 'application/javascript' });
const swURL = URL.createObjectURL(swBlob);
navigator.serviceWorker.register(swURL).then(() => {
console.log('Service Worker registered');
}).catch((err) => {
console.error('Service Worker registration failed:', err);
});
}
}
setupPWA();
init(); init();
</script> </script>