Add page to list and remove shared entries

This commit is contained in:
Frédéric Guillot 2020-03-22 18:48:14 -07:00
parent 84229f1af9
commit 9871e4f5d0
25 changed files with 457 additions and 51 deletions

View File

@ -59,7 +59,7 @@ func IsSchemaUpToDate(db *sql.DB) error {
var currentVersion int
db.QueryRow(`SELECT version FROM schema_version`).Scan(&currentVersion)
if currentVersion != schemaVersion {
return fmt.Errorf(`database schema is not up to date: current=v%d expected=v%d`, currentVersion, schemaVersion)
return fmt.Errorf(`the database schema is not up to date: current=v%d expected=v%d`, currentVersion, schemaVersion)
}
return nil
}

View File

@ -51,6 +51,7 @@ var translations = map[string]string{
"menu.feed_entries": "Artikel",
"menu.api_keys": "API-Schlüssel",
"menu.create_api_key": "Erstellen Sie einen neuen API-Schlüssel",
"menu.shared_entries": "Geteilte Einträge",
"search.label": "Suche",
"search.placeholder": "Suche...",
"pagination.next": "Nächste",
@ -78,6 +79,10 @@ var translations = map[string]string{
"entry.comments.title": "Kommentare anzeigen",
"entry.share.label": "Teilen",
"entry.share.title": "Diesen Artikel teilen",
"entry.unshare.label": "Unshare",
"entry.shared_entry.title": "Öffnen Sie den öffentlichen Link",
"entry.shared_entry.label": "Teilen",
"page.shared_entries.title": "Geteilte Einträge",
"page.unread.title": "Ungelesen",
"page.starred.title": "Lesezeichen",
"page.categories.title": "Kategorien",
@ -191,6 +196,7 @@ var translations = map[string]string{
"page.api_keys.table.actions": "Aktionen",
"page.api_keys.never_used": "Nie benutzt",
"page.new_api_key.title": "Neuer API-Schlüssel",
"alert.no_shared_entry": "Es gibt keinen gemeinsamen Eintrag.",
"alert.no_bookmark": "Es existiert derzeit kein Lesezeichen.",
"alert.no_category": "Es ist keine Kategorie vorhanden.",
"alert.no_category_entry": "Es befindet sich kein Artikel in dieser Kategorie.",
@ -379,6 +385,7 @@ var translations = map[string]string{
"menu.feed_entries": "Entries",
"menu.api_keys": "API Keys",
"menu.create_api_key": "Create a new API key",
"menu.shared_entries": "Shared entries",
"search.label": "Search",
"search.placeholder": "Search...",
"pagination.next": "Next",
@ -406,6 +413,10 @@ var translations = map[string]string{
"entry.comments.title": "View Comments",
"entry.share.label": "Share",
"entry.share.title": "Share this article",
"entry.unshare.label": "Unshare",
"entry.shared_entry.title": "Open the public link",
"entry.shared_entry.label": "Share",
"page.shared_entries.title": "Shared Entries",
"page.unread.title": "Unread",
"page.starred.title": "Starred",
"page.categories.title": "Categories",
@ -519,6 +530,7 @@ var translations = map[string]string{
"page.api_keys.table.actions": "Actions",
"page.api_keys.never_used": "Never Used",
"page.new_api_key.title": "New API Key",
"alert.no_shared_entry": "There is no shared entry.",
"alert.no_bookmark": "There is no bookmark at the moment.",
"alert.no_category": "There is no category.",
"alert.no_category_entry": "There are no articles in this category.",
@ -687,6 +699,7 @@ var translations = map[string]string{
"menu.feed_entries": "Artículos",
"menu.api_keys": "Claves API",
"menu.create_api_key": "Crear una nueva clave API",
"menu.shared_entries": "Entradas compartidas",
"search.label": "Buscar",
"search.placeholder": "Búsqueda...",
"pagination.next": "Siguiente",
@ -714,6 +727,10 @@ var translations = map[string]string{
"entry.comments.title": "Ver comentarios",
"entry.share.label": "Comparta",
"entry.share.title": "Comparta este articulo",
"entry.unshare.label": "No compartir",
"entry.shared_entry.title": "Abrir el enlace público",
"entry.shared_entry.label": "Compartir",
"page.shared_entries.title": "Entradas compartidas",
"page.unread.title": "No leídos",
"page.starred.title": "Marcadores",
"page.categories.title": "Categorias",
@ -827,6 +844,7 @@ var translations = map[string]string{
"page.api_keys.table.actions": "Acciones",
"page.api_keys.never_used": "Nunca usado",
"page.new_api_key.title": "Nueva clave API",
"alert.no_shared_entry": "No hay entrada compartida.",
"alert.no_bookmark": "No hay marcador en este momento.",
"alert.no_category": "No hay categoría.",
"alert.no_category_entry": "No hay artículos en esta categoria.",
@ -995,6 +1013,7 @@ var translations = map[string]string{
"menu.feed_entries": "Articles",
"menu.api_keys": "Clés d'API",
"menu.create_api_key": "Créer une nouvelle clé d'API",
"menu.shared_entries": "Articles partagés",
"search.label": "Recherche",
"search.placeholder": "Recherche...",
"pagination.next": "Suivant",
@ -1022,6 +1041,10 @@ var translations = map[string]string{
"entry.comments.title": "Voir les commentaires",
"entry.share.label": "Partager",
"entry.share.title": "Partager cet article",
"entry.unshare.label": "Enlever le partage",
"entry.shared_entry.title": "Ouvrir le lien public",
"entry.shared_entry.label": "Partage",
"page.shared_entries.title": "Articles partagés",
"page.unread.title": "Non lus",
"page.starred.title": "Favoris",
"page.categories.title": "Catégories",
@ -1135,6 +1158,7 @@ var translations = map[string]string{
"page.api_keys.table.actions": "Actions",
"page.api_keys.never_used": "Jamais utilisé",
"page.new_api_key.title": "Nouvelle clé d'API",
"alert.no_shared_entry": "Il n'y a pas d'article partagé.",
"alert.no_bookmark": "Il n'y a aucun favoris pour le moment.",
"alert.no_category": "Il n'y a aucune catégorie.",
"alert.no_category_entry": "Il n'y a aucun article dans cette catégorie.",
@ -1323,6 +1347,7 @@ var translations = map[string]string{
"menu.feed_entries": "Articoli",
"menu.api_keys": "Chiavi API",
"menu.create_api_key": "Crea una nuova chiave API",
"menu.shared_entries": "Voci condivise",
"search.label": "Cerca",
"search.placeholder": "Cerca...",
"pagination.next": "Successivo",
@ -1350,6 +1375,10 @@ var translations = map[string]string{
"entry.comments.title": "Mostra i commenti",
"entry.share.label": "Condividi",
"entry.share.title": "Condividi questo articolo",
"entry.unshare.label": "Unshare",
"entry.shared_entry.title": "Apri il link pubblico",
"entry.shared_entry.label": "Condivisione",
"page.shared_entries.title": "Voci condivise",
"page.unread.title": "Da leggere",
"page.starred.title": "Preferiti",
"page.categories.title": "Categorie",
@ -1463,6 +1492,7 @@ var translations = map[string]string{
"page.api_keys.table.actions": "Azioni",
"page.api_keys.never_used": "Mai usato",
"page.new_api_key.title": "Nuova chiave API",
"alert.no_shared_entry": "Non ci sono voci condivise.",
"alert.no_bookmark": "Nessun preferito disponibile.",
"alert.no_category": "Nessuna categoria disponibile.",
"alert.no_category_entry": "Questa categoria non contiene alcun articolo.",
@ -1631,6 +1661,7 @@ var translations = map[string]string{
"menu.feed_entries": "記事一覧",
"menu.api_keys": "APIキー",
"menu.create_api_key": "新しいAPIキーを作成する",
"menu.shared_entries": "共有エントリ",
"search.label": "検索",
"search.placeholder": "…を検索",
"pagination.next": "次",
@ -1658,6 +1689,10 @@ var translations = map[string]string{
"entry.comments.title": "コメントを見る",
"entry.share.label": "共有",
"entry.share.title": "この記事を共有する",
"entry.unshare.label": "共有解除",
"entry.shared_entry.title": "公開リンクを開く",
"entry.shared_entry.label": "共有する",
"page.shared_entries.title": "共有エントリ",
"page.unread.title": "未読",
"page.starred.title": "星付き",
"page.categories.title": "カテゴリ",
@ -1771,6 +1806,7 @@ var translations = map[string]string{
"page.api_keys.table.actions": "アクション",
"page.api_keys.never_used": "使われたことがない",
"page.new_api_key.title": "新しいAPIキー",
"alert.no_shared_entry": "共有エントリはありません。",
"alert.no_bookmark": "現在星付きはありません。",
"alert.no_category": "カテゴリが存在しません。",
"alert.no_category_entry": "このカテゴリには記事がありません。",
@ -1939,6 +1975,7 @@ var translations = map[string]string{
"menu.feed_entries": "Lidwoord",
"menu.api_keys": "API-sleutels",
"menu.create_api_key": "Maak een nieuwe API-sleutel",
"menu.shared_entries": "Gedeelde vermeldingen",
"search.label": "Zoeken",
"search.placeholder": "Zoeken...",
"pagination.next": "Volgende",
@ -1966,6 +2003,10 @@ var translations = map[string]string{
"entry.comments.title": "Bekijk de reacties",
"entry.share.label": "Deel",
"entry.share.title": "Deel dit artikel",
"entry.unshare.label": "Delen ongedaan maken",
"entry.shared_entry.title": "Open de openbare link",
"entry.shared_entry.label": "Delen",
"page.shared_entries.title": "Gedeelde vermeldingen",
"page.unread.title": "Ongelezen",
"page.starred.title": "Favorieten",
"page.categories.title": "Categorieën",
@ -2079,6 +2120,7 @@ var translations = map[string]string{
"page.api_keys.table.actions": "Acties",
"page.api_keys.never_used": "Nooit gebruikt",
"page.new_api_key.title": "Nieuwe API-sleutel",
"alert.no_shared_entry": "Er is geen gedeelde toegang.",
"alert.no_bookmark": "Er zijn op dit moment geen favorieten.",
"alert.no_category": "Er zijn geen categorieën.",
"alert.no_category_entry": "Deze categorie bevat geen feeds.",
@ -2265,6 +2307,7 @@ var translations = map[string]string{
"menu.feed_entries": "Artykuły",
"menu.api_keys": "Klucze API",
"menu.create_api_key": "Utwórz nowy klucz API",
"menu.shared_entries": "Udostępnione wpisy",
"search.label": "Szukaj",
"search.placeholder": "Szukaj...",
"pagination.next": "Następny",
@ -2292,6 +2335,10 @@ var translations = map[string]string{
"entry.comments.title": "Zobacz komentarze",
"entry.share.label": "Podzielić się",
"entry.share.title": "Podzielić się ten artykuł",
"entry.unshare.label": "Unshare",
"entry.shared_entry.title": "Otwórz publiczny link",
"entry.shared_entry.label": "Udostępnianie",
"page.shared_entries.title": "Udostępnione wpisy",
"page.unread.title": "Nieprzeczytane",
"page.starred.title": "Oznaczone gwiazdką",
"page.categories.title": "Kategorie",
@ -2407,6 +2454,7 @@ var translations = map[string]string{
"page.api_keys.table.actions": "Działania",
"page.api_keys.never_used": "Nigdy nie używany",
"page.new_api_key.title": "Nowy klucz API",
"alert.no_shared_entry": "Brak wspólnego wpisu.",
"alert.no_bookmark": "Obecnie nie ma żadnych zakładek.",
"alert.no_category": "Nie ma żadnej kategorii!",
"alert.no_category_entry": "W tej kategorii nie ma żadnych artykułów",
@ -2599,6 +2647,7 @@ var translations = map[string]string{
"menu.feed_entries": "статьи",
"menu.api_keys": "API-ключи",
"menu.create_api_key": "Создать новый ключ API",
"menu.shared_entries": "Общие записи",
"search.label": "Поиск",
"search.placeholder": "Поиск…",
"pagination.next": "Следующая",
@ -2626,6 +2675,10 @@ var translations = map[string]string{
"entry.comments.title": "Показать комментарии",
"entry.share.label": "поделиться",
"entry.share.title": "поделиться эту статью",
"entry.unshare.label": "Удалить из открытого списка",
"entry.shared_entry.title": "Открыть публичную ссылку",
"entry.shared_entry.label": "обмен",
"page.shared_entries.title": "Общие записи",
"page.unread.title": "Непрочитанное",
"page.starred.title": "Избранное",
"page.categories.title": "Категории",
@ -2741,6 +2794,7 @@ var translations = map[string]string{
"page.api_keys.table.actions": "Действия",
"page.api_keys.never_used": "Никогда не использовался",
"page.new_api_key.title": "Новый ключ API",
"alert.no_shared_entry": "Там нет общей записи.",
"alert.no_bookmark": "Нет закладок на данный момент.",
"alert.no_category": "Категории отсутствуют.",
"alert.no_category_entry": "В этой категории нет статей.",
@ -2915,6 +2969,7 @@ var translations = map[string]string{
"menu.feed_entries": "文章",
"menu.api_keys": "API密钥",
"menu.create_api_key": "创建一个新的API密钥",
"menu.shared_entries": "共享条目",
"search.label": "搜索",
"search.placeholder": "搜索…",
"pagination.next": "下一页",
@ -2942,6 +2997,10 @@ var translations = map[string]string{
"entry.comments.title": "查看评论",
"entry.share.label": "分享",
"entry.share.title": "分享这篇文章",
"entry.unshare.label": "取消分享",
"entry.shared_entry.title": "打开公共链接",
"entry.shared_entry.label": "分享分享",
"page.shared_entries.title": "共享条目",
"page.unread.title": "未读",
"page.starred.title": "星标",
"page.categories.title": "分类",
@ -3053,6 +3112,7 @@ var translations = map[string]string{
"page.api_keys.table.actions": "操作",
"page.api_keys.never_used": "没用过",
"page.new_api_key.title": "新的API密钥",
"alert.no_shared_entry": "没有共享条目。",
"alert.no_bookmark": "目前没有书签",
"alert.no_category": "目前没有分类",
"alert.no_category_entry": "该分类下没有文章",
@ -3189,14 +3249,14 @@ var translations = map[string]string{
}
var translationsChecksums = map[string]string{
"de_DE": "7360a69e038d71e00f64c03891401cd517779687d46a907688f4a9a7b6205146",
"en_US": "5d9cad74ccfd94393aa98a25f28fa4f41895d8f758461760601d04c92f898d02",
"es_ES": "813b8cd42907dfbc19ff51f3367e0dbb013d373b013d7854df512e846652ff21",
"fr_FR": "bf770b1ecfd722bbf4fa29d2ea567b064c8bcb517141073ab3d170d27f4e53e4",
"it_IT": "fe2c7147f3c39784f482cf922d9d3a85a94f15af8ff28ebcec64723555a3fb10",
"ja_JP": "508025c0c7e7f57195ae011c4499ab58a85d043c828565c1740df879fb2376c1",
"nl_NL": "e621a5e7408928624a060a832d9fc36b74026221bd7b07894a4cce267be3cdd1",
"pl_PL": "6edcefd04e453c84b03207653c54f7be9a4a8ce4699e06c82bfcca2d7946f47e",
"ru_RU": "d7ad59bbd7a150af9d476c4c3034eb85762de7381e2925d75e373584ed45c725",
"zh_CN": "e5f169a3c83c9bd7a41e9737e001e58fec243eee7aa23a71d37bfa8e05d92860",
"de_DE": "aa7025ff266508152d31ed22e816588c3beaf6ef0ddff20012d303ab55a584d1",
"en_US": "c1cd8a4c6360881299609332bc930c0d59a30aea5ae90a6c87bcc06dbba7c69d",
"es_ES": "94f4da8c6160ca30c59294ec520f8648496b94904b61ac47c7ca24bfa4fe793b",
"fr_FR": "80a2d02c7a90e90024af4f5eb3aad710f245963df99538d7d71c0efcaae79f82",
"it_IT": "b033ade2a67a273253d3251df97e6b2da7e2adbec60a33de5d0f41198e6783b2",
"ja_JP": "2136cad37933c112a6e69f28936c216c8f262b28c47b57b18482c56a3f8932fb",
"nl_NL": "4a3a4a117f11cf62de5cf515c5adc74c8467d05feac1844fee4f81d863173887",
"pl_PL": "c088a74ad9e4dca6bdbf73b0b4fce97db60b5066cb03c6884a9462573b0f93ad",
"ru_RU": "506a34fdfa35dacf2d86b16f44d47addf2e0f1f376d2a86a474619d6654967cc",
"zh_CN": "463037b8bd51bb1e940f432fd621d62d4e81697298b8058124d287b5cbaee10f",
}

View File

@ -46,6 +46,7 @@
"menu.feed_entries": "Artikel",
"menu.api_keys": "API-Schlüssel",
"menu.create_api_key": "Erstellen Sie einen neuen API-Schlüssel",
"menu.shared_entries": "Geteilte Einträge",
"search.label": "Suche",
"search.placeholder": "Suche...",
"pagination.next": "Nächste",
@ -73,6 +74,10 @@
"entry.comments.title": "Kommentare anzeigen",
"entry.share.label": "Teilen",
"entry.share.title": "Diesen Artikel teilen",
"entry.unshare.label": "Unshare",
"entry.shared_entry.title": "Öffnen Sie den öffentlichen Link",
"entry.shared_entry.label": "Teilen",
"page.shared_entries.title": "Geteilte Einträge",
"page.unread.title": "Ungelesen",
"page.starred.title": "Lesezeichen",
"page.categories.title": "Kategorien",
@ -186,6 +191,7 @@
"page.api_keys.table.actions": "Aktionen",
"page.api_keys.never_used": "Nie benutzt",
"page.new_api_key.title": "Neuer API-Schlüssel",
"alert.no_shared_entry": "Es gibt keinen gemeinsamen Eintrag.",
"alert.no_bookmark": "Es existiert derzeit kein Lesezeichen.",
"alert.no_category": "Es ist keine Kategorie vorhanden.",
"alert.no_category_entry": "Es befindet sich kein Artikel in dieser Kategorie.",

View File

@ -46,6 +46,7 @@
"menu.feed_entries": "Entries",
"menu.api_keys": "API Keys",
"menu.create_api_key": "Create a new API key",
"menu.shared_entries": "Shared entries",
"search.label": "Search",
"search.placeholder": "Search...",
"pagination.next": "Next",
@ -73,6 +74,10 @@
"entry.comments.title": "View Comments",
"entry.share.label": "Share",
"entry.share.title": "Share this article",
"entry.unshare.label": "Unshare",
"entry.shared_entry.title": "Open the public link",
"entry.shared_entry.label": "Share",
"page.shared_entries.title": "Shared Entries",
"page.unread.title": "Unread",
"page.starred.title": "Starred",
"page.categories.title": "Categories",
@ -186,6 +191,7 @@
"page.api_keys.table.actions": "Actions",
"page.api_keys.never_used": "Never Used",
"page.new_api_key.title": "New API Key",
"alert.no_shared_entry": "There is no shared entry.",
"alert.no_bookmark": "There is no bookmark at the moment.",
"alert.no_category": "There is no category.",
"alert.no_category_entry": "There are no articles in this category.",

View File

@ -46,6 +46,7 @@
"menu.feed_entries": "Artículos",
"menu.api_keys": "Claves API",
"menu.create_api_key": "Crear una nueva clave API",
"menu.shared_entries": "Entradas compartidas",
"search.label": "Buscar",
"search.placeholder": "Búsqueda...",
"pagination.next": "Siguiente",
@ -73,6 +74,10 @@
"entry.comments.title": "Ver comentarios",
"entry.share.label": "Comparta",
"entry.share.title": "Comparta este articulo",
"entry.unshare.label": "No compartir",
"entry.shared_entry.title": "Abrir el enlace público",
"entry.shared_entry.label": "Compartir",
"page.shared_entries.title": "Entradas compartidas",
"page.unread.title": "No leídos",
"page.starred.title": "Marcadores",
"page.categories.title": "Categorias",
@ -186,6 +191,7 @@
"page.api_keys.table.actions": "Acciones",
"page.api_keys.never_used": "Nunca usado",
"page.new_api_key.title": "Nueva clave API",
"alert.no_shared_entry": "No hay entrada compartida.",
"alert.no_bookmark": "No hay marcador en este momento.",
"alert.no_category": "No hay categoría.",
"alert.no_category_entry": "No hay artículos en esta categoria.",

View File

@ -46,6 +46,7 @@
"menu.feed_entries": "Articles",
"menu.api_keys": "Clés d'API",
"menu.create_api_key": "Créer une nouvelle clé d'API",
"menu.shared_entries": "Articles partagés",
"search.label": "Recherche",
"search.placeholder": "Recherche...",
"pagination.next": "Suivant",
@ -73,6 +74,10 @@
"entry.comments.title": "Voir les commentaires",
"entry.share.label": "Partager",
"entry.share.title": "Partager cet article",
"entry.unshare.label": "Enlever le partage",
"entry.shared_entry.title": "Ouvrir le lien public",
"entry.shared_entry.label": "Partage",
"page.shared_entries.title": "Articles partagés",
"page.unread.title": "Non lus",
"page.starred.title": "Favoris",
"page.categories.title": "Catégories",
@ -186,6 +191,7 @@
"page.api_keys.table.actions": "Actions",
"page.api_keys.never_used": "Jamais utilisé",
"page.new_api_key.title": "Nouvelle clé d'API",
"alert.no_shared_entry": "Il n'y a pas d'article partagé.",
"alert.no_bookmark": "Il n'y a aucun favoris pour le moment.",
"alert.no_category": "Il n'y a aucune catégorie.",
"alert.no_category_entry": "Il n'y a aucun article dans cette catégorie.",

View File

@ -46,6 +46,7 @@
"menu.feed_entries": "Articoli",
"menu.api_keys": "Chiavi API",
"menu.create_api_key": "Crea una nuova chiave API",
"menu.shared_entries": "Voci condivise",
"search.label": "Cerca",
"search.placeholder": "Cerca...",
"pagination.next": "Successivo",
@ -73,6 +74,10 @@
"entry.comments.title": "Mostra i commenti",
"entry.share.label": "Condividi",
"entry.share.title": "Condividi questo articolo",
"entry.unshare.label": "Unshare",
"entry.shared_entry.title": "Apri il link pubblico",
"entry.shared_entry.label": "Condivisione",
"page.shared_entries.title": "Voci condivise",
"page.unread.title": "Da leggere",
"page.starred.title": "Preferiti",
"page.categories.title": "Categorie",
@ -186,6 +191,7 @@
"page.api_keys.table.actions": "Azioni",
"page.api_keys.never_used": "Mai usato",
"page.new_api_key.title": "Nuova chiave API",
"alert.no_shared_entry": "Non ci sono voci condivise.",
"alert.no_bookmark": "Nessun preferito disponibile.",
"alert.no_category": "Nessuna categoria disponibile.",
"alert.no_category_entry": "Questa categoria non contiene alcun articolo.",

View File

@ -46,6 +46,7 @@
"menu.feed_entries": "記事一覧",
"menu.api_keys": "APIキー",
"menu.create_api_key": "新しいAPIキーを作成する",
"menu.shared_entries": "共有エントリ",
"search.label": "検索",
"search.placeholder": "…を検索",
"pagination.next": "次",
@ -73,6 +74,10 @@
"entry.comments.title": "コメントを見る",
"entry.share.label": "共有",
"entry.share.title": "この記事を共有する",
"entry.unshare.label": "共有解除",
"entry.shared_entry.title": "公開リンクを開く",
"entry.shared_entry.label": "共有する",
"page.shared_entries.title": "共有エントリ",
"page.unread.title": "未読",
"page.starred.title": "星付き",
"page.categories.title": "カテゴリ",
@ -186,6 +191,7 @@
"page.api_keys.table.actions": "アクション",
"page.api_keys.never_used": "使われたことがない",
"page.new_api_key.title": "新しいAPIキー",
"alert.no_shared_entry": "共有エントリはありません。",
"alert.no_bookmark": "現在星付きはありません。",
"alert.no_category": "カテゴリが存在しません。",
"alert.no_category_entry": "このカテゴリには記事がありません。",

View File

@ -46,6 +46,7 @@
"menu.feed_entries": "Lidwoord",
"menu.api_keys": "API-sleutels",
"menu.create_api_key": "Maak een nieuwe API-sleutel",
"menu.shared_entries": "Gedeelde vermeldingen",
"search.label": "Zoeken",
"search.placeholder": "Zoeken...",
"pagination.next": "Volgende",
@ -73,6 +74,10 @@
"entry.comments.title": "Bekijk de reacties",
"entry.share.label": "Deel",
"entry.share.title": "Deel dit artikel",
"entry.unshare.label": "Delen ongedaan maken",
"entry.shared_entry.title": "Open de openbare link",
"entry.shared_entry.label": "Delen",
"page.shared_entries.title": "Gedeelde vermeldingen",
"page.unread.title": "Ongelezen",
"page.starred.title": "Favorieten",
"page.categories.title": "Categorieën",
@ -186,6 +191,7 @@
"page.api_keys.table.actions": "Acties",
"page.api_keys.never_used": "Nooit gebruikt",
"page.new_api_key.title": "Nieuwe API-sleutel",
"alert.no_shared_entry": "Er is geen gedeelde toegang.",
"alert.no_bookmark": "Er zijn op dit moment geen favorieten.",
"alert.no_category": "Er zijn geen categorieën.",
"alert.no_category_entry": "Deze categorie bevat geen feeds.",

View File

@ -46,6 +46,7 @@
"menu.feed_entries": "Artykuły",
"menu.api_keys": "Klucze API",
"menu.create_api_key": "Utwórz nowy klucz API",
"menu.shared_entries": "Udostępnione wpisy",
"search.label": "Szukaj",
"search.placeholder": "Szukaj...",
"pagination.next": "Następny",
@ -73,6 +74,10 @@
"entry.comments.title": "Zobacz komentarze",
"entry.share.label": "Podzielić się",
"entry.share.title": "Podzielić się ten artykuł",
"entry.unshare.label": "Unshare",
"entry.shared_entry.title": "Otwórz publiczny link",
"entry.shared_entry.label": "Udostępnianie",
"page.shared_entries.title": "Udostępnione wpisy",
"page.unread.title": "Nieprzeczytane",
"page.starred.title": "Oznaczone gwiazdką",
"page.categories.title": "Kategorie",
@ -188,6 +193,7 @@
"page.api_keys.table.actions": "Działania",
"page.api_keys.never_used": "Nigdy nie używany",
"page.new_api_key.title": "Nowy klucz API",
"alert.no_shared_entry": "Brak wspólnego wpisu.",
"alert.no_bookmark": "Obecnie nie ma żadnych zakładek.",
"alert.no_category": "Nie ma żadnej kategorii!",
"alert.no_category_entry": "W tej kategorii nie ma żadnych artykułów",

View File

@ -46,6 +46,7 @@
"menu.feed_entries": "статьи",
"menu.api_keys": "API-ключи",
"menu.create_api_key": "Создать новый ключ API",
"menu.shared_entries": "Общие записи",
"search.label": "Поиск",
"search.placeholder": "Поиск…",
"pagination.next": "Следующая",
@ -73,6 +74,10 @@
"entry.comments.title": "Показать комментарии",
"entry.share.label": "поделиться",
"entry.share.title": "поделиться эту статью",
"entry.unshare.label": "Удалить из открытого списка",
"entry.shared_entry.title": "Открыть публичную ссылку",
"entry.shared_entry.label": "обмен",
"page.shared_entries.title": "Общие записи",
"page.unread.title": "Непрочитанное",
"page.starred.title": "Избранное",
"page.categories.title": "Категории",
@ -188,6 +193,7 @@
"page.api_keys.table.actions": "Действия",
"page.api_keys.never_used": "Никогда не использовался",
"page.new_api_key.title": "Новый ключ API",
"alert.no_shared_entry": "Там нет общей записи.",
"alert.no_bookmark": "Нет закладок на данный момент.",
"alert.no_category": "Категории отсутствуют.",
"alert.no_category_entry": "В этой категории нет статей.",

View File

@ -46,6 +46,7 @@
"menu.feed_entries": "文章",
"menu.api_keys": "API密钥",
"menu.create_api_key": "创建一个新的API密钥",
"menu.shared_entries": "共享条目",
"search.label": "搜索",
"search.placeholder": "搜索…",
"pagination.next": "下一页",
@ -73,6 +74,10 @@
"entry.comments.title": "查看评论",
"entry.share.label": "分享",
"entry.share.title": "分享这篇文章",
"entry.unshare.label": "取消分享",
"entry.shared_entry.title": "打开公共链接",
"entry.shared_entry.label": "分享分享",
"page.shared_entries.title": "共享条目",
"page.unread.title": "未读",
"page.starred.title": "星标",
"page.categories.title": "分类",
@ -184,6 +189,7 @@
"page.api_keys.table.actions": "操作",
"page.api_keys.never_used": "没用过",
"page.new_api_key.title": "新的API密钥",
"alert.no_shared_entry": "没有共享条目。",
"alert.no_bookmark": "目前没有书签",
"alert.no_category": "目前没有分类",
"alert.no_category_entry": "该分类下没有文章",

View File

@ -272,7 +272,15 @@ func (s *Storage) ToggleBookmark(userID int64, entryID int64) error {
// FlushHistory set all entries with the status "read" to "removed".
func (s *Storage) FlushHistory(userID int64) error {
query := `UPDATE entries SET status=$1, changed_at=now() WHERE user_id=$2 AND status=$3 AND starred='f'`
query := `
UPDATE
entries
SET
status=$1,
changed_at=now()
WHERE
user_id=$2 AND status=$3 AND starred='f' AND share_code=''
`
_, err := s.db.Exec(query, model.EntryStatusRemoved, userID, model.EntryStatusRead)
if err != nil {
return fmt.Errorf(`store: unable to flush history: %v`, err)
@ -353,34 +361,36 @@ func (s *Storage) EntryURLExists(feedID int64, entryURL string) bool {
return result
}
// GetEntryShareCode returns the share code of the provided entry.
// EntryShareCode returns the share code of the provided entry.
// It generates a new one if not already defined.
func (s *Storage) GetEntryShareCode(userID int64, entryID int64) (shareCode string, err error) {
func (s *Storage) EntryShareCode(userID int64, entryID int64) (shareCode string, err error) {
query := `SELECT share_code FROM entries WHERE user_id=$1 AND id=$2`
err = s.db.QueryRow(query, userID, entryID).Scan(&shareCode)
if err != nil || shareCode != "" {
return
}
shareCode = crypto.GenerateRandomStringHex(20)
query = `UPDATE entries SET share_code = $1 WHERE user_id=$2 AND id=$3`
result, err := s.db.Exec(query, shareCode, userID, entryID)
if err != nil {
err = fmt.Errorf(`store: unable to set share_code for entry #%d: %v`, entryID, err)
err = fmt.Errorf(`store: unable to get share code for entry #%d: %v`, entryID, err)
return
}
count, err := result.RowsAffected()
if err != nil {
err = fmt.Errorf(`store: unable to set share_code for entry #%d: %v`, entryID, err)
return
}
if shareCode == "" {
shareCode = crypto.GenerateRandomStringHex(20)
if count == 0 {
err = errors.New(`store: nothing has been updated`)
query = `UPDATE entries SET share_code = $1 WHERE user_id=$2 AND id=$3`
_, err = s.db.Exec(query, shareCode, userID, entryID)
if err != nil {
err = fmt.Errorf(`store: unable to set share code for entry #%d: %v`, entryID, err)
return
}
}
return
}
// UnshareEntry removes the share code for the given entry.
func (s *Storage) UnshareEntry(userID int64, entryID int64) (err error) {
query := `UPDATE entries SET share_code='' WHERE user_id=$1 AND id=$2`
_, err = s.db.Exec(query, userID, entryID)
if err != nil {
err = fmt.Errorf(`store: unable to remove share code for entry #%d: %v`, entryID, err)
}
return
}

View File

@ -135,6 +135,12 @@ func (e *EntryQueryBuilder) WithShareCode(shareCode string) *EntryQueryBuilder {
return e
}
// WithShareCodeNotEmpty adds a filter for non-empty share code.
func (e *EntryQueryBuilder) WithShareCodeNotEmpty() *EntryQueryBuilder {
e.conditions = append(e.conditions, "e.share_code <> ''")
return e
}
// WithOrder set the sorting order.
func (e *EntryQueryBuilder) WithOrder(order string) *EntryQueryBuilder {
e.order = order

View File

@ -185,6 +185,16 @@ SOFTWARE.
<line x1="10" y1="14" x2="20" y2="4" />
<polyline points="15 4 20 4 20 9" />
</svg>
{{ end }}
{{ define "icon_delete" }}
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-trash" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/>
<line x1="4" y1="7" x2="20" y2="7" />
<line x1="10" y1="11" x2="10" y2="17" />
<line x1="14" y1="11" x2="14" y2="17" />
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" />
<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" />
</svg>
{{ end }}`,
"item_meta": `{{ define "item_meta" }}
<div class="item-meta">
@ -197,6 +207,13 @@ SOFTWARE.
</li>
</ul>
<ul class="item-meta-icons">
{{ if .entry.ShareCode }}
<li>
<a href="{{ route "sharedEntry" "shareCode" .entry.ShareCode }}"
title="{{ t "entry.shared_entry.title" }}"
target="_blank">{{ template "icon_share" }}<span class="icon-label">{{ t "entry.shared_entry.label" }}</span></a>
</li>
{{ end }}
{{ if .hasSaveEntry }}
<li>
<a href="#"
@ -455,8 +472,8 @@ var templateCommonMapChecksums = map[string]string{
"entry_pagination": "cdca9cf12586e41e5355190b06d9168f57f77b85924d1e63b13524bc15abcbf6",
"feed_list": "46cbfc441404dc55c56a9fd7ddc43d98216762f2562f2a17e35eb508dc84246f",
"feed_menu": "318d8662dda5ca9dfc75b909c8461e79c86fb5082df1428f67aaf856f19f4b50",
"icons": "d9b4105a89364d913ad975b569286e6bd79f270da995856d21a10537e42b93f4",
"item_meta": "be80837365e7dbcf28da44fbb2a31cccc29f29d83b88bf8da06609739a91a383",
"icons": "f0d94c2cfa6655b44adaf97f0b95c52a9cff5c31f3a8829ad438e4db7114af7e",
"item_meta": "a5b07cc6597e5c8f3ca849ee486acb3f16f062d8a1eaa47d2fb402ae6825b7ef",
"layout": "a1f67b8908745ee4f9cee6f7bbbb0b242d4dcc101207ad4a9d67242b45683299",
"pagination": "7b61288e86283c4cf0dc83bcbf8bf1c00c7cb29e60201c8c0b633b2450d2911f",
"settings_menu": "e2b777630c0efdbc529800303c01d6744ed3af80ec505ac5a5b3f99c9b989156",

View File

@ -85,4 +85,14 @@ SOFTWARE.
<line x1="10" y1="14" x2="20" y2="4" />
<polyline points="15 4 20 4 20 9" />
</svg>
{{ end }}
{{ define "icon_delete" }}
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-trash" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/>
<line x1="4" y1="7" x2="20" y2="7" />
<line x1="10" y1="11" x2="10" y2="17" />
<line x1="14" y1="11" x2="14" y2="17" />
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" />
<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" />
</svg>
{{ end }}

View File

@ -9,6 +9,13 @@
</li>
</ul>
<ul class="item-meta-icons">
{{ if .entry.ShareCode }}
<li>
<a href="{{ route "sharedEntry" "shareCode" .entry.ShareCode }}"
title="{{ t "entry.shared_entry.title" }}"
target="_blank">{{ template "icon_share" }}<span class="icon-label">{{ t "entry.shared_entry.label" }}</span></a>
</li>
{{ end }}
{{ if .hasSaveEntry }}
<li>
<a href="#"

View File

@ -45,10 +45,15 @@
</li>
{{ end }}
<li>
<a href="{{ route "shareGenerate" "entryID" .entry.ID }}"
title="{{ t "entry.share.title" }}"
target="_blank"
>{{ template "icon_share" }}<span class="icon-label">{{ t "entry.share.label" }}</span></a>
{{ if .entry.ShareCode }}
<a href="{{ route "sharedEntry" "shareCode" .entry.ShareCode }}"
title="{{ t "entry.shared_entry.title" }}"
target="_blank">{{ template "icon_share" }}<span class="icon-label">{{ t "entry.shared_entry.label" }}</span></a>
{{ else }}
<a href="{{ route "shareEntry" "entryID" .entry.ID }}"
title="{{ t "entry.share.title" }}"
target="_blank">{{ template "icon_share" }}<span class="icon-label">{{ t "entry.share.label" }}</span></a>
{{ end }}
</li>
<li>
<a href="#"

View File

@ -14,6 +14,15 @@
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}">{{ t "menu.flush_history" }}</a>
</li>
<li>
<a href="{{ route "sharedEntries" }}">{{ t "menu.shared_entries" }}</a>
</li>
</ul>
{{ else }}
<ul>
<li>
<a href="{{ route "sharedEntries" }}">{{ t "menu.shared_entries" }}</a>
</li>
</ul>
{{ end }}
</section>

View File

@ -0,0 +1,71 @@
{{ define "title"}}{{ t "page.shared_entries.title" }} ({{ .total }}){{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.shared_entries.title" }} ({{ .total }})</h1>
{{ if .entries }}
<ul>
<li>
<a href="#"
data-confirm="true"
data-url="{{ route "flushHistory" }}"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}">{{ t "menu.flush_history" }}</a>
</li>
<li>
<a href="{{ route "sharedEntries" }}">{{ t "menu.shared_entries" }}</a>
</li>
</ul>
{{ end }}
</section>
{{ if not .entries }}
<p class="alert alert-info">{{ t "alert.no_shared_entry" }}</p>
{{ else }}
<div class="items">
{{ range .entries }}
<article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
<div class="item-header">
<span class="item-title">
{{ if ne .Feed.Icon.IconID 0 }}
<img src="{{ route "icon" "iconID" .Feed.Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Feed.Title }}">
{{ end }}
<a href="{{ route "readEntry" "entryID" .ID }}">{{ .Title }}</a>
{{ if .ShareCode }}
<a href="{{ route "sharedEntry" "shareCode" .ShareCode }}"
title="{{ t "entry.shared_entry.title" }}"
target="_blank">{{ template "icon_share" }}</a>
{{ end }}
</span>
<span class="category"><a href="{{ route "categoryEntries" "categoryID" .Feed.Category.ID }}">{{ .Feed.Category.Title }}</a></span>
</div>
<div class="item-meta">
<ul class="item-meta-info">
<li>
<a href="{{ route "feedEntries" "feedID" .Feed.ID }}" title="{{ .Feed.SiteURL }}">{{ truncate .Feed.Title 35 }}</a>
</li>
<li>
<time datetime="{{ isodate .Date }}" title="{{ isodate .Date }}">{{ elapsed $.user.Timezone .Date }}</time>
</li>
</ul>
<ul class="item-meta-icons">
<li>
{{ template "icon_delete" }}
<a href="#"
data-confirm="true"
data-url="{{ route "unshareEntry" "entryID" .ID }}"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}">{{ t "entry.unshare.label" }}</a>
</li>
</ul>
</div>
</article>
{{ end }}
</div>
{{ end }}
{{ end }}

View File

@ -692,10 +692,15 @@ var templateViewsMap = map[string]string{
</li>
{{ end }}
<li>
<a href="{{ route "shareGenerate" "entryID" .entry.ID }}"
title="{{ t "entry.share.title" }}"
target="_blank"
>{{ template "icon_share" }}<span class="icon-label">{{ t "entry.share.label" }}</span></a>
{{ if .entry.ShareCode }}
<a href="{{ route "sharedEntry" "shareCode" .entry.ShareCode }}"
title="{{ t "entry.shared_entry.title" }}"
target="_blank">{{ template "icon_share" }}<span class="icon-label">{{ t "entry.shared_entry.label" }}</span></a>
{{ else }}
<a href="{{ route "shareEntry" "entryID" .entry.ID }}"
title="{{ t "entry.share.title" }}"
target="_blank">{{ template "icon_share" }}<span class="icon-label">{{ t "entry.share.label" }}</span></a>
{{ end }}
</li>
<li>
<a href="#"
@ -941,6 +946,15 @@ var templateViewsMap = map[string]string{
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}">{{ t "menu.flush_history" }}</a>
</li>
<li>
<a href="{{ route "sharedEntries" }}">{{ t "menu.shared_entries" }}</a>
</li>
</ul>
{{ else }}
<ul>
<li>
<a href="{{ route "sharedEntries" }}">{{ t "menu.shared_entries" }}</a>
</li>
</ul>
{{ end }}
</section>
@ -1319,6 +1333,78 @@ var templateViewsMap = map[string]string{
</div>
{{ end }}
{{ end }}
`,
"shared_entries": `{{ define "title"}}{{ t "page.shared_entries.title" }} ({{ .total }}){{ end }}
{{ define "content"}}
<section class="page-header">
<h1>{{ t "page.shared_entries.title" }} ({{ .total }})</h1>
{{ if .entries }}
<ul>
<li>
<a href="#"
data-confirm="true"
data-url="{{ route "flushHistory" }}"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}">{{ t "menu.flush_history" }}</a>
</li>
<li>
<a href="{{ route "sharedEntries" }}">{{ t "menu.shared_entries" }}</a>
</li>
</ul>
{{ end }}
</section>
{{ if not .entries }}
<p class="alert alert-info">{{ t "alert.no_shared_entry" }}</p>
{{ else }}
<div class="items">
{{ range .entries }}
<article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
<div class="item-header">
<span class="item-title">
{{ if ne .Feed.Icon.IconID 0 }}
<img src="{{ route "icon" "iconID" .Feed.Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Feed.Title }}">
{{ end }}
<a href="{{ route "readEntry" "entryID" .ID }}">{{ .Title }}</a>
{{ if .ShareCode }}
<a href="{{ route "sharedEntry" "shareCode" .ShareCode }}"
title="{{ t "entry.shared_entry.title" }}"
target="_blank">{{ template "icon_share" }}</a>
{{ end }}
</span>
<span class="category"><a href="{{ route "categoryEntries" "categoryID" .Feed.Category.ID }}">{{ .Feed.Category.Title }}</a></span>
</div>
<div class="item-meta">
<ul class="item-meta-info">
<li>
<a href="{{ route "feedEntries" "feedID" .Feed.ID }}" title="{{ .Feed.SiteURL }}">{{ truncate .Feed.Title 35 }}</a>
</li>
<li>
<time datetime="{{ isodate .Date }}" title="{{ isodate .Date }}">{{ elapsed $.user.Timezone .Date }}</time>
</li>
</ul>
<ul class="item-meta-icons">
<li>
{{ template "icon_delete" }}
<a href="#"
data-confirm="true"
data-url="{{ route "unshareEntry" "entryID" .ID }}"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}">{{ t "entry.unshare.label" }}</a>
</li>
</ul>
</div>
</article>
{{ end }}
</div>
{{ end }}
{{ end }}
`,
"unread_entries": `{{ define "title"}}{{ t "page.unread.title" }} {{ if gt .countUnread 0 }}({{ .countUnread }}){{ end }} {{ end }}
@ -1457,16 +1543,17 @@ var templateViewsMapChecksums = map[string]string{
"edit_category": "b1c0b38f1b714c5d884edcd61e5b5295a5f1c8b71c469b35391e4dcc97cc6d36",
"edit_feed": "cc0b5dbb73f81398410958b41771ed38246bc7ae4bd548228f0d48c49a598c2a",
"edit_user": "c692db9de1a084c57b93e95a14b041d39bf489846cbb91fc982a62b72b77062a",
"entry": "03814d36909f3af1a9164c407d8733bcf1f15c4aee516186d07561a81fa42eb3",
"entry": "0e405b2370aaefaaa122c955f58fd395b9f19612e4cc7b209fc79e7b00c5561b",
"feed_entries": "9c70b82f55e4b311eff20be1641733612e3c1b406ce8010861e4c417d97b6dcc",
"feeds": "ec7d3fa96735bd8422ba69ef0927dcccddc1cc51327e0271f0312d3f881c64fd",
"history_entries": "87e17d39de70eb3fdbc4000326283be610928758eae7924e4b08dcb446f3b6a9",
"history_entries": "93c0c4cc541eec7f07f5c2634f250ea82ac64024939179276b6f636b72c189bf",
"import": "1b59b3bd55c59fcbc6fbb346b414dcdd26d1b4e0c307e437bb58b3f92ef01ad1",
"integrations": "30329452743b35c668278f519245fd9be05c1726856e0384ba542f7c307f2788",
"login": "79ff2ca488c0a19b37c8fa227a21f73e94472eb357a51a077197c852f7713f11",
"search_entries": "274950d03298c24f3942e209c0faed580a6d57be9cf76a6c236175a7e766ac6a",
"sessions": "5d5c677bddbd027e0b0c9f7a0dd95b66d9d95b4e130959f31fb955b926c2201c",
"settings": "d949ecdd28a33eadafaa3a727e548b3466c5aa44b0a4bbf86cc49784704ff7f6",
"shared_entries": "19caea053664220bb9519df295eb2a17cf5836eaa9104b7ee24c60b88bb524e9",
"unread_entries": "e38f7ffce17dfad3151b08cd33771a2cefe8ca9db42df04fc98bd1d675dd6075",
"users": "d7ff52efc582bbad10504f4a04fa3adcc12d15890e45dff51cac281e0c446e45",
}

View File

@ -135,7 +135,7 @@ func (m *middleware) isPublicRoute(r *http.Request) bool {
"favicon",
"webManifest",
"robots",
"share",
"sharedEntry",
"healthcheck":
return true
default:

View File

@ -1,4 +1,4 @@
// Copyright 2017 Frédéric Guillot. All rights reserved.
// Copyright 2020 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
@ -17,18 +17,28 @@ import (
"miniflux.app/ui/view"
)
func (h *handler) shareGenerate(w http.ResponseWriter, r *http.Request) {
func (h *handler) createSharedEntry(w http.ResponseWriter, r *http.Request) {
entryID := request.RouteInt64Param(r, "entryID")
shareCode, err := h.store.GetEntryShareCode(request.UserID(r), entryID)
shareCode, err := h.store.EntryShareCode(request.UserID(r), entryID)
if err != nil {
html.ServerError(w, r, err)
return
}
html.Redirect(w, r, route.Path(h.router, "share", "shareCode", shareCode))
html.Redirect(w, r, route.Path(h.router, "sharedEntry", "shareCode", shareCode))
}
func (h *handler) sharePage(w http.ResponseWriter, r *http.Request) {
func (h *handler) unshareEntry(w http.ResponseWriter, r *http.Request) {
entryID := request.RouteInt64Param(r, "entryID")
if err := h.store.UnshareEntry(request.UserID(r), entryID); err != nil {
html.ServerError(w, r, err)
return
}
html.Redirect(w, r, route.Path(h.router, "sharedEntries"))
}
func (h *handler) sharedEntry(w http.ResponseWriter, r *http.Request) {
shareCode := request.RouteStringParam(r, "shareCode")
if shareCode == "" {
html.NotFound(w, r)

52
ui/shared_entries.go Normal file
View File

@ -0,0 +1,52 @@
// Copyright 2020 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
package ui // import "miniflux.app/ui"
import (
"net/http"
"miniflux.app/http/request"
"miniflux.app/http/response/html"
"miniflux.app/model"
"miniflux.app/ui/session"
"miniflux.app/ui/view"
)
func (h *handler) sharedEntries(w http.ResponseWriter, r *http.Request) {
user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithShareCodeNotEmpty()
builder.WithOrder(model.DefaultSortingOrder)
builder.WithDirection(user.EntryDirection)
entries, err := builder.GetEntries()
if err != nil {
html.ServerError(w, r, err)
return
}
count, err := builder.CountEntries()
if err != nil {
html.ServerError(w, r, err)
return
}
sess := session.New(h.store, request.SessionID(r))
view := view.New(h.tpl, r, sess)
view.Set("entries", entries)
view.Set("total", count)
view.Set("menu", "history")
view.Set("user", user)
view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("shared_entries"))
}

View File

@ -89,8 +89,10 @@ func Serve(router *mux.Router, store *storage.Storage, pool *worker.Pool, feedHa
uiRouter.HandleFunc("/entry/bookmark/{entryID}", handler.toggleBookmark).Name("toggleBookmark").Methods("POST")
// Share pages.
uiRouter.HandleFunc("/entry/share/{entryID}", handler.shareGenerate).Name("shareGenerate").Methods("GET")
uiRouter.HandleFunc("/share/{shareCode}", handler.sharePage).Name("share").Methods("GET")
uiRouter.HandleFunc("/entry/share/{entryID}", handler.createSharedEntry).Name("shareEntry").Methods("GET")
uiRouter.HandleFunc("/entry/unshare/{entryID}", handler.unshareEntry).Name("unshareEntry").Methods("POST")
uiRouter.HandleFunc("/share/{shareCode}", handler.sharedEntry).Name("sharedEntry").Methods("GET")
uiRouter.HandleFunc("/shares", handler.sharedEntries).Name("sharedEntries").Methods("GET")
// User pages.
uiRouter.HandleFunc("/users", handler.showUsersPage).Name("users").Methods("GET")