Просмотр исходного кода

Add toast message for some keyboard shortcuts

Add notification message when using keyboard shortcuts: f, s, and m.
Jebbs 6 лет назад
Родитель
Сommit
bf357a0e2d

+ 55 - 10
locale/translations.go

@@ -53,14 +53,19 @@ var translations = map[string]string{
     "pagination.previous": "Vorherige",
     "entry.status.unread": "Ungelesen",
     "entry.status.read": "Gelesen",
+    "entry.status.toast.unread": "Als ungelesen markiert",
+    "entry.status.toast.read": "Als gelesen markiert",
     "entry.status.title": "Status des Artikels ändern",
     "entry.bookmark.toggle.on": "Lesezeichen hinzufügen",
     "entry.bookmark.toggle.off": "Lesezeichen entfernen",
+    "entry.bookmark.toast.on": "Markiert",
+    "entry.bookmark.toast.off": "Nicht markiert",
     "entry.state.saving": "Speichern...",
     "entry.state.loading": "Lade...",
     "entry.save.label": "Speichern",
     "entry.save.title": "Diesen Artikel speichern",
     "entry.save.completed": "Erledigt!",
+    "entry.save.toast.completed": "Artikel gespeichert",
     "entry.scraper.label": "Inhalt herunterladen",
     "entry.scraper.title": "Inhalt herunterladen",
     "entry.scraper.completed": "Erledigt!",
@@ -349,14 +354,19 @@ var translations = map[string]string{
     "pagination.previous": "Previous",
     "entry.status.unread": "Unread",
     "entry.status.read": "Read",
+    "entry.status.toast.unread": "Marked as unread",
+    "entry.status.toast.read": "Marked as read",
     "entry.status.title": "Change entry status",
     "entry.bookmark.toggle.on": "Star",
     "entry.bookmark.toggle.off": "Unstar",
+    "entry.bookmark.toast.on": "Starred",
+    "entry.bookmark.toast.off": "Unstarred",
     "entry.state.saving": "Saving...",
     "entry.state.loading": "Loading...",
     "entry.save.label": "Save",
     "entry.save.title": "Save this article",
     "entry.save.completed": "Done!",
+    "entry.save.toast.completed": "Article saved",
     "entry.scraper.label": "Fetch original content",
     "entry.scraper.title": "Fetch original content",
     "entry.scraper.completed": "Done!",
@@ -625,14 +635,19 @@ var translations = map[string]string{
     "pagination.previous": "Anterior",
     "entry.status.unread": "No leído",
     "entry.status.read": "Leído",
+    "entry.status.toast.unread": "Marcado como no leído",
+    "entry.status.toast.read": "Marcado como leído",
     "entry.status.title": "Cambiar estado de entrada",
     "entry.bookmark.toggle.on": "Marcar",
     "entry.bookmark.toggle.off": "Desmarcar",
+    "entry.bookmark.toast.on": "Sembrado de estrellas",
+    "entry.bookmark.toast.off": "Sin estrellas",
     "entry.state.saving": "Guardando...",
     "entry.state.loading": "Cargando...",
     "entry.save.label": "Guardar",
     "entry.save.title": "Guardar este articulo",
     "entry.save.completed": "¡Hecho!",
+    "entry.save.toast.completed": "Artículo guardado",
     "entry.scraper.label": "Obtener contenido original",
     "entry.scraper.title": "Obtener contenido original",
     "entry.scraper.completed": "¡Hecho!",
@@ -902,13 +917,18 @@ var translations = map[string]string{
     "entry.status.unread": "Non lu",
     "entry.status.read": "Lu",
     "entry.status.title": "Changer le statut de l'entrée",
+    "entry.status.toast.unread": "Marqué comme non lu",
+    "entry.status.toast.read": "Marqué comme lu",
     "entry.bookmark.toggle.on": "Favoris",
     "entry.bookmark.toggle.off": "Enlever favoris",
+    "entry.bookmark.toast.on": "Ajouté aux favoris",
+    "entry.bookmark.toast.off": "Enlevé des favoris",
     "entry.state.saving": "Sauvegarde en cours...",
     "entry.state.loading": "Chargement...",
     "entry.save.label": "Sauvegarder",
     "entry.save.title": "Sauvegarder cet article",
     "entry.save.completed": "Terminé !",
+    "entry.save.toast.completed": "Article sauvegardé",
     "entry.scraper.label": "Contenu original",
     "entry.scraper.title": "Récupérer le contenu original",
     "entry.scraper.completed": "Terminé !",
@@ -1197,14 +1217,19 @@ var translations = map[string]string{
     "pagination.previous": "Precedente",
     "entry.status.unread": "Da leggere",
     "entry.status.read": "Letto",
+    "entry.status.toast.unread": "Contrassegnato come non letto",
+    "entry.status.toast.read": "Contrassegnato come letto",
     "entry.status.title": "Cambia lo stato dell'articolo",
     "entry.bookmark.toggle.on": "Aggiungi ai preferiti",
     "entry.bookmark.toggle.off": "Rimuovi dai preferiti",
+    "entry.bookmark.toast.on": "Ha recitato",
+    "entry.bookmark.toast.off": "Non speciali",
     "entry.state.saving": "Salvataggio in corso...",
     "entry.state.loading": "Caricamento in corso...",
     "entry.save.label": "Salva",
     "entry.save.title": "Salva questo articolo",
     "entry.save.completed": "Fatto!",
+    "entry.save.toast.completed": "Articolo salvato",
     "entry.scraper.label": "Scarica il contenuto integrale",
     "entry.scraper.title": "Scarica il contenuto integrale",
     "entry.scraper.completed": "Fatto!",
@@ -1473,14 +1498,19 @@ var translations = map[string]string{
     "pagination.previous": "Vorige",
     "entry.status.unread": "Ongelezen",
     "entry.status.read": "Gelezen",
+    "entry.status.toast.unread": "Gemarkeerd als ongelezen",
+    "entry.status.toast.read": "Gemarkeerd als gelezen",
     "entry.status.title": "Verander status van item",
     "entry.bookmark.toggle.on": "Ster toevoegen",
     "entry.bookmark.toggle.off": "Ster weghalen",
+    "entry.bookmark.toast.on": "Met ster",
+    "entry.bookmark.toast.off": "Ster verwijderd",
     "entry.state.saving": "Opslaag...",
     "entry.state.loading": "Laden...",
     "entry.save.label": "Opslaan",
     "entry.save.title": "Artikel opslaan",
     "entry.save.completed": "Done!",
+    "entry.save.toast.completed": "Artikel opgeslagen",
     "entry.scraper.label": "Fetch original content",
     "entry.scraper.title": "Fetch original content",
     "entry.scraper.completed": "Klaar!",
@@ -1767,14 +1797,19 @@ var translations = map[string]string{
     "pagination.previous": "Poprzedni",
     "entry.status.unread": "Nieprzeczytane",
     "entry.status.read": "Przeczytane",
+    "entry.status.toast.unread": "Oznaczone jako nieprzeczytane",
+    "entry.status.toast.read": "Oznaczone jako przeczytane",
     "entry.status.title": "Zmień status artykułu",
     "entry.bookmark.toggle.on": "Oznacz gwiazdką",
     "entry.bookmark.toggle.off": "Usuń gwiazdkę",
+    "entry.bookmark.toast.on": "Oznaczone gwiazdką",
+    "entry.bookmark.toast.off": "Bez gwiazdek",
     "entry.state.saving": "Zapisywanie...",
     "entry.state.loading": "Ładowanie...",
     "entry.save.label": "Zapisz",
     "entry.save.title": "Zapisz ten artykuł",
     "entry.save.completed": "Gotowe!",
+    "entry.save.toast.completed": "Artykuł zapisany",
     "entry.scraper.label": "Pobierz treść",
     "entry.scraper.title": "Pobierz oryginalną treść",
     "entry.scraper.completed": "Gotowe!",
@@ -2069,14 +2104,19 @@ var translations = map[string]string{
     "pagination.previous": "Предыдущая",
     "entry.status.unread": "Непрочитано",
     "entry.status.read": "Прочитано",
+    "entry.status.toast.unread": "Помечено как непрочитанное",
+    "entry.status.toast.read": "Помечено как прочитанное",
     "entry.status.title": "Изменить статус записи",
     "entry.bookmark.toggle.on": "Добавить в Избранное",
     "entry.bookmark.toggle.off": "Удалить из Избранного",
+    "entry.bookmark.toast.on": "Помеченные",
+    "entry.bookmark.toast.off": "Без пометок",
     "entry.state.saving": "Сохранение…",
     "entry.state.loading": "Загрузка…",
     "entry.save.label": "Сохранить",
     "entry.save.title": "Сохранить эту статью",
     "entry.save.completed": "Готово!",
+    "entry.save.toast.completed": "Статья сохранена",
     "entry.scraper.label": "Извлечь оригинальное содержимое",
     "entry.scraper.title": "Извлечь оригинальное содержимое",
     "entry.scraper.completed": "Готово!",
@@ -2353,14 +2393,19 @@ var translations = map[string]string{
     "pagination.previous": "上一页",
     "entry.status.unread": "未读",
     "entry.status.read": "标为已读",
+    "entry.status.toast.unread": "已标为未读",
+    "entry.status.toast.read": "已标为已读",
     "entry.status.title": "更改状态",
     "entry.bookmark.toggle.on": "标记星标",
     "entry.bookmark.toggle.off": "去掉星标",
+    "entry.bookmark.toast.on": "已标记星标",
+    "entry.bookmark.toast.off": "已去掉星标",
     "entry.state.saving": "保存中…",
     "entry.state.loading": "载入中…",
     "entry.save.label": "保存",
     "entry.save.title": "保存这篇文章",
     "entry.save.completed": "完成",
+    "entry.save.toast.completed": "已保存文章",
     "entry.scraper.label": "抓取原内容",
     "entry.scraper.title": "抓取原内容",
     "entry.scraper.completed": "完成",
@@ -2425,7 +2470,7 @@ var translations = map[string]string{
     "page.keyboard_shortcuts.open_item": "打开选定的条目",
     "page.keyboard_shortcuts.open_original": "打开原始链接",
     "page.keyboard_shortcuts.toggle_read_status": "切换已读/未读状态",
-    "page.keyboard_shortcuts.mark_page_as_read": "标记当前",
+    "page.keyboard_shortcuts.mark_page_as_read": "标记当前页已读",
     "page.keyboard_shortcuts.download_content": "下载原始内容",
     "page.keyboard_shortcuts.toggle_bookmark_status": "切换收藏状态",
     "page.keyboard_shortcuts.save_article": "保存文章",
@@ -2592,13 +2637,13 @@ var translations = map[string]string{
 }
 
 var translationsChecksums = map[string]string{
-	"de_DE": "2ca6c01934316256bf3f06bd1d40fb7700834b285ac87a24692389e4f39de7c2",
-	"en_US": "547bca5fe9062da289f6d8ab0d3c3f6156d6ae5c3718fa6c0fdbb3853e4c7a8a",
-	"es_ES": "eb01f7a1fd73cdc54468435887f1c1201489aeceda25f852a63ce6aa80e54e52",
-	"fr_FR": "76f0555737a9b5c7ec5e40e6242e24b74ebb9457290a3924a9fc2058b5b6da1c",
-	"it_IT": "335d2a9b3eda6313a9521abf4b7fd8597575a5aa0a664cebe54a467ac5db944d",
-	"nl_NL": "f30abf2bf7eddd499a012beee07f47da8633788ebf6db5ff685922a6ec66f5fd",
-	"pl_PL": "a664bd0d472818557d98de50ed8f04f96c2b9307a66c24c04e589dc07c465a8b",
-	"ru_RU": "7d4c82d2c3710bbf3b9ea07ed2cfcc32e7c7b45836539b5ce0ab10ec1290e615",
-	"zh_CN": "dc68f7d06b360ada0fed620522cec80baf7ed417fb54a3c3271849ccdaa69086",
+	"de_DE": "52c82c151a27455501e54a4ea20339c965f030d7204ae9f55bf2639ef396b015",
+	"en_US": "ef73c3934c5df6c2346f96a4eb4b308f84404c58029aac2ee6859bc205ecb6b3",
+	"es_ES": "567fad5046d07efd69b9d29a3e8fa05503f935c02624c71851d9b1b3a8fa82d5",
+	"fr_FR": "11a3f01603a73b4a0c2921aea592bdb24086286f4f1343df4adaeb4a1471c1b9",
+	"it_IT": "19b9614980ded9ee4a5eea1f6623a8d2d4b763ffe81eae633d8c768bb58d6aea",
+	"nl_NL": "a91e2195ac0731a3788405a51c4201e1a89dcce35ef792356e8c17adb57aee97",
+	"pl_PL": "097bc9beac12f33d3a5e5ee98ccba0875e4d1c1bf13e38251a66ac450834c5b3",
+	"ru_RU": "b253bf709a2f4bcac2f894bd1797247481fa7c6b70a0a0d8785d8680be83bac8",
+	"zh_CN": "cb974ad8c374278057db4ca58ff0e59314dc191e2ea59af0d1472a438a9ce3e0",
 }

+ 5 - 0
locale/translations/de_DE.json

@@ -48,14 +48,19 @@
     "pagination.previous": "Vorherige",
     "entry.status.unread": "Ungelesen",
     "entry.status.read": "Gelesen",
+    "entry.status.toast.unread": "Als ungelesen markiert",
+    "entry.status.toast.read": "Als gelesen markiert",
     "entry.status.title": "Status des Artikels ändern",
     "entry.bookmark.toggle.on": "Lesezeichen hinzufügen",
     "entry.bookmark.toggle.off": "Lesezeichen entfernen",
+    "entry.bookmark.toast.on": "Markiert",
+    "entry.bookmark.toast.off": "Nicht markiert",
     "entry.state.saving": "Speichern...",
     "entry.state.loading": "Lade...",
     "entry.save.label": "Speichern",
     "entry.save.title": "Diesen Artikel speichern",
     "entry.save.completed": "Erledigt!",
+    "entry.save.toast.completed": "Artikel gespeichert",
     "entry.scraper.label": "Inhalt herunterladen",
     "entry.scraper.title": "Inhalt herunterladen",
     "entry.scraper.completed": "Erledigt!",

+ 5 - 0
locale/translations/en_US.json

@@ -48,14 +48,19 @@
     "pagination.previous": "Previous",
     "entry.status.unread": "Unread",
     "entry.status.read": "Read",
+    "entry.status.toast.unread": "Marked as unread",
+    "entry.status.toast.read": "Marked as read",
     "entry.status.title": "Change entry status",
     "entry.bookmark.toggle.on": "Star",
     "entry.bookmark.toggle.off": "Unstar",
+    "entry.bookmark.toast.on": "Starred",
+    "entry.bookmark.toast.off": "Unstarred",
     "entry.state.saving": "Saving...",
     "entry.state.loading": "Loading...",
     "entry.save.label": "Save",
     "entry.save.title": "Save this article",
     "entry.save.completed": "Done!",
+    "entry.save.toast.completed": "Article saved",
     "entry.scraper.label": "Fetch original content",
     "entry.scraper.title": "Fetch original content",
     "entry.scraper.completed": "Done!",

+ 5 - 0
locale/translations/es_ES.json

@@ -48,14 +48,19 @@
     "pagination.previous": "Anterior",
     "entry.status.unread": "No leído",
     "entry.status.read": "Leído",
+    "entry.status.toast.unread": "Marcado como no leído",
+    "entry.status.toast.read": "Marcado como leído",
     "entry.status.title": "Cambiar estado de entrada",
     "entry.bookmark.toggle.on": "Marcar",
     "entry.bookmark.toggle.off": "Desmarcar",
+    "entry.bookmark.toast.on": "Sembrado de estrellas",
+    "entry.bookmark.toast.off": "Sin estrellas",
     "entry.state.saving": "Guardando...",
     "entry.state.loading": "Cargando...",
     "entry.save.label": "Guardar",
     "entry.save.title": "Guardar este articulo",
     "entry.save.completed": "¡Hecho!",
+    "entry.save.toast.completed": "Artículo guardado",
     "entry.scraper.label": "Obtener contenido original",
     "entry.scraper.title": "Obtener contenido original",
     "entry.scraper.completed": "¡Hecho!",

+ 5 - 0
locale/translations/fr_FR.json

@@ -49,13 +49,18 @@
     "entry.status.unread": "Non lu",
     "entry.status.read": "Lu",
     "entry.status.title": "Changer le statut de l'entrée",
+    "entry.status.toast.unread": "Marqué comme non lu",
+    "entry.status.toast.read": "Marqué comme lu",
     "entry.bookmark.toggle.on": "Favoris",
     "entry.bookmark.toggle.off": "Enlever favoris",
+    "entry.bookmark.toast.on": "Ajouté aux favoris",
+    "entry.bookmark.toast.off": "Enlevé des favoris",
     "entry.state.saving": "Sauvegarde en cours...",
     "entry.state.loading": "Chargement...",
     "entry.save.label": "Sauvegarder",
     "entry.save.title": "Sauvegarder cet article",
     "entry.save.completed": "Terminé !",
+    "entry.save.toast.completed": "Article sauvegardé",
     "entry.scraper.label": "Contenu original",
     "entry.scraper.title": "Récupérer le contenu original",
     "entry.scraper.completed": "Terminé !",

+ 5 - 0
locale/translations/it_IT.json

@@ -48,14 +48,19 @@
     "pagination.previous": "Precedente",
     "entry.status.unread": "Da leggere",
     "entry.status.read": "Letto",
+    "entry.status.toast.unread": "Contrassegnato come non letto",
+    "entry.status.toast.read": "Contrassegnato come letto",
     "entry.status.title": "Cambia lo stato dell'articolo",
     "entry.bookmark.toggle.on": "Aggiungi ai preferiti",
     "entry.bookmark.toggle.off": "Rimuovi dai preferiti",
+    "entry.bookmark.toast.on": "Ha recitato",
+    "entry.bookmark.toast.off": "Non speciali",
     "entry.state.saving": "Salvataggio in corso...",
     "entry.state.loading": "Caricamento in corso...",
     "entry.save.label": "Salva",
     "entry.save.title": "Salva questo articolo",
     "entry.save.completed": "Fatto!",
+    "entry.save.toast.completed": "Articolo salvato",
     "entry.scraper.label": "Scarica il contenuto integrale",
     "entry.scraper.title": "Scarica il contenuto integrale",
     "entry.scraper.completed": "Fatto!",

+ 5 - 0
locale/translations/nl_NL.json

@@ -48,14 +48,19 @@
     "pagination.previous": "Vorige",
     "entry.status.unread": "Ongelezen",
     "entry.status.read": "Gelezen",
+    "entry.status.toast.unread": "Gemarkeerd als ongelezen",
+    "entry.status.toast.read": "Gemarkeerd als gelezen",
     "entry.status.title": "Verander status van item",
     "entry.bookmark.toggle.on": "Ster toevoegen",
     "entry.bookmark.toggle.off": "Ster weghalen",
+    "entry.bookmark.toast.on": "Met ster",
+    "entry.bookmark.toast.off": "Ster verwijderd",
     "entry.state.saving": "Opslaag...",
     "entry.state.loading": "Laden...",
     "entry.save.label": "Opslaan",
     "entry.save.title": "Artikel opslaan",
     "entry.save.completed": "Done!",
+    "entry.save.toast.completed": "Artikel opgeslagen",
     "entry.scraper.label": "Fetch original content",
     "entry.scraper.title": "Fetch original content",
     "entry.scraper.completed": "Klaar!",

+ 5 - 0
locale/translations/pl_PL.json

@@ -48,14 +48,19 @@
     "pagination.previous": "Poprzedni",
     "entry.status.unread": "Nieprzeczytane",
     "entry.status.read": "Przeczytane",
+    "entry.status.toast.unread": "Oznaczone jako nieprzeczytane",
+    "entry.status.toast.read": "Oznaczone jako przeczytane",
     "entry.status.title": "Zmień status artykułu",
     "entry.bookmark.toggle.on": "Oznacz gwiazdką",
     "entry.bookmark.toggle.off": "Usuń gwiazdkę",
+    "entry.bookmark.toast.on": "Oznaczone gwiazdką",
+    "entry.bookmark.toast.off": "Bez gwiazdek",
     "entry.state.saving": "Zapisywanie...",
     "entry.state.loading": "Ładowanie...",
     "entry.save.label": "Zapisz",
     "entry.save.title": "Zapisz ten artykuł",
     "entry.save.completed": "Gotowe!",
+    "entry.save.toast.completed": "Artykuł zapisany",
     "entry.scraper.label": "Pobierz treść",
     "entry.scraper.title": "Pobierz oryginalną treść",
     "entry.scraper.completed": "Gotowe!",

+ 5 - 0
locale/translations/ru_RU.json

@@ -48,14 +48,19 @@
     "pagination.previous": "Предыдущая",
     "entry.status.unread": "Непрочитано",
     "entry.status.read": "Прочитано",
+    "entry.status.toast.unread": "Помечено как непрочитанное",
+    "entry.status.toast.read": "Помечено как прочитанное",
     "entry.status.title": "Изменить статус записи",
     "entry.bookmark.toggle.on": "Добавить в Избранное",
     "entry.bookmark.toggle.off": "Удалить из Избранного",
+    "entry.bookmark.toast.on": "Помеченные",
+    "entry.bookmark.toast.off": "Без пометок",
     "entry.state.saving": "Сохранение…",
     "entry.state.loading": "Загрузка…",
     "entry.save.label": "Сохранить",
     "entry.save.title": "Сохранить эту статью",
     "entry.save.completed": "Готово!",
+    "entry.save.toast.completed": "Статья сохранена",
     "entry.scraper.label": "Извлечь оригинальное содержимое",
     "entry.scraper.title": "Извлечь оригинальное содержимое",
     "entry.scraper.completed": "Готово!",

+ 6 - 1
locale/translations/zh_CN.json

@@ -48,14 +48,19 @@
     "pagination.previous": "上一页",
     "entry.status.unread": "未读",
     "entry.status.read": "标为已读",
+    "entry.status.toast.unread": "已标为未读",
+    "entry.status.toast.read": "已标为已读",
     "entry.status.title": "更改状态",
     "entry.bookmark.toggle.on": "标记星标",
     "entry.bookmark.toggle.off": "去掉星标",
+    "entry.bookmark.toast.on": "已标记星标",
+    "entry.bookmark.toast.off": "已去掉星标",
     "entry.state.saving": "保存中…",
     "entry.state.loading": "载入中…",
     "entry.save.label": "保存",
     "entry.save.title": "保存这篇文章",
     "entry.save.completed": "完成",
+    "entry.save.toast.completed": "已保存文章",
     "entry.scraper.label": "抓取原内容",
     "entry.scraper.title": "抓取原内容",
     "entry.scraper.completed": "完成",
@@ -120,7 +125,7 @@
     "page.keyboard_shortcuts.open_item": "打开选定的条目",
     "page.keyboard_shortcuts.open_original": "打开原始链接",
     "page.keyboard_shortcuts.toggle_read_status": "切换已读/未读状态",
-    "page.keyboard_shortcuts.mark_page_as_read": "标记当前",
+    "page.keyboard_shortcuts.mark_page_as_read": "标记当前页已读",
     "page.keyboard_shortcuts.download_content": "下载原始内容",
     "page.keyboard_shortcuts.toggle_bookmark_status": "切换收藏状态",
     "page.keyboard_shortcuts.save_article": "保存文章",

+ 4 - 1
template/common.go

@@ -115,6 +115,9 @@ var templateCommonMap = map[string]string{
 <body
     data-entries-status-url="{{ route "updateEntriesStatus" }}"
     {{ if .user }}{{ if not .user.KeyboardShortcuts }}data-disable-keyboard-shortcuts="true"{{ end }}{{ end }}>
+    <div class="toast-wrap">
+        <span class="toast-msg"></span>
+    </div>
     {{ if .user }}
     <header class="header">
         <nav>
@@ -247,6 +250,6 @@ var templateCommonMap = map[string]string{
 var templateCommonMapChecksums = map[string]string{
 	"entry_pagination": "4faa91e2eae150c5e4eab4d258e039dfdd413bab7602f0009360e6d52898e353",
 	"item_meta":        "34deb081a054f2948ad808bdb2c8603d6ab00c58f2f50c4ead0b47ae092888eb",
-	"layout":           "0204dc6636be38ff00a2ad6b70ac56c4ae8f8fb0a27f987a73819520129cbb84",
+	"layout":           "93a4873adf5deb99b77f60e71465eab817c32a381de696b93ff27b7eaa47bb3b",
 	"pagination":       "3386e90c6e1230311459e9a484629bc5d5bf39514a75ef2e73bbbc61142f7abb",
 }

+ 3 - 0
template/html/common/layout.html

@@ -41,6 +41,9 @@
 <body
     data-entries-status-url="{{ route "updateEntriesStatus" }}"
     {{ if .user }}{{ if not .user.KeyboardShortcuts }}data-disable-keyboard-shortcuts="true"{{ end }}{{ end }}>
+    <div class="toast-wrap">
+        <span class="toast-msg"></span>
+    </div>
     {{ if .user }}
     <header class="header">
         <nav>

+ 5 - 0
template/html/entry.html

@@ -14,6 +14,8 @@
                         data-toggle-status="true"
                         data-label-read="✔&#xfe0e;&nbsp;{{ t "entry.status.read" }}"
                         data-label-unread="✘&nbsp;{{ t "entry.status.unread" }}"
+                        data-toast-read="✔︎&nbsp;{{ t "entry.status.toast.read" }}"
+                        data-toast-unread="✘&nbsp;{{ t "entry.status.toast.unread" }}"
                         data-value="{{ if eq .entry.Status "read" }}read{{ else }}unread{{ end }}"
                         >{{ if eq .entry.Status "read" }}✘&nbsp;{{ t "entry.status.unread" }}{{ else }}✔&#xfe0e;&nbsp;{{ t "entry.status.read" }}{{ end }}</a>
                 </li>
@@ -24,6 +26,8 @@
                         data-label-loading="{{ t "entry.state.saving" }}"
                         data-label-star="☆&nbsp;{{ t "entry.bookmark.toggle.on" }}"
                         data-label-unstar="★&nbsp;{{ t "entry.bookmark.toggle.off" }}"
+                        data-toast-star="★&nbsp;{{ t "entry.bookmark.toast.on" }}"
+                        data-toast-unstar="☆&nbsp;{{ t "entry.bookmark.toast.off" }}"
                         data-value="{{ if .entry.Starred }}star{{ else }}unstar{{ end }}"
                         >{{ if .entry.Starred }}★&nbsp;{{ t "entry.bookmark.toggle.off" }}{{ else }}☆&nbsp;{{ t "entry.bookmark.toggle.on" }}{{ end }}</a>
                 </li>
@@ -35,6 +39,7 @@
                             data-save-url="{{ route "saveEntry" "entryID" .entry.ID }}"
                             data-label-loading="{{ t "entry.state.saving" }}"
                             data-label-done="{{ t "entry.save.completed" }}"
+                            data-toast-done="{{ t "entry.save.toast.completed" }}"
                             >{{ t "entry.save.title" }}</a>
                     </li>
                 {{ end }}

+ 6 - 1
template/views.go

@@ -593,6 +593,8 @@ var templateViewsMap = map[string]string{
                         data-toggle-status="true"
                         data-label-read="✔&#xfe0e;&nbsp;{{ t "entry.status.read" }}"
                         data-label-unread="✘&nbsp;{{ t "entry.status.unread" }}"
+                        data-toast-read="✔︎&nbsp;{{ t "entry.status.toast.read" }}"
+                        data-toast-unread="✘&nbsp;{{ t "entry.status.toast.unread" }}"
                         data-value="{{ if eq .entry.Status "read" }}read{{ else }}unread{{ end }}"
                         >{{ if eq .entry.Status "read" }}✘&nbsp;{{ t "entry.status.unread" }}{{ else }}✔&#xfe0e;&nbsp;{{ t "entry.status.read" }}{{ end }}</a>
                 </li>
@@ -603,6 +605,8 @@ var templateViewsMap = map[string]string{
                         data-label-loading="{{ t "entry.state.saving" }}"
                         data-label-star="☆&nbsp;{{ t "entry.bookmark.toggle.on" }}"
                         data-label-unstar="★&nbsp;{{ t "entry.bookmark.toggle.off" }}"
+                        data-toast-star="★&nbsp;{{ t "entry.bookmark.toast.on" }}"
+                        data-toast-unstar="☆&nbsp;{{ t "entry.bookmark.toast.off" }}"
                         data-value="{{ if .entry.Starred }}star{{ else }}unstar{{ end }}"
                         >{{ if .entry.Starred }}★&nbsp;{{ t "entry.bookmark.toggle.off" }}{{ else }}☆&nbsp;{{ t "entry.bookmark.toggle.on" }}{{ end }}</a>
                 </li>
@@ -614,6 +618,7 @@ var templateViewsMap = map[string]string{
                             data-save-url="{{ route "saveEntry" "entryID" .entry.ID }}"
                             data-label-loading="{{ t "entry.state.saving" }}"
                             data-label-done="{{ t "entry.save.completed" }}"
+                            data-toast-done="{{ t "entry.save.toast.completed" }}"
                             >{{ t "entry.save.title" }}</a>
                     </li>
                 {{ end }}
@@ -1476,7 +1481,7 @@ var templateViewsMapChecksums = map[string]string{
 	"edit_category":       "daf073d2944a180ce5aaeb80b597eb69597a50dff55a9a1d6cf7938b48d768cb",
 	"edit_feed":           "34aa0d668b3ea1a1b5fa480c20cebeae729b37010af3bb915d2a9eed73d3b996",
 	"edit_user":           "f4f99412ba771cfca2a2a42778b023b413c5494e9a287053ba8cf380c2865c5f",
-	"entry":               "e14434fc6f57963eae26057a18c835d0328af783d41f5af04b03387b4da604be",
+	"entry":               "24aeba26ef9a51ce585ca5c4af090f1de7d7bfd7f1e3ff1b63af520e2afa76bd",
 	"feed_entries":        "9c70b82f55e4b311eff20be1641733612e3c1b406ce8010861e4c417d97b6dcc",
 	"feeds":               "fa2dad422445eca898c1daa4ab742691207a8c0d3c274eed84462bc610d22219",
 	"history_entries":     "87e17d39de70eb3fdbc4000326283be610928758eae7924e4b08dcb446f3b6a9",

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
ui/static/css.go


+ 29 - 0
ui/static/css/common.css

@@ -151,6 +151,35 @@ a:hover {
     display: none;
 }
 
+.toast-wrap {
+    visibility: hidden;
+    opacity: 0;
+    position: fixed;
+    left: 0;
+    bottom: 10%;
+    color: #fff;
+    width: 100%;
+    text-align: center;
+ }
+
+ .toast-msg {
+    background-color: rgba(0,0,0,0.7);
+    padding: 2px 5px;
+    border-radius: 5px;
+ }
+ 
+.toastAnimate {
+    animation: toastKeyFrames 2s;
+}
+
+@keyframes toastKeyFrames {
+    0% {visibility: hidden; opacity: 0;}
+   25% {visibility: visible; opacity: 1; z-index: 9999}
+   50% {visibility: visible; opacity: 1; z-index: 9999}
+   75% {visibility: visible; opacity: 1; z-index: 9999}
+   100% {visibility: hidden; opacity: 0; z-index: 0}
+}
+
 @media (min-width: 600px) {
     body {
         margin: auto;

+ 10 - 9
ui/static/js.go

@@ -59,18 +59,18 @@ let searchInputElement=document.getElementById("search-input");if(searchInputEle
 function showKeyboardShortcuts(){let template=document.getElementById("keyboard-shortcuts");if(template!==null){ModalHandler.open(template.content);}}
 function markPageAsRead(){let items=DomHelper.getVisibleElements(".items .item");let entryIDs=[];items.forEach((element)=>{element.classList.add("item-status-read");entryIDs.push(parseInt(element.dataset.id,10));});if(entryIDs.length>0){updateEntriesStatus(entryIDs,"read",()=>{let element=document.querySelector("a[data-action=markPageAsRead]");let showOnlyUnread=false;if(element){showOnlyUnread=element.dataset.showOnlyUnread||false;}
 if(showOnlyUnread){window.location.reload();}else{goToPage("next",true);}});}}
-function handleEntryStatus(element){let currentEntry=findEntry(element);if(currentEntry){toggleEntryStatus(currentEntry);if(isListView()&&currentEntry.classList.contains('current-item')){goToNextListItem();}}}
-function toggleEntryStatus(element){let entryID=parseInt(element.dataset.id,10);let link=element.querySelector("a[data-toggle-status]");let currentStatus=link.dataset.value;let newStatus=currentStatus==="read"?"unread":"read";updateEntriesStatus([entryID],newStatus);if(currentStatus==="read"){link.innerHTML=link.dataset.labelRead;link.dataset.value="unread";}else{link.innerHTML=link.dataset.labelUnread;link.dataset.value="read";}
+function handleEntryStatus(element){let toasting=!element;let currentEntry=findEntry(element);if(currentEntry){toggleEntryStatus(currentEntry,toasting);if(isListView()&&currentEntry.classList.contains('current-item')){goToNextListItem();}}}
+function toggleEntryStatus(element,toasting){let entryID=parseInt(element.dataset.id,10);let link=element.querySelector("a[data-toggle-status]");let currentStatus=link.dataset.value;let newStatus=currentStatus==="read"?"unread":"read";updateEntriesStatus([entryID],newStatus);if(currentStatus==="read"){link.innerHTML=link.dataset.labelRead;link.dataset.value="unread";if(toasting){toast(link.dataset.toastUnread);}}else{link.innerHTML=link.dataset.labelUnread;link.dataset.value="read";if(toasting){toast(link.dataset.toastRead);}}
 if(element.classList.contains("item-status-"+currentStatus)){element.classList.remove("item-status-"+currentStatus);element.classList.add("item-status-"+newStatus);}}
 function markEntryAsRead(element){if(element.classList.contains("item-status-unread")){element.classList.remove("item-status-unread");element.classList.add("item-status-read");let entryID=parseInt(element.dataset.id,10);updateEntriesStatus([entryID],"read");}}
 function updateEntriesStatus(entryIDs,status,callback){let url=document.body.dataset.entriesStatusUrl;let request=new RequestBuilder(url);request.withBody({entry_ids:entryIDs,status:status});request.withCallback(callback);request.execute();if(status==="read"){decrementUnreadCounter(1);}else{incrementUnreadCounter(1);}}
-function handleSaveEntry(element){let currentEntry=findEntry(element);if(currentEntry){saveEntry(currentEntry.querySelector("a[data-save-entry]"));}}
-function saveEntry(element){if(!element){return;}
+function handleSaveEntry(element){let toasting=!element;let currentEntry=findEntry(element);if(currentEntry){saveEntry(currentEntry.querySelector("a[data-save-entry]"),toasting);}}
+function saveEntry(element,toasting){if(!element){return;}
 if(element.dataset.completed){return;}
-element.innerHTML=element.dataset.labelLoading;let request=new RequestBuilder(element.dataset.saveUrl);request.withCallback(()=>{element.innerHTML=element.dataset.labelDone;element.dataset.completed=true;});request.execute();}
-function handleBookmark(element){let currentEntry=findEntry(element);if(currentEntry){toggleBookmark(currentEntry);}}
-function toggleBookmark(parentElement){let element=parentElement.querySelector("a[data-toggle-bookmark]");if(!element){return;}
-element.innerHTML=element.dataset.labelLoading;let request=new RequestBuilder(element.dataset.bookmarkUrl);request.withCallback(()=>{if(element.dataset.value==="star"){element.innerHTML=element.dataset.labelStar;element.dataset.value="unstar";}else{element.innerHTML=element.dataset.labelUnstar;element.dataset.value="star";}});request.execute();}
+element.innerHTML=element.dataset.labelLoading;let request=new RequestBuilder(element.dataset.saveUrl);request.withCallback(()=>{element.innerHTML=element.dataset.labelDone;element.dataset.completed=true;if(toasting){toast(element.dataset.toastDone);}});request.execute();}
+function handleBookmark(element){let toasting=!element;let currentEntry=findEntry(element);if(currentEntry){toggleBookmark(currentEntry,toasting);}}
+function toggleBookmark(parentElement,toasting){let element=parentElement.querySelector("a[data-toggle-bookmark]");if(!element){return;}
+element.innerHTML=element.dataset.labelLoading;let request=new RequestBuilder(element.dataset.bookmarkUrl);request.withCallback(()=>{if(element.dataset.value==="star"){element.innerHTML=element.dataset.labelStar;element.dataset.value="unstar";if(toasting){toast(element.dataset.toastUnstar);}}else{element.innerHTML=element.dataset.labelUnstar;element.dataset.value="star";if(toasting){toast(element.dataset.toastStar);}}});request.execute();}
 function handleFetchOriginalContent(){if(isListView()){return;}
 let element=document.querySelector("a[data-fetch-content-entry]");if(!element){return;}
 if(element.dataset.completed){return;}
@@ -98,6 +98,7 @@ function isEntry(){return document.querySelector("section.entry")!==null;}
 function isListView(){return document.querySelector(".items")!==null;}
 function findEntry(element){if(isListView()){if(element){return DomHelper.findParent(element,"item");}else{return document.querySelector(".current-item");}}else{return document.querySelector(".entry");}}
 function handleConfirmationMessage(linkElement,callback){linkElement.style.display="none";let containerElement=linkElement.parentNode;let questionElement=document.createElement("span");let yesElement=document.createElement("a");yesElement.href="#";yesElement.appendChild(document.createTextNode(linkElement.dataset.labelYes));yesElement.onclick=(event)=>{event.preventDefault();let loadingElement=document.createElement("span");loadingElement.className="loading";loadingElement.appendChild(document.createTextNode(linkElement.dataset.labelLoading));questionElement.remove();containerElement.appendChild(loadingElement);callback(linkElement.dataset.url,linkElement.dataset.redirectUrl);};let noElement=document.createElement("a");noElement.href="#";noElement.appendChild(document.createTextNode(linkElement.dataset.labelNo));noElement.onclick=(event)=>{event.preventDefault();linkElement.style.display="inline";questionElement.remove();};questionElement.className="confirm";questionElement.appendChild(document.createTextNode(linkElement.dataset.labelQuestion+" "));questionElement.appendChild(yesElement);questionElement.appendChild(document.createTextNode(", "));questionElement.appendChild(noElement);containerElement.appendChild(questionElement);}
+function toast(msg){if(!msg)return;document.querySelector('.toast-wrap .toast-msg').innerHTML=msg;let toastWrapper=document.querySelector('.toast-wrap');toastWrapper.classList.remove('toastAnimate');setTimeout(function(){toastWrapper.classList.add('toastAnimate');},100);}
 document.addEventListener("DOMContentLoaded",function(){handleSubmitButtons();if(!document.querySelector("body[data-disable-keyboard-shortcuts=true]")){let keyboardHandler=new KeyboardHandler();keyboardHandler.on("g u",()=>goToPage("unread"));keyboardHandler.on("g b",()=>goToPage("starred"));keyboardHandler.on("g h",()=>goToPage("history"));keyboardHandler.on("g f",()=>goToFeedOrFeeds());keyboardHandler.on("g c",()=>goToPage("categories"));keyboardHandler.on("g s",()=>goToPage("settings"));keyboardHandler.on("ArrowLeft",()=>goToPrevious());keyboardHandler.on("ArrowRight",()=>goToNext());keyboardHandler.on("k",()=>goToPrevious());keyboardHandler.on("p",()=>goToPrevious());keyboardHandler.on("j",()=>goToNext());keyboardHandler.on("n",()=>goToNext());keyboardHandler.on("h",()=>goToPage("previous"));keyboardHandler.on("l",()=>goToPage("next"));keyboardHandler.on("o",()=>openSelectedItem());keyboardHandler.on("v",()=>openOriginalLink());keyboardHandler.on("m",()=>handleEntryStatus());keyboardHandler.on("A",()=>markPageAsRead());keyboardHandler.on("s",()=>handleSaveEntry());keyboardHandler.on("d",()=>handleFetchOriginalContent());keyboardHandler.on("f",()=>handleBookmark());keyboardHandler.on("?",()=>showKeyboardShortcuts());keyboardHandler.on("#",()=>unsubscribeFromFeed());keyboardHandler.on("/",(e)=>setFocusToSearchInput(e));keyboardHandler.on("Escape",()=>ModalHandler.close());keyboardHandler.listen();}
 let touchHandler=new TouchHandler();touchHandler.listen();onClick("a[data-save-entry]",(event)=>handleSaveEntry(event.target));onClick("a[data-toggle-bookmark]",(event)=>handleBookmark(event.target));onClick("a[data-fetch-content-entry]",()=>handleFetchOriginalContent());onClick("a[data-action=search]",(event)=>setFocusToSearchInput(event));onClick("a[data-action=markPageAsRead]",()=>handleConfirmationMessage(event.target,()=>markPageAsRead()));onClick("a[data-toggle-status]",(event)=>handleEntryStatus(event.target));onClick("a[data-confirm]",(event)=>handleConfirmationMessage(event.target,(url,redirectURL)=>{let request=new RequestBuilder(url);request.withCallback(()=>{if(redirectURL){window.location.href=redirectURL;}else{window.location.reload();}});request.execute();}));if(document.documentElement.clientWidth<600){onClick(".logo",()=>toggleMainMenu());onClick(".header nav li",(event)=>onClickMainMenuListItem(event));}
 if("serviceWorker"in navigator){let scriptElement=document.getElementById("service-worker-script");if(scriptElement){navigator.serviceWorker.register(scriptElement.src);}}});})();`,
@@ -105,6 +106,6 @@ if("serviceWorker"in navigator){let scriptElement=document.getElementById("servi
 }
 
 var JavascriptsChecksums = map[string]string{
-	"app": "ef0f82521c4b721401ee093f08788dd1416fd461bc4023ef6f81f2fa813aed73",
+	"app": "a42ba7e5f07586c160c427db8329463bed97fc88e7948c1c7ad9c2e698f620d8",
 	"sw":  "55fffa223919cc18572788fb9c62fccf92166c0eb5d3a1d6f91c31f24d020be9",
 }

+ 34 - 6
ui/static/js/app.js

@@ -116,9 +116,10 @@ function markPageAsRead() {
 
 // Handle entry status changes from the list view and entry view.
 function handleEntryStatus(element) {
+    let toasting = !element;
     let currentEntry = findEntry(element);
     if (currentEntry) {
-        toggleEntryStatus(currentEntry);
+        toggleEntryStatus(currentEntry, toasting);
         if (isListView() && currentEntry.classList.contains('current-item')) {
             goToNextListItem();
         }
@@ -126,7 +127,7 @@ function handleEntryStatus(element) {
 }
 
 // Change the entry status to the opposite value.
-function toggleEntryStatus(element) {
+function toggleEntryStatus(element, toasting) {
     let entryID = parseInt(element.dataset.id, 10);
     let link = element.querySelector("a[data-toggle-status]");
 
@@ -138,9 +139,15 @@ function toggleEntryStatus(element) {
     if (currentStatus === "read") {
         link.innerHTML = link.dataset.labelRead;
         link.dataset.value = "unread";
+        if (toasting) {
+            toast(link.dataset.toastUnread);
+        }
     } else {
         link.innerHTML = link.dataset.labelUnread;
         link.dataset.value = "read";
+        if (toasting) {
+            toast(link.dataset.toastRead);
+        }
     }
 
     if (element.classList.contains("item-status-" + currentStatus)) {
@@ -177,14 +184,15 @@ function updateEntriesStatus(entryIDs, status, callback) {
 
 // Handle save entry from list view and entry view.
 function handleSaveEntry(element) {
+    let toasting = !element;
     let currentEntry = findEntry(element);
     if (currentEntry) {
-        saveEntry(currentEntry.querySelector("a[data-save-entry]"));
+        saveEntry(currentEntry.querySelector("a[data-save-entry]"), toasting);
     }
 }
 
 // Send the Ajax request to save an entry.
-function saveEntry(element) {
+function saveEntry(element, toasting) {
     if (!element) {
         return;
     }
@@ -199,20 +207,24 @@ function saveEntry(element) {
     request.withCallback(() => {
         element.innerHTML = element.dataset.labelDone;
         element.dataset.completed = true;
+        if (toasting) {
+            toast(element.dataset.toastDone);
+        }
     });
     request.execute();
 }
 
 // Handle bookmark from the list view and entry view.
 function handleBookmark(element) {
+    let toasting = !element;
     let currentEntry = findEntry(element);
     if (currentEntry) {
-        toggleBookmark(currentEntry);
+        toggleBookmark(currentEntry, toasting);
     }
 }
 
 // Send the Ajax request and change the icon when bookmarking an entry.
-function toggleBookmark(parentElement) {
+function toggleBookmark(parentElement, toasting) {
     let element = parentElement.querySelector("a[data-toggle-bookmark]");
     if (!element) {
         return;
@@ -225,9 +237,15 @@ function toggleBookmark(parentElement) {
         if (element.dataset.value === "star") {
             element.innerHTML = element.dataset.labelStar;
             element.dataset.value = "unstar";
+            if (toasting) {
+                toast(element.dataset.toastUnstar);
+            }
         } else {
             element.innerHTML = element.dataset.labelUnstar;
             element.dataset.value = "star";
+            if (toasting) {
+                toast(element.dataset.toastStar);
+            }
         }
     });
     request.execute();
@@ -493,3 +511,13 @@ function handleConfirmationMessage(linkElement, callback) {
 
     containerElement.appendChild(questionElement);
 }
+
+function toast(msg) {
+    if (!msg) return;
+    document.querySelector('.toast-wrap .toast-msg').innerHTML = msg;
+    let toastWrapper = document.querySelector('.toast-wrap');
+    toastWrapper.classList.remove('toastAnimate');
+    setTimeout(function () {
+        toastWrapper.classList.add('toastAnimate');
+    }, 100);
+}

Некоторые файлы не были показаны из-за большого количества измененных файлов