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
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:
21
linux/gsettings/org.rssuper.app.settings.gschema.xml
Normal file
21
linux/gsettings/org.rssuper.app.settings.gschema.xml
Normal 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>
|
||||
@@ -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
162
linux/src/app-settings.vala
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
224
linux/src/tests/settings-store-tests.vala
Normal file
224
linux/src/tests/settings-store-tests.vala
Normal 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");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user