Add Preferences UI and config persistence in mac_cocoa.py
Co-authored-by: Copilot <[email protected]>
This commit is contained in:
1 parent
12c168bbfe
commit
46470ced11
1 file changed
+159
+159
@@ -6,6 +6,8 @@ This is a minimal native UI: Generate Report, Copy to Clipboard, and Debug outpu
|
||||
|
||||
import os
|
||||
import threading
|
||||
import json
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from app import current_week, format_date_range, get_latest_sunday, get_previous_sunday
|
||||
from clients import jellyfin
|
||||
@@ -13,6 +15,34 @@ from clients import jellyfin
|
||||
import objc
|
||||
from AppKit import *
|
||||
|
||||
CONFIG_PATH = str(Path.home() / ".media_episodes_viewer_config.json")
|
||||
|
||||
|
||||
def load_config():
|
||||
try:
|
||||
with open(CONFIG_PATH, "r") as f:
|
||||
return json.load(f)
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
|
||||
def save_config(cfg: dict) -> bool:
|
||||
try:
|
||||
with open(CONFIG_PATH, "w") as f:
|
||||
json.dump(cfg, f)
|
||||
# update process environment so jellyfin client picks values up
|
||||
if cfg.get("host"):
|
||||
os.environ["JELLYFIN_HOST"] = cfg.get("host").rstrip("/")
|
||||
if cfg.get("key"):
|
||||
os.environ["JELLYFIN_API_KEY"] = cfg.get("key")
|
||||
if cfg.get("user"):
|
||||
os.environ["JELLYFIN_USER_ID"] = cfg.get("user")
|
||||
if cfg.get("total_episodes"):
|
||||
os.environ["TOTAL_EPISODES"] = str(cfg.get("total_episodes"))
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
class AppDelegate(NSObject):
|
||||
def applicationDidFinishLaunching_(self, notification):
|
||||
@@ -42,6 +72,13 @@ class AppDelegate(NSObject):
|
||||
gen_btn.setAction_("generateReport:")
|
||||
content.addSubview_(gen_btn)
|
||||
|
||||
# Preferences button
|
||||
prefs_btn = NSButton.alloc().initWithFrame_(NSMakeRect(620, 610, 120, 30))
|
||||
prefs_btn.setTitle_("Preferences...")
|
||||
prefs_btn.setTarget_(self)
|
||||
prefs_btn.setAction_("openPreferences:")
|
||||
content.addSubview_(prefs_btn)
|
||||
|
||||
# Report label and box
|
||||
report_label = NSTextField.alloc().initWithFrame_(NSMakeRect(20, 580, 200, 18))
|
||||
report_label.setStringValue_("Report:")
|
||||
@@ -169,6 +206,128 @@ class AppDelegate(NSObject):
|
||||
alert.setInformativeText_(str(e))
|
||||
alert.runModal()
|
||||
|
||||
def openPreferences_(self, sender):
|
||||
try:
|
||||
prefs_rect = NSMakeRect(0.0, 0.0, 480.0, 220.0)
|
||||
self.prefs_window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer_(prefs_rect, (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable), NSBackingStoreBuffered, False)
|
||||
self.prefs_window.center()
|
||||
self.prefs_window.setTitle_("Preferences")
|
||||
content = self.prefs_window.contentView()
|
||||
|
||||
# Host
|
||||
host_label = NSTextField.alloc().initWithFrame_(NSMakeRect(20, 170, 120, 18))
|
||||
host_label.setStringValue_("Jellyfin Host:")
|
||||
host_label.setBezeled_(False)
|
||||
host_label.setDrawsBackground_(False)
|
||||
host_label.setEditable_(False)
|
||||
host_label.setSelectable_(False)
|
||||
content.addSubview_(host_label)
|
||||
|
||||
host_field = NSTextField.alloc().initWithFrame_(NSMakeRect(150, 165, 300, 24))
|
||||
host_field.setStringValue_(os.environ.get("JELLYFIN_HOST", ""))
|
||||
content.addSubview_(host_field)
|
||||
self.prefs_host = host_field
|
||||
|
||||
# API Key
|
||||
api_label = NSTextField.alloc().initWithFrame_(NSMakeRect(20, 130, 120, 18))
|
||||
api_label.setStringValue_("API Key:")
|
||||
api_label.setBezeled_(False)
|
||||
api_label.setDrawsBackground_(False)
|
||||
api_label.setEditable_(False)
|
||||
api_label.setSelectable_(False)
|
||||
content.addSubview_(api_label)
|
||||
|
||||
api_field = NSTextField.alloc().initWithFrame_(NSMakeRect(150, 125, 300, 24))
|
||||
api_field.setStringValue_(os.environ.get("JELLYFIN_API_KEY", ""))
|
||||
content.addSubview_(api_field)
|
||||
self.prefs_api_key = api_field
|
||||
|
||||
# User ID
|
||||
user_label = NSTextField.alloc().initWithFrame_(NSMakeRect(20, 90, 120, 18))
|
||||
user_label.setStringValue_("User ID:")
|
||||
user_label.setBezeled_(False)
|
||||
user_label.setDrawsBackground_(False)
|
||||
user_label.setEditable_(False)
|
||||
user_label.setSelectable_(False)
|
||||
content.addSubview_(user_label)
|
||||
|
||||
user_field = NSTextField.alloc().initWithFrame_(NSMakeRect(150, 85, 300, 24))
|
||||
user_field.setStringValue_(os.environ.get("JELLYFIN_USER_ID", ""))
|
||||
content.addSubview_(user_field)
|
||||
self.prefs_user_id = user_field
|
||||
|
||||
# Total episodes
|
||||
total_label = NSTextField.alloc().initWithFrame_(NSMakeRect(20, 50, 120, 18))
|
||||
total_label.setStringValue_("Total Episodes:")
|
||||
total_label.setBezeled_(False)
|
||||
total_label.setDrawsBackground_(False)
|
||||
total_label.setEditable_(False)
|
||||
total_label.setSelectable_(False)
|
||||
content.addSubview_(total_label)
|
||||
|
||||
total_field = NSTextField.alloc().initWithFrame_(NSMakeRect(150, 45, 100, 24))
|
||||
total_field.setStringValue_(os.environ.get("TOTAL_EPISODES", "1155"))
|
||||
content.addSubview_(total_field)
|
||||
self.prefs_total_episodes = total_field
|
||||
|
||||
# Save button
|
||||
save_btn = NSButton.alloc().initWithFrame_(NSMakeRect(340, 10, 120, 30))
|
||||
save_btn.setTitle_("Save")
|
||||
save_btn.setTarget_(self)
|
||||
save_btn.setAction_("savePreferences:")
|
||||
content.addSubview_(save_btn)
|
||||
|
||||
self.prefs_window.makeKeyAndOrderFront_(None)
|
||||
NSApp.activateIgnoringOtherApps_(True)
|
||||
except Exception as e:
|
||||
alert = NSAlert.alloc().init()
|
||||
alert.setMessageText_("Prefs failed")
|
||||
alert.setInformativeText_(str(e))
|
||||
alert.runModal()
|
||||
|
||||
def savePreferences_(self, sender):
|
||||
try:
|
||||
host = (self.prefs_host.string() or "").strip()
|
||||
key = (self.prefs_api_key.string() or "").strip()
|
||||
user = (self.prefs_user_id.string() or "").strip()
|
||||
total = (self.prefs_total_episodes.string() or "").strip()
|
||||
cfg = {}
|
||||
if host:
|
||||
cfg["host"] = host
|
||||
if key:
|
||||
cfg["key"] = key
|
||||
if user:
|
||||
cfg["user"] = user
|
||||
if total:
|
||||
try:
|
||||
cfg["total_episodes"] = int(total)
|
||||
except Exception:
|
||||
pass
|
||||
ok = save_config(cfg)
|
||||
if ok:
|
||||
alert = NSAlert.alloc().init()
|
||||
alert.setMessageText_("Saved")
|
||||
alert.setInformativeText_("Preferences saved.")
|
||||
alert.runModal()
|
||||
try:
|
||||
self.debug_view.setString_(f"Saved config: host={cfg.get('host')}, user={cfg.get('user')}, total={cfg.get('total_episodes')}\n" + (self.debug_view.string() or ""))
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
self.prefs_window.close()
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
alert = NSAlert.alloc().init()
|
||||
alert.setMessageText_("Save failed")
|
||||
alert.setInformativeText_("Could not write config file")
|
||||
alert.runModal()
|
||||
except Exception as e:
|
||||
alert = NSAlert.alloc().init()
|
||||
alert.setMessageText_("Save failed")
|
||||
alert.setInformativeText_(str(e))
|
||||
alert.runModal()
|
||||
|
||||
|
||||
def main():
|
||||
app = NSApplication.sharedApplication()
|
||||
|
||||
Reference in new issue
Block a user