From 7da72cf89a4000c69b127161a0ba8aea1369dab8 Mon Sep 17 00:00:00 2001
From: Philipp Rempe <philipp.rempe@gmx.net>
Date: Sun, 27 Sep 2020 16:41:04 +0200
Subject: [PATCH] Add setting for swipe gesture on entries on mobile

---
 database/migration.go               |  2 +-
 database/sql.go                     |  3 +++
 database/sql/schema_version_38.sql  |  1 +
 locale/translations.go              | 33 ++++++++++++++++--------
 locale/translations/de_DE.json      |  1 +
 locale/translations/en_US.json      |  1 +
 locale/translations/es_ES.json      |  1 +
 locale/translations/fr_FR.json      |  1 +
 locale/translations/it_IT.json      |  1 +
 locale/translations/ja_JP.json      |  1 +
 locale/translations/nl_NL.json      |  1 +
 locale/translations/pl_PL.json      |  1 +
 locale/translations/pt_BR.json      |  1 +
 locale/translations/ru_RU.json      |  1 +
 locale/translations/zh_CN.json      |  1 +
 model/user.go                       |  3 ++-
 storage/user.go                     | 22 ++++++++++++----
 template/html/bookmark_entries.html |  2 +-
 template/html/category_entries.html |  2 +-
 template/html/feed_entries.html     |  4 +--
 template/html/history_entries.html  |  2 +-
 template/html/search_entries.html   |  2 +-
 template/html/settings.html         |  4 ++-
 template/html/shared_entries.html   |  2 +-
 template/html/unread_entries.html   |  4 +--
 template/views.go                   | 39 ++++++++++++++++-------------
 ui/form/settings.go                 |  3 +++
 ui/settings_show.go                 |  1 +
 28 files changed, 94 insertions(+), 46 deletions(-)
 create mode 100644 database/sql/schema_version_38.sql

diff --git a/database/migration.go b/database/migration.go
index 9a800816..9838442e 100644
--- a/database/migration.go
+++ b/database/migration.go
@@ -12,7 +12,7 @@ import (
 	"miniflux.app/logger"
 )
 
-const schemaVersion = 37
+const schemaVersion = 38
 
 // Migrate executes database migrations.
 func Migrate(db *sql.DB) {
diff --git a/database/sql.go b/database/sql.go
index 5b2ed4a8..50fae493 100644
--- a/database/sql.go
+++ b/database/sql.go
@@ -191,6 +191,8 @@ create index entries_user_feed_idx on entries (user_id, feed_id);
 `,
 	"schema_version_36": `CREATE INDEX entries_feed_id_status_hash_idx ON entries USING btree (feed_id, status, hash);`,
 	"schema_version_37": `CREATE INDEX entries_user_id_status_starred_idx ON entries (user_id, status, starred);`,
+	"schema_version_38": `alter table users add column entry_swipe boolean default 't';
+`,
 	"schema_version_4": `create type entry_sorting_direction as enum('asc', 'desc');
 alter table users add column entry_direction entry_sorting_direction default 'asc';
 `,
@@ -251,6 +253,7 @@ var SqlMapChecksums = map[string]string{
 	"schema_version_35": "162a55df78eed4b9c9c141878132d5f1d97944b96f35a79e38f55716cdd6b3d2",
 	"schema_version_36": "8164be7818268ad3d4bdcad03a7868b58e32b27cde9b4f056cd82f7b182a0722",
 	"schema_version_37": "fc9eb1b452341664ddf24c1a9cf01502ac2578136e54a4853081652959285cb9",
+	"schema_version_38": "e91d2f4075ceb7b8a16a25f350f36dee12cfd1ad86b8b6414c4cf2e9a003358c",
 	"schema_version_4":  "216ea3a7d3e1704e40c797b5dc47456517c27dbb6ca98bf88812f4f63d74b5d9",
 	"schema_version_5":  "46397e2f5f2c82116786127e9f6a403e975b14d2ca7b652a48cd1ba843e6a27c",
 	"schema_version_6":  "9d05b4fb223f0e60efc716add5048b0ca9c37511cf2041721e20505d6d798ce4",
diff --git a/database/sql/schema_version_38.sql b/database/sql/schema_version_38.sql
new file mode 100644
index 00000000..2527ad60
--- /dev/null
+++ b/database/sql/schema_version_38.sql
@@ -0,0 +1 @@
+alter table users add column entry_swipe boolean default 't';
diff --git a/locale/translations.go b/locale/translations.go
index 679af9d2..f9bde112 100644
--- a/locale/translations.go
+++ b/locale/translations.go
@@ -269,6 +269,7 @@ var translations = map[string]string{
     "form.prefs.select.older_first": "Älteste Artikel zuerst",
     "form.prefs.select.recent_first": "Neueste Artikel zuerst",
     "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",
     "form.prefs.label.custom_css": "Benutzerdefiniertes CSS",
     "form.import.label.file": "OPML Datei",
@@ -615,6 +616,7 @@ var translations = map[string]string{
     "form.prefs.select.older_first": "Older entries first",
     "form.prefs.select.recent_first": "Recent entries first",
     "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",
     "form.prefs.label.custom_css": "Custom CSS",
     "form.import.label.file": "OPML file",
@@ -941,6 +943,7 @@ var translations = map[string]string{
     "form.prefs.select.older_first": "Entradas más viejas primero",
     "form.prefs.select.recent_first": "Entradas recientes primero",
     "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",
     "form.prefs.label.custom_css": "CSS personalizado",
     "form.import.label.file": "Archivo OPML",
@@ -1267,6 +1270,7 @@ var translations = map[string]string{
     "form.prefs.select.older_first": "Ancien éléments en premier",
     "form.prefs.select.recent_first": "Éléments récents en premier",
     "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",
     "form.prefs.label.custom_css": "CSS personnalisé",
     "form.import.label.file": "Fichier OPML",
@@ -1613,6 +1617,7 @@ var translations = map[string]string{
     "form.prefs.select.older_first": "Prima i più vecchi",
     "form.prefs.select.recent_first": "Prima i più recenti",
     "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",
     "form.prefs.label.custom_css": "CSS personalizzati",
     "form.import.label.file": "File OPML",
@@ -1939,6 +1944,7 @@ var translations = map[string]string{
     "form.prefs.select.older_first": "古い記事を最初に",
     "form.prefs.select.recent_first": "新しい記事を最初に",
     "form.prefs.label.keyboard_shortcuts": "キーボード・ショートカットを有効にする",
+    "form.prefs.label.entry_swipe": "モバイルのエントリでスワイプジェスチャーを有効にする",
     "form.prefs.label.show_reading_time": "記事の推定読書時間を表示する",
     "form.prefs.label.custom_css": "カスタムCSS",
     "form.import.label.file": "OPML ファイル",
@@ -2265,6 +2271,7 @@ var translations = map[string]string{
     "form.prefs.select.older_first": "Oudere items eerst",
     "form.prefs.select.recent_first": "Recente items eerst",
     "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",
     "form.prefs.label.custom_css": "Aangepaste CSS",
     "form.import.label.file": "OPML-bestand",
@@ -2610,6 +2617,7 @@ var translations = map[string]string{
     "form.prefs.label.entries_per_page": "Wpisy na stronie",
     "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.label.custom_css": "Niestandardowy CSS",
@@ -2961,6 +2969,7 @@ var translations = map[string]string{
     "form.prefs.select.older_first": "Itens mais velhos primeiro",
     "form.prefs.select.recent_first": "Itens mais recentes",
     "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",
     "form.prefs.label.custom_css": "CSS customizado",
     "form.import.label.file": "Arquivo OPML",
@@ -3289,6 +3298,7 @@ var translations = map[string]string{
     "form.prefs.select.older_first": "Сначала старые записи",
     "form.prefs.select.recent_first": "Сначала последние записи",
     "form.prefs.label.keyboard_shortcuts": "Включить сочетания клавиш",
+    "form.prefs.label.entry_swipe": "Включить жест смахивания для записей на мобильном устройстве",
     "form.prefs.label.show_reading_time": "Показать примерное время чтения статей",
     "form.prefs.label.custom_css": "Пользовательские CSS",
     "form.import.label.file": "OPML файл",
@@ -3619,6 +3629,7 @@ var translations = map[string]string{
     "form.prefs.select.older_first": "æ—§->æ–°",
     "form.prefs.select.recent_first": "æ–°->æ—§",
     "form.prefs.label.keyboard_shortcuts": "启用键盘快捷键",
+    "form.prefs.label.entry_swipe": "在移动设备上的条目上启用滑动手势",
     "form.prefs.label.show_reading_time": "显示文章的预计阅读时间",
     "form.prefs.label.custom_css": "自定义CSS",
     "form.import.label.file": "OPML 文件",
@@ -3695,15 +3706,15 @@ var translations = map[string]string{
 }
 
 var translationsChecksums = map[string]string{
-	"de_DE": "8f96cb46f5a7e8f64ee8f10176dc3a2f3d53953d250317da83a79d0700b47c82",
-	"en_US": "d33324caed406ecf6ce03920b15e235d46b258457a8bd48cd1ade685b9a3ad6b",
-	"es_ES": "2ff9333218dba2b86cb84f377dad66b9dc73848aee6bb09889cbdc10e58ca077",
-	"fr_FR": "07dc2cfdbc14cdf16312423158656f5526d3c3c7be490abf5503109a408e5056",
-	"it_IT": "d4f68a507e1deb9fab3aa38fb78d9e9e4040386d6f36611ec5f105adfb4b0d03",
-	"ja_JP": "5c4c063ebaee14bed941b020e0d19de5ef5e8d3bf11c1967b1f321d57d5af6a9",
-	"nl_NL": "f862027e192be7a09730470acc2639971c4abf01b256d5bb81246960cc54adcf",
-	"pl_PL": "35147e55f1800964d268dc04b9cc25a9c8fa98077f759c5d3a5bd339f0eee53e",
-	"pt_BR": "2461105ebc2a2d57b3a63a29ee21f74e3d1eba54c049abcfd077dd30acc8d0a2",
-	"ru_RU": "402f15d3c68e008a1ffa3dddb4002126a29c1cf93359a64bca944a8da541da72",
-	"zh_CN": "21ca934599220fa3d3ba06b390b619ce9d1565be329b8b5e35d43f7e3ad3a269",
+	"de_DE": "dbd9141c3b2f436d16ff660735904897c235406094f0e7d70cbceb509c6063b6",
+	"en_US": "61ef12ca29c271905a594ba1fe600871c930e7cfa25f0721bf076cd056cf60d4",
+	"es_ES": "74e1b08adc78c9bd2fe05df69d19232fca86cb5fc94379ee42cef34878e4b8e5",
+	"fr_FR": "3b61ad39a8d5227aac7b49897a6f78828c7e4a2040fe9636af932515c89d9785",
+	"it_IT": "048498833a7c9bb519cde0a61f955e15cbcf117b2006955305fb23cc652ed9f4",
+	"ja_JP": "cd8cac53f606066d60b3bc5586c0a484ee97466e3cca4816228ce74faf5916fe",
+	"nl_NL": "b76c996efdbc814688ad3db50a906397d45717b19f49a4702b4e65f50df23600",
+	"pl_PL": "a27aecbb6cd96d0714b2c934f5d96e01ab229e031e9e5ea0de96cec8c5cae0bf",
+	"pt_BR": "8e3cdaa0e39485a6eb5cf3942ec23b8f6a16e8efc551f52a35f74e444ebd70e3",
+	"ru_RU": "92d224b6563777efe64e1972884547f27e7374074b9f4f1fc2eeb331f6c5597c",
+	"zh_CN": "de59177700df00c27352d785c62f66ee49955b8b294f0eaf944ad7c4025838c7",
 }
diff --git a/locale/translations/de_DE.json b/locale/translations/de_DE.json
index b2d9b5ad..0f41b21b 100644
--- a/locale/translations/de_DE.json
+++ b/locale/translations/de_DE.json
@@ -264,6 +264,7 @@
     "form.prefs.select.older_first": "Älteste Artikel zuerst",
     "form.prefs.select.recent_first": "Neueste Artikel zuerst",
     "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",
     "form.prefs.label.custom_css": "Benutzerdefiniertes CSS",
     "form.import.label.file": "OPML Datei",
diff --git a/locale/translations/en_US.json b/locale/translations/en_US.json
index 4805c33b..47a5539e 100644
--- a/locale/translations/en_US.json
+++ b/locale/translations/en_US.json
@@ -264,6 +264,7 @@
     "form.prefs.select.older_first": "Older entries first",
     "form.prefs.select.recent_first": "Recent entries first",
     "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",
     "form.prefs.label.custom_css": "Custom CSS",
     "form.import.label.file": "OPML file",
diff --git a/locale/translations/es_ES.json b/locale/translations/es_ES.json
index 0134800b..d84d4664 100644
--- a/locale/translations/es_ES.json
+++ b/locale/translations/es_ES.json
@@ -264,6 +264,7 @@
     "form.prefs.select.older_first": "Entradas más viejas primero",
     "form.prefs.select.recent_first": "Entradas recientes primero",
     "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",
     "form.prefs.label.custom_css": "CSS personalizado",
     "form.import.label.file": "Archivo OPML",
diff --git a/locale/translations/fr_FR.json b/locale/translations/fr_FR.json
index 543e35c1..90f6c7e0 100644
--- a/locale/translations/fr_FR.json
+++ b/locale/translations/fr_FR.json
@@ -264,6 +264,7 @@
     "form.prefs.select.older_first": "Ancien éléments en premier",
     "form.prefs.select.recent_first": "Éléments récents en premier",
     "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",
     "form.prefs.label.custom_css": "CSS personnalisé",
     "form.import.label.file": "Fichier OPML",
diff --git a/locale/translations/it_IT.json b/locale/translations/it_IT.json
index 3b32e388..a291feeb 100644
--- a/locale/translations/it_IT.json
+++ b/locale/translations/it_IT.json
@@ -264,6 +264,7 @@
     "form.prefs.select.older_first": "Prima i più vecchi",
     "form.prefs.select.recent_first": "Prima i più recenti",
     "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",
     "form.prefs.label.custom_css": "CSS personalizzati",
     "form.import.label.file": "File OPML",
diff --git a/locale/translations/ja_JP.json b/locale/translations/ja_JP.json
index 01833d31..b721e790 100644
--- a/locale/translations/ja_JP.json
+++ b/locale/translations/ja_JP.json
@@ -264,6 +264,7 @@
     "form.prefs.select.older_first": "古い記事を最初に",
     "form.prefs.select.recent_first": "新しい記事を最初に",
     "form.prefs.label.keyboard_shortcuts": "キーボード・ショートカットを有効にする",
+    "form.prefs.label.entry_swipe": "モバイルのエントリでスワイプジェスチャーを有効にする",
     "form.prefs.label.show_reading_time": "記事の推定読書時間を表示する",
     "form.prefs.label.custom_css": "カスタムCSS",
     "form.import.label.file": "OPML ファイル",
diff --git a/locale/translations/nl_NL.json b/locale/translations/nl_NL.json
index cf95433b..e977ad57 100644
--- a/locale/translations/nl_NL.json
+++ b/locale/translations/nl_NL.json
@@ -264,6 +264,7 @@
     "form.prefs.select.older_first": "Oudere items eerst",
     "form.prefs.select.recent_first": "Recente items eerst",
     "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",
     "form.prefs.label.custom_css": "Aangepaste CSS",
     "form.import.label.file": "OPML-bestand",
diff --git a/locale/translations/pl_PL.json b/locale/translations/pl_PL.json
index 4b4e0081..af52a4d0 100644
--- a/locale/translations/pl_PL.json
+++ b/locale/translations/pl_PL.json
@@ -265,6 +265,7 @@
     "form.prefs.label.entries_per_page": "Wpisy na stronie",
     "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.label.custom_css": "Niestandardowy CSS",
diff --git a/locale/translations/pt_BR.json b/locale/translations/pt_BR.json
index 4d41d490..53cf38dc 100644
--- a/locale/translations/pt_BR.json
+++ b/locale/translations/pt_BR.json
@@ -264,6 +264,7 @@
     "form.prefs.select.older_first": "Itens mais velhos primeiro",
     "form.prefs.select.recent_first": "Itens mais recentes",
     "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",
     "form.prefs.label.custom_css": "CSS customizado",
     "form.import.label.file": "Arquivo OPML",
diff --git a/locale/translations/ru_RU.json b/locale/translations/ru_RU.json
index 20522a9f..df5d1b9b 100644
--- a/locale/translations/ru_RU.json
+++ b/locale/translations/ru_RU.json
@@ -266,6 +266,7 @@
     "form.prefs.select.older_first": "Сначала старые записи",
     "form.prefs.select.recent_first": "Сначала последние записи",
     "form.prefs.label.keyboard_shortcuts": "Включить сочетания клавиш",
+    "form.prefs.label.entry_swipe": "Включить жест смахивания для записей на мобильном устройстве",
     "form.prefs.label.show_reading_time": "Показать примерное время чтения статей",
     "form.prefs.label.custom_css": "Пользовательские CSS",
     "form.import.label.file": "OPML файл",
diff --git a/locale/translations/zh_CN.json b/locale/translations/zh_CN.json
index 1d8a4b8a..7eb8f13c 100644
--- a/locale/translations/zh_CN.json
+++ b/locale/translations/zh_CN.json
@@ -262,6 +262,7 @@
     "form.prefs.select.older_first": "æ—§->æ–°",
     "form.prefs.select.recent_first": "æ–°->æ—§",
     "form.prefs.label.keyboard_shortcuts": "启用键盘快捷键",
+    "form.prefs.label.entry_swipe": "在移动设备上的条目上启用滑动手势",
     "form.prefs.label.show_reading_time": "显示文章的预计阅读时间",
     "form.prefs.label.custom_css": "自定义CSS",
     "form.import.label.file": "OPML 文件",
diff --git a/model/user.go b/model/user.go
index 52564c98..a2c49abb 100644
--- a/model/user.go
+++ b/model/user.go
@@ -23,9 +23,10 @@ type User struct {
 	EntryDirection    string            `json:"entry_sorting_direction"`
 	EntriesPerPage    int               `json:"entries_per_page"`
 	KeyboardShortcuts bool              `json:"keyboard_shortcuts"`
-	ShowReadingTime	  bool              `json:"show_reading_time"`
+	ShowReadingTime   bool              `json:"show_reading_time"`
 	LastLoginAt       *time.Time        `json:"last_login_at,omitempty"`
 	Extra             map[string]string `json:"extra"`
+	EntrySwipe        bool              `json:"entry_swipe"`
 }
 
 // NewUser returns a new User.
diff --git a/storage/user.go b/storage/user.go
index 46ff9386..bb164ab4 100644
--- a/storage/user.go
+++ b/storage/user.go
@@ -76,7 +76,7 @@ func (s *Storage) CreateUser(user *model.User) (err error) {
 		VALUES
 			(LOWER($1), $2, $3, $4)
 		RETURNING
-			id, username, is_admin, language, theme, timezone, entry_direction, entries_per_page, keyboard_shortcuts, show_reading_time
+			id, username, is_admin, language, theme, timezone, entry_direction, entries_per_page, keyboard_shortcuts, show_reading_time, entry_swipe
 	`
 
 	err = s.db.QueryRow(query, user.Username, password, user.IsAdmin, extra).Scan(
@@ -90,6 +90,7 @@ func (s *Storage) CreateUser(user *model.User) (err error) {
 		&user.EntriesPerPage,
 		&user.KeyboardShortcuts,
 		&user.ShowReadingTime,
+		&user.EntrySwipe,
 	)
 	if err != nil {
 		return fmt.Errorf(`store: unable to create user: %v`, err)
@@ -139,9 +140,10 @@ func (s *Storage) UpdateUser(user *model.User) error {
 				entry_direction=$7,
 				entries_per_page=$8,
 				keyboard_shortcuts=$9,
-				show_reading_time=$10
+				show_reading_time=$10,
+				entry_swipe=$11
 			WHERE
-				id=$11
+				id=$12
 		`
 
 		_, err = s.db.Exec(
@@ -156,6 +158,7 @@ func (s *Storage) UpdateUser(user *model.User) error {
 			user.EntriesPerPage,
 			user.KeyboardShortcuts,
 			user.ShowReadingTime,
+			user.EntrySwipe,
 			user.ID,
 		)
 		if err != nil {
@@ -172,9 +175,10 @@ func (s *Storage) UpdateUser(user *model.User) error {
 				entry_direction=$6,
 				entries_per_page=$7,
 				keyboard_shortcuts=$8,
-				show_reading_time=$9
+				show_reading_time=$9,
+				entry_swipe=$10
 			WHERE
-				id=$10
+				id=$11
 		`
 
 		_, err := s.db.Exec(
@@ -188,6 +192,7 @@ func (s *Storage) UpdateUser(user *model.User) error {
 			user.EntriesPerPage,
 			user.KeyboardShortcuts,
 			user.ShowReadingTime,
+			user.EntrySwipe,
 			user.ID,
 		)
 
@@ -227,6 +232,7 @@ func (s *Storage) UserByID(userID int64) (*model.User, error) {
 			entries_per_page,
 			keyboard_shortcuts,
 			show_reading_time,
+			entry_swipe,
 			last_login_at,
 			extra
 		FROM
@@ -251,6 +257,7 @@ func (s *Storage) UserByUsername(username string) (*model.User, error) {
 			entries_per_page,
 			keyboard_shortcuts,
 			show_reading_time,
+			entry_swipe,
 			last_login_at,
 			extra
 		FROM
@@ -275,6 +282,7 @@ func (s *Storage) UserByExtraField(field, value string) (*model.User, error) {
 			entries_per_page,
 			keyboard_shortcuts,
 			show_reading_time,
+			entry_swipe,
 			last_login_at,
 			extra
 		FROM
@@ -299,6 +307,7 @@ func (s *Storage) UserByAPIKey(token string) (*model.User, error) {
 			u.entries_per_page,
 			u.keyboard_shortcuts,
 			u.show_reading_time,
+			u.entry_swipe,
 			u.last_login_at,
 			u.extra
 		FROM
@@ -326,6 +335,7 @@ func (s *Storage) fetchUser(query string, args ...interface{}) (*model.User, err
 		&user.EntriesPerPage,
 		&user.KeyboardShortcuts,
 		&user.ShowReadingTime,
+		&user.EntrySwipe,
 		&user.LastLoginAt,
 		&extra,
 	)
@@ -392,6 +402,7 @@ func (s *Storage) Users() (model.Users, error) {
 			entries_per_page,
 			keyboard_shortcuts,
 			show_reading_time,
+			entry_swipe,
 			last_login_at,
 			extra
 		FROM
@@ -419,6 +430,7 @@ func (s *Storage) Users() (model.Users, error) {
 			&user.EntriesPerPage,
 			&user.KeyboardShortcuts,
 			&user.ShowReadingTime,
+			&user.EntrySwipe,
 			&user.LastLoginAt,
 			&extra,
 		)
diff --git a/template/html/bookmark_entries.html b/template/html/bookmark_entries.html
index 4f365844..510d50da 100644
--- a/template/html/bookmark_entries.html
+++ b/template/html/bookmark_entries.html
@@ -10,7 +10,7 @@
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
diff --git a/template/html/category_entries.html b/template/html/category_entries.html
index 14e1feb2..f4d76ae8 100644
--- a/template/html/category_entries.html
+++ b/template/html/category_entries.html
@@ -35,7 +35,7 @@
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
diff --git a/template/html/feed_entries.html b/template/html/feed_entries.html
index 2a5744f9..67f38fb0 100644
--- a/template/html/feed_entries.html
+++ b/template/html/feed_entries.html
@@ -3,7 +3,7 @@
 {{ define "content"}}
 <section class="page-header">
     <h1 dir="auto">
-        <a href="{{ .feed.SiteURL | safeURL  }}" title="{{ .feed.SiteURL }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer" data-original-link="true">{{ .feed.Title }}</a> 
+        <a href="{{ .feed.SiteURL | safeURL  }}" title="{{ .feed.SiteURL }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer" data-original-link="true">{{ .feed.Title }}</a>
         ({{ .total }})
     </h1>
     <ul>
@@ -63,7 +63,7 @@
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
diff --git a/template/html/history_entries.html b/template/html/history_entries.html
index 36826f27..aa5a1fa2 100644
--- a/template/html/history_entries.html
+++ b/template/html/history_entries.html
@@ -32,7 +32,7 @@
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
diff --git a/template/html/search_entries.html b/template/html/search_entries.html
index eb09e06d..5b233802 100644
--- a/template/html/search_entries.html
+++ b/template/html/search_entries.html
@@ -10,7 +10,7 @@
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
diff --git a/template/html/settings.html b/template/html/settings.html
index 497dbd94..315ebb0e 100644
--- a/template/html/settings.html
+++ b/template/html/settings.html
@@ -53,9 +53,11 @@
     <input type="number" name="entries_per_page" id="form-entries-per-page" value="{{ .form.EntriesPerPage }}" min="1">
 
     <label><input type="checkbox" name="keyboard_shortcuts" value="1" {{ if .form.KeyboardShortcuts }}checked{{ end }}> {{ t "form.prefs.label.keyboard_shortcuts" }}</label>
-    
+
     <label><input type="checkbox" name="show_reading_time" value="1" {{ if .form.ShowReadingTime }}checked{{ end }}> {{ t "form.prefs.label.show_reading_time" }}</label>
 
+    <label><input type="checkbox" name="entry_swipe" value="1" {{ if .form.EntrySwipe }}checked{{ end }}> {{ t "form.prefs.label.entry_swipe" }}</label>
+
     <label>{{t "form.prefs.label.custom_css" }}</label><textarea name="custom_css" cols="40" rows="5">{{ .form.CustomCSS }}</textarea>
     <div class="buttons">
         <button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
diff --git a/template/html/shared_entries.html b/template/html/shared_entries.html
index 0abb954d..1423723b 100644
--- a/template/html/shared_entries.html
+++ b/template/html/shared_entries.html
@@ -26,7 +26,7 @@
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
diff --git a/template/html/unread_entries.html b/template/html/unread_entries.html
index 5eec1d43..4051830f 100644
--- a/template/html/unread_entries.html
+++ b/template/html/unread_entries.html
@@ -33,7 +33,7 @@
 {{ else }}
     <div class="items hide-read-items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
@@ -64,4 +64,4 @@
     {{ template "pagination" .pagination }}
 {{ end }}
 
-{{ end }}
\ No newline at end of file
+{{ end }}
diff --git a/template/views.go b/template/views.go
index 019ad14d..ba6a5c81 100644
--- a/template/views.go
+++ b/template/views.go
@@ -182,7 +182,7 @@ var templateViewsMap = map[string]string{
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
@@ -298,7 +298,7 @@ var templateViewsMap = map[string]string{
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
@@ -841,7 +841,7 @@ var templateViewsMap = map[string]string{
 {{ define "content"}}
 <section class="page-header">
     <h1 dir="auto">
-        <a href="{{ .feed.SiteURL | safeURL  }}" title="{{ .feed.SiteURL }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer" data-original-link="true">{{ .feed.Title }}</a> 
+        <a href="{{ .feed.SiteURL | safeURL  }}" title="{{ .feed.SiteURL }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer" data-original-link="true">{{ .feed.Title }}</a>
         ({{ .total }})
     </h1>
     <ul>
@@ -901,7 +901,7 @@ var templateViewsMap = map[string]string{
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
@@ -985,7 +985,7 @@ var templateViewsMap = map[string]string{
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
@@ -1241,7 +1241,7 @@ var templateViewsMap = map[string]string{
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
@@ -1354,9 +1354,11 @@ var templateViewsMap = map[string]string{
     <input type="number" name="entries_per_page" id="form-entries-per-page" value="{{ .form.EntriesPerPage }}" min="1">
 
     <label><input type="checkbox" name="keyboard_shortcuts" value="1" {{ if .form.KeyboardShortcuts }}checked{{ end }}> {{ t "form.prefs.label.keyboard_shortcuts" }}</label>
-    
+
     <label><input type="checkbox" name="show_reading_time" value="1" {{ if .form.ShowReadingTime }}checked{{ end }}> {{ t "form.prefs.label.show_reading_time" }}</label>
 
+    <label><input type="checkbox" name="entry_swipe" value="1" {{ if .form.EntrySwipe }}checked{{ end }}> {{ t "form.prefs.label.entry_swipe" }}</label>
+
     <label>{{t "form.prefs.label.custom_css" }}</label><textarea name="custom_css" cols="40" rows="5">{{ .form.CustomCSS }}</textarea>
     <div class="buttons">
         <button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
@@ -1411,7 +1413,7 @@ var templateViewsMap = map[string]string{
 {{ else }}
     <div class="items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
@@ -1490,7 +1492,7 @@ var templateViewsMap = map[string]string{
 {{ else }}
     <div class="items hide-read-items">
         {{ range .entries }}
-        <article class="item touch-item item-status-{{ .Status }}" data-id="{{ .ID }}">
+        <article class="item {{ if $.user.EntrySwipe }}touch-item{{ end }} item-status-{{ .Status }}" data-id="{{ .ID }}">
             <div class="item-header" dir="auto">
                 <span class="item-title">
                     {{ if ne .Feed.Icon.IconID 0 }}
@@ -1521,7 +1523,8 @@ var templateViewsMap = map[string]string{
     {{ template "pagination" .pagination }}
 {{ end }}
 
-{{ end }}`,
+{{ end }}
+`,
 	"users": `{{ define "title"}}{{ t "page.users.title" }}{{ end }}
 
 {{ define "content"}}
@@ -1581,9 +1584,9 @@ var templateViewsMapChecksums = map[string]string{
 	"about":               "4035658497363d7af7f79be83190404eb21ec633fe8ec636bdfc219d9fc78cfc",
 	"add_subscription":    "63961a83964acca354bc30eaae1f5e80f410ae4091af8da317380d4298f79032",
 	"api_keys":            "27d401b31a72881d5232486ba17eb47edaf5246eaedce81de88698c15ebb2284",
-	"bookmark_entries":    "892fe6cbf5a3301416dfb76e62935b495ca194275cfe113105a85b40ce7c200f",
+	"bookmark_entries":    "eacbbdce7fa85ec66c4c12f02879daab562a17ff79f1aac1805617e83e3a3a42",
 	"categories":          "9dfc3cb7bb91c7750753fe962ee4540dd1843e5f75f9e0a575ee964f6f9923e9",
-	"category_entries":    "8fa0e0b8f85e2572c40dee855b6d636207c3561086b234c93100673774c06746",
+	"category_entries":    "ef3005f8f4c96182587acbf31b979cc26b1ac8f755a74cd5a25681260f4b6d63",
 	"category_feeds":      "07154127087f9b127f7290abad6020c35ad9ceb2490b869120b7628bc4413808",
 	"choose_subscription": "22109d760ea8079c491561d0106f773c885efbf66f87d81fcf8700218260d2a0",
 	"create_api_key":      "5f74d4e92a6684927f5305096378c8be278159a5cd88ce652c7be3280a7d1685",
@@ -1593,16 +1596,16 @@ var templateViewsMapChecksums = map[string]string{
 	"edit_feed":           "7e86275f8e9325ddbffe79f6db871e58ad86d08c396e9b2ff8af69a09c4bf63b",
 	"edit_user":           "c692db9de1a084c57b93e95a14b041d39bf489846cbb91fc982a62b72b77062a",
 	"entry":               "c503dcf77de37090b9f05352bb9d99729085eec6e7bc22be94f2b4b244b4e48c",
-	"feed_entries":        "ea5b88e3ad6b166d83b70e021d7b420d025f80decb6e24c79d13f8ce7c910b04",
+	"feed_entries":        "89977ea86b8d43305d587b70e6d9c45c2c88249b3966f2d31051dc7a5f1c48b6",
 	"feeds":               "ec7d3fa96735bd8422ba69ef0927dcccddc1cc51327e0271f0312d3f881c64fd",
-	"history_entries":     "341f0da8b6c27a8377901aa80bb1d5c923672af32f689d36de14deabce5c737f",
+	"history_entries":     "261b47e5f2f699a9cef1b3b690f80d7aabf585d05b77d67645d623f7ff6c0fbb",
 	"import":              "1b59b3bd55c59fcbc6fbb346b414dcdd26d1b4e0c307e437bb58b3f92ef01ad1",
 	"integrations":        "7d0d936a60b50371e9b0ff411ca31a646a5897bc84894febb09cd4b08fc91f2b",
 	"login":               "79ff2ca488c0a19b37c8fa227a21f73e94472eb357a51a077197c852f7713f11",
-	"search_entries":      "c0786ddc6b17e865007b975eefb97417935cbc601f5917cca1ee0d3f584594bc",
+	"search_entries":      "6a3e5876cb7541a2f08f56e30ab46a2d7d64894ec5e170f627b2dd674d8aeefe",
 	"sessions":            "5d5c677bddbd027e0b0c9f7a0dd95b66d9d95b4e130959f31fb955b926c2201c",
-	"settings":            "a4d3df17e6abc75881ec1ca5f92a9c2cfe24e3e08e5d844df848b4d6aaa1bbc0",
-	"shared_entries":      "1494d81e46f6af534a73cf6a91f8dfda1932a477bb3a70143513896ac0f0220b",
-	"unread_entries":      "fbb368f70ee78bd605ac4c13707bd79ea50c6980248da0ac3830253b36ea83ad",
+	"settings":            "6f77f9431beb9aa2e28840a60a6463d1a9eb0e92c1929b204584c85c71d0c7a3",
+	"shared_entries":      "f87a42bf44dc3606c5a44b185263c1b9a612a8ae194f75061253d4dde7b095a2",
+	"unread_entries":      "21c584da7ca8192655c62f16a7ac92dbbfdf1307588ffe51eb4a8bbf3f9f7526",
 	"users":               "d7ff52efc582bbad10504f4a04fa3adcc12d15890e45dff51cac281e0c446e45",
 }
diff --git a/ui/form/settings.go b/ui/form/settings.go
index af850399..b61d1d5a 100644
--- a/ui/form/settings.go
+++ b/ui/form/settings.go
@@ -25,6 +25,7 @@ type SettingsForm struct {
 	KeyboardShortcuts bool
 	ShowReadingTime   bool
 	CustomCSS         string
+	EntrySwipe        bool
 }
 
 // Merge updates the fields of the given user.
@@ -38,6 +39,7 @@ func (s *SettingsForm) Merge(user *model.User) *model.User {
 	user.KeyboardShortcuts = s.KeyboardShortcuts
 	user.ShowReadingTime = s.ShowReadingTime
 	user.Extra["custom_css"] = s.CustomCSS
+	user.EntrySwipe = s.EntrySwipe;
 
 	if s.Password != "" {
 		user.Password = s.Password
@@ -92,5 +94,6 @@ func NewSettingsForm(r *http.Request) *SettingsForm {
 		KeyboardShortcuts: r.FormValue("keyboard_shortcuts") == "1",
 		ShowReadingTime:   r.FormValue("show_reading_time") == "1",
 		CustomCSS:         r.FormValue("custom_css"),
+		EntrySwipe:        r.FormValue("entry_swipe") == "1",
 	}
 }
diff --git a/ui/settings_show.go b/ui/settings_show.go
index a50f9760..d877feff 100644
--- a/ui/settings_show.go
+++ b/ui/settings_show.go
@@ -36,6 +36,7 @@ func (h *handler) showSettingsPage(w http.ResponseWriter, r *http.Request) {
 		KeyboardShortcuts: user.KeyboardShortcuts,
 		ShowReadingTime:   user.ShowReadingTime,
 		CustomCSS:         user.Extra["custom_css"],
+		EntrySwipe:        user.EntrySwipe,
 	}
 
 	timezones, err := h.store.Timezones()
-- 
GitLab