fix readme repo diagram, add agents.md
Some checks failed
CI - Multi-Platform Native / Build iOS (RSSuper) (push) Has been cancelled
CI - Multi-Platform Native / Build macOS (push) Has been cancelled
CI - Multi-Platform Native / Build Android (push) Has been cancelled
CI - Multi-Platform Native / Build Linux (push) Has been cancelled
CI - Multi-Platform Native / Integration Tests (push) Has been cancelled
CI - Multi-Platform Native / Build Summary (push) Has been cancelled

This commit is contained in:
2026-03-31 12:54:01 -04:00
parent 6a7efebdfc
commit b79e6e7aa2
7 changed files with 629 additions and 9 deletions

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schema id="org.rssuper.app.settings" path="/org/rssuper/app/settings/">
<key type="s" name="reading-prefs-file">
<default>'reading_preferences.json'</default>
<description>Reading preferences file name</description>
</key>
<key type="s" name="sync-prefs-file">
<default>'sync_preferences.json'</default>
<description>Sync preferences file name</description>
</key>
<key type="b" name="background-sync-enabled">
<default>false</default>
<description>Enable background sync</description>
</key>
<key type="i" name="sync-interval-minutes">
<default>15</default>
<description>Sync interval in minutes</description>
</key>
</schema>
</schemalist>

View File

@@ -20,6 +20,19 @@ xml_dep = dependency('libxml-2.0', version: '>= 2.0')
soup_dep = dependency('libsoup-3.0', version: '>= 3.0')
gtk_dep = dependency('gtk4', version: '>= 4.0')
# GSettings schemas
schema_files = [
'gsettings/org.rssuper.notification.preferences.gschema.xml',
'gsettings/org.rssuper.app.settings.gschema.xml',
]
compile_schemas = custom_target('Compile GSettings schemas',
output: 'schemas.glibdir',
command: glib_dep.get_variable(name: 'glib-mkenums') + ' --targetdir=build --schema-dir=gsettings schemas.glibdir',
dependencies: glib_dep,
install: false
)
# Source files
models = files(
'src/models/feed-item.vala',
@@ -32,6 +45,13 @@ models = files(
'src/models/bookmark.vala',
)
# Settings files
settings = files(
'src/settings-store.vala',
'src/app-settings.vala',
'src/notification-preferences-store.vala',
)
# Database files
database = files(
'src/database/db-error.vala',
@@ -76,6 +96,13 @@ models_lib = library('rssuper-models', models,
install: false
)
# Settings library
settings_lib = library('rssuper-settings', settings,
dependencies: [glib_dep, gio_dep, json_dep],
link_with: [models_lib],
install: false
)
# Database library
database_lib = library('rssuper-database', database,
dependencies: [glib_dep, gio_dep, json_dep, sqlite_dep, gobject_dep],
@@ -153,9 +180,19 @@ notification_manager_test_exe = executable('notification-manager-tests',
install: false
)
# Settings store test executable
settings_store_test_exe = executable('settings-store-tests',
'src/tests/settings-store-tests.vala',
dependencies: [glib_dep, gio_dep, json_dep],
link_with: [models_lib, settings_lib],
vala_args: ['--vapidir', '.', '--pkg', 'gio-2.0'],
install: false
)
# Test definitions
test('database tests', test_exe)
test('parser tests', parser_test_exe)
test('feed fetcher tests', fetcher_test_exe)
test('notification service tests', notification_service_test_exe)
test('notification manager tests', notification_manager_test_exe)
test('settings store tests', settings_store_test_exe)

162
linux/src/app-settings.vala Normal file
View File

@@ -0,0 +1,162 @@
/*
* app-settings.vala
*
* Application settings interface and utilities.
* Provides a unified interface for accessing application settings.
*/
using GLib;
namespace RSSuper {
/**
* AppSettings - Application settings interface
*
* Provides access to all application-level settings including:
* - Reading preferences
* - Sync preferences
* - Theme settings
* - Language settings
*/
public class AppSettings : Object {
// Singleton instance
private static AppSettings? _instance;
// Settings store
private SettingsStore? _settings_store;
// Theme
private Theme _theme;
// Language
private string _language;
// GSettings schema key
private const string SCHEMA_KEY = "org.rssuper.app.settings";
/**
* Get singleton instance
*/
public static AppSettings? get_instance() {
if (_instance == null) {
_instance = new AppSettings();
}
return _instance;
}
/**
* Constructor
*/
private AppSettings() {
_settings_store = SettingsStore.get_instance();
// Load theme
_theme = Theme.SYSTEM;
_language = "en";
}
/**
* Get reading preferences
*/
public ReadingPreferences? get_reading_preferences() {
return _settings_store.get_reading_preferences();
}
/**
* Set reading preferences
*/
public void set_reading_preferences(ReadingPreferences prefs) {
_settings_store.set_reading_preferences(prefs);
}
/**
* Get background sync enabled
*/
public bool get_background_sync_enabled() {
return _settings_store.get_background_sync_enabled();
}
/**
* Set background sync enabled
*/
public void set_background_sync_enabled(bool enabled) {
_settings_store.set_background_sync_enabled(enabled);
}
/**
* Get sync interval in minutes
*/
public int get_sync_interval_minutes() {
return _settings_store.get_sync_interval_minutes();
}
/**
* Set sync interval in minutes
*/
public void set_sync_interval_minutes(int minutes) {
_settings_store.set_sync_interval_minutes(minutes);
}
/**
* Get theme
*/
public Theme get_theme() {
return _theme;
}
/**
* Set theme
*/
public void set_theme(Theme theme) {
_theme = theme;
}
/**
* Get language
*/
public string get_language() {
return _language;
}
/**
* Set language
*/
public void set_language(string language) {
_language = language;
}
/**
* Get all settings as dictionary
*/
public Dictionary<string, object> get_all_settings() {
return _settings_store.get_all_settings();
}
/**
* Set all settings from dictionary
*/
public void set_all_settings(Dictionary<string, object> settings) {
_settings_store.set_all_settings(settings);
}
/**
* Reset all settings to defaults
*/
public void reset_to_defaults() {
_settings_store.reset_to_defaults();
_theme = Theme.SYSTEM;
_language = "en";
}
}
/**
* Theme - Available theme options
*/
public enum RSSuper.Theme {
SYSTEM,
LIGHT,
DARK
}
}

View File

@@ -0,0 +1,224 @@
/*
* settings-store-tests.vala
*
* Unit tests for settings store.
*/
using GLib;
namespace RSSuper {
public void main(string[] args) {
print("Running Settings Store Tests\n");
print("============================\n\n");
// Test ReadingPreferences
test_reading_preferences();
// Test SettingsStore
test_settings_store();
// Test AppSettings
test_app_settings();
print("\nAll tests passed!\n");
}
/**
* Test ReadingPreferences
*/
private void test_reading_preferences() {
print("Testing ReadingPreferences...\n");
// Test default constructor
var prefs = new ReadingPreferences();
assert(prefs.font_size == FontSize.MEDIUM);
assert(prefs.line_height == LineHeight.NORMAL);
assert(prefs.show_table_of_contents == true);
assert(prefs.show_reading_time == true);
assert(prefs.show_author == true);
assert(prefs.show_date == true);
print(" ✓ Default constructor sets correct defaults\n");
// Test with_values constructor
var prefs2 = new ReadingPreferences.with_values(
FontSize.LARGE,
LineHeight.RELAXED,
false,
false,
false,
false
);
assert(prefs2.font_size == FontSize.LARGE);
assert(prefs2.line_height == LineHeight.RELAXED);
assert(prefs2.show_table_of_contents == false);
assert(prefs2.show_reading_time == false);
assert(prefs2.show_author == false);
assert(prefs2.show_date == false);
print(" ✓ with_values constructor sets correct values\n");
// Test to_json_string
var json_str = prefs.to_json_string();
assert(json_str.contains("fontSize"));
assert(json_str.contains("lineHeight"));
assert(json_str.contains("showTableOfContents"));
print(" ✓ to_json_string produces valid JSON\n");
// Test from_json_string
var prefs3 = ReadingPreferences.from_json_string(json_str);
assert(prefs3 != null);
assert(prefs3.font_size == FontSize.MEDIUM);
print(" ✓ from_json_string parses JSON correctly\n");
// Test font_size_from_string
assert(ReadingPreferences.font_size_from_string("small") == FontSize.SMALL);
assert(ReadingPreferences.font_size_from_string("medium") == FontSize.MEDIUM);
assert(ReadingPreferences.font_size_from_string("large") == FontSize.LARGE);
assert(ReadingPreferences.font_size_from_string("xlarge") == FontSize.XLARGE);
assert(ReadingPreferences.font_size_from_string("invalid") == FontSize.MEDIUM);
print(" ✓ font_size_from_string parses correctly\n");
// Test line_height_from_string
assert(ReadingPreferences.line_height_from_string("normal") == LineHeight.NORMAL);
assert(ReadingPreferences.line_height_from_string("relaxed") == LineHeight.RELAXED);
assert(ReadingPreferences.line_height_from_string("loose") == LineHeight.LOOSE);
assert(ReadingPreferences.line_height_from_string("invalid") == LineHeight.NORMAL);
print(" ✓ line_height_from_string parses correctly\n");
// Test equals
assert(prefs.equals(prefs2) == false);
var prefs4 = new ReadingPreferences();
assert(prefs.equals(prefs4) == true);
print(" ✓ equals works correctly\n");
// Test copy_from
var prefs5 = new ReadingPreferences();
prefs5.copy_from(prefs2);
assert(prefs5.font_size == FontSize.LARGE);
assert(prefs5.line_height == LineHeight.RELAXED);
print(" ✓ copy_from copies values correctly\n");
// Test reset_to_defaults
prefs.font_size = FontSize.LARGE;
prefs.reset_to_defaults();
assert(prefs.font_size == FontSize.MEDIUM);
print(" ✓ reset_to_defaults resets to defaults\n");
print("ReadingPreferences tests passed!\n\n");
}
/**
* Test SettingsStore
*/
private void test_settings_store() {
print("Testing SettingsStore...\n");
// Test singleton pattern
var store1 = SettingsStore.get_instance();
var store2 = SettingsStore.get_instance();
assert(store1 == store2);
print(" ✓ Singleton pattern works correctly\n");
// Test reading preferences
var prefs = new ReadingPreferences.with_values(FontSize.LARGE);
store1.set_reading_preferences(prefs);
var retrieved_prefs = store1.get_reading_preferences();
assert(retrieved_prefs != null);
assert(retrieved_prefs.font_size == FontSize.LARGE);
print(" ✓ Reading preferences stored and retrieved correctly\n");
// Test background sync enabled
store1.set_background_sync_enabled(true);
assert(store1.get_background_sync_enabled() == true);
store1.set_background_sync_enabled(false);
assert(store1.get_background_sync_enabled() == false);
print(" ✓ Background sync enabled works correctly\n");
// Test sync interval
store1.set_sync_interval_minutes(30);
assert(store1.get_sync_interval_minutes() == 30);
store1.set_sync_interval_minutes(15);
assert(store1.get_sync_interval_minutes() == 15);
print(" ✓ Sync interval works correctly\n");
// Test get_all_settings
var all_settings = store1.get_all_settings();
assert(all_settings.containsKey("fontSize"));
assert(all_settings.containsKey("backgroundSyncEnabled"));
assert(all_settings.containsKey("syncIntervalMinutes"));
print(" ✓ get_all_settings returns correct keys\n");
// Test set_all_settings
var new_settings = new Dictionary<string, object>();
new_settings["fontSize"] = "large";
new_settings["backgroundSyncEnabled"] = true;
new_settings["syncIntervalMinutes"] = 60;
store1.set_all_settings(new_settings);
assert(store1.get_reading_preferences().font_size == FontSize.LARGE);
assert(store1.get_background_sync_enabled() == true);
assert(store1.get_sync_interval_minutes() == 60);
print(" ✓ set_all_settings sets all values correctly\n");
// Test reset_to_defaults
store1.reset_to_defaults();
assert(store1.get_reading_preferences().font_size == FontSize.MEDIUM);
assert(store1.get_background_sync_enabled() == false);
assert(store1.get_sync_interval_minutes() == 15);
print(" ✓ reset_to_defaults resets all values\n");
print("SettingsStore tests passed!\n\n");
}
/**
* Test AppSettings
*/
private void test_app_settings() {
print("Testing AppSettings...\n");
// Test singleton pattern
var settings1 = AppSettings.get_instance();
var settings2 = AppSettings.get_instance();
assert(settings1 == settings2);
print(" ✓ Singleton pattern works correctly\n");
// Test theme
settings1.set_theme(Theme.DARK);
assert(settings1.get_theme() == Theme.DARK);
settings1.set_theme(Theme.LIGHT);
assert(settings1.get_theme() == Theme.LIGHT);
settings1.set_theme(Theme.SYSTEM);
assert(settings1.get_theme() == Theme.SYSTEM);
print(" ✓ Theme works correctly\n");
// Test language
settings1.set_language("en");
assert(settings1.get_language() == "en");
settings1.set_language("es");
assert(settings1.get_language() == "es");
print(" ✓ Language works correctly\n");
// Test reading preferences through AppSettings
var prefs = new ReadingPreferences.with_values(FontSize.XLARGE);
settings1.set_reading_preferences(prefs);
var retrieved_prefs = settings1.get_reading_preferences();
assert(retrieved_prefs != null);
assert(retrieved_prefs.font_size == FontSize.XLARGE);
print(" ✓ Reading preferences through AppSettings works\n");
// Test sync settings through AppSettings
settings1.set_background_sync_enabled(true);
assert(settings1.get_background_sync_enabled() == true);
settings1.set_sync_interval_minutes(45);
assert(settings1.get_sync_interval_minutes() == 45);
print(" ✓ Sync settings through AppSettings works\n");
// Test reset_to_defaults
settings1.reset_to_defaults();
assert(settings1.get_theme() == Theme.SYSTEM);
assert(settings1.get_language() == "en");
print(" ✓ reset_to_defaults works correctly\n");
print("AppSettings tests passed!\n\n");
}
}