All checks were successful
Validate / Hassfest (push) Successful in 3s
Phase 10 — Telegram Bot Commands: - Add commands_config JSON field to TelegramBot model (enabled cmds, default count, response mode, rate limits, locale) - Create command handler with 14 commands: /status, /albums, /events, /summary, /latest, /memory, /random, /search, /find, /person, /place, /favorites, /people, /help - Add search_smart, search_metadata, search_by_person, get_random, download_asset, get_asset_thumbnail to ImmichClient - Auto-register commands with Telegram setMyCommands API (EN+RU) - Rate limiting per chat per command category - Media mode: download thumbnails and send as photos to Telegram - Webhook handler routes /commands before falling through to AI chat - Frontend: expandable Commands section per bot with checkboxes, count/mode/locale settings, rate limit inputs, sync button Phase 11 — Snackbar Notifications: - Create snackbar store (snackbar.svelte.ts) with $state rune - Create Snackbar component with fly/fade transitions, typed colors - Mount globally in +layout.svelte - Replace all alert() calls with typed snackbar notifications - Add success snacks to all CRUD operations across all pages - 4 types: success (3s), error (5s), info (3s), warning (4s) - Max 3 visible, auto-dismiss, manual dismiss via X button Both: Add ~30 i18n keys (EN+RU) for commands UI and snack messages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3.8 KiB
3.8 KiB
Phase 11: Snackbar Notifications
Status: Done Parent: primary-plan.md
Goal
Replace browser alert() calls, silent failures, and inconsistent error handling with a unified snackbar/toast notification system. Every user-triggered action (save, delete, test, etc.) should provide clear visual feedback via a dismissable snackbar that appears at the bottom of the screen.
Design
Snackbar Types
| Type | Color | Icon | Auto-dismiss | Use Case |
|---|---|---|---|---|
success |
Green | mdiCheckCircle |
3s | Save, delete, test passed |
error |
Red | mdiAlertCircle |
5s (or manual) | API errors, validation failures |
info |
Blue | mdiInformation |
3s | Status updates, copy-to-clipboard |
warning |
Amber | mdiAlert |
4s | Non-critical issues, deprecation notices |
Behavior
- Appears at bottom-center of viewport, above the mobile nav bar
- Stacks vertically (newest on top, max 3 visible)
- Slide-up entrance, fade-out exit animation
- Manual dismiss via X button on all types
- Errors with detail: expandable to show full error message
position: fixedwith inline styles (per project convention)
Implementation Plan
Task 1: Create Snackbar Store + Component
Files to create:
-
frontend/src/lib/stores/snackbar.svelte.ts— reactive store using$stateaddSnack(type, message, options?)— push notificationremoveSnack(id)— dismisssnacks— reactive array of active notifications- Auto-dismiss timer per snack
-
frontend/src/lib/components/Snackbar.svelte— renders snack stack- Fixed position at bottom-center
- Svelte transitions (fly + fade)
- Icon per type, dismiss button, optional detail expand
- Responsive: full-width on mobile, max-width on desktop
Task 2: Mount Snackbar in Layout
Files to modify:
frontend/src/routes/+layout.svelte— add<Snackbar />component (renders globally)
Task 3: Replace All Alert/Silent Patterns
Files to modify (each page):
| Page | Current Pattern | Replace With |
|---|---|---|
servers/+page.svelte |
alert() on error, silent success |
snack.success('Server saved'), snack.error(err.message) |
trackers/+page.svelte |
alert() on error, silent success |
snack.success('Tracker created'), etc. |
targets/+page.svelte |
alert() on error, silent success |
snack.success('Target saved'), snack.error(...) |
template-configs/+page.svelte |
alert() on error, silent success |
snack.success('Template saved'), etc. |
tracking-configs/+page.svelte |
alert() on error, silent success |
snack.success('Config saved'), etc. |
telegram-bots/+page.svelte |
alert() on error, silent success |
snack.success('Bot registered'), etc. |
users/+page.svelte |
alert() on error, silent success |
snack.success('User updated'), etc. |
login/+page.svelte |
alert() on error |
snack.error('Invalid credentials') |
Task 4: Add i18n Keys
Files to modify:
frontend/src/lib/i18n/en.json— addsnack.*keys for all messagesfrontend/src/lib/i18n/ru.json— Russian translations
Task 5: Add Snackbar to API Helper
Files to create/modify:
- Consider a shared
api.tshelper that wrapsfetch()and auto-shows error snackbars on non-2xx responses, reducing boilerplate in each page.
Acceptance Criteria
- Every create/update/delete action shows a success snackbar
- Every API error shows an error snackbar with the server's message
- No remaining
alert()calls in the codebase - Snackbars auto-dismiss (success: 3s, error: 5s)
- Snackbars are accessible (role="alert", aria-live)
- Stacking works correctly (max 3, newest on top)
- Animations are smooth (slide-up in, fade out)
- Mobile: snackbar appears above bottom nav bar
- All snackbar messages are i18n'd (EN + RU)