diff --git a/frontend/src/lib/components/IconGridSelect.svelte b/frontend/src/lib/components/IconGridSelect.svelte
index dfb3a20..25a9f22 100644
--- a/frontend/src/lib/components/IconGridSelect.svelte
+++ b/frontend/src/lib/components/IconGridSelect.svelte
@@ -138,10 +138,9 @@
border-color: var(--color-primary);
}
.icon-grid-compact {
- width: auto;
- padding: 0.3rem 0.5rem;
+ padding: 0.25rem 0.5rem;
gap: 0.3rem;
- font-size: 0.8rem;
+ font-size: 0.875rem;
}
.icon-grid-compact .icon-grid-trigger-label {
flex: none;
diff --git a/frontend/src/lib/grid-items.ts b/frontend/src/lib/grid-items.ts
index ffcc677..b6715be 100644
--- a/frontend/src/lib/grid-items.ts
+++ b/frontend/src/lib/grid-items.ts
@@ -9,96 +9,105 @@ import type { GridItem } from '$lib/components/IconGridSelect.svelte';
// --- Sort ---
export const sortByItems = (): GridItem[] => [
- { value: 'none', icon: 'mdiMinus', label: t('trackingConfig.sortNone') },
- { value: 'date', icon: 'mdiCalendar', label: t('trackingConfig.sortDate') },
- { value: 'rating', icon: 'mdiStar', label: t('trackingConfig.sortRating') },
- { value: 'name', icon: 'mdiSortAlphabeticalAscending', label: t('trackingConfig.sortName') },
- { value: 'random', icon: 'mdiDice3', label: t('trackingConfig.sortRandom') },
+ { value: 'none', icon: 'mdiMinus', label: t('trackingConfig.sortNone'), desc: t('gridDesc.sortNone') },
+ { value: 'date', icon: 'mdiCalendar', label: t('trackingConfig.sortDate'), desc: t('gridDesc.sortDate') },
+ { value: 'rating', icon: 'mdiStar', label: t('trackingConfig.sortRating'), desc: t('gridDesc.sortRating') },
+ { value: 'name', icon: 'mdiSortAlphabeticalAscending', label: t('trackingConfig.sortName'), desc: t('gridDesc.sortName') },
+ { value: 'random', icon: 'mdiDice3', label: t('trackingConfig.sortRandom'), desc: t('gridDesc.sortRandom') },
];
export const sortOrderItems = (): GridItem[] => [
- { value: 'descending', icon: 'mdiSortDescending', label: t('trackingConfig.orderDesc') },
- { value: 'ascending', icon: 'mdiSortAscending', label: t('trackingConfig.orderAsc') },
+ { value: 'descending', icon: 'mdiSortDescending', label: t('trackingConfig.orderDesc'), desc: t('gridDesc.orderDesc') },
+ { value: 'ascending', icon: 'mdiSortAscending', label: t('trackingConfig.orderAsc'), desc: t('gridDesc.orderAsc') },
];
// --- Album mode ---
export const albumModeItems = (): GridItem[] => [
- { value: 'per_collection', icon: 'mdiViewGrid', label: t('trackingConfig.albumModePerAlbum') },
- { value: 'combined', icon: 'mdiSetMerge', label: t('trackingConfig.albumModeCombined') },
- { value: 'random', icon: 'mdiDice3', label: t('trackingConfig.albumModeRandom') },
+ { value: 'per_collection', icon: 'mdiViewGrid', label: t('trackingConfig.albumModePerAlbum'), desc: t('gridDesc.albumModePerAlbum') },
+ { value: 'combined', icon: 'mdiSetMerge', label: t('trackingConfig.albumModeCombined'), desc: t('gridDesc.albumModeCombined') },
+ { value: 'random', icon: 'mdiDice3', label: t('trackingConfig.albumModeRandom'), desc: t('gridDesc.albumModeRandom') },
];
// --- Asset type ---
export const assetTypeItems = (): GridItem[] => [
- { value: 'all', icon: 'mdiSelectAll', label: t('trackingConfig.assetTypeAll') },
- { value: 'photo', icon: 'mdiImage', label: t('trackingConfig.assetTypePhoto') },
- { value: 'video', icon: 'mdiVideo', label: t('trackingConfig.assetTypeVideo') },
+ { value: 'all', icon: 'mdiSelectAll', label: t('trackingConfig.assetTypeAll'), desc: t('gridDesc.assetTypeAll') },
+ { value: 'photo', icon: 'mdiImage', label: t('trackingConfig.assetTypePhoto'), desc: t('gridDesc.assetTypePhoto') },
+ { value: 'video', icon: 'mdiVideo', label: t('trackingConfig.assetTypeVideo'), desc: t('gridDesc.assetTypeVideo') },
];
// --- Memory source ---
export const memorySourceItems = (): GridItem[] => [
- { value: 'albums', icon: 'mdiImageMultiple', label: t('trackingConfig.memorySourceAlbums') },
- { value: 'native', icon: 'mdiMemory', label: t('trackingConfig.memorySourceNative') },
+ { value: 'albums', icon: 'mdiImageMultiple', label: t('trackingConfig.memorySourceAlbums'), desc: t('gridDesc.memorySourceAlbums') },
+ { value: 'native', icon: 'mdiMemory', label: t('trackingConfig.memorySourceNative'), desc: t('gridDesc.memorySourceNative') },
];
// --- Locale ---
export const localeItems = (): GridItem[] => [
- { value: 'en', icon: 'mdiAlphabeticalVariant', label: 'English' },
- { value: 'ru', icon: 'mdiAlphabeticalVariant', label: 'Русский' },
+ { value: 'en', icon: 'mdiAlphabeticalVariant', label: 'English', desc: t('gridDesc.localeEn') },
+ { value: 'ru', icon: 'mdiAlphabeticalVariant', label: 'Русский', desc: t('gridDesc.localeRu') },
];
// --- Response mode ---
export const responseModeItems = (tFn: typeof t): GridItem[] => [
- { value: 'media', icon: 'mdiImage', label: tFn('commandConfig.modeMedia') },
- { value: 'text', icon: 'mdiText', label: tFn('commandConfig.modeText') },
+ { value: 'media', icon: 'mdiImage', label: tFn('commandConfig.modeMedia'), desc: tFn('gridDesc.modeMedia') },
+ { value: 'text', icon: 'mdiText', label: tFn('commandConfig.modeText'), desc: tFn('gridDesc.modeText') },
];
// --- Event type filter (dashboard) ---
export const eventTypeFilterItems = (): GridItem[] => [
- { value: '', icon: 'mdiFilterOff', label: t('dashboard.allEvents') },
- { value: 'assets_added', icon: 'mdiImagePlus', label: t('dashboard.filterAssetsAdded') },
- { value: 'assets_removed', icon: 'mdiImageMinus', label: t('dashboard.filterAssetsRemoved') },
- { value: 'collection_renamed', icon: 'mdiRename', label: t('dashboard.filterRenamed') },
- { value: 'collection_deleted', icon: 'mdiDeleteAlert', label: t('dashboard.filterDeleted') },
- { value: 'sharing_changed', icon: 'mdiShareVariant', label: t('dashboard.filterSharingChanged') },
+ { value: '', icon: 'mdiFilterOff', label: t('dashboard.allEvents'), desc: t('gridDesc.allEvents') },
+ { value: 'assets_added', icon: 'mdiImagePlus', label: t('dashboard.filterAssetsAdded'), desc: t('gridDesc.assetsAdded') },
+ { value: 'assets_removed', icon: 'mdiImageMinus', label: t('dashboard.filterAssetsRemoved'), desc: t('gridDesc.assetsRemoved') },
+ { value: 'collection_renamed', icon: 'mdiRename', label: t('dashboard.filterRenamed'), desc: t('gridDesc.renamed') },
+ { value: 'collection_deleted', icon: 'mdiDeleteAlert', label: t('dashboard.filterDeleted'), desc: t('gridDesc.deleted') },
+ { value: 'sharing_changed', icon: 'mdiShareVariant', label: t('dashboard.filterSharingChanged'), desc: t('gridDesc.sharingChanged') },
];
// --- Sort filter (dashboard) ---
export const sortFilterItems = (): GridItem[] => [
- { value: 'newest', icon: 'mdiSortClockDescending', label: t('dashboard.newestFirst') },
- { value: 'oldest', icon: 'mdiSortClockAscending', label: t('dashboard.oldestFirst') },
+ { value: 'newest', icon: 'mdiSortClockDescending', label: t('dashboard.newestFirst'), desc: t('gridDesc.newestFirst') },
+ { value: 'oldest', icon: 'mdiSortClockAscending', label: t('dashboard.oldestFirst'), desc: t('gridDesc.oldestFirst') },
];
// --- Chat action (Telegram targets) ---
export const chatActionItems = (): GridItem[] => [
- { value: '', icon: 'mdiMinus', label: t('targets.chatActionNone') },
- { value: 'typing', icon: 'mdiKeyboard', label: t('targets.chatActionTyping') },
- { value: 'upload_photo', icon: 'mdiImagePlus', label: t('targets.chatActionUploadPhoto') },
- { value: 'upload_video', icon: 'mdiVideoPlus', label: t('targets.chatActionUploadVideo') },
- { value: 'upload_document', icon: 'mdiFileUpload', label: t('targets.chatActionUploadDoc') },
- { value: 'record_video', icon: 'mdiVideo', label: t('targets.chatActionRecordVideo') },
- { value: 'record_voice', icon: 'mdiMicrophone', label: t('targets.chatActionRecordVoice') },
+ { value: '', icon: 'mdiMinus', label: t('targets.chatActionNone'), desc: t('gridDesc.chatActionNone') },
+ { value: 'typing', icon: 'mdiKeyboard', label: t('targets.chatActionTyping'), desc: t('gridDesc.chatActionTyping') },
+ { value: 'upload_photo', icon: 'mdiImagePlus', label: t('targets.chatActionUploadPhoto'), desc: t('gridDesc.chatActionUploadPhoto') },
+ { value: 'upload_video', icon: 'mdiVideoPlus', label: t('targets.chatActionUploadVideo'), desc: t('gridDesc.chatActionUploadVideo') },
+ { value: 'upload_document', icon: 'mdiFileUpload', label: t('targets.chatActionUploadDoc'), desc: t('gridDesc.chatActionUploadDoc') },
+ { value: 'record_video', icon: 'mdiVideo', label: t('targets.chatActionRecordVideo'), desc: t('gridDesc.chatActionRecordVideo') },
+ { value: 'record_voice', icon: 'mdiMicrophone', label: t('targets.chatActionRecordVoice'), desc: t('gridDesc.chatActionRecordVoice') },
];
// --- Preview target type ---
export const previewTargetTypeItems = (): GridItem[] => [
- { value: 'telegram', icon: 'mdiSend', label: t('targets.typeTelegram') },
- { value: 'webhook', icon: 'mdiWebhook', label: t('targets.typeWebhook') },
+ { value: 'telegram', icon: 'mdiSend', label: t('targets.typeTelegram'), desc: t('gridDesc.previewTelegram') },
+ { value: 'webhook', icon: 'mdiWebhook', label: t('targets.typeWebhook'), desc: t('gridDesc.previewWebhook') },
+];
+
+// --- Provider type filter (with "All" option) ---
+
+export const providerTypeFilterItems = (): GridItem[] => [
+ { value: '', icon: 'mdiFilterOff', label: t('common.allTypes'), desc: t('gridDesc.allEvents') },
+ { value: 'immich', icon: 'mdiCamera', label: t('providers.typeImmich'), desc: t('gridDesc.providerImmich') },
+ { value: 'gitea', icon: 'mdiGit', label: t('providers.typeGitea'), desc: t('gridDesc.providerGitea') },
+ { value: 'scheduler', icon: 'mdiClockOutline', label: t('providers.typeScheduler'), desc: t('gridDesc.providerScheduler') },
];
// --- Provider type ---
export const providerTypeItems = (): GridItem[] => [
- { value: 'immich', icon: 'mdiCamera', label: t('providers.typeImmich') },
- { value: 'gitea', icon: 'mdiGit', label: t('providers.typeGitea') },
- { value: 'scheduler', icon: 'mdiClockOutline', label: t('providers.typeScheduler') },
+ { value: 'immich', icon: 'mdiCamera', label: t('providers.typeImmich'), desc: t('gridDesc.providerImmich') },
+ { value: 'gitea', icon: 'mdiGit', label: t('providers.typeGitea'), desc: t('gridDesc.providerGitea') },
+ { value: 'scheduler', icon: 'mdiClockOutline', label: t('providers.typeScheduler'), desc: t('gridDesc.providerScheduler') },
];
diff --git a/frontend/src/lib/i18n/en.json b/frontend/src/lib/i18n/en.json
index 90cc957..332a6dd 100644
--- a/frontend/src/lib/i18n/en.json
+++ b/frontend/src/lib/i18n/en.json
@@ -755,6 +755,47 @@
"allProviders": "All providers",
"noFilterResults": "No items match the current filter."
},
+ "gridDesc": {
+ "sortNone": "No sorting applied",
+ "sortDate": "Sort by creation date",
+ "sortRating": "Sort by star rating",
+ "sortName": "Sort by file name",
+ "sortRandom": "Randomize order",
+ "orderDesc": "Newest or highest first",
+ "orderAsc": "Oldest or lowest first",
+ "albumModePerAlbum": "One message per album",
+ "albumModeCombined": "All albums in one message",
+ "albumModeRandom": "Pick a random album",
+ "assetTypeAll": "Photos and videos",
+ "assetTypePhoto": "Photos only",
+ "assetTypeVideo": "Videos only",
+ "memorySourceAlbums": "Scan tracked albums for On This Day matches",
+ "memorySourceNative": "Use Immich native memories API",
+ "localeEn": "English interface",
+ "localeRu": "Russian interface",
+ "modeMedia": "Send actual photo/video files",
+ "modeText": "Send file names and links only",
+ "allEvents": "Show all event types",
+ "assetsAdded": "New files added to album",
+ "assetsRemoved": "Files removed from album",
+ "renamed": "Album was renamed",
+ "deleted": "Album was deleted",
+ "sharingChanged": "Album sharing toggled",
+ "newestFirst": "Most recent events on top",
+ "oldestFirst": "Oldest events on top",
+ "chatActionNone": "No indicator shown",
+ "chatActionTyping": "Show typing... bubble",
+ "chatActionUploadPhoto": "Show uploading photo...",
+ "chatActionUploadVideo": "Show uploading video...",
+ "chatActionUploadDoc": "Show uploading document...",
+ "chatActionRecordVideo": "Show recording video...",
+ "chatActionRecordVoice": "Show recording voice...",
+ "previewTelegram": "Preview with Telegram HTML format",
+ "previewWebhook": "Preview as plain text",
+ "providerImmich": "Self-hosted photo server",
+ "providerGitea": "Self-hosted Git service",
+ "providerScheduler": "Time-based scheduled messages"
+ },
"error": {
"notFound": "Page not found",
"goHome": "Go home"
diff --git a/frontend/src/lib/i18n/ru.json b/frontend/src/lib/i18n/ru.json
index b7e2715..37e6088 100644
--- a/frontend/src/lib/i18n/ru.json
+++ b/frontend/src/lib/i18n/ru.json
@@ -755,6 +755,47 @@
"allProviders": "Все провайдеры",
"noFilterResults": "Нет элементов, соответствующих фильтру."
},
+ "gridDesc": {
+ "sortNone": "Без сортировки",
+ "sortDate": "По дате создания",
+ "sortRating": "По рейтингу",
+ "sortName": "По имени файла",
+ "sortRandom": "Случайный порядок",
+ "orderDesc": "Сначала новые или высокие",
+ "orderAsc": "Сначала старые или низкие",
+ "albumModePerAlbum": "Отдельное сообщение для каждого альбома",
+ "albumModeCombined": "Все альбомы в одном сообщении",
+ "albumModeRandom": "Случайный альбом",
+ "assetTypeAll": "Фото и видео",
+ "assetTypePhoto": "Только фото",
+ "assetTypeVideo": "Только видео",
+ "memorySourceAlbums": "Поиск совпадений в отслеживаемых альбомах",
+ "memorySourceNative": "Использовать API воспоминаний Immich",
+ "localeEn": "Английский интерфейс",
+ "localeRu": "Русский интерфейс",
+ "modeMedia": "Отправка файлов фото/видео",
+ "modeText": "Только имена файлов и ссылки",
+ "allEvents": "Показать все типы событий",
+ "assetsAdded": "Новые файлы добавлены в альбом",
+ "assetsRemoved": "Файлы удалены из альбома",
+ "renamed": "Альбом переименован",
+ "deleted": "Альбом удалён",
+ "sharingChanged": "Изменён доступ к альбому",
+ "newestFirst": "Сначала новые события",
+ "oldestFirst": "Сначала старые события",
+ "chatActionNone": "Индикатор не показывается",
+ "chatActionTyping": "Показать «печатает...»",
+ "chatActionUploadPhoto": "Показать «отправляет фото...»",
+ "chatActionUploadVideo": "Показать «отправляет видео...»",
+ "chatActionUploadDoc": "Показать «отправляет документ...»",
+ "chatActionRecordVideo": "Показать «записывает видео...»",
+ "chatActionRecordVoice": "Показать «записывает голос...»",
+ "previewTelegram": "Предпросмотр в формате Telegram HTML",
+ "previewWebhook": "Предпросмотр как текст",
+ "providerImmich": "Фотосервер для самостоятельного размещения",
+ "providerGitea": "Git-сервер для самостоятельного размещения",
+ "providerScheduler": "Запланированные сообщения по расписанию"
+ },
"error": {
"notFound": "Страница не найдена",
"goHome": "На главную"
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte
index c36d9f0..aefa418 100644
--- a/frontend/src/routes/+page.svelte
+++ b/frontend/src/routes/+page.svelte
@@ -257,9 +257,9 @@
placeholder={t('dashboard.searchEvents')}
class="w-full px-3 py-1.5 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" />
-