Application specific preferences saving now enabled.

This commit is contained in:
Storm Dragon committed 2026-10-28 04:51:39 -04:00
1 parent f88e5b81a2
commit 60abcc37d9
23 files changed
+1004 -248

No files matched your search

+34
View File
@@ -0,0 +1,34 @@
// Copyright (c) 2026 Storm Dragon
// SPDX-License-Identifier: GPL-3.0-or-later
package preferences
import (
"git.stormux.org/storm/fenrir/internal/config"
"git.stormux.org/storm/fenrir/internal/interaction"
"testing"
)
func TestApplicationSettingsOnlyExposeRestorableControls(t *testing.T) {
base := config.Defaults()
session, err := New_application_session(base, nil, "Ninjam application settings")
if err != nil {
t.Fatal(err)
}
values := session.Values()
for _, path := range []string{"presentation.speech.driver", "presentation.sound.theme", "keyboard.layout", "keyboard.devices", "reading.punctuation_profile", "clipboard.persistent"} {
if _, exists := values[path]; exists {
t.Fatal("startup/global control exposed", path)
}
}
if _, exists := values["presentation.speech.voice"]; !exists {
t.Fatal("voice control missing")
}
session.Handle(interaction.Key{Name: "tab"})
session.Handle(interaction.Key{Name: "tab"})
session.Handle(interaction.Key{Name: "up"})
saved, err := Application_settings(session, base)
if err != nil || saved.Presentation.Speech.Rate != base.Presentation.Speech.Rate+1 || saved.Keyboard.Layout != base.Keyboard.Layout {
t.Fatal(saved, err)
}
}
+3
View File
@@ -119,6 +119,9 @@ func (d Discovery) Refresh_speech(session *interaction.Session, previous *config
"presentation.speech.voice": &next.Presentation.Speech.Voice,
} {
control, ok := values[path]
if !ok && path == "presentation.speech.driver" {
continue
}
if !ok || control.Selected < 0 || control.Selected >= len(control.Choices) {
return false
}
+29 -5
View File
@@ -38,10 +38,18 @@ type Choices map[string][]config.Choice
const MenuTitle = "Fenrir Menu"
func New_session(settings config.Settings, order []string, discovered ...Choices) (*interaction.Session, error) {
return new_session(settings, order, MenuTitle, false, discovered...)
}
func New_application_session(settings config.Settings, order []string, title string, discovered ...Choices) (*interaction.Session, error) {
return new_session(settings, order, title, true, discovered...)
}
func new_session(settings config.Settings, order []string, title string, application bool, discovered ...Choices) (*interaction.Session, error) {
if err := settings.Validate(); err != nil {
return nil, err
}
form := interaction.Form{Type: interaction.TabForm, Title: MenuTitle}
form := interaction.Form{Type: interaction.TabForm, Title: title}
for _, section := range config.Ordered_sections(config.Sections(), order) {
if section.Label == "" {
continue
@@ -50,6 +58,9 @@ func New_session(settings config.Settings, order []string, discovered ...Choices
var append_section func(config.Section, string) error
append_section = func(section config.Section, group string) error {
for _, definition := range section.Settings {
if application && !config.Application_setting(definition.Path) {
continue
}
control, err := make_control(definition, settings, discovered)
if err != nil {
return err
@@ -76,6 +87,9 @@ func New_session(settings config.Settings, order []string, discovered ...Choices
if err := append_section(section, ""); err != nil {
return nil, err
}
if len(tab.Controls) == 0 {
continue
}
tab.Controls = append(tab.Controls, interaction.Control{ID: "ok", Label: "OK", Kind: interaction.Button, Action: "save"}, interaction.Control{ID: "cancel", Label: "Cancel", Kind: interaction.Button, Action: "cancel"})
form.Tabs = append(form.Tabs, tab)
}
@@ -137,15 +151,25 @@ func make_control(definition config.Definition, settings config.Settings, discov
}
func Settings(session *interaction.Session, base config.Settings) (config.Settings, error) {
return settings_values(session, base, false)
}
func Application_settings(session *interaction.Session, base config.Settings) (config.Settings, error) {
return settings_values(session, base, true)
}
func settings_values(session *interaction.Session, base config.Settings, application bool) (config.Settings, error) {
values := session.Values()
// Visibility follows the form's selected driver, including unsaved switches.
driver := values["presentation.speech.driver"]
if driver.Selected < 0 || driver.Selected >= len(driver.Choices) {
driver, hasDriver := values["presentation.speech.driver"]
if (!application && !hasDriver) || (hasDriver && (driver.Selected < 0 || driver.Selected >= len(driver.Choices))) {
return config.Settings{}, fmt.Errorf("invalid speech driver selection")
}
base.Presentation.Speech.Driver = driver.Choices[driver.Selected].ID
if hasDriver {
base.Presentation.Speech.Driver = driver.Choices[driver.Selected].ID
}
for _, definition := range config.Definitions() {
if !definition.Available(base) {
if !definition.Available(base) || (application && !config.Application_setting(definition.Path)) {
continue
}
control, ok := values[definition.Path]