From b0d121a2ef96fe01fd6a2c29a31bf41b4791ab89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=A2=D1=80=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Wed, 5 Aug 2026 13:15:07 +0300 Subject: [PATCH] now it is PWA --- README.md | 9 ++++++++- icon-192.png | Bin 0 -> 3355 bytes icon-512.png | Bin 0 -> 14012 bytes index.html | 26 +++++++++++++++++++++++++- manifest.json | 13 +++++++++++++ style.css | 4 ---- sw.js | 35 +++++++++++++++++++++++++++++++++++ 7 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 icon-192.png create mode 100644 icon-512.png create mode 100644 manifest.json create mode 100644 sw.js diff --git a/README.md b/README.md index e3a6c9b..ddb9bf8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# OTAMan — APDU Helper & Secured Packet Builder +# OTAMan — APDU Helper & Secured Packet Builder, SIM OTA in PWA Standalone offline HTML/JS tool for building APDU commands for SIM, USIM, and GlobalPlatform RAM, assembling secure packets per ETSI TS 102 225, and constructing BER-TLV command scripts per ETSI TS 102 226. @@ -371,6 +371,13 @@ Swaps nibble pairs of an even-length hex string. --- +## PWA + +OTAMan is a Progressive Web App and can be installed for offline use. Use the **INSTALL PWA** button in the header, or use the browser's install prompt. + +- Service worker pre-caches all assets on first visit +- App icons at 192×192 and 512×512 + ## Theme Dark theme is supported. The app follows the OS preference on first visit, and a manual toggle button (🌙/☀️) at the top-right corner persists the choice in `localStorage`. diff --git a/icon-192.png b/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..84dd3fd2c0f1b8b1349a904cb9f44292bf3c4aa6 GIT binary patch literal 3355 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 KqeR{I@xK7$n({6H literal 0 HcmV?d00001 diff --git a/icon-512.png b/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..41add8003525d346e53d1f990c0650e2dfe4305a GIT binary patch literal 14012 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 literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 950e238..58b0514 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,9 @@ OTAMan + + + @@ -14,7 +17,8 @@

OTAMan

-
+
+ github
@@ -2369,6 +2373,26 @@ toggleSimOverride('usim'); updateP1P2Display('sim'); updateP1P2Display('usim'); updateRamFields(); +// PWA +let deferredPrompt; +const installBtn = document.getElementById('install-btn'); +if (!window.matchMedia('(display-mode: standalone)').matches) { + window.addEventListener('beforeinstallprompt', e => { + e.preventDefault(); + deferredPrompt = e; + installBtn.style.display = ''; + }); + installBtn.addEventListener('click', async () => { + if (!deferredPrompt) return; + deferredPrompt.prompt(); + const { outcome } = await deferredPrompt.userChoice; + if (outcome === 'accepted') deferredPrompt = null; + }); + window.addEventListener('appinstalled', () => { installBtn.style.display = 'none'; }); +} +if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('sw.js'); +} diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..8919da7 --- /dev/null +++ b/manifest.json @@ -0,0 +1,13 @@ +{ + "name": "OTAMan", + "short_name": "OTAMan", + "description": "Offline APDU helper for SIM/USIM/RAM commands", + "start_url": "index.html", + "display": "standalone", + "background_color": "#fafafa", + "theme_color": "#2563eb", + "icons": [ + { "src": "icon-192.png", "sizes": "192x192", "type": "image/png" }, + { "src": "icon-512.png", "sizes": "512x512", "type": "image/png" } + ] +} \ No newline at end of file diff --git a/style.css b/style.css index 847cb34..f8f1a9a 100644 --- a/style.css +++ b/style.css @@ -615,10 +615,6 @@ video { display: none; } -.min-h-\[100px\] { - min-height: 100px; -} - .w-1\/3 { width: 33.333333%; } diff --git a/sw.js b/sw.js new file mode 100644 index 0000000..7612dae --- /dev/null +++ b/sw.js @@ -0,0 +1,35 @@ +const CACHE = 'otaman-v1'; +const URLS = [ + 'index.html', + 'style.css', + 'sim.png', + 'icon-192.png', + 'icon-512.png', + 'manifest.json', + 'des-bundle.js', +]; + +self.addEventListener('install', e => { + e.waitUntil( + caches.open(CACHE).then(c => c.addAll(URLS)) + ); + self.skipWaiting(); +}); + +self.addEventListener('activate', e => { + e.waitUntil( + caches.keys().then(keys => + Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k))) + ) + ); +}); + +self.addEventListener('fetch', e => { + e.respondWith( + caches.match(e.request).then(r => r || fetch(e.request).then(res => { + const clone = res.clone(); + caches.open(CACHE).then(c => c.put(e.request, clone)); + return res; + })) + ); +}); \ No newline at end of file