Files
cinny/public/manifest.json
T
jaredandClaude Opus 5 96a97a2f86 feat(pwa): register as an Android share target (#155)
public/manifest.json declares share_target (POST multipart to
/share-target: title/text/url + image/video/audio/pdf/text files). The
service worker answers that POST itself: it stashes the form in a Cache
API bucket and 303s to the in-app /share page, which lists what arrived,
offers a room search, and on pick writes the files into that room's
upload-board atom (encrypting first for E2EE rooms via the composer's
shared filesToUploadItems) and the title/text/url into its draft, then
opens the room — the user still presses Send. The stash is cleared once
placed; reopening /share afterwards says so.

nginx/caddy examples and the prod image config gain a 303 for
/share-target so a POST that reaches the origin before the worker
controls the page lands on /share instead of a 405. iOS has no share
target support and ignores the manifest entry.

Verified headless against the built preview: SW-controlled page → POST
/share-target (two PNGs + title + text) → /share lists both files and the
text → pick the DM → composer shows both files on the upload board and
the text in the draft → /share reports nothing pending.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-20 13:36:05 -04:00

103 lines
2.4 KiB
JSON

{
"name": "Lotus Chat",
"short_name": "Lotus Chat",
"description": "Lotus Chat \u2014 the Lotus Guild Matrix client",
"dir": "auto",
"lang": "en-US",
"display": "standalone",
"orientation": "portrait",
"start_url": "./",
"background_color": "#0a0a0a",
"theme_color": "#980000",
"icons": [
{
"src": "./public/res/android/android-chrome-36x36.png",
"sizes": "36x36",
"type": "image/png"
},
{
"src": "./public/res/android/android-chrome-48x48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "./public/res/android/android-chrome-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "./public/res/android/android-chrome-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "./public/res/android/android-chrome-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "./public/res/android/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./public/res/android/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "./public/res/android/android-chrome-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "./public/res/android/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "./public/res/android/maskable-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "./public/res/android/maskable-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
],
"categories": ["social", "communication", "productivity"],
"share_target": {
"action": "./share-target",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"title": "title",
"text": "text",
"url": "url",
"files": [
{
"name": "files",
"accept": ["image/*", "video/*", "audio/*", "application/pdf", "text/plain"]
}
]
}
},
"shortcuts": [
{
"name": "New Message",
"short_name": "DM",
"description": "Open a new direct message",
"url": "/",
"icons": [
{
"src": "public/res/android/android-chrome-96x96.png",
"sizes": "96x96"
}
]
}
]
}