diff --git a/client/model.go b/client/model.go
index 938b13c6..0b9cdeb9 100644
--- a/client/model.go
+++ b/client/model.go
@@ -34,6 +34,7 @@ type User struct {
ShowReadingTime bool `json:"show_reading_time"`
EntrySwipe bool `json:"entry_swipe"`
LastLoginAt *time.Time `json:"last_login_at"`
+ DisplayMode string `json:"display_mode"`
}
func (u User) String() string {
@@ -65,6 +66,7 @@ type UserModificationRequest struct {
KeyboardShortcuts *bool `json:"keyboard_shortcuts"`
ShowReadingTime *bool `json:"show_reading_time"`
EntrySwipe *bool `json:"entry_swipe"`
+ DisplayMode *string `json:"display_mode"`
}
// Users represents a list of users.
diff --git a/database/migrations.go b/database/migrations.go
index 2f108874..c7dfc8d9 100644
--- a/database/migrations.go
+++ b/database/migrations.go
@@ -521,4 +521,12 @@ var migrations = []func(tx *sql.Tx) error{
`)
return err
},
+ func(tx *sql.Tx) (err error) {
+ sql := `
+ CREATE TYPE webapp_display_mode AS enum('fullscreen', 'standalone', 'minimal-ui', 'browser');
+ ALTER TABLE users ADD COLUMN display_mode webapp_display_mode default 'standalone';
+ `
+ _, err = tx.Exec(sql)
+ return err
+ },
}
diff --git a/locale/translations/de_DE.json b/locale/translations/de_DE.json
index 478a66ba..64184b99 100644
--- a/locale/translations/de_DE.json
+++ b/locale/translations/de_DE.json
@@ -254,6 +254,7 @@
"error.invalid_language": "Ungültige Sprache.",
"error.invalid_timezone": "Ungültige Zeitzone.",
"error.invalid_entry_direction": "Ungültige Sortierreihenfolge.",
+ "error.invalid_display_mode": "Ungültiger Web-App-Anzeigemodus.",
"form.feed.label.title": "Titel",
"form.feed.label.site_url": "Webseite-URL",
"form.feed.label.feed_url": "Abonnement-URL",
@@ -280,8 +281,13 @@
"form.prefs.label.theme": "Thema",
"form.prefs.label.entry_sorting": "Sortierung der Artikel",
"form.prefs.label.entries_per_page": "Einträge pro Seite",
+ "form.prefs.label.display_mode": "Anzeigemodus der Web-App (muss neu installiert werden)",
"form.prefs.select.older_first": "Älteste Artikel zuerst",
"form.prefs.select.recent_first": "Neueste Artikel zuerst",
+ "form.prefs.select.fullscreen": "Vollbildschirm",
+ "form.prefs.select.standalone": "Eigenständige",
+ "form.prefs.select.minimal_ui": "Minimal",
+ "form.prefs.select.browser": "Browser",
"form.prefs.label.keyboard_shortcuts": "Tastaturkürzel aktivieren",
"form.prefs.label.entry_swipe": "Wischgeste für Einträge auf dem Handy aktivieren",
"form.prefs.label.show_reading_time": "Geschätzte Lesezeit für Artikel anzeigen",
diff --git a/locale/translations/en_US.json b/locale/translations/en_US.json
index 75e7e1b0..6cd654a6 100644
--- a/locale/translations/en_US.json
+++ b/locale/translations/en_US.json
@@ -233,6 +233,7 @@
"error.invalid_language": "Invalid language.",
"error.invalid_timezone": "Invalid timezone.",
"error.invalid_entry_direction": "Invalid entry direction.",
+ "error.invalid_display_mode": "Invalid web app display mode.",
"error.empty_file": "This file is empty.",
"error.bad_credentials": "Invalid username or password.",
"error.fields_mandatory": "All fields are mandatory.",
@@ -280,8 +281,13 @@
"form.prefs.label.theme": "Theme",
"form.prefs.label.entry_sorting": "Entry Sorting",
"form.prefs.label.entries_per_page": "Entries per page",
+ "form.prefs.label.display_mode": "Web app display mode (needs reinstalling)",
"form.prefs.select.older_first": "Older entries first",
"form.prefs.select.recent_first": "Recent entries first",
+ "form.prefs.select.fullscreen": "Fullscreen",
+ "form.prefs.select.standalone": "Standalone",
+ "form.prefs.select.minimal_ui": "Minimal",
+ "form.prefs.select.browser": "Browser",
"form.prefs.label.keyboard_shortcuts": "Enable keyboard shortcuts",
"form.prefs.label.entry_swipe": "Enable swipe gesture on entries on mobile",
"form.prefs.label.show_reading_time": "Show estimated reading time for articles",
diff --git a/locale/translations/es_ES.json b/locale/translations/es_ES.json
index ab2f5e1d..1944f31a 100644
--- a/locale/translations/es_ES.json
+++ b/locale/translations/es_ES.json
@@ -254,6 +254,7 @@
"error.invalid_language": "Idioma no válido.",
"error.invalid_timezone": "Zona horaria no válida.",
"error.invalid_entry_direction": "Dirección de entrada no válida.",
+ "error.invalid_display_mode": "Modo de visualización de la aplicación web no válido.",
"form.feed.label.title": "Título",
"form.feed.label.site_url": "URL del sitio",
"form.feed.label.feed_url": "URL de la fuente",
@@ -280,8 +281,13 @@
"form.prefs.label.theme": "Tema",
"form.prefs.label.entry_sorting": "Clasificación de entradas",
"form.prefs.label.entries_per_page": "Entradas por página",
+ "form.prefs.label.display_mode": "Modo de visualización de la aplicación web (necesita reinstalación)",
"form.prefs.select.older_first": "Entradas más viejas primero",
"form.prefs.select.recent_first": "Entradas recientes primero",
+ "form.prefs.select.fullscreen": "Pantalla completa",
+ "form.prefs.select.standalone": "Ser único",
+ "form.prefs.select.minimal_ui": "Mínimo",
+ "form.prefs.select.browser": "Navegador",
"form.prefs.label.keyboard_shortcuts": "Habilitar atajos de teclado",
"form.prefs.label.entry_swipe": "Habilitar el gesto de deslizar el dedo en las entradas en el móvil",
"form.prefs.label.show_reading_time": "Mostrar el tiempo estimado de lectura de los artículos",
diff --git a/locale/translations/fr_FR.json b/locale/translations/fr_FR.json
index 708f9d8f..09dd3b10 100644
--- a/locale/translations/fr_FR.json
+++ b/locale/translations/fr_FR.json
@@ -254,6 +254,7 @@
"error.invalid_language": "Langue non valide.",
"error.invalid_timezone": "Fuseau horaire non valide.",
"error.invalid_entry_direction": "Ordre de trie non valide.",
+ "error.invalid_display_mode": "Mode d'affichage de l'application web non valide.",
"form.feed.label.title": "Titre",
"form.feed.label.site_url": "URL du site web",
"form.feed.label.feed_url": "URL du flux",
@@ -280,8 +281,13 @@
"form.prefs.label.theme": "Thème",
"form.prefs.label.entry_sorting": "Ordre des éléments",
"form.prefs.label.entries_per_page": "Entrées par page",
+ "form.prefs.label.display_mode": "Mode d'affichage de l'application web (doit être réinstallé)",
"form.prefs.select.older_first": "Ancien éléments en premier",
"form.prefs.select.recent_first": "Éléments récents en premier",
+ "form.prefs.select.fullscreen": "Plein écran",
+ "form.prefs.select.standalone": "Autonome",
+ "form.prefs.select.minimal_ui": "Minimal",
+ "form.prefs.select.browser": "Navigateur",
"form.prefs.label.keyboard_shortcuts": "Activer les raccourcis clavier",
"form.prefs.label.entry_swipe": "Activer le geste de balayage sur les entrées sur mobile",
"form.prefs.label.show_reading_time": "Afficher le temps de lecture estimé des articles",
diff --git a/locale/translations/it_IT.json b/locale/translations/it_IT.json
index f857d563..34e10156 100644
--- a/locale/translations/it_IT.json
+++ b/locale/translations/it_IT.json
@@ -254,6 +254,7 @@
"error.invalid_language": "Lingua non valida.",
"error.invalid_timezone": "Fuso orario non valido.",
"error.invalid_entry_direction": "Ordinamento non valido.",
+ "error.invalid_display_mode": "Modalità di visualizzazione web app non valida.",
"form.feed.label.title": "Titolo",
"form.feed.label.site_url": "URL del sito",
"form.feed.label.feed_url": "URL del feed",
@@ -280,8 +281,13 @@
"form.prefs.label.theme": "Tema",
"form.prefs.label.entry_sorting": "Ordinamento articoli",
"form.prefs.label.entries_per_page": "Articoli per pagina",
+ "form.prefs.label.display_mode": "Modalità di visualizzazione web app (necessita la reinstallazione)",
"form.prefs.select.older_first": "Prima i più vecchi",
"form.prefs.select.recent_first": "Prima i più recenti",
+ "form.prefs.select.fullscreen": "Schermo intero",
+ "form.prefs.select.standalone": "Autonoma",
+ "form.prefs.select.minimal_ui": "Minimale",
+ "form.prefs.select.browser": "Browser",
"form.prefs.label.keyboard_shortcuts": "Abilita le scorciatoie da tastiera",
"form.prefs.label.entry_swipe": "Abilita il gesto di scorrimento sulle voci sul cellulare",
"form.prefs.label.show_reading_time": "Mostra il tempo di lettura stimato per gli articoli",
diff --git a/locale/translations/ja_JP.json b/locale/translations/ja_JP.json
index 4ac53262..a4a8fb79 100644
--- a/locale/translations/ja_JP.json
+++ b/locale/translations/ja_JP.json
@@ -254,6 +254,7 @@
"error.invalid_language": "言語が無効です。",
"error.invalid_timezone": "タイムゾーンが無効です。",
"error.invalid_entry_direction": "ソート順が無効です。",
+ "error.invalid_display_mode": "Webアプリの表示モードが無効です。",
"form.feed.label.title": "タイトル",
"form.feed.label.site_url": "サイト URL",
"form.feed.label.feed_url": "フィード URL",
@@ -280,8 +281,13 @@
"form.prefs.label.theme": "テーマ",
"form.prefs.label.entry_sorting": "記事の並べ替え",
"form.prefs.label.entries_per_page": "ページあたりのエントリ",
+ "form.prefs.label.display_mode": "Webアプリの表示モード (再インストールが必要)",
"form.prefs.select.older_first": "古い記事を最初に",
"form.prefs.select.recent_first": "新しい記事を最初に",
+ "form.prefs.select.fullscreen": "全画面表示",
+ "form.prefs.select.standalone": "スタンドアロン",
+ "form.prefs.select.minimal_ui": "最小限",
+ "form.prefs.select.browser": "ブラウザ",
"form.prefs.label.keyboard_shortcuts": "キーボード・ショートカットを有効にする",
"form.prefs.label.entry_swipe": "モバイルのエントリでスワイプジェスチャーを有効にする",
"form.prefs.label.show_reading_time": "記事の推定読書時間を表示する",
diff --git a/locale/translations/nl_NL.json b/locale/translations/nl_NL.json
index fdc86657..aafb6955 100644
--- a/locale/translations/nl_NL.json
+++ b/locale/translations/nl_NL.json
@@ -254,6 +254,7 @@
"error.invalid_language": "Ongeldige taal.",
"error.invalid_timezone": "Ongeldige tijdzone.",
"error.invalid_entry_direction": "Ongeldige sorteervolgorde.",
+ "error.invalid_display_mode": "Ongeldige weergavemodus voor webapp.",
"form.feed.label.title": "Naam",
"form.feed.label.site_url": "Website URL",
"form.feed.label.feed_url": "Feed URL",
@@ -280,8 +281,13 @@
"form.prefs.label.theme": "Skin",
"form.prefs.label.entry_sorting": "Volgorde van items",
"form.prefs.label.entries_per_page": "Inzendingen per pagina",
+ "form.prefs.label.display_mode": "Weergavemodus voor webapp (moet opnieuw worden geïnstalleerd)",
"form.prefs.select.older_first": "Oudere items eerst",
"form.prefs.select.recent_first": "Recente items eerst",
+ "form.prefs.select.fullscreen": "Volledig scherm",
+ "form.prefs.select.standalone": "Standalone",
+ "form.prefs.select.minimal_ui": "Minimaal",
+ "form.prefs.select.browser": "Browser",
"form.prefs.label.keyboard_shortcuts": "Schakel sneltoetsen in",
"form.prefs.label.entry_swipe": "Schakel veegbewegingen in voor items op mobiel",
"form.prefs.label.show_reading_time": "Toon geschatte leestijd voor artikelen",
diff --git a/locale/translations/pl_PL.json b/locale/translations/pl_PL.json
index 71f00fbf..fd3f1b90 100644
--- a/locale/translations/pl_PL.json
+++ b/locale/translations/pl_PL.json
@@ -256,6 +256,7 @@
"error.invalid_language": "Nieprawidłowy język.",
"error.invalid_timezone": "Nieprawidłowa strefa czasowa.",
"error.invalid_entry_direction": "Nieprawidłowa kolejność sortowania.",
+ "error.invalid_display_mode": "Nieprawidłowy tryb wyświetlania aplikacji internetowej.",
"form.feed.label.title": "Tytuł",
"form.feed.label.site_url": "URL strony",
"form.feed.label.feed_url": "URL kanału",
@@ -282,11 +283,16 @@
"form.prefs.label.theme": "Wygląd",
"form.prefs.label.entry_sorting": "Sortowanie artykułów",
"form.prefs.label.entries_per_page": "Wpisy na stronie",
+ "form.prefs.label.display_mode": "Tryb wyświetlania aplikacji internetowej (wymaga ponownej instalacji)",
"form.prefs.select.older_first": "Najstarsze wpisy jako pierwsze",
"form.prefs.label.keyboard_shortcuts": "Włącz skróty klawiaturowe",
"form.prefs.label.entry_swipe": "Włącz gest przesuwania na wpisach na telefonie komórkowym",
"form.prefs.label.show_reading_time": "Pokaż szacowany czas czytania artykułów",
"form.prefs.select.recent_first": "Najnowsze wpisy jako pierwsze",
+ "form.prefs.select.fullscreen": "Pełny ekran",
+ "form.prefs.select.standalone": "Samodzielny",
+ "form.prefs.select.minimal_ui": "Minimalny",
+ "form.prefs.select.browser": "Przeglądarka",
"form.prefs.label.custom_css": "Niestandardowy CSS",
"form.import.label.file": "Plik OPML",
"form.import.label.url": "URL",
diff --git a/locale/translations/pt_BR.json b/locale/translations/pt_BR.json
index 35bda31b..360f1f3c 100644
--- a/locale/translations/pt_BR.json
+++ b/locale/translations/pt_BR.json
@@ -254,6 +254,7 @@
"error.invalid_language": "Idioma inválido.",
"error.invalid_timezone": "Fuso horário inválido.",
"error.invalid_entry_direction": "Direção de entrada inválida.",
+ "error.invalid_display_mode": "Modo de exibição de aplicativo inválido da web.",
"form.feed.label.title": "Título",
"form.feed.label.site_url": "URL do site",
"form.feed.label.feed_url": "URL da fonte",
@@ -280,8 +281,13 @@
"form.prefs.label.theme": "Tema",
"form.prefs.label.entry_sorting": "Ordenação dos itens",
"form.prefs.label.entries_per_page": "Itens por página",
+ "form.prefs.label.display_mode": "Modo de exibição do aplicativo Web (precisa ser reinstalado)",
"form.prefs.select.older_first": "Itens mais velhos primeiro",
"form.prefs.select.recent_first": "Itens mais recentes",
+ "form.prefs.select.fullscreen": "Tela completa",
+ "form.prefs.select.standalone": "Autônomo",
+ "form.prefs.select.minimal_ui": "Mínimo",
+ "form.prefs.select.browser": "Navegador",
"form.prefs.label.keyboard_shortcuts": "Habilitar atalhos do teclado",
"form.prefs.label.entry_swipe": "Ativar gesto de deslizar nas entradas no celular",
"form.prefs.label.show_reading_time": "Mostrar tempo estimado de leitura de artigos",
diff --git a/locale/translations/ru_RU.json b/locale/translations/ru_RU.json
index 770f3bee..0a5a3822 100644
--- a/locale/translations/ru_RU.json
+++ b/locale/translations/ru_RU.json
@@ -256,6 +256,7 @@
"error.invalid_language": "Неверный язык.",
"error.invalid_timezone": "Неверный часовой пояс.",
"error.invalid_entry_direction": "Неверное направление входа.",
+ "error.invalid_display_mode": "Недопустимый режим отображения веб-приложения.",
"form.feed.label.title": "Название",
"form.feed.label.site_url": "URL сайта",
"form.feed.label.feed_url": "URL подписки",
@@ -282,8 +283,13 @@
"form.prefs.label.theme": "Тема",
"form.prefs.label.entry_sorting": "Сортировка записей",
"form.prefs.label.entries_per_page": "Записи на странице",
+ "form.prefs.label.display_mode": "Режим отображения веб-приложения (требуется переустановка)",
"form.prefs.select.older_first": "Сначала старые записи",
"form.prefs.select.recent_first": "Сначала последние записи",
+ "form.prefs.select.fullscreen": "Полноэкранный",
+ "form.prefs.select.standalone": "Автономный",
+ "form.prefs.select.minimal_ui": "Минимальный",
+ "form.prefs.select.browser": "Браузер",
"form.prefs.label.keyboard_shortcuts": "Включить сочетания клавиш",
"form.prefs.label.entry_swipe": "Включить жест смахивания для записей на мобильном устройстве",
"form.prefs.label.show_reading_time": "Показать примерное время чтения статей",
diff --git a/locale/translations/zh_CN.json b/locale/translations/zh_CN.json
index 29ee1e51..eeb6f312 100644
--- a/locale/translations/zh_CN.json
+++ b/locale/translations/zh_CN.json
@@ -252,6 +252,7 @@
"error.invalid_language": "语言无效。",
"error.invalid_timezone": "无效的时区。",
"error.invalid_entry_direction": "无效的输入方向。",
+ "error.invalid_display_mode": "无效的Web应用显示模式。",
"form.feed.label.title": "标题",
"form.feed.label.site_url": "站点 URL",
"form.feed.label.feed_url": "源 URL",
@@ -278,8 +279,13 @@
"form.prefs.label.theme": "主题",
"form.prefs.label.entry_sorting": "内容排序",
"form.prefs.label.entries_per_page": "每页条目",
+ "form.prefs.label.display_mode": "Web应用程序显示模式 (需要重新安装)",
"form.prefs.select.older_first": "旧->新",
"form.prefs.select.recent_first": "新->旧",
+ "form.prefs.select.fullscreen": "全屏",
+ "form.prefs.select.standalone": "单机版",
+ "form.prefs.select.minimal_ui": "最小的",
+ "form.prefs.select.browser": "浏览器",
"form.prefs.label.keyboard_shortcuts": "启用键盘快捷键",
"form.prefs.label.entry_swipe": "在移动设备上的条目上启用滑动手势",
"form.prefs.label.show_reading_time": "显示文章的预计阅读时间",
diff --git a/model/user.go b/model/user.go
index 5453a41a..347104b7 100644
--- a/model/user.go
+++ b/model/user.go
@@ -28,6 +28,7 @@ type User struct {
ShowReadingTime bool `json:"show_reading_time"`
EntrySwipe bool `json:"entry_swipe"`
LastLoginAt *time.Time `json:"last_login_at"`
+ DisplayMode string `json:"display_mode"`
}
// UserCreationRequest represents the request to create a user.
@@ -55,6 +56,7 @@ type UserModificationRequest struct {
KeyboardShortcuts *bool `json:"keyboard_shortcuts"`
ShowReadingTime *bool `json:"show_reading_time"`
EntrySwipe *bool `json:"entry_swipe"`
+ DisplayMode *string `json:"display_mode"`
}
// Patch updates the User object with the modification request.
@@ -114,6 +116,10 @@ func (u *UserModificationRequest) Patch(user *User) {
if u.EntrySwipe != nil {
user.EntrySwipe = *u.EntrySwipe
}
+
+ if u.DisplayMode != nil {
+ user.DisplayMode = *u.DisplayMode
+ }
}
// UseTimezone converts last login date to the given timezone.
diff --git a/storage/user.go b/storage/user.go
index 2d539e1b..e86f4bb2 100644
--- a/storage/user.go
+++ b/storage/user.go
@@ -83,7 +83,8 @@ func (s *Storage) CreateUser(userCreationRequest *model.UserCreationRequest) (*m
entry_swipe,
stylesheet,
google_id,
- openid_connect_id
+ openid_connect_id,
+ display_mode
`
tx, err := s.db.Begin()
@@ -114,6 +115,7 @@ func (s *Storage) CreateUser(userCreationRequest *model.UserCreationRequest) (*m
&user.Stylesheet,
&user.GoogleID,
&user.OpenIDConnectID,
+ &user.DisplayMode,
)
if err != nil {
tx.Rollback()
@@ -162,9 +164,10 @@ func (s *Storage) UpdateUser(user *model.User) error {
entry_swipe=$11,
stylesheet=$12,
google_id=$13,
- openid_connect_id=$14
+ openid_connect_id=$14,
+ display_mode=$15
WHERE
- id=$15
+ id=$16
`
_, err = s.db.Exec(
@@ -183,6 +186,7 @@ func (s *Storage) UpdateUser(user *model.User) error {
user.Stylesheet,
user.GoogleID,
user.OpenIDConnectID,
+ user.DisplayMode,
user.ID,
)
if err != nil {
@@ -203,9 +207,10 @@ func (s *Storage) UpdateUser(user *model.User) error {
entry_swipe=$10,
stylesheet=$11,
google_id=$12,
- openid_connect_id=$13
+ openid_connect_id=$13,
+ display_mode=$14
WHERE
- id=$14
+ id=$15
`
_, err := s.db.Exec(
@@ -223,6 +228,7 @@ func (s *Storage) UpdateUser(user *model.User) error {
user.Stylesheet,
user.GoogleID,
user.OpenIDConnectID,
+ user.DisplayMode,
user.ID,
)
@@ -262,7 +268,8 @@ func (s *Storage) UserByID(userID int64) (*model.User, error) {
last_login_at,
stylesheet,
google_id,
- openid_connect_id
+ openid_connect_id,
+ display_mode
FROM
users
WHERE
@@ -289,7 +296,8 @@ func (s *Storage) UserByUsername(username string) (*model.User, error) {
last_login_at,
stylesheet,
google_id,
- openid_connect_id
+ openid_connect_id,
+ display_mode
FROM
users
WHERE
@@ -316,7 +324,8 @@ func (s *Storage) UserByField(field, value string) (*model.User, error) {
last_login_at,
stylesheet,
google_id,
- openid_connect_id
+ openid_connect_id,
+ display_mode
FROM
users
WHERE
@@ -350,7 +359,8 @@ func (s *Storage) UserByAPIKey(token string) (*model.User, error) {
u.last_login_at,
u.stylesheet,
u.google_id,
- u.openid_connect_id
+ u.openid_connect_id,
+ u.display_mode
FROM
users u
LEFT JOIN
@@ -379,6 +389,7 @@ func (s *Storage) fetchUser(query string, args ...interface{}) (*model.User, err
&user.Stylesheet,
&user.GoogleID,
&user.OpenIDConnectID,
+ &user.DisplayMode,
)
if err == sql.ErrNoRows {
@@ -442,7 +453,8 @@ func (s *Storage) Users() (model.Users, error) {
last_login_at,
stylesheet,
google_id,
- openid_connect_id
+ openid_connect_id,
+ display_mode
FROM
users
ORDER BY username ASC
@@ -472,6 +484,7 @@ func (s *Storage) Users() (model.Users, error) {
&user.Stylesheet,
&user.GoogleID,
&user.OpenIDConnectID,
+ &user.DisplayMode,
)
if err != nil {
diff --git a/template/templates/views/settings.html b/template/templates/views/settings.html
index 3caf517b..f8725f09 100644
--- a/template/templates/views/settings.html
+++ b/template/templates/views/settings.html
@@ -43,6 +43,14 @@
{{ end }}
+
+
+