diff --git a/data/cz.vesp.roster.gschema.xml b/data/cz.vesp.roster.gschema.xml
index f91a8b2..406510b 100644
--- a/data/cz.vesp.roster.gschema.xml
+++ b/data/cz.vesp.roster.gschema.xml
@@ -1,5 +1,15 @@
+
+ true
+ Force TLS verification
+ When enabled, TLS certificates will be verified. Disable to test endpoints with self-signed or invalid certificates.
+
+
+ 30
+ Request timeout
+ Timeout for HTTP requests in seconds
+
diff --git a/src/http_client.py b/src/http_client.py
index 736ca12..287f10c 100644
--- a/src/http_client.py
+++ b/src/http_client.py
@@ -19,7 +19,7 @@
import gi
gi.require_version('Soup', '3.0')
-from gi.repository import Soup, GLib
+from gi.repository import Soup, GLib, Gio
import time
from typing import Optional, Callable, Any
@@ -32,7 +32,36 @@ class HttpClient:
def __init__(self):
"""Initialize HTTP client with reusable session."""
self.session = Soup.Session.new()
- self.session.set_timeout(30) # 30 second timeout
+
+ # Load settings
+ self.settings = Gio.Settings.new('cz.vesp.roster')
+
+ # Initialize TLS verification flag
+ self.force_tls_verification = True
+
+ # Apply initial settings
+ self._apply_settings()
+
+ # Listen for settings changes
+ self.settings.connect('changed::force-tls-verification', self._on_settings_changed)
+ self.settings.connect('changed::request-timeout', self._on_settings_changed)
+
+ def _apply_settings(self):
+ """Apply settings to the HTTP session."""
+ # Store TLS verification preference (will be applied per-message)
+ self.force_tls_verification = self.settings.get_boolean('force-tls-verification')
+
+ # Apply timeout setting
+ timeout = self.settings.get_int('request-timeout')
+ self.session.set_timeout(timeout)
+
+ def _on_settings_changed(self, settings, key):
+ """Handle settings changes."""
+ self._apply_settings()
+
+ def _accept_all_certificates(self, msg, tls_certificate, tls_errors):
+ """Accept all TLS certificates when verification is disabled."""
+ return True # Accept certificate regardless of errors
def execute_request_async(self, request: HttpRequest, callback: Callable, user_data: Any = None):
"""
@@ -59,6 +88,11 @@ class HttpClient:
callback(None, f"Invalid URL: {e}", user_data)
return
+ # Handle TLS certificate verification
+ if not self.force_tls_verification:
+ # Connect signal to accept all certificates when verification is disabled
+ msg.connect('accept-certificate', self._accept_all_certificates)
+
# Add headers
headers = msg.get_request_headers()
for key, value in request.headers.items():
diff --git a/src/main.py b/src/main.py
index 351d6b7..98e4a04 100644
--- a/src/main.py
+++ b/src/main.py
@@ -25,6 +25,7 @@ gi.require_version('Adw', '1')
from gi.repository import Gtk, Gio, Adw
from .window import RosterWindow
+from .preferences_dialog import PreferencesDialog
class RosterApplication(Adw.Application):
@@ -67,7 +68,9 @@ class RosterApplication(Adw.Application):
def on_preferences_action(self, widget, _):
"""Callback for the app.preferences action."""
- print('app.preferences action activated')
+ preferences = PreferencesDialog()
+ preferences.set_transient_for(self.props.active_window)
+ preferences.present()
def on_shortcuts_action(self, widget, _):
"""Callback for the app.shortcuts action."""
diff --git a/src/meson.build b/src/meson.build
index 3925436..0de6bb2 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -37,6 +37,7 @@ roster_sources = [
'tab_manager.py',
'constants.py',
'icon_picker_dialog.py',
+ 'preferences_dialog.py',
]
install_data(roster_sources, install_dir: moduledir)
diff --git a/src/preferences-dialog.ui b/src/preferences-dialog.ui
new file mode 100644
index 0000000..9c175be
--- /dev/null
+++ b/src/preferences-dialog.ui
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+ Preferences
+ True
+ 600
+ 400
+
+
+
+
+
+
diff --git a/src/preferences_dialog.py b/src/preferences_dialog.py
new file mode 100644
index 0000000..6f97848
--- /dev/null
+++ b/src/preferences_dialog.py
@@ -0,0 +1,49 @@
+# preferences_dialog.py
+#
+# Copyright 2025 Pavel Baksy
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from gi.repository import Adw, Gtk, Gio
+
+
+@Gtk.Template(resource_path='/cz/vesp/roster/preferences-dialog.ui')
+class PreferencesDialog(Adw.PreferencesWindow):
+ __gtype_name__ = 'PreferencesDialog'
+
+ tls_verification_row = Gtk.Template.Child()
+ timeout_row = Gtk.Template.Child()
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+
+ # Get settings
+ self.settings = Gio.Settings.new('cz.vesp.roster')
+
+ # Bind settings to UI
+ self.settings.bind(
+ 'force-tls-verification',
+ self.tls_verification_row,
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ )
+
+ self.settings.bind(
+ 'request-timeout',
+ self.timeout_row,
+ 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ )
diff --git a/src/roster.gresource.xml b/src/roster.gresource.xml
index 561d1ca..b782723 100644
--- a/src/roster.gresource.xml
+++ b/src/roster.gresource.xml
@@ -3,6 +3,7 @@
main-window.ui
shortcuts-dialog.ui
+ preferences-dialog.ui
icon-picker-dialog.ui
widgets/header-row.ui
widgets/history-item.ui