Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ Response: { id, originalUrl, videoPath, audioPath, thumbnailPath, title, artist,
Request: { "title": "new caption" }
Response: { "title": "new caption" }
```
Only allowed by the uploader, and only if no one else has watched the clip.
Host-only. Only the group host can edit clip captions.

### DELETE /api/clips/[id]
Only allowed by the uploader, and only if no one else has watched the clip.
Host can delete any clip. Non-host uploaders can only delete their own clips if no one else has watched them.

### GET /api/clips/unwatched-count
```
Expand All @@ -126,6 +126,7 @@ Response: { "count": 5 }
| GET | `/api/clips/[id]/reactions` | List reactions |
| POST | `/api/clips/[id]/reactions` | Toggle a reaction |
| POST | `/api/clips/[id]/retry` | Retry failed download |
| POST | `/api/clips/[id]/refetch` | Refetch metadata from source |

### POST /api/clips/[id]/watched
```
Expand Down Expand Up @@ -176,6 +177,12 @@ Retries a failed download. Only available for clips with `status: 'failed'`.
Response: { "status": "downloading" }
```

### POST /api/clips/[id]/refetch
Host-only. Refetches metadata (title, creator info) from the source URL via yt-dlp.
```
Response: { "title": "...", "creatorName": "...", "creatorUrl": "..." }
```

## Group Management

Host-only endpoints (unless noted). Requires `createdBy === currentUser`.
Expand Down Expand Up @@ -305,6 +312,7 @@ Response: { "clipCount": 42, "memberCount": 8, "storageMb": 1200, "maxStorageMb"
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/notifications` | Paginated notification feed |
| DELETE | `/api/notifications/[id]` | Delete a single notification |
| POST | `/api/notifications/mark-read` | Mark notifications as read |
| GET | `/api/notifications/unread-count` | Unread notification count |
| GET | `/api/notifications/preferences` | Fetch notification preferences |
Expand All @@ -313,7 +321,13 @@ Response: { "clipCount": 42, "memberCount": 8, "storageMb": 1200, "maxStorageMb"
### GET /api/notifications
```
Query params: ?limit=30&offset=0
Response: { "notifications": [{ "id", "type", "clipId", "emoji", "commentPreview", "actorUsername", "actorAvatar", "clipThumbnail", "clipTitle", "read", "createdAt" }] }
Response: { "notifications": [{ "id", "type", "clipId", "emoji", "commentPreview", "actorUsername", "actorAvatar", "clipThumbnail", "clipTitle", "clipContentType", "read", "createdAt" }] }
```

### DELETE /api/notifications/[id]
Deletes a single notification by ID for the current user.
```
Response: { "ok": true }
```

### POST /api/notifications/mark-read
Expand Down
2 changes: 2 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,11 @@ scrolly/
│ │ ├── api/ # REST API (see docs/api.md)
│ │ │ ├── auth/
│ │ │ ├── clips/
│ │ │ │ └── [id]/refetch/+server.ts # Host-only metadata refetch
│ │ │ ├── gifs/
│ │ │ ├── group/
│ │ │ ├── notifications/
│ │ │ │ └── [id]/+server.ts # Delete single notification
│ │ │ ├── profile/
│ │ │ ├── push/
│ │ │ ├── videos/
Expand Down
13 changes: 11 additions & 2 deletions docs/notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,24 @@ Scrolly has two notification systems: an **in-app activity feed** and **web push
## In-App Activity Feed

The in-app activity feed shows a chronological list of notifications via the `ActivitySheet` component. Users see:
- New clips added by other group members
- Reactions on their clips
- Comments on their clips

New clip notifications are **push-only** — they are not stored in the `notifications` database table. Reaction and comment notifications are stored in the `notifications` table with read/unread tracking. The bottom navigation shows an unread badge count.
All notification types are stored in the `notifications` database table with read/unread tracking. The bottom navigation shows an unread badge count. Users can dismiss individual notifications via the `DELETE /api/notifications/[id]` endpoint.

### Auto-Clear Behavior

Certain user actions automatically delete related notifications to keep the activity feed clean:
- **Watching a clip** deletes any `new_clip` notification for that clip
- **Viewing comments** on a clip deletes `comment`, `reply`, and `mention` notifications for that clip

### API Endpoints

| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/notifications` | Paginated notification feed |
| DELETE | `/api/notifications/[id]` | Delete a single notification |
| POST | `/api/notifications/mark-read` | Mark notifications as read (all or by clip/type) |
| GET | `/api/notifications/unread-count` | Unread badge count |
| GET | `/api/notifications/preferences` | Fetch notification preferences |
Expand All @@ -28,7 +36,7 @@ Real-time push notifications via the Web Push Protocol (VAPID).

| Event | Who gets notified | When sent | Preference key |
|-------|-------------------|-----------|----------------|
| New clip added | All group members except poster (push only) | After download succeeds (`status: 'ready'`) | `newAdds` |
| New clip added | All group members except poster (push + in-app) | After download succeeds (`status: 'ready'`) | `newAdds` |
| Reaction on a clip | Clip owner only (push + in-app) | Immediately after reaction is persisted | `reactions` |
| Comment on a clip | Clip owner only (push + in-app) | Immediately after comment is persisted | `comments` |
| Daily reminder | Per-user opt-in | — | `dailyReminder` (not yet scheduled) |
Expand Down Expand Up @@ -98,6 +106,7 @@ VAPID_SUBJECT=mailto:you@example.com
| Subscribe API | `src/routes/api/push/subscribe/+server.ts` | POST/DELETE push subscriptions |
| Test API | `src/routes/api/push/test/+server.ts` | POST test notification to current user |
| Notifications API | `src/routes/api/notifications/+server.ts` | GET notification feed |
| Delete notification API | `src/routes/api/notifications/[id]/+server.ts` | DELETE single notification |
| Mark-read API | `src/routes/api/notifications/mark-read/+server.ts` | POST mark as read |
| Unread-count API | `src/routes/api/notifications/unread-count/+server.ts` | GET unread badge count |
| Preferences API | `src/routes/api/notifications/preferences/+server.ts` | GET/PATCH preferences |
Expand Down