Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions internal/database/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -1457,4 +1457,8 @@ var migrations = [...]func(tx *sql.Tx) error{
`)
return err
},
func(tx *sql.Tx) (err error) {
_, err = tx.Exec(`ALTER TABLE users ADD COLUMN disable_bulk_operations_confirmations bool default 'f'`)
return err
},
}
1 change: 1 addition & 0 deletions internal/locale/translations/ar_SA.json
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@
"form.prefs.label.show_reading_time": "إظهار الوقت المقدر للقراءة للمقالات",
"form.prefs.label.theme": "السمة",
"form.prefs.label.timezone": "المنطقة الزمنية",
"form.prefs.label.disable_bulk_operations_confirmations": "تعطيل التأكيدات للعمليات الجماعية (تعليم الجميع كمقروء، تعليم الصفحة كمقروء)",
"form.prefs.select.alphabetical": "أبجدي",
"form.prefs.select.browser": "المتصفح",
"form.prefs.select.created_time": "وقت إنشاء المقال",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/de_DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"form.prefs.label.show_reading_time": "Geschätzte Lesezeit für Artikel anzeigen",
"form.prefs.label.theme": "Thema",
"form.prefs.label.timezone": "Zeitzone",
"form.prefs.label.disable_bulk_operations_confirmations": "Bestätigungsaufforderungen für Massenvorgänge deaktivieren (alle als gelesen markieren, Seite als gelesen markieren)",
"form.prefs.select.alphabetical": "Alphabetisch",
"form.prefs.select.browser": "Systembrowser",
"form.prefs.select.created_time": "Artikel erstellt am",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/el_EL.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"form.prefs.label.show_reading_time": "Εμφάνιση εκτιμώμενου χρόνου ανάγνωσης για άρθρα",
"form.prefs.label.theme": "Θέμα",
"form.prefs.label.timezone": "Ζώνη Ώρας",
"form.prefs.label.disable_bulk_operations_confirmations": "Απενεργοποίηση προτροπών επιβεβαίωσης για μαζικές λειτουργίες (σήμανση όλων ως διαβασμένα, σήμανση σελίδας ως διαβασμένη)",
"form.prefs.select.alphabetical": "Αλφαβητική σειρά",
"form.prefs.select.browser": "Περιηγητής",
"form.prefs.select.created_time": "Χρόνος δημιουργίας καταχώρησης",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@
"form.prefs.label.mark_read_on_view_or_media_completion": "Mark entries as read when viewed. For audio/video, mark as read at 90%% completion",
"form.prefs.label.media_playback_rate": "Playback speed of the audio/video",
"form.prefs.label.open_external_links_in_new_tab": "Open external links in a new tab (adds target=\"_blank\" to links)",
"form.prefs.label.disable_bulk_operations_confirmations": "Disable confirmation prompts for bulk operations (mark all as read, mark page as read)",
"form.prefs.label.show_reading_time": "Show estimated reading time for entries",
"form.prefs.label.theme": "Theme",
"form.prefs.label.timezone": "Timezone",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/es_ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"form.prefs.label.show_reading_time": "Mostrar el tiempo estimado de lectura de los artículos",
"form.prefs.label.theme": "Tema",
"form.prefs.label.timezone": "Zona horaria",
"form.prefs.label.disable_bulk_operations_confirmations": "Deshabilitar mensajes de confirmación para operaciones masivas (marcar todo como leído, marcar página como leída)",
"form.prefs.select.alphabetical": "Alfabético",
"form.prefs.select.browser": "Navegador",
"form.prefs.select.created_time": "Hora de creación del artículo",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/fi_FI.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"form.prefs.label.show_reading_time": "Näytä artikkeleiden arvioitu lukuaika",
"form.prefs.label.theme": "Teema",
"form.prefs.label.timezone": "Aikavyöhyke",
"form.prefs.label.disable_bulk_operations_confirmations": "Poista vahvistuskehotteet massatoiminnoista (merkitse kaikki luetuiksi, merkitse sivu luetuksi)",
"form.prefs.select.alphabetical": "Aakkosjärjestys",
"form.prefs.select.browser": "Selain",
"form.prefs.select.created_time": "Luomisaika",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/fr_FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"form.prefs.label.show_reading_time": "Afficher le temps de lecture estimé des articles",
"form.prefs.label.theme": "Thème",
"form.prefs.label.timezone": "Fuseau horaire",
"form.prefs.label.disable_bulk_operations_confirmations": "Désactiver les invites de confirmation pour les opérations en masse (marquer tout comme lu, marquer la page comme lue)",
"form.prefs.select.alphabetical": "Alphabétique",
"form.prefs.select.browser": "Navigateur",
"form.prefs.select.created_time": "Heure de création de l'entrée",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/gl_ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"form.prefs.label.show_reading_time": "Mostrar tempo de lectura estimado para as entradas",
"form.prefs.label.theme": "Decorado",
"form.prefs.label.timezone": "Zona horaria",
"form.prefs.label.disable_bulk_operations_confirmations": "Desactivar mensaxes de confirmación para operacións masivas (marcar todo como lido, marcar páxina como lida)",
"form.prefs.select.alphabetical": "Alfabética",
"form.prefs.select.browser": "Navegador",
"form.prefs.select.created_time": "Hora de creación da entrada",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/hi_IN.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"form.prefs.label.show_reading_time": "विषय के लिए अनुमानित पढ़ने का समय दिखाएं",
"form.prefs.label.theme": "थीम",
"form.prefs.label.timezone": "समय क्षेत्र",
"form.prefs.label.disable_bulk_operations_confirmations": "ब्यूक संचालनों के लिए पुष्टि स्वीकृत अस्वीकार करें (सभी को पढ़ा हुआ चिह्नित करें, पृष्ठ को पढ़ा हुआ चिह्नित करें)",
"form.prefs.select.alphabetical": "वर्णक्रम",
"form.prefs.select.browser": "ब्राउज़र",
"form.prefs.select.created_time": "प्रवेश बनाया समय",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/id_ID.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@
"form.prefs.label.show_reading_time": "Tampilkan perkiraan waktu baca untuk artikel",
"form.prefs.label.theme": "Tema",
"form.prefs.label.timezone": "Zona Waktu",
"form.prefs.label.disable_bulk_operations_confirmations": "Nonaktifkan konfirmasi untuk operasi massal (tandai semua sebagai dibaca, tandai halaman sebagai dibaca)",
"form.prefs.select.alphabetical": "Secara alfabet",
"form.prefs.select.browser": "Peramban",
"form.prefs.select.created_time": "Waktu entri dibuat",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/it_IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"form.prefs.label.show_reading_time": "Mostra il tempo di lettura stimato per gli articoli",
"form.prefs.label.theme": "Tema",
"form.prefs.label.timezone": "Fuso orario",
"form.prefs.label.disable_bulk_operations_confirmations": "Disabilita le richieste di conferma per le operazioni in blocco (segna tutto come letto, segna pagina come letta)",
"form.prefs.select.alphabetical": "In ordine alfabetico",
"form.prefs.select.browser": "Browser",
"form.prefs.select.created_time": "Tempo di creazione dell'entrata",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/ja_JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@
"form.prefs.label.show_reading_time": "記事の推定読書時間を表示する",
"form.prefs.label.theme": "テーマ",
"form.prefs.label.timezone": "タイムゾーン",
"form.prefs.label.disable_bulk_operations_confirmations": "一括操作の確認ダイアログを無効化する(全て既読にする、ページを既読にする)",
"form.prefs.select.alphabetical": "アルファベット順",
"form.prefs.select.browser": "ブラウザ",
"form.prefs.select.created_time": "記事の取得時刻",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/nan_Latn_pehoeji.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@
"form.prefs.label.show_reading_time": "Hián-sī siau-sit àn-sǹg ài gōa-kú lâi tha̍k",
"form.prefs.label.theme": "Chú-tôe",
"form.prefs.label.timezone": "Sî-khu",
"form.prefs.label.disable_bulk_operations_confirmations": "Hip ê chènghoat chhiam-miâ úi tō-hōn chok-iŭ (àn sóŭ Ů chiút chèn chò hoat-thǎk, àn iáh chiút chèn chò hoat-thǎk)",
"form.prefs.select.alphabetical": "Chiàu lī-bú pâi",
"form.prefs.select.browser": "Iû-lâm-khì",
"form.prefs.select.created_time": "Siau-sit kiàn-li̍p sî-kan",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/nl_NL.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"form.prefs.label.show_reading_time": "Toon geschatte leestijd van artikelen",
"form.prefs.label.theme": "Thema",
"form.prefs.label.timezone": "Tijdzone",
"form.prefs.label.disable_bulk_operations_confirmations": "Bevestigingsprompts uitschakelen voor bulkoperaties (markeer alles als gelezen, markeer pagina als gelezen)",
"form.prefs.select.alphabetical": "Alfabetisch",
"form.prefs.select.browser": "Systeembrowser",
"form.prefs.select.created_time": "Tijdstip van aanmaken artikel",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/pl_PL.json
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@
"form.prefs.label.show_reading_time": "Pokaż szacowany czas czytania wpisów",
"form.prefs.label.theme": "Wygląd",
"form.prefs.label.timezone": "Strefa czasowa",
"form.prefs.label.disable_bulk_operations_confirmations": "Wyłącz potwierdzenia dla operacji zbiorczych (oznacz wszystko jako przeczytane, oznacz stronę jako przeczytaną)",
"form.prefs.select.alphabetical": "Alfabetycznie",
"form.prefs.select.browser": "Przeglądarkowy",
"form.prefs.select.created_time": "Czas utworzenia wpisu",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/pt_BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"form.prefs.label.show_reading_time": "Mostrar tempo estimado de leitura de artigos",
"form.prefs.label.theme": "Tema",
"form.prefs.label.timezone": "Fuso horário",
"form.prefs.label.disable_bulk_operations_confirmations": "Desabilitar confirmações para operações em massa (marcar tudo como lido, marcar página como lida)",
"form.prefs.select.alphabetical": "Por ordem alfabética",
"form.prefs.select.browser": "Navegador",
"form.prefs.select.created_time": "Entrada tempo criado",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/ro_RO.json
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@
"form.prefs.label.show_reading_time": "Afișare timp estimat de citire pentru înregistrări",
"form.prefs.label.theme": "Temă",
"form.prefs.label.timezone": "Fus orar",
"form.prefs.label.disable_bulk_operations_confirmations": "Dezactivează confirmările pentru operațiunile în masă (marchează tot ca citit, marchează pagina ca citită)",
"form.prefs.select.alphabetical": "Alfabetic",
"form.prefs.select.browser": "Browser",
"form.prefs.select.created_time": "Dată creare înregistrare",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/ru_RU.json
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@
"form.prefs.label.show_reading_time": "Показать примерное время чтения статей",
"form.prefs.label.theme": "Тема",
"form.prefs.label.timezone": "Часовой пояс",
"form.prefs.label.disable_bulk_operations_confirmations": "Отключить подтверждения для массовых операций (отметить всё как прочитанное, отметить страницу как прочитанную)",
"form.prefs.select.alphabetical": "В алфавитном порядке",
"form.prefs.select.browser": "Браузер",
"form.prefs.select.created_time": "Время создания статьи",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/tr_TR.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"form.prefs.label.show_reading_time": "Makaleler için tahmini okuma süresini göster",
"form.prefs.label.theme": "Tema",
"form.prefs.label.timezone": "Saat Dilimi",
"form.prefs.label.disable_bulk_operations_confirmations": "Toplu işlemler için onay istemlerini devre dışı bırak (tümünü okundu olarak işaretle, sayfayı okundu olarak işaretle)",
"form.prefs.select.alphabetical": "Alfabetik",
"form.prefs.select.browser": "Tarayıcı",
"form.prefs.select.created_time": "İçeriğin oluşturulma zamanı",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/uk_UA.json
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@
"form.prefs.label.show_reading_time": "Показувати приблизний час читання для записів",
"form.prefs.label.theme": "Тема",
"form.prefs.label.timezone": "Часовий пояс",
"form.prefs.label.disable_bulk_operations_confirmations": "Вимкнути підтвердження для масових операцій (позначити все як прочитане, позначити сторінку як прочитану)",
"form.prefs.select.alphabetical": "За алфавітом",
"form.prefs.select.browser": "Браузер",
"form.prefs.select.created_time": "Дата створення запису",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@
"form.prefs.label.show_reading_time": "显示条目的预计阅读时间",
"form.prefs.label.theme": "主题",
"form.prefs.label.timezone": "时区",
"form.prefs.label.disable_bulk_operations_confirmations": "Disable confirmation prompts for bulk operations (mark all as read, mark page as read)",

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new label is still in English in the Chinese locale file. Please provide a zh_CN translation (or, if English fallback is preferred, omit the key here and rely on the fallback mechanism, if supported by the i18n loader).

Suggested change
"form.prefs.label.disable_bulk_operations_confirmations": "Disable confirmation prompts for bulk operations (mark all as read, mark page as read)",
"form.prefs.label.disable_bulk_operations_confirmations": "禁用批量操作确认提示(全部标记为已读、将当前页标记为已读)",

Copilot uses AI. Check for mistakes.
"form.prefs.select.alphabetical": "字母顺序",
"form.prefs.select.browser": "浏览器",
"form.prefs.select.created_time": "条目创建时间",
Expand Down
1 change: 1 addition & 0 deletions internal/locale/translations/zh_TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@
"form.prefs.label.show_reading_time": "顯示文章的預計閱讀時間",
"form.prefs.label.theme": "主題",
"form.prefs.label.timezone": "時區",
"form.prefs.label.disable_bulk_operations_confirmations": "Disable confirmation prompts for bulk operations (mark all as read, mark page as read)",

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new label is still in English in the zh_TW locale file. Please translate it to Traditional Chinese (or rely on the project’s fallback behavior if untranslated strings are acceptable).

Suggested change
"form.prefs.label.disable_bulk_operations_confirmations": "Disable confirmation prompts for bulk operations (mark all as read, mark page as read)",
"form.prefs.label.disable_bulk_operations_confirmations": "停用大量操作的確認提示(全部標記為已讀、將本頁標記為已讀)",

Copilot uses AI. Check for mistakes.
"form.prefs.select.alphabetical": "按字母順序",
"form.prefs.select.browser": "瀏覽器",
"form.prefs.select.created_time": "文章建立時間",
Expand Down
14 changes: 10 additions & 4 deletions internal/model/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ type User struct {
MediaPlaybackRate float64 `json:"media_playback_rate"`
BlockFilterEntryRules string `json:"block_filter_entry_rules"`
KeepFilterEntryRules string `json:"keep_filter_entry_rules"`
AlwaysOpenExternalLinks bool `json:"always_open_external_links"`
OpenExternalLinksInNewTab bool `json:"open_external_links_in_new_tab"`
AlwaysOpenExternalLinks bool `json:"always_open_external_links"`
OpenExternalLinksInNewTab bool `json:"open_external_links_in_new_tab"`
DisableBulkOperationsConfirmations bool `json:"disable_bulk_operations_confirmations"`
Comment on lines +44 to +46

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These new/modified struct fields have extra spacing that doesn’t match gofmt output (compare with the fields above). Please run gofmt on this file so field/type alignment is consistent and future diffs stay minimal.

Copilot uses AI. Check for mistakes.
}

// UserCreationRequest represents the request to create a user.
Expand Down Expand Up @@ -84,8 +85,9 @@ type UserModificationRequest struct {
MediaPlaybackRate *float64 `json:"media_playback_rate"`
BlockFilterEntryRules *string `json:"block_filter_entry_rules"`
KeepFilterEntryRules *string `json:"keep_filter_entry_rules"`
AlwaysOpenExternalLinks *bool `json:"always_open_external_links"`
OpenExternalLinksInNewTab *bool `json:"open_external_links_in_new_tab"`
AlwaysOpenExternalLinks *bool `json:"always_open_external_links"`
OpenExternalLinksInNewTab *bool `json:"open_external_links_in_new_tab"`
DisableBulkOperationsConfirmations *bool `json:"disable_bulk_operations_confirmations"`
Comment on lines +88 to +90

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same formatting issue here: the added fields use non-gofmt spacing/alignment. Running gofmt will normalize this section (and avoid churn in future edits).

Copilot uses AI. Check for mistakes.
}

// Patch updates the User object with the modification request.
Expand Down Expand Up @@ -209,6 +211,10 @@ func (u *UserModificationRequest) Patch(user *User) {
if u.OpenExternalLinksInNewTab != nil {
user.OpenExternalLinksInNewTab = *u.OpenExternalLinksInNewTab
}

if u.DisableBulkOperationsConfirmations != nil {
user.DisableBulkOperationsConfirmations = *u.DisableBulkOperationsConfirmations
}
}

// UseTimezone converts last login date to the given timezone.
Expand Down
99 changes: 99 additions & 0 deletions internal/model/user_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package model

import (
"testing"
)

func TestUserModificationRequestPatch(t *testing.T) {
user := &User{
Username: "original",
Theme: "original_theme",
Language: "original_language",
Timezone: "original_timezone",
AlwaysOpenExternalLinks: false,
OpenExternalLinksInNewTab: false,
DisableBulkOperationsConfirmations: false,
}

Comment on lines +10 to +20

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new test file doesn’t appear to be gofmt’d (field alignment in the struct literals is inconsistent). Please run gofmt so formatting matches the rest of the Go codebase and diffs remain stable.

Copilot uses AI. Check for mistakes.
// Test patching DisableBulkOperationsConfirmations
trueValue := true
req := &UserModificationRequest{
DisableBulkOperationsConfirmations: &trueValue,
}
req.Patch(user)

if !user.DisableBulkOperationsConfirmations {
t.Error("Expected DisableBulkOperationsConfirmations to be true after patch")
}

// Test that nil values don't modify the user
user2 := &User{
Username: "original",
DisableBulkOperationsConfirmations: true,
}
req2 := &UserModificationRequest{} // All fields nil
req2.Patch(user2)

if user2.Username != "original" {
t.Error("Username should not change when not provided in request")
}
if !user2.DisableBulkOperationsConfirmations {
t.Error("DisableBulkOperationsConfirmations should remain true when not provided in request")
}

// Test patching false value
falseValue := false
user3 := &User{
DisableBulkOperationsConfirmations: true,
}
req3 := &UserModificationRequest{
DisableBulkOperationsConfirmations: &falseValue,
}
req3.Patch(user3)

if user3.DisableBulkOperationsConfirmations {
t.Error("Expected DisableBulkOperationsConfirmations to be false after patch")
}
}

func TestUserModificationRequestPatchMultipleFields(t *testing.T) {
user := &User{
Username: "original_user",
Theme: "original_theme",
AlwaysOpenExternalLinks: false,
OpenExternalLinksInNewTab: false,
DisableBulkOperationsConfirmations: false,
}

newUsername := "new_user"
newTheme := "new_theme"
trueValue := true

req := &UserModificationRequest{
Username: &newUsername,
Theme: &newTheme,
AlwaysOpenExternalLinks: &trueValue,
OpenExternalLinksInNewTab: &trueValue,
DisableBulkOperationsConfirmations: &trueValue,
}
req.Patch(user)

if user.Username != "new_user" {
t.Errorf("Expected Username to be 'new_user', got '%s'", user.Username)
}
if user.Theme != "new_theme" {
t.Errorf("Expected Theme to be 'new_theme', got '%s'", user.Theme)
}
if !user.AlwaysOpenExternalLinks {
t.Error("Expected AlwaysOpenExternalLinks to be true")
}
if !user.OpenExternalLinksInNewTab {
t.Error("Expected OpenExternalLinksInNewTab to be true")
}
if !user.DisableBulkOperationsConfirmations {
t.Error("Expected DisableBulkOperationsConfirmations to be true")
}
}
Loading