feat: Material Icons, customizable app name & dark/light mode toggle

- Add Google Material Icons integration with smart_toy robot icon
- Implement app_settings database table for persistent configuration
- Add App Name customization in Settings (changes navigation & title)
- Add Dark/Light Mode theme switcher
  - Dark Mode: Lightened black (#0f0f0f) with blue accents (#0a84ff)
  - Light Mode: Clean white/gray with red accents (#ef4444)
- Create context_processor for global app_settings injection
- Redesign Settings page with new App Design section
- Optimize CSS: 724 additions, reduced complexity
- Remove outdated agent reminders (70 lines cleanup)
This commit is contained in:
pdyde 2026-02-21 16:59:18 +01:00
parent f43bf1646d
commit 2a9941f35f
14 changed files with 461 additions and 582 deletions

63
app.py
View file

@ -289,6 +289,38 @@ def init_journal():
)
""")
# App-Settings Tabelle für globale Einstellungen
con.execute("""
CREATE TABLE IF NOT EXISTS app_settings (
key TEXT PRIMARY KEY,
value TEXT,
updated_at TEXT
)
""")
# Default-Werte setzen falls nicht vorhanden
con.execute("""
INSERT OR IGNORE INTO app_settings (key, value, updated_at)
VALUES ('app_name', 'Frankenbot', ?), ('theme', 'dark', ?)
""", (datetime.now().isoformat(), datetime.now().isoformat()))
con.commit()
con.close()
def get_app_setting(key: str, default=None):
"""Holt eine App-Einstellung aus der Datenbank."""
con = sqlite3.connect(EMAIL_JOURNAL_DB)
row = con.execute("SELECT value FROM app_settings WHERE key=?", (key,)).fetchone()
con.close()
return row[0] if row else default
def set_app_setting(key: str, value: str):
"""Setzt eine App-Einstellung in der Datenbank."""
con = sqlite3.connect(EMAIL_JOURNAL_DB)
con.execute("""
INSERT OR REPLACE INTO app_settings (key, value, updated_at)
VALUES (?, ?, ?)
""", (key, value, datetime.now().isoformat()))
con.commit()
con.close()
@ -347,6 +379,14 @@ app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@app.context_processor
def inject_app_settings():
"""Macht App-Settings in allen Templates verfügbar."""
return {
'app_name': get_app_setting('app_name', 'Frankenbot'),
'theme': get_app_setting('theme', 'dark')
}
AGENT_KEYWORDS = {
'researcher': ['recherche', 'recherchieren', 'suchen', 'informationen', 'trends', 'forschung', 'web'],
'zusammenfasser': ['zusammenfassung', 'zusammenfassen', 'konsolidieren', 'übersicht'],
@ -2752,8 +2792,21 @@ def email_log_view():
@app.route('/settings', methods=['GET', 'POST'])
def settings():
"""Poller-Einstellungen zur Laufzeit ändern."""
"""App-Einstellungen & Poller-Einstellungen zur Laufzeit ändern."""
if request.method == 'POST':
# App-Name & Theme Einstellungen
if 'app_name' in request.form:
app_name = request.form.get('app_name', 'Frankenbot').strip()
theme = request.form.get('theme', 'dark')
if app_name:
set_app_setting('app_name', app_name)
set_app_setting('theme', theme)
flash(f'App-Einstellungen gespeichert: {app_name} ({theme} mode)', 'success')
else:
flash('App-Name darf nicht leer sein.', 'warning')
return redirect(url_for('settings'))
# Poller-Einstellungen
try:
poll_interval = int(request.form.get('poll_interval', 120))
failsafe_window = int(request.form.get('failsafe_window', 600))
@ -2776,12 +2829,18 @@ def settings():
).fetchall()
con.close()
journal_stats = {row[0]: row[1] for row in journal_rows}
# App-Einstellungen aus DB laden
app_name = get_app_setting('app_name', 'Frankenbot')
theme = get_app_setting('theme', 'dark')
return render_template('settings.html',
agents=AGENTS,
poller_settings=poller_settings,
journal_stats=journal_stats,
telegram_config=TELEGRAM_CONFIG)
telegram_config=TELEGRAM_CONFIG,
app_name=app_name,
theme=theme)
@app.route('/settings/journal-clear', methods=['POST'])