1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-06-27 16:36:00 +00:00
miniflux-v2/internal/ui/form/settings.go

197 lines
7.1 KiB
Go
Raw Normal View History

// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
2017-11-19 21:10:04 -08:00
package form // import "miniflux.app/v2/internal/ui/form"
2017-11-19 21:10:04 -08:00
import (
"net/http"
"strconv"
2017-11-27 21:30:04 -08:00
"miniflux.app/v2/internal/config"
"miniflux.app/v2/internal/locale"
"miniflux.app/v2/internal/model"
2017-11-19 21:10:04 -08:00
)
// MarkReadBehavior list all possible behaviors for automatically marking an entry as read
type MarkReadBehavior string
var (
NoAutoMarkAsRead MarkReadBehavior = "no-auto"
MarkAsReadOnView MarkReadBehavior = "on-view"
MarkAsReadOnViewButWaitForPlayerCompletion MarkReadBehavior = "on-view-but-wait-for-player-completion"
MarkAsReadOnlyOnPlayerCompletion MarkReadBehavior = "on-player-completion"
)
2017-11-27 21:30:04 -08:00
// SettingsForm represents the settings form.
2017-11-19 21:10:04 -08:00
type SettingsForm struct {
Username string
Password string
Confirmation string
Theme string
Language string
Timezone string
EntryDirection string
EntryOrder string
EntriesPerPage int
KeyboardShortcuts bool
ShowReadingTime bool
CustomCSS string
EntrySwipe bool
GestureNav string
DisplayMode string
DefaultReadingSpeed int
CJKReadingSpeed int
DefaultHomePage string
CategoriesSortingOrder string
MarkReadOnView bool
// MarkReadBehavior is a string representation of the MarkReadOnView and MarkReadOnMediaPlayerCompletion fields together
MarkReadBehavior MarkReadBehavior
MediaPlaybackRate float64
BlockFilterEntryRules string
KeepFilterEntryRules string
}
// MarkAsReadBehavior returns the MarkReadBehavior from the given MarkReadOnView and MarkReadOnMediaPlayerCompletion values.
// Useful to convert the values from the User model to the form
func MarkAsReadBehavior(markReadOnView, markReadOnMediaPlayerCompletion bool) MarkReadBehavior {
switch {
case markReadOnView && !markReadOnMediaPlayerCompletion:
return MarkAsReadOnView
case markReadOnView && markReadOnMediaPlayerCompletion:
return MarkAsReadOnViewButWaitForPlayerCompletion
case !markReadOnView && markReadOnMediaPlayerCompletion:
return MarkAsReadOnlyOnPlayerCompletion
case !markReadOnView && !markReadOnMediaPlayerCompletion:
fallthrough // Explicit defaulting
default:
return NoAutoMarkAsRead
}
}
// ExtractMarkAsReadBehavior returns the MarkReadOnView and MarkReadOnMediaPlayerCompletion values from the given MarkReadBehavior.
// Useful to extract the values from the form to the User model
func ExtractMarkAsReadBehavior(behavior MarkReadBehavior) (markReadOnView, markReadOnMediaPlayerCompletion bool) {
switch behavior {
case MarkAsReadOnView:
return true, false
case MarkAsReadOnViewButWaitForPlayerCompletion:
return true, true
case MarkAsReadOnlyOnPlayerCompletion:
return false, true
case NoAutoMarkAsRead:
fallthrough // Explicit defaulting
default:
return false, false
}
2017-11-19 21:10:04 -08:00
}
2017-11-27 21:30:04 -08:00
// Merge updates the fields of the given user.
2017-11-19 21:10:04 -08:00
func (s *SettingsForm) Merge(user *model.User) *model.User {
if !config.Opts.DisableLocalAuth() {
user.Username = s.Username
}
2017-11-19 21:10:04 -08:00
user.Theme = s.Theme
user.Language = s.Language
user.Timezone = s.Timezone
2017-12-02 17:04:01 -08:00
user.EntryDirection = s.EntryDirection
user.EntryOrder = s.EntryOrder
user.EntriesPerPage = s.EntriesPerPage
user.KeyboardShortcuts = s.KeyboardShortcuts
2020-07-17 04:46:24 +02:00
user.ShowReadingTime = s.ShowReadingTime
user.Stylesheet = s.CustomCSS
user.EntrySwipe = s.EntrySwipe
user.GestureNav = s.GestureNav
user.DisplayMode = s.DisplayMode
2021-08-30 16:53:05 +02:00
user.CJKReadingSpeed = s.CJKReadingSpeed
user.DefaultReadingSpeed = s.DefaultReadingSpeed
2022-07-20 22:07:55 +02:00
user.DefaultHomePage = s.DefaultHomePage
user.CategoriesSortingOrder = s.CategoriesSortingOrder
user.MediaPlaybackRate = s.MediaPlaybackRate
2024-07-03 04:03:49 +00:00
user.BlockFilterEntryRules = s.BlockFilterEntryRules
user.KeepFilterEntryRules = s.KeepFilterEntryRules
2017-11-19 21:10:04 -08:00
MarkReadOnView, MarkReadOnMediaPlayerCompletion := ExtractMarkAsReadBehavior(s.MarkReadBehavior)
user.MarkReadOnView = MarkReadOnView
user.MarkReadOnMediaPlayerCompletion = MarkReadOnMediaPlayerCompletion
2017-11-19 21:10:04 -08:00
if s.Password != "" {
user.Password = s.Password
}
return user
}
2017-11-27 21:30:04 -08:00
// Validate makes sure the form values are valid.
func (s *SettingsForm) Validate() *locale.LocalizedError {
if (s.Username == "" && !config.Opts.DisableLocalAuth()) || s.Theme == "" || s.Language == "" || s.Timezone == "" || s.EntryDirection == "" || s.DisplayMode == "" || s.DefaultHomePage == "" {
return locale.NewLocalizedError("error.settings_mandatory_fields")
2017-11-19 21:10:04 -08:00
}
2021-08-30 16:53:05 +02:00
if s.CJKReadingSpeed <= 0 || s.DefaultReadingSpeed <= 0 {
return locale.NewLocalizedError("error.settings_reading_speed_is_positive")
2021-08-30 16:53:05 +02:00
}
if s.Confirmation == "" {
// Firefox insists on auto-completing the password field.
// If the confirmation field is blank, the user probably
// didn't intend to change their password.
s.Password = ""
} else if s.Password != "" {
2017-11-19 21:10:04 -08:00
if s.Password != s.Confirmation {
return locale.NewLocalizedError("error.different_passwords")
2017-11-19 21:10:04 -08:00
}
}
if s.MediaPlaybackRate < 0.25 || s.MediaPlaybackRate > 4 {
return locale.NewLocalizedError("error.settings_media_playback_rate_range")
}
2017-11-19 21:10:04 -08:00
return nil
}
2017-11-27 21:30:04 -08:00
// NewSettingsForm returns a new SettingsForm.
2017-11-19 21:10:04 -08:00
func NewSettingsForm(r *http.Request) *SettingsForm {
entriesPerPage, err := strconv.ParseInt(r.FormValue("entries_per_page"), 10, 0)
if err != nil {
entriesPerPage = 0
}
2021-08-30 16:53:05 +02:00
defaultReadingSpeed, err := strconv.ParseInt(r.FormValue("default_reading_speed"), 10, 0)
if err != nil {
defaultReadingSpeed = 0
}
cjkReadingSpeed, err := strconv.ParseInt(r.FormValue("cjk_reading_speed"), 10, 0)
if err != nil {
cjkReadingSpeed = 0
}
mediaPlaybackRate, err := strconv.ParseFloat(r.FormValue("media_playback_rate"), 64)
if err != nil {
mediaPlaybackRate = 1
}
2017-11-19 21:10:04 -08:00
return &SettingsForm{
Username: r.FormValue("username"),
Password: r.FormValue("password"),
Confirmation: r.FormValue("confirmation"),
Theme: r.FormValue("theme"),
Language: r.FormValue("language"),
Timezone: r.FormValue("timezone"),
EntryDirection: r.FormValue("entry_direction"),
EntryOrder: r.FormValue("entry_order"),
EntriesPerPage: int(entriesPerPage),
KeyboardShortcuts: r.FormValue("keyboard_shortcuts") == "1",
ShowReadingTime: r.FormValue("show_reading_time") == "1",
CustomCSS: r.FormValue("custom_css"),
EntrySwipe: r.FormValue("entry_swipe") == "1",
GestureNav: r.FormValue("gesture_nav"),
DisplayMode: r.FormValue("display_mode"),
DefaultReadingSpeed: int(defaultReadingSpeed),
CJKReadingSpeed: int(cjkReadingSpeed),
DefaultHomePage: r.FormValue("default_home_page"),
CategoriesSortingOrder: r.FormValue("categories_sorting_order"),
MarkReadOnView: r.FormValue("mark_read_on_view") == "1",
MarkReadBehavior: MarkReadBehavior(r.FormValue("mark_read_behavior")),
MediaPlaybackRate: mediaPlaybackRate,
2024-07-03 04:03:49 +00:00
BlockFilterEntryRules: r.FormValue("block_filter_entry_rules"),
KeepFilterEntryRules: r.FormValue("keep_filter_entry_rules"),
2017-11-19 21:10:04 -08:00
}
}