Skip to content

Commit 19b0f59

Browse files
author
tung@cloud.phamthanh.me
committed
share image
1 parent 55e0524 commit 19b0f59

3 files changed

Lines changed: 61 additions & 4 deletions

File tree

docs/pwa_share_image.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Share Image Implementation in Feathernote
2+
3+
## Overview
4+
Feathernote supports sharing images (e.g., screenshots) from Android devices directly into the app's 'Shared Inbox' note via the PWA Share Target API.
5+
6+
## Manifest Configuration
7+
The `src/manifest.json` file is configured with a `share_target` block using `multipart/form-data`. The `params` field includes an `image` entry within a `files` array, which tells the browser to accept shared files matching `image/*`.
8+
9+
```json
10+
"share_target": {
11+
"action": "/share",
12+
"method": "POST",
13+
"enctype": "multipart/form-data",
14+
"params": {
15+
"title": "title",
16+
"text": "text",
17+
"url": "url",
18+
"files": [
19+
{
20+
"name": "image",
21+
"accept": ["image/*"]
22+
}
23+
]
24+
}
25+
}
26+
```
27+
28+
## Service Worker Handling (`/share`)
29+
The `/share` handler in `src/serviceworker.js` processes incoming share requests:
30+
31+
1. **Extraction**: It extracts the `FormData` from the POST request.
32+
2. **File Retrieval**: It retrieves the file using `data.get('image')`.
33+
3. **Storage**: If a valid `File` object is retrieved:
34+
* A unique ID is generated via `generateUniqueId('img')`.
35+
* The file blob is stored in the `IMAGE_STORE` IndexedDB using `addImageDB`.
36+
* A markdown image reference `![Shared Image](/images/<id>)` is created.
37+
4. **Note Integration**:
38+
* The image reference and existing text/link content are combined into a final string using `filter(Boolean).join('\n\n')`.
39+
* This content is prepended to the existing 'Shared Inbox' note or used to create a new one if it doesn't exist.
40+
5. **Backward Compatibility**: The code checks `imageFile instanceof File`. If no image is shared, the reference remains empty and the text/link sharing logic proceeds as it did previously.

src/manifest.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@
1313
"params": {
1414
"title": "title",
1515
"text": "text",
16-
"url": "url"
16+
"url": "url",
17+
"files": [
18+
{
19+
"name": "image",
20+
"accept": ["image/*"]
21+
}
22+
]
1723
}
1824
},
1925
"icons": [

src/serviceworker.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,17 @@ self.addEventListener('fetch', (event) => {
180180
let text = data.get('text') || '';
181181
let title = data.get('title') || '';
182182
let sharedUrl = data.get('url') || '';
183+
let imageFile = data.get('image');
183184

184185
title = title.replace(/\n/g, ' ');
185186

187+
let imageReference = '';
188+
if (imageFile instanceof File) {
189+
const imageId = generateUniqueId('img');
190+
await addImageDB({ id: imageId, blob: imageFile, synced: false });
191+
imageReference = `![Shared Image](/images/${imageId})`;
192+
}
193+
186194
const urlRegex = /(https?:\/\/[^\s]+)/g;
187195

188196
if (!sharedUrl) {
@@ -287,11 +295,14 @@ self.addEventListener('fetch', (event) => {
287295
inboxNote = await getNoteByTitleDB(TITLE_SHARED);
288296
}
289297

298+
// Combine image reference and the new item content
299+
const finalContent = [imageReference, newItem].filter(Boolean).join('\n\n');
300+
290301
if (inboxNote) {
291302
if (inboxNote.content) {
292-
inboxNote.content = newItem + '\n' + inboxNote.content;
303+
inboxNote.content = finalContent + '\n' + inboxNote.content;
293304
} else {
294-
inboxNote.content = newItem;
305+
inboxNote.content = finalContent;
295306
}
296307
inboxNote.updatedAt = new Date().toISOString();
297308
await updateNoteDB(inboxNote);
@@ -304,7 +315,7 @@ self.addEventListener('fetch', (event) => {
304315
const newNote = {
305316
id: 'shared-inbox-' + generateUniqueId(),
306317
title: TITLE_SHARED,
307-
content: newItem,
318+
content: finalContent,
308319
createdAt: new Date().toISOString(),
309320
updatedAt: new Date().toISOString(),
310321
tags: ['shared', 'inbox'],

0 commit comments

Comments
 (0)