mirror of
https://git.hiabuto.net/C3MA/CCMA.git
synced 2026-07-01 19:26:53 +02:00
feat: configure minimum splash duration
This commit is contained in:
@@ -55,6 +55,7 @@ class CCMAApp(tk.Tk):
|
||||
run_housekeeper=self.config_obj.run_housekeeper_on_startup,
|
||||
monitor=self.startup_monitor,
|
||||
housekeeper_settings=self.config_obj.housekeeper_settings(),
|
||||
minimum_display_seconds=self.config_obj.splash_minimum_seconds,
|
||||
)
|
||||
except Exception as exc:
|
||||
self._startup_failed(exc)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"Dropdowns zeigen deutsche Begriffe bei weiterhin englischen Speicher-Keys; der Hausmeisterstatus liegt einheitlich in housekeeper.json.",
|
||||
"Mehrstufiger Mahnworkflow mit Hausmeister-Regel, Entwurf, Versandbestätigung, Zahlungsfrist, optionaler Gebühr und Mahnsperre ergänzt.",
|
||||
"Splash-Screen auf das eingebettete CCMA-Hintergrundmotiv umgestellt und redundante Titeltexte entfernt.",
|
||||
"Konfigurierbare Mindestanzeigezeit des Splash-Screens mit fünf Sekunden Standardwert ergänzt.",
|
||||
"Hausmeister um konfigurierbare Geburtstags- und Mitgliedsjubiläumsmeldungen erweitert.",
|
||||
"Statusänderungen werden mit altem und neuem Klartextwert in der Mitgliederchronik protokolliert.",
|
||||
"Fensterposition, normaler Fensterzustand und Maximierung werden gespeichert; der Splash startet auf dem zuletzt verwendeten Monitor.",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
@@ -18,6 +19,7 @@ class AppConfig:
|
||||
gnucash_path: str = ""
|
||||
theme_mode: str = "dark"
|
||||
run_housekeeper_on_startup: bool = True
|
||||
splash_minimum_seconds: float = 5.0
|
||||
birthday_days_before: int = 7
|
||||
birthday_days_after: int = 2
|
||||
anniversary_days_before: int = 14
|
||||
@@ -40,6 +42,7 @@ class AppConfig:
|
||||
"gnucash_path": self.gnucash_path,
|
||||
"theme_mode": self.theme_mode,
|
||||
"run_housekeeper_on_startup": self.run_housekeeper_on_startup,
|
||||
"splash_minimum_seconds": _non_negative_float(self.splash_minimum_seconds, 5.0),
|
||||
"birthday_days_before": self.birthday_days_before,
|
||||
"birthday_days_after": self.birthday_days_after,
|
||||
"anniversary_days_before": self.anniversary_days_before,
|
||||
@@ -96,6 +99,7 @@ def load_config() -> AppConfig:
|
||||
gnucash_path=str(data.get("gnucash_path", "")),
|
||||
theme_mode=str(data.get("theme_mode", "dark")),
|
||||
run_housekeeper_on_startup=bool(data.get("run_housekeeper_on_startup", True)),
|
||||
splash_minimum_seconds=_non_negative_float(data.get("splash_minimum_seconds", 5.0), 5.0),
|
||||
birthday_days_before=int(data.get("birthday_days_before", 7)),
|
||||
birthday_days_after=int(data.get("birthday_days_after", 2)),
|
||||
anniversary_days_before=int(data.get("anniversary_days_before", 14)),
|
||||
@@ -113,3 +117,11 @@ def _legacy_config_directory() -> Path:
|
||||
if os.name == "nt":
|
||||
return Path(os.environ.get("APPDATA", Path.home())) / "C3MA"
|
||||
return Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config")) / "c3ma"
|
||||
|
||||
|
||||
def _non_negative_float(value: object, default: float) -> float:
|
||||
try:
|
||||
parsed = float(value)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
return max(0.0, parsed) if math.isfinite(parsed) else default
|
||||
|
||||
+25
-1
@@ -1,6 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
import threading
|
||||
import time
|
||||
import tkinter as tk
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
@@ -33,6 +35,7 @@ class SplashScreen(tk.Toplevel):
|
||||
run_housekeeper: bool = True,
|
||||
monitor: MonitorBounds | None = None,
|
||||
housekeeper_settings: HousekeeperSettings | None = None,
|
||||
minimum_display_seconds: float = 5.0,
|
||||
):
|
||||
super().__init__(master)
|
||||
self.repository = repository
|
||||
@@ -41,6 +44,10 @@ class SplashScreen(tk.Toplevel):
|
||||
self.run_housekeeper = run_housekeeper
|
||||
self.monitor = monitor
|
||||
self.housekeeper_settings = housekeeper_settings
|
||||
self.minimum_display_seconds = (
|
||||
max(0.0, float(minimum_display_seconds)) if math.isfinite(float(minimum_display_seconds)) else 5.0
|
||||
)
|
||||
self.shown_at = time.monotonic()
|
||||
self._messages: Queue[tuple[str, object]] = Queue()
|
||||
self.overrideredirect(True)
|
||||
self.resizable(False, False)
|
||||
@@ -145,7 +152,15 @@ class SplashScreen(tk.Toplevel):
|
||||
def _finish(self, result: StartupResult) -> None:
|
||||
self.progress.stop()
|
||||
self._set_status(f"Bereit · {len(result.findings)} Vorgänge benötigen Aufmerksamkeit")
|
||||
self.after(350, lambda: self._complete(result))
|
||||
self._after_minimum(lambda: self._complete(result))
|
||||
|
||||
def _after_minimum(self, callback: Callable[[], None]) -> None:
|
||||
remaining_ms = _remaining_minimum_ms(
|
||||
self.shown_at,
|
||||
self.minimum_display_seconds,
|
||||
time.monotonic(),
|
||||
)
|
||||
self.after(remaining_ms, callback)
|
||||
|
||||
def _set_status(self, text: str) -> None:
|
||||
self.canvas.itemconfigure(self.status_item, text=text)
|
||||
@@ -156,6 +171,10 @@ class SplashScreen(tk.Toplevel):
|
||||
|
||||
def _fail(self, error: Exception) -> None:
|
||||
self.progress.stop()
|
||||
self._set_status("Start fehlgeschlagen")
|
||||
self._after_minimum(lambda: self._complete_error(error))
|
||||
|
||||
def _complete_error(self, error: Exception) -> None:
|
||||
self.destroy()
|
||||
self.on_error(error)
|
||||
|
||||
@@ -177,3 +196,8 @@ def centered_position(
|
||||
x = min(max(pointer_x - width // 2, screen_x), maximum_x)
|
||||
y = min(max(pointer_y - height // 2, screen_y), maximum_y)
|
||||
return x, y
|
||||
|
||||
|
||||
def _remaining_minimum_ms(started_at: float, minimum_seconds: float, now: float) -> int:
|
||||
remaining = max(0.0, minimum_seconds - max(0.0, now - started_at))
|
||||
return int(remaining * 1000 + 0.999)
|
||||
|
||||
Reference in New Issue
Block a user