PWA: installable app (web/win/android/ios) + download/help page + push notifications
- manifest.webmanifest + service worker (offline shell + push + notificationclick) + PNG icons (192/512/apple) + iOS meta + SW registration → installable everywhere - /Download page: per-OS install help (web/windows/android/ios), install button (beforeinstallprompt), 'enable notifications' flow, usage guide, Bazaar/TWA note; nav + footer links - Web Push foundation: WebPushSubscription entity + /push/subscribe (stores), VAPID + push settings in /Admin/Settings, on-device local notification; server broadcast documented (WebPush via Nexus) - docs/PWA-TWA.md: VAPID keygen, server-push wiring, Bubblewrap→Cafe Bazaar + assetlinks steps - Verified: manifest/sw/icons served, download page, subscribe stores (200), layout wired Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
# Hamkadr PWA, notifications & Cafe Bazaar (TWA)
|
||||
|
||||
Hamkadr ships as a **PWA** (installable web app). The same PWA is wrapped as a **TWA** (Trusted
|
||||
Web Activity) to publish on **Cafe Bazaar** / Google Play as a real Android app — no separate
|
||||
codebase.
|
||||
|
||||
## What's already in the app
|
||||
- `GET /manifest.webmanifest` — name, icons (`/icons/icon-192.png`, `-512`), `display: standalone`, fa/RTL.
|
||||
- `GET /sw.js` — service worker: offline shell + `push` + `notificationclick` handlers.
|
||||
- Registered in `_Layout` + iOS `apple-*` meta tags + `apple-touch-icon`.
|
||||
- `/Download` — install + "enable notifications" + per-OS help.
|
||||
- `POST /push/subscribe` — stores the browser's Web Push subscription (`WebPushSubscription`).
|
||||
- VAPID + push settings in `/Admin/Settings`.
|
||||
|
||||
Install paths: **Web/Windows** = browser "Install"; **Android** = Add to Home screen (or Bazaar TWA);
|
||||
**iOS** = Safari → Share → Add to Home Screen.
|
||||
|
||||
## Notifications
|
||||
1. **On-device (works now):** the "🔔 فعالسازی اعلانها" button asks permission and shows a local
|
||||
confirmation notification. The service worker is ready to display server pushes.
|
||||
2. **Server push (to wire):** generate a VAPID key pair and paste it in `/Admin/Settings`:
|
||||
```bash
|
||||
npx web-push generate-vapid-keys # → Public Key + Private Key
|
||||
```
|
||||
Subscriptions are already captured in `WebPushSubscriptions`. To send, add the **WebPush** NuGet
|
||||
(through the Nexus proxy) and a small broadcaster:
|
||||
```csharp
|
||||
var client = new WebPush.WebPushClient();
|
||||
var vapid = new WebPush.VapidDetails(subject, publicKey, privateKey);
|
||||
foreach (var s in subs)
|
||||
client.SendNotification(new WebPush.PushSubscription(s.Endpoint, s.P256dh, s.Auth),
|
||||
JsonSerializer.Serialize(new { title, body, url }), vapid);
|
||||
```
|
||||
⚠️ Iran note: Chrome's push goes through FCM, which may be filtered. The **TWA on Bazaar** can
|
||||
instead use Bazaar's own push (Pushe/native) for reliable Android delivery.
|
||||
|
||||
## Publishing to Cafe Bazaar (TWA)
|
||||
1. Install Bubblewrap: `npm i -g @bubblewrap/cli`
|
||||
2. Initialize from the live manifest:
|
||||
```bash
|
||||
bubblewrap init --manifest https://hamkadr.ir/manifest.webmanifest
|
||||
bubblewrap build # produces app-release-signed.apk + the signing key
|
||||
```
|
||||
3. **Digital Asset Links** — so the TWA opens full-screen with no URL bar. Get the SHA-256
|
||||
fingerprint Bubblewrap printed and serve this at **`https://hamkadr.ir/.well-known/assetlinks.json`**:
|
||||
```json
|
||||
[{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": { "namespace": "android_app", "package_name": "ir.hamkadr.twa",
|
||||
"sha256_cert_fingerprints": ["<SHA256_FROM_BUBBLEWRAP>"] }
|
||||
}]
|
||||
```
|
||||
Easiest: add a tiny `location = /.well-known/assetlinks.json { ... }` block to the central nginx
|
||||
(next to the hamkadr vhost) returning that JSON, then `nginx -s reload`.
|
||||
4. Upload the signed APK to **Cafe Bazaar** developer panel; for Play, upload the AAB.
|
||||
Reference in New Issue
Block a user