fix disk monitor preferences profile ownership
This commit is contained in:
+52
-2
@@ -137,8 +137,8 @@ CREATE INDEX IF NOT EXISTS idx_jobs_created ON jobs(created_at);
|
|||||||
CREATE INDEX IF NOT EXISTS idx_jobs_profile_created ON jobs(profile_id, created_at);
|
CREATE INDEX IF NOT EXISTS idx_jobs_profile_created ON jobs(profile_id, created_at);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS disk_monitor_preferences (
|
CREATE TABLE IF NOT EXISTS disk_monitor_preferences (
|
||||||
|
profile_id INTEGER PRIMARY KEY,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
profile_id INTEGER NOT NULL,
|
|
||||||
paths_json TEXT,
|
paths_json TEXT,
|
||||||
mode TEXT DEFAULT 'default',
|
mode TEXT DEFAULT 'default',
|
||||||
selected_path TEXT,
|
selected_path TEXT,
|
||||||
@@ -146,10 +146,10 @@ CREATE TABLE IF NOT EXISTS disk_monitor_preferences (
|
|||||||
stop_threshold INTEGER DEFAULT 98,
|
stop_threshold INTEGER DEFAULT 98,
|
||||||
created_at TEXT NOT NULL,
|
created_at TEXT NOT NULL,
|
||||||
updated_at TEXT NOT NULL,
|
updated_at TEXT NOT NULL,
|
||||||
PRIMARY KEY(user_id, profile_id),
|
|
||||||
FOREIGN KEY(user_id) REFERENCES users(id),
|
FOREIGN KEY(user_id) REFERENCES users(id),
|
||||||
FOREIGN KEY(profile_id) REFERENCES rtorrent_profiles(id)
|
FOREIGN KEY(profile_id) REFERENCES rtorrent_profiles(id)
|
||||||
);
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_disk_monitor_preferences_owner ON disk_monitor_preferences(user_id);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS labels (
|
CREATE TABLE IF NOT EXISTS labels (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
@@ -531,6 +531,55 @@ def create_schema(conn: sqlite3.Connection) -> None:
|
|||||||
conn.executescript(SCHEMA)
|
conn.executescript(SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_profile_scoped_disk_monitor_preferences(conn: sqlite3.Connection) -> None:
|
||||||
|
"""Migrate disk monitor settings from user+profile rows to one shared row per profile."""
|
||||||
|
columns = conn.execute("PRAGMA table_info(disk_monitor_preferences)").fetchall()
|
||||||
|
pk_columns = [str(row["name"]) for row in columns if int(row.get("pk") or 0)]
|
||||||
|
if pk_columns == ["profile_id"]:
|
||||||
|
conn.execute("CREATE INDEX IF NOT EXISTS idx_disk_monitor_preferences_owner ON disk_monitor_preferences(user_id)")
|
||||||
|
return
|
||||||
|
|
||||||
|
now = utcnow()
|
||||||
|
conn.execute("DROP INDEX IF EXISTS idx_disk_monitor_preferences_owner")
|
||||||
|
conn.execute("DROP TABLE IF EXISTS disk_monitor_preferences_new")
|
||||||
|
conn.execute("DROP TABLE IF EXISTS disk_monitor_preferences_old_user_profile")
|
||||||
|
conn.execute("""
|
||||||
|
CREATE TABLE disk_monitor_preferences_new (
|
||||||
|
profile_id INTEGER PRIMARY KEY,
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
paths_json TEXT,
|
||||||
|
mode TEXT DEFAULT 'default',
|
||||||
|
selected_path TEXT,
|
||||||
|
stop_enabled INTEGER DEFAULT 0,
|
||||||
|
stop_threshold INTEGER DEFAULT 98,
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id),
|
||||||
|
FOREIGN KEY(profile_id) REFERENCES rtorrent_profiles(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
conn.execute("""
|
||||||
|
INSERT INTO disk_monitor_preferences_new(
|
||||||
|
profile_id,user_id,paths_json,mode,selected_path,stop_enabled,stop_threshold,created_at,updated_at
|
||||||
|
)
|
||||||
|
SELECT profile_id,user_id,paths_json,mode,selected_path,stop_enabled,stop_threshold,
|
||||||
|
COALESCE(created_at, ?), COALESCE(updated_at, ?)
|
||||||
|
FROM (
|
||||||
|
SELECT d.*,
|
||||||
|
ROW_NUMBER() OVER (
|
||||||
|
PARTITION BY profile_id
|
||||||
|
ORDER BY COALESCE(updated_at, created_at, '') DESC, user_id ASC
|
||||||
|
) AS rn
|
||||||
|
FROM disk_monitor_preferences d
|
||||||
|
WHERE profile_id IS NOT NULL
|
||||||
|
)
|
||||||
|
WHERE rn=1
|
||||||
|
""", (now, now))
|
||||||
|
conn.execute("ALTER TABLE disk_monitor_preferences RENAME TO disk_monitor_preferences_old_user_profile")
|
||||||
|
conn.execute("ALTER TABLE disk_monitor_preferences_new RENAME TO disk_monitor_preferences")
|
||||||
|
conn.execute("CREATE INDEX IF NOT EXISTS idx_disk_monitor_preferences_owner ON disk_monitor_preferences(user_id)")
|
||||||
|
|
||||||
|
|
||||||
def seed_default_user(conn: sqlite3.Connection) -> None:
|
def seed_default_user(conn: sqlite3.Connection) -> None:
|
||||||
"""Ensure the built-in admin user and default preferences exist."""
|
"""Ensure the built-in admin user and default preferences exist."""
|
||||||
now = utcnow()
|
now = utcnow()
|
||||||
@@ -584,6 +633,7 @@ def init_db():
|
|||||||
except sqlite3.OperationalError:
|
except sqlite3.OperationalError:
|
||||||
pass
|
pass
|
||||||
create_schema(conn)
|
create_schema(conn)
|
||||||
|
ensure_profile_scoped_disk_monitor_preferences(conn)
|
||||||
seed_default_user(conn)
|
seed_default_user(conn)
|
||||||
try:
|
try:
|
||||||
from .services.auth import ensure_admin_user
|
from .services.auth import ensure_admin_user
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ PROFILE_BACKUP_TABLES = [
|
|||||||
PROFILE_TABLE_SCOPES = {
|
PROFILE_TABLE_SCOPES = {
|
||||||
"rtorrent_profiles": "profile_id",
|
"rtorrent_profiles": "profile_id",
|
||||||
"profile_preferences": "user_profile",
|
"profile_preferences": "user_profile",
|
||||||
"disk_monitor_preferences": "user_profile",
|
"disk_monitor_preferences": "profile",
|
||||||
"labels": "profile",
|
"labels": "profile",
|
||||||
"ratio_groups": "profile",
|
"ratio_groups": "profile",
|
||||||
"rss_feeds": "profile",
|
"rss_feeds": "profile",
|
||||||
@@ -44,7 +44,7 @@ PROFILE_TABLE_SCOPES = {
|
|||||||
PROFILE_TABLE_FILTERS = {
|
PROFILE_TABLE_FILTERS = {
|
||||||
"rtorrent_profiles": "id=?",
|
"rtorrent_profiles": "id=?",
|
||||||
"profile_preferences": "user_id=? AND profile_id=?",
|
"profile_preferences": "user_id=? AND profile_id=?",
|
||||||
"disk_monitor_preferences": "user_id=? AND profile_id=?",
|
"disk_monitor_preferences": "profile_id=?",
|
||||||
"labels": "profile_id=?",
|
"labels": "profile_id=?",
|
||||||
"ratio_groups": "profile_id=?",
|
"ratio_groups": "profile_id=?",
|
||||||
"rss_feeds": "profile_id=?",
|
"rss_feeds": "profile_id=?",
|
||||||
@@ -273,6 +273,12 @@ def restore_app_backup(backup_id: int, user_id: int | None = None) -> dict:
|
|||||||
return {"restored": restored, "backup_type": "app"}
|
return {"restored": restored, "backup_type": "app"}
|
||||||
|
|
||||||
|
|
||||||
|
def _single_profile_row(rows: list[dict]) -> list[dict]:
|
||||||
|
if not rows:
|
||||||
|
return []
|
||||||
|
return [sorted(rows, key=lambda row: str(row.get("updated_at") or row.get("created_at") or ""), reverse=True)[0]]
|
||||||
|
|
||||||
|
|
||||||
def _rewrite_profile_row(table: str, row: dict, user_id: int, target_profile_id: int) -> dict:
|
def _rewrite_profile_row(table: str, row: dict, user_id: int, target_profile_id: int) -> dict:
|
||||||
clean = dict(row)
|
clean = dict(row)
|
||||||
if table == "rtorrent_profiles":
|
if table == "rtorrent_profiles":
|
||||||
@@ -305,6 +311,8 @@ def restore_profile_backup(backup_id: int, target_profile_id: int, user_id: int
|
|||||||
try:
|
try:
|
||||||
for table in PROFILE_BACKUP_TABLES:
|
for table in PROFILE_BACKUP_TABLES:
|
||||||
rows = tables.get(table) or []
|
rows = tables.get(table) or []
|
||||||
|
if table == "disk_monitor_preferences":
|
||||||
|
rows = _single_profile_row([dict(row) for row in rows])
|
||||||
where = PROFILE_TABLE_FILTERS.get(table)
|
where = PROFILE_TABLE_FILTERS.get(table)
|
||||||
params = _profile_filter_params(table, user_id, int(target_profile_id))
|
params = _profile_filter_params(table, user_id, int(target_profile_id))
|
||||||
conn.execute(f"DELETE FROM {table} WHERE {where}", params)
|
conn.execute(f"DELETE FROM {table} WHERE {where}", params)
|
||||||
|
|||||||
@@ -296,17 +296,39 @@ def legacy_disk_monitor_preferences(user_id: int | None = None) -> dict:
|
|||||||
return _normalize_disk_monitor(row)
|
return _normalize_disk_monitor(row)
|
||||||
|
|
||||||
|
|
||||||
|
def _disk_monitor_owner_label(row: dict | None) -> str:
|
||||||
|
if not row:
|
||||||
|
return ""
|
||||||
|
return str(row.get("owner_display_name") or row.get("owner_username") or row.get("owner_email") or (f"user #{row.get('user_id')}" if row.get("user_id") else "")).strip()
|
||||||
|
|
||||||
|
|
||||||
def get_disk_monitor_preferences(profile_id: int | None = None, user_id: int | None = None) -> dict:
|
def get_disk_monitor_preferences(profile_id: int | None = None, user_id: int | None = None) -> dict:
|
||||||
user_id = user_id or auth.current_user_id() or default_user_id()
|
user_id = user_id or auth.current_user_id() or default_user_id()
|
||||||
profile_id = int(profile_id or _active_profile_id_for_user(user_id) or 0)
|
profile_id = int(profile_id or _active_profile_id_for_user(user_id) or 0)
|
||||||
if not profile_id:
|
if not profile_id:
|
||||||
return legacy_disk_monitor_preferences(user_id)
|
return legacy_disk_monitor_preferences(user_id)
|
||||||
|
if not auth.can_access_profile(profile_id, user_id):
|
||||||
|
return legacy_disk_monitor_preferences(user_id)
|
||||||
with connect() as conn:
|
with connect() as conn:
|
||||||
row = conn.execute("SELECT * FROM disk_monitor_preferences WHERE user_id=? AND profile_id=?", (user_id, profile_id)).fetchone()
|
row = conn.execute(
|
||||||
|
"""
|
||||||
|
SELECT d.*, u.username AS owner_username, u.display_name AS owner_display_name, u.email AS owner_email
|
||||||
|
FROM disk_monitor_preferences d
|
||||||
|
LEFT JOIN users u ON u.id=d.user_id
|
||||||
|
WHERE d.profile_id=?
|
||||||
|
""",
|
||||||
|
(profile_id,),
|
||||||
|
).fetchone()
|
||||||
if row:
|
if row:
|
||||||
return _normalize_disk_monitor(row)
|
clean = _normalize_disk_monitor(row)
|
||||||
|
clean["disk_monitor_owner_user_id"] = int(row.get("user_id") or 0)
|
||||||
|
clean["disk_monitor_owner_label"] = _disk_monitor_owner_label(row)
|
||||||
|
return clean
|
||||||
# Backward-compatible seed: existing global disk monitor values become defaults for first use of a profile.
|
# Backward-compatible seed: existing global disk monitor values become defaults for first use of a profile.
|
||||||
return legacy_disk_monitor_preferences(user_id)
|
clean = legacy_disk_monitor_preferences(user_id)
|
||||||
|
clean["disk_monitor_owner_user_id"] = 0
|
||||||
|
clean["disk_monitor_owner_label"] = ""
|
||||||
|
return clean
|
||||||
|
|
||||||
|
|
||||||
def save_disk_monitor_preferences(profile_id: int | None, data: dict, user_id: int | None = None) -> dict:
|
def save_disk_monitor_preferences(profile_id: int | None, data: dict, user_id: int | None = None) -> dict:
|
||||||
@@ -314,6 +336,8 @@ def save_disk_monitor_preferences(profile_id: int | None, data: dict, user_id: i
|
|||||||
profile_id = int(profile_id or _active_profile_id_for_user(user_id) or 0)
|
profile_id = int(profile_id or _active_profile_id_for_user(user_id) or 0)
|
||||||
if not profile_id:
|
if not profile_id:
|
||||||
return legacy_disk_monitor_preferences(user_id)
|
return legacy_disk_monitor_preferences(user_id)
|
||||||
|
if not auth.can_write_profile(profile_id, user_id):
|
||||||
|
raise PermissionError("No write access to profile")
|
||||||
current = get_disk_monitor_preferences(profile_id, user_id)
|
current = get_disk_monitor_preferences(profile_id, user_id)
|
||||||
merged = dict(current)
|
merged = dict(current)
|
||||||
for key in ("disk_monitor_paths_json", "disk_monitor_mode", "disk_monitor_selected_path", "disk_monitor_stop_enabled", "disk_monitor_stop_threshold"):
|
for key in ("disk_monitor_paths_json", "disk_monitor_mode", "disk_monitor_selected_path", "disk_monitor_stop_enabled", "disk_monitor_stop_threshold"):
|
||||||
@@ -323,10 +347,14 @@ def save_disk_monitor_preferences(profile_id: int | None, data: dict, user_id: i
|
|||||||
now = utcnow()
|
now = utcnow()
|
||||||
with connect() as conn:
|
with connect() as conn:
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"INSERT INTO disk_monitor_preferences(user_id,profile_id,paths_json,mode,selected_path,stop_enabled,stop_threshold,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?,?) "
|
"INSERT INTO disk_monitor_preferences(profile_id,user_id,paths_json,mode,selected_path,stop_enabled,stop_threshold,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?,?) "
|
||||||
"ON CONFLICT(user_id,profile_id) DO UPDATE SET paths_json=excluded.paths_json, mode=excluded.mode, selected_path=excluded.selected_path, stop_enabled=excluded.stop_enabled, stop_threshold=excluded.stop_threshold, updated_at=excluded.updated_at",
|
"ON CONFLICT(profile_id) DO UPDATE SET user_id=excluded.user_id, paths_json=excluded.paths_json, mode=excluded.mode, selected_path=excluded.selected_path, stop_enabled=excluded.stop_enabled, stop_threshold=excluded.stop_threshold, updated_at=excluded.updated_at",
|
||||||
(user_id, profile_id, clean["disk_monitor_paths_json"], clean["disk_monitor_mode"], clean["disk_monitor_selected_path"], clean["disk_monitor_stop_enabled"], clean["disk_monitor_stop_threshold"], now, now),
|
(profile_id, user_id, clean["disk_monitor_paths_json"], clean["disk_monitor_mode"], clean["disk_monitor_selected_path"], clean["disk_monitor_stop_enabled"], clean["disk_monitor_stop_threshold"], now, now),
|
||||||
)
|
)
|
||||||
|
clean["disk_monitor_owner_user_id"] = int(user_id)
|
||||||
|
with connect() as conn:
|
||||||
|
row = conn.execute("SELECT display_name AS owner_display_name, username AS owner_username, email AS owner_email, id AS user_id FROM users WHERE id=?", (user_id,)).fetchone()
|
||||||
|
clean["disk_monitor_owner_label"] = _disk_monitor_owner_label(row)
|
||||||
return clean
|
return clean
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ def _clear_disk_refresh_cache(profile_id: int) -> None:
|
|||||||
|
|
||||||
def _emit_profile_disk_refresh(profile_id: int, reason: str, hash_count: int = 0, delay_seconds: int = 0) -> None:
|
def _emit_profile_disk_refresh(profile_id: int, reason: str, hash_count: int = 0, delay_seconds: int = 0) -> None:
|
||||||
_clear_disk_refresh_cache(profile_id)
|
_clear_disk_refresh_cache(profile_id)
|
||||||
# Note: The browser performs the fresh /api/system/disk read so user-specific disk monitor preferences stay respected.
|
# Note: The browser performs the fresh /api/system/disk read so profile-scoped disk monitor preferences stay respected.
|
||||||
_emit("disk_refresh_requested", {
|
_emit("disk_refresh_requested", {
|
||||||
"profile_id": int(profile_id),
|
"profile_id": int(profile_id),
|
||||||
"hash_count": int(hash_count or 0),
|
"hash_count": int(hash_count or 0),
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
export const preferencesToolsSource = " async function loadPreferences(){\n try{\n const j=await (await fetch(`/api/preferences?_=${Date.now()}`, {cache:'no-store'})).json();\n const prefs=j.preferences||{};\n portCheckEnabled=!!Number(prefs.port_check_enabled ?? portCheckEnabled);\n reverseDnsEnabled=!!Number(prefs.reverse_dns_enabled ?? (reverseDnsEnabled?1:0));\n if($('reverseDnsEnabled')) $('reverseDnsEnabled').checked=reverseDnsEnabled;\n automationToastsEnabled=Number(prefs.automation_toasts_enabled ?? (automationToastsEnabled?1:0))!==0;\n smartQueueToastsEnabled=Number(prefs.smart_queue_toasts_enabled ?? (smartQueueToastsEnabled?1:0))!==0;\n easterEggEnabled=Number(prefs.easter_egg_enabled ?? (easterEggEnabled?1:0))!==0;\n easterEggLoadingImageUrl=String(prefs.easter_egg_loading_image_url ?? easterEggLoadingImageUrl ?? '').trim();\n easterEggClickImageUrl=String(prefs.easter_egg_click_image_url ?? easterEggClickImageUrl ?? '').trim();\n diskMonitorMode=prefs.disk_monitor_mode||diskMonitorMode;\n diskMonitorSelectedPath=prefs.disk_monitor_selected_path||'';\n try{ diskMonitorPaths=JSON.parse(prefs.disk_monitor_paths_json||'[]'); }catch(_){ diskMonitorPaths=[]; }\n bootstrapTheme=prefs.bootstrap_theme||bootstrapTheme;\n fontFamily=prefs.font_family||fontFamily;\n interfaceScale=Number(prefs.interface_scale||interfaceScale||100);\n torrentListFontSize=clampTorrentListFontSize(prefs.torrent_list_font_size||torrentListFontSize||13);\n compactTorrentListEnabled=Number(prefs.compact_torrent_list_enabled ?? (compactTorrentListEnabled?1:0))!==0;\n try{ footerItems={...DEFAULT_FOOTER_ITEMS,...JSON.parse(prefs.footer_items_json||'{}')}; }catch(_){ footerItems={...DEFAULT_FOOTER_ITEMS}; }\n }catch(e){ console.warn('Preference load failed', e); }\n if($('portCheckEnabled')) $('portCheckEnabled').checked=portCheckEnabled; if($('automationToastsEnabled')) $('automationToastsEnabled').checked=automationToastsEnabled; if($('smartQueueToastsEnabled')) $('smartQueueToastsEnabled').checked=smartQueueToastsEnabled; if($('easterEggEnabled')) $('easterEggEnabled').checked=easterEggEnabled; if($('easterEggLoadingImageUrl')) $('easterEggLoadingImageUrl').value=easterEggLoadingImageUrl; if($('easterEggClickImageUrl')) $('easterEggClickImageUrl').value=easterEggClickImageUrl; if($('diskMonitorMode')) $('diskMonitorMode').value=diskMonitorMode; if($('diskMonitorSelectedPath')) $('diskMonitorSelectedPath').value=diskMonitorSelectedPath; renderDiskMonitorPaths(); applyInitialLoaderEasterEgg(); scheduleRender(true); applyBootstrapTheme(bootstrapTheme); applyFontFamily(fontFamily); applyInterfaceScale(interfaceScale); applyTorrentListFontSize(torrentListFontSize); applyCompactTorrentList(compactTorrentListEnabled); renderFooterPreferences(); applyFooterPreferences(); await loadPortCheck(false); }";
|
export const preferencesToolsSource = " async function loadPreferences(){\n try{\n const j=await (await fetch(`/api/preferences?_=${Date.now()}`, {cache:'no-store'})).json();\n const prefs=j.preferences||{};\n portCheckEnabled=!!Number(prefs.port_check_enabled ?? portCheckEnabled);\n reverseDnsEnabled=!!Number(prefs.reverse_dns_enabled ?? (reverseDnsEnabled?1:0));\n if($('reverseDnsEnabled')) $('reverseDnsEnabled').checked=reverseDnsEnabled;\n automationToastsEnabled=Number(prefs.automation_toasts_enabled ?? (automationToastsEnabled?1:0))!==0;\n smartQueueToastsEnabled=Number(prefs.smart_queue_toasts_enabled ?? (smartQueueToastsEnabled?1:0))!==0;\n easterEggEnabled=Number(prefs.easter_egg_enabled ?? (easterEggEnabled?1:0))!==0;\n easterEggLoadingImageUrl=String(prefs.easter_egg_loading_image_url ?? easterEggLoadingImageUrl ?? '').trim();\n easterEggClickImageUrl=String(prefs.easter_egg_click_image_url ?? easterEggClickImageUrl ?? '').trim();\n diskMonitorMode=prefs.disk_monitor_mode||diskMonitorMode;\n diskMonitorSelectedPath=prefs.disk_monitor_selected_path||'';\n diskMonitorOwnerLabel=String(prefs.disk_monitor_owner_label||'').trim();\n try{ diskMonitorPaths=JSON.parse(prefs.disk_monitor_paths_json||'[]'); }catch(_){ diskMonitorPaths=[]; }\n bootstrapTheme=prefs.bootstrap_theme||bootstrapTheme;\n fontFamily=prefs.font_family||fontFamily;\n interfaceScale=Number(prefs.interface_scale||interfaceScale||100);\n torrentListFontSize=clampTorrentListFontSize(prefs.torrent_list_font_size||torrentListFontSize||13);\n compactTorrentListEnabled=Number(prefs.compact_torrent_list_enabled ?? (compactTorrentListEnabled?1:0))!==0;\n try{ footerItems={...DEFAULT_FOOTER_ITEMS,...JSON.parse(prefs.footer_items_json||'{}')}; }catch(_){ footerItems={...DEFAULT_FOOTER_ITEMS}; }\n }catch(e){ console.warn('Preference load failed', e); }\n if($('portCheckEnabled')) $('portCheckEnabled').checked=portCheckEnabled; if($('automationToastsEnabled')) $('automationToastsEnabled').checked=automationToastsEnabled; if($('smartQueueToastsEnabled')) $('smartQueueToastsEnabled').checked=smartQueueToastsEnabled; if($('easterEggEnabled')) $('easterEggEnabled').checked=easterEggEnabled; if($('easterEggLoadingImageUrl')) $('easterEggLoadingImageUrl').value=easterEggLoadingImageUrl; if($('easterEggClickImageUrl')) $('easterEggClickImageUrl').value=easterEggClickImageUrl; if($('diskMonitorMode')) $('diskMonitorMode').value=diskMonitorMode; if($('diskMonitorSelectedPath')) $('diskMonitorSelectedPath').value=diskMonitorSelectedPath; renderDiskMonitorPaths(); applyInitialLoaderEasterEgg(); scheduleRender(true); applyBootstrapTheme(bootstrapTheme); applyFontFamily(fontFamily); applyInterfaceScale(interfaceScale); applyTorrentListFontSize(torrentListFontSize); applyCompactTorrentList(compactTorrentListEnabled); renderFooterPreferences(); applyFooterPreferences(); await loadPortCheck(false); }";
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user