From 49da04ef4b3031458fae86a87a26d45da9bc1a6a Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Tue, 19 Mar 2024 17:45:25 +0100 Subject: [PATCH 01/13] Also convert [class] in css --- css_inject.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/css_inject.py b/css_inject.py index 6d0b27a..61a9846 100644 --- a/css_inject.py +++ b/css_inject.py @@ -64,6 +64,14 @@ async def load(self) -> Result: if split_css[x].startswith(".") and split_css[x][1:] in CLASS_MAPPINGS: split_css[x] = "." + CLASS_MAPPINGS[split_css[x][1:]] + self.css = ("".join(split_css)).replace("\\", "\\\\").replace("`", "\\`") + + split_css = re.split(r"(\[class[*^|~]=\"[_a-zA-Z0-9-]*\"\])", self.css) + + for x in range(len(split_css)): + if split_css[x].startswith("[class") and split_css[x].endswith("\"]") and split_css[x][9:-2] in CLASS_MAPPINGS: + split_css[x] = split_css[x][0:9] + CLASS_MAPPINGS[split_css[x][9:-2]] + split_css[x][-2:] + self.css = ("".join(split_css)).replace("\\", "\\\\").replace("`", "\\`") Log(f"Loaded css at {self.cssPath}") From 7f048faca53271a5174c0198dfbfa797b2dbba01 Mon Sep 17 00:00:00 2001 From: Beebles <102569435+beebls@users.noreply.github.com> Date: Sun, 24 Mar 2024 17:23:15 -0600 Subject: [PATCH 02/13] add unminify mode --- package.json | 2 +- pnpm-lock.yaml | 8 +-- src/deckyPatches/SteamTabElementsFinder.tsx | 21 +++++++ src/deckyPatches/UnminifyMode.tsx | 62 +++++++++++++++++++++ src/index.tsx | 8 +-- src/pages/settings/PluginSettings.tsx | 22 +++++++- src/state/CssLoaderState.tsx | 3 + 7 files changed, 114 insertions(+), 12 deletions(-) create mode 100644 src/deckyPatches/SteamTabElementsFinder.tsx create mode 100644 src/deckyPatches/UnminifyMode.tsx diff --git a/package.json b/package.json index e868ec8..555dbbc 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ }, "dependencies": { "color": "^4.2.3", - "decky-frontend-lib": "^3.24.3", + "decky-frontend-lib": "^3.25.0", "lodash": "^4.17.21", "react-icons": "^4.12.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index af6d5dc..a7e1df3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^4.2.3 version: 4.2.3 decky-frontend-lib: - specifier: ^3.24.3 - version: 3.24.3 + specifier: ^3.25.0 + version: 3.25.0 lodash: specifier: ^4.17.21 version: 4.17.21 @@ -711,8 +711,8 @@ packages: resolution: {integrity: sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==} dev: true - /decky-frontend-lib@3.24.3: - resolution: {integrity: sha512-293oUaAgLrezvoz+TOQkarjwAlVlejkelB1WjtxQV4Y5qMpUZhNUtfpQAscGhwg9oQy6UGpZ5urkdPzLiVY52w==} + /decky-frontend-lib@3.25.0: + resolution: {integrity: sha512-2lBoHS2AIRmuluq/bGdHBz+uyToQE7k3K/vDq1MQbDZ4eC+8CGDuh2T8yZOj3D0yjGP2MdikNNAWPA9Z5l2qDg==} dev: false /decode-uri-component@0.2.2: diff --git a/src/deckyPatches/SteamTabElementsFinder.tsx b/src/deckyPatches/SteamTabElementsFinder.tsx new file mode 100644 index 0000000..3bdeda0 --- /dev/null +++ b/src/deckyPatches/SteamTabElementsFinder.tsx @@ -0,0 +1,21 @@ +import { getGamepadNavigationTrees } from "decky-frontend-lib"; + +export function getElementFromNavID(navID: string) { + const all = getGamepadNavigationTrees(); + if (!all) return null; + const tree = all?.find((e: any) => e.m_ID == navID); + if (!tree) return null; + return tree.Root.Element; +} +export function getSP() { + return getElementFromNavID("root_1_"); +} +export function getQAM() { + return getElementFromNavID("QuickAccess-NA"); +} +export function getMainMenu() { + return getElementFromNavID("MainNavMenuContainer"); +} +export function getRootElements() { + return [getSP(), getQAM(), getMainMenu()].filter((e) => e); +} diff --git a/src/deckyPatches/UnminifyMode.tsx b/src/deckyPatches/UnminifyMode.tsx new file mode 100644 index 0000000..77c4db2 --- /dev/null +++ b/src/deckyPatches/UnminifyMode.tsx @@ -0,0 +1,62 @@ +import { unminifyClass } from "decky-frontend-lib"; +import { getRootElements } from "./SteamTabElementsFinder"; + +export function unminifyElement(element: Element) { + if (element.classList.length === 0) return; + + const classList = Array.from(element.classList); + const unminifiedClassList = classList.map((c) => unminifyClass(c) ?? c); + element.setAttribute("unminified-class", unminifiedClassList.join(" ")); +} + +export function recursivelyUnminifyElement(element: Element) { + unminifyElement(element); + Array.from(element.children).forEach(recursivelyUnminifyElement); +} + +export function initialUnminification(rootElement: any) { + const allElements = rootElement.ownerDocument.all as HTMLAllCollection; + Array.from(allElements).forEach(unminifyElement); +} + +var mutationObservers: MutationObserver[] = []; + +export function disconnectMutationObservers() { + mutationObservers.forEach((observer) => observer.disconnect()); + mutationObservers = []; +} + +export function mutationObserverCallback(mutations: MutationRecord[]) { + mutations.forEach((mutation) => { + if (mutation.type === "childList" && mutation.addedNodes.length > 0) { + mutation.addedNodes.forEach((node) => { + recursivelyUnminifyElement(node as Element); + }); + } + if (mutation.type === "attributes" && mutation.attributeName === "class") { + unminifyElement(mutation.target as HTMLElement); + } + }); +} + +export function setUpMutationObserver(rootElement: any) { + const mutationObserver = new MutationObserver(mutationObserverCallback); + mutationObserver.observe(rootElement.ownerDocument.documentElement, { + attributes: true, + attributeFilter: ["class"], + childList: true, + subtree: true, + }); + mutationObservers.push(mutationObserver); +} + +export function enableUnminifyMode() { + if (mutationObservers.length > 0) disconnectMutationObservers(); + const roots = getRootElements(); + roots.forEach(initialUnminification); + roots.forEach(setUpMutationObserver); +} + +export function disableUnminifyMode() { + disconnectMutationObservers(); +} diff --git a/src/index.tsx b/src/index.tsx index c0eb4b0..4cd407c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,11 +4,8 @@ import { PanelSection, PanelSectionRow, ServerAPI, - DialogButton, - Focusable, - Navigation, } from "decky-frontend-lib"; -import { useEffect, useState, FC } from "react"; +import { useEffect, useState } from "react"; import * as python from "./python"; import * as api from "./api"; import { RiPaintFill } from "react-icons/ri"; @@ -21,8 +18,8 @@ import { Flags, Theme } from "./ThemeTypes"; import { dummyFunction, getInstalledThemes, reloadBackend } from "./python"; import { bulkThemeUpdateCheck } from "./logic/bulkThemeUpdateCheck"; import { disableNavPatch, enableNavPatch } from "./deckyPatches/NavPatch"; -import { FaCog, FaStore } from "react-icons/fa"; import { SettingsPageRouter } from "./pages/settings/SettingsPageRouter"; +import { disableUnminifyMode } from "./deckyPatches/UnminifyMode"; function Content() { const { localThemeList, setGlobalState } = useCssLoaderState(); @@ -205,6 +202,7 @@ export default definePlugin((serverApi: ServerAPI) => { onDismount: () => { const { updateCheckTimeout } = state.getPublicState(); if (updateCheckTimeout) clearTimeout(updateCheckTimeout); + disableUnminifyMode(); disableNavPatch(); }, }; diff --git a/src/pages/settings/PluginSettings.tsx b/src/pages/settings/PluginSettings.tsx index ae5d89e..2c45681 100644 --- a/src/pages/settings/PluginSettings.tsx +++ b/src/pages/settings/PluginSettings.tsx @@ -1,7 +1,7 @@ import { Focusable, ToggleField } from "decky-frontend-lib"; import { useMemo, useState, useEffect } from "react"; import { useCssLoaderState } from "../../state"; -import { storeWrite, toast } from "../../python"; +import { toast } from "../../python"; import { setNavPatch } from "../../deckyPatches/NavPatch"; import { getWatchState, @@ -11,9 +11,10 @@ import { getBetaTranslationsState, } from "../../backend/pythonMethods/pluginSettingsMethods"; import { booleanStoreWrite } from "../../backend/pythonMethods/storeUtils"; +import { disableUnminifyMode, enableUnminifyMode } from "../../deckyPatches/UnminifyMode"; export function PluginSettings() { - const { navPatchInstance } = useCssLoaderState(); + const { navPatchInstance, unminifyModeOn, setGlobalState } = useCssLoaderState(); const [serverOn, setServerOn] = useState(false); const [watchOn, setWatchOn] = useState(false); const [betaTranslationsOn, setBetaTranslationsOn] = useState(false); @@ -39,6 +40,15 @@ export function PluginSettings() { void fetchBetaTranslationsState(); }, []); + function setUnminify(enabled: boolean) { + setGlobalState("unminifyModeOn", enabled); + if (enabled) { + enableUnminifyMode(); + return; + } + disableUnminifyMode(); + } + async function setWatch(enabled: boolean) { await toggleWatchState(enabled, false); await fetchWatchState(); @@ -95,6 +105,14 @@ export function PluginSettings() { onChange={setWatch} /> + + + ); } diff --git a/src/state/CssLoaderState.tsx b/src/state/CssLoaderState.tsx index 1f46f63..057d510 100644 --- a/src/state/CssLoaderState.tsx +++ b/src/state/CssLoaderState.tsx @@ -42,6 +42,7 @@ interface PublicCssLoaderState { nextUpdateCheckTime: number; updateCheckTimeout: NodeJS.Timeout | undefined; + unminifyModeOn: boolean; navPatchInstance: Patch | undefined; updateStatuses: UpdateStatus[]; selectedPreset: Theme | undefined; @@ -152,6 +153,7 @@ export class CssLoaderState { private submissionThemeList: ThemeQueryResponse = { total: 0, items: [] }; private backendVersion: number = 6; private hiddenMotd: string = ""; + private unminifyModeOn: boolean = false; // You can listen to this eventBus' 'stateUpdate' event and use that to trigger a useState or other function that causes a re-render public eventBus = new EventTarget(); @@ -175,6 +177,7 @@ export class CssLoaderState { unpinnedThemes: this.unpinnedThemes, isInstalling: this.isInstalling, hiddenMotd: this.hiddenMotd, + unminifyModeOn: this.unminifyModeOn, navPatchInstance: this.navPatchInstance, selectedRepo: this.selectedRepo, From b1d77e992e9c0db5872debca9f19dddd4f6a8ad6 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Thu, 28 Mar 2024 18:06:06 +0100 Subject: [PATCH 03/13] Add new user agent --- css_inject.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/css_inject.py b/css_inject.py index 61a9846..b2d9003 100644 --- a/css_inject.py +++ b/css_inject.py @@ -150,7 +150,7 @@ async def remove(self) -> Result: "desktoppopup": ["OverlayBrowser_Browser", "SP Overlay:.*", "notificationtoasts_.*", "SteamBrowser_Find", "OverlayTab\\d+_Find", "!ModalDialogPopup", "!FullModalOverlay"], "desktopoverlay": ["desktoppopup"], "desktopcontextmenu": [".*Menu", ".*Supernav"], - "bigpicture": ["~Valve Steam Gamepad/default~", "~Valve%20Steam%20Gamepad/default~"], + "bigpicture": ["~Valve Steam Gamepad/default~", "~Valve%20Steam%20Gamepad~"], "bigpictureoverlay": ["QuickAccess", "MainMenu"], "store": ["~https://store.steampowered.com~", "~https://steamcommunity.com~"], From c58937f4749bee34c0fc002140a1d8aa90e5639b Mon Sep 17 00:00:00 2001 From: Beebles <102569435+beebls@users.noreply.github.com> Date: Mon, 1 Apr 2024 16:24:25 -0600 Subject: [PATCH 04/13] use class hash map --- src/deckyPatches/UnminifyMode.tsx | 34 +++++++++++++++++++++++++-- src/pages/settings/PluginSettings.tsx | 2 +- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/deckyPatches/UnminifyMode.tsx b/src/deckyPatches/UnminifyMode.tsx index 77c4db2..4f765bd 100644 --- a/src/deckyPatches/UnminifyMode.tsx +++ b/src/deckyPatches/UnminifyMode.tsx @@ -1,11 +1,40 @@ -import { unminifyClass } from "decky-frontend-lib"; +import { classMap } from "decky-frontend-lib"; import { getRootElements } from "./SteamTabElementsFinder"; +const classHashMap = new Map(); + +function initializeClassHashMap() { + const withoutLocalizationClasses = classMap.filter((module) => Object.keys(module).length < 1000); + + const allClasses = withoutLocalizationClasses + .map((module) => { + let filteredModule = {}; + Object.entries(module).forEach(([propertyName, value]) => { + // Filter out things that start with a number (eg: Breakpoints like 800px) + // I have confirmed the new classes don't start with numbers + if (isNaN(Number(value.charAt(0)))) { + filteredModule[propertyName] = value; + } + }); + return filteredModule; + }) + .filter((module) => { + // Some modules will be empty after the filtering, remove those + return Object.keys(module).length > 0; + }); + + allClasses.forEach((module: Record) => { + Object.entries(module).forEach(([propertyName, value]) => { + classHashMap.set(value, propertyName); + }); + }); +} + export function unminifyElement(element: Element) { if (element.classList.length === 0) return; const classList = Array.from(element.classList); - const unminifiedClassList = classList.map((c) => unminifyClass(c) ?? c); + const unminifiedClassList = classList.map((c) => classHashMap.get(c) || c); element.setAttribute("unminified-class", unminifiedClassList.join(" ")); } @@ -52,6 +81,7 @@ export function setUpMutationObserver(rootElement: any) { export function enableUnminifyMode() { if (mutationObservers.length > 0) disconnectMutationObservers(); + initializeClassHashMap(); const roots = getRootElements(); roots.forEach(initialUnminification); roots.forEach(setUpMutationObserver); diff --git a/src/pages/settings/PluginSettings.tsx b/src/pages/settings/PluginSettings.tsx index 2c45681..c8d86f0 100644 --- a/src/pages/settings/PluginSettings.tsx +++ b/src/pages/settings/PluginSettings.tsx @@ -109,7 +109,7 @@ export function PluginSettings() { From d2bef293f3f7978767272346972563dd6893bc67 Mon Sep 17 00:00:00 2001 From: Beebles <102569435+beebls@users.noreply.github.com> Date: Mon, 1 Apr 2024 16:43:08 -0600 Subject: [PATCH 05/13] remove dupes from classhashmap --- src/deckyPatches/ClassHashMap.tsx | 47 +++++++++++++++++++++++++++++++ src/deckyPatches/UnminifyMode.tsx | 31 +------------------- 2 files changed, 48 insertions(+), 30 deletions(-) create mode 100644 src/deckyPatches/ClassHashMap.tsx diff --git a/src/deckyPatches/ClassHashMap.tsx b/src/deckyPatches/ClassHashMap.tsx new file mode 100644 index 0000000..156e395 --- /dev/null +++ b/src/deckyPatches/ClassHashMap.tsx @@ -0,0 +1,47 @@ +import { classMap } from "decky-frontend-lib"; + +export var classHashMap = new Map(); + +export function initializeClassHashMap() { + const withoutLocalizationClasses = classMap.filter((module) => Object.keys(module).length < 1000); + + const allClasses = withoutLocalizationClasses + .map((module) => { + let filteredModule = {}; + Object.entries(module).forEach(([propertyName, value]) => { + // Filter out things that start with a number (eg: Breakpoints like 800px) + // I have confirmed the new classes don't start with numbers + if (isNaN(Number(value.charAt(0)))) { + filteredModule[propertyName] = value; + } + }); + return filteredModule; + }) + .filter((module) => { + // Some modules will be empty after the filtering, remove those + return Object.keys(module).length > 0; + }); + + const mappings = allClasses.reduce((acc, cur) => { + Object.entries(cur).forEach(([property, value]) => { + if (acc[property]) { + acc[property].push(value); + } else { + acc[property] = [value]; + } + }); + return acc; + }, {}); + + const hashMapNoDupes = Object.entries(mappings).reduce>( + (acc, entry) => { + if (entry[1].length === 1) { + acc.set(entry[1][0], entry[0]); + } + return acc; + }, + new Map() + ); + + classHashMap = hashMapNoDupes; +} diff --git a/src/deckyPatches/UnminifyMode.tsx b/src/deckyPatches/UnminifyMode.tsx index 4f765bd..d104ead 100644 --- a/src/deckyPatches/UnminifyMode.tsx +++ b/src/deckyPatches/UnminifyMode.tsx @@ -1,35 +1,6 @@ -import { classMap } from "decky-frontend-lib"; +import { classHashMap, initializeClassHashMap } from "./ClassHashMap"; import { getRootElements } from "./SteamTabElementsFinder"; -const classHashMap = new Map(); - -function initializeClassHashMap() { - const withoutLocalizationClasses = classMap.filter((module) => Object.keys(module).length < 1000); - - const allClasses = withoutLocalizationClasses - .map((module) => { - let filteredModule = {}; - Object.entries(module).forEach(([propertyName, value]) => { - // Filter out things that start with a number (eg: Breakpoints like 800px) - // I have confirmed the new classes don't start with numbers - if (isNaN(Number(value.charAt(0)))) { - filteredModule[propertyName] = value; - } - }); - return filteredModule; - }) - .filter((module) => { - // Some modules will be empty after the filtering, remove those - return Object.keys(module).length > 0; - }); - - allClasses.forEach((module: Record) => { - Object.entries(module).forEach(([propertyName, value]) => { - classHashMap.set(value, propertyName); - }); - }); -} - export function unminifyElement(element: Element) { if (element.classList.length === 0) return; From 45137b75b60f104f8414817d9167ad5946037127 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 7 Apr 2024 23:27:21 +0200 Subject: [PATCH 06/13] Add backend fetch_class_mappings function --- main.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index 72bd0fc..f09f58a 100644 --- a/main.py +++ b/main.py @@ -180,6 +180,20 @@ async def get_last_load_errors(self): async def upload_theme(self, name : str, base_url : str, bearer_token : str) -> dict: return (await self.loader.upload_theme(name, base_url, bearer_token)).to_dict() + async def fetch_class_mappings(self): + await self._fetch_class_mappings(self) + return Result(True).to_dict() + + async def _fetch_class_mappings(self, run_in_bg : bool = False): + global SUCCESSFUL_FETCH_THIS_RUN + + SUCCESSFUL_FETCH_THIS_RUN = False + css_translations_path = os.path.join(get_theme_path(), "css_translations.json") + if run_in_bg: + asyncio.get_event_loop().create_task(every(60, fetch_class_mappings, css_translations_path, self.loader)) + else: + await fetch_class_mappings(css_translations_path, self.loader) + async def _main(self): global Initialized if Initialized: @@ -208,8 +222,7 @@ async def _main(self): if (ALWAYS_RUN_SERVER or store_or_file_config("server")): await self.enable_server(self) - css_translations_path = os.path.join(get_theme_path(), "css_translations.json") - asyncio.get_event_loop().create_task(every(60, fetch_class_mappings, css_translations_path, self.loader)) + await self._fetch_class_mappings(self, True) await initialize() if __name__ == '__main__': From 44805c69398592c5856c4ebc71dca9709dadd537 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Tue, 9 Apr 2024 12:33:34 +0200 Subject: [PATCH 07/13] Automatically get steam branch for translations --- css_utils.py | 4 ++++ main.py | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/css_utils.py b/css_utils.py index 59882c6..9067182 100644 --- a/css_utils.py +++ b/css_utils.py @@ -99,6 +99,10 @@ def get_steam_path() -> str: else: return f"{get_user_home()}/.steam/steam" +def is_steam_beta_active() -> bool: + beta_path = os.path.join(get_steam_path(), "package", "beta") + return os.path.exists(beta_path) + def create_steam_symlink() -> Result: return create_symlink(get_theme_path(), os.path.join(get_steam_path(), "steamui", "themes_custom")) diff --git a/main.py b/main.py index f09f58a..e9e9492 100644 --- a/main.py +++ b/main.py @@ -5,7 +5,7 @@ sys.path.append(os.path.dirname(__file__)) -from css_utils import Log, create_steam_symlink, Result, get_theme_path, store_read as util_store_read, store_write as util_store_write, store_or_file_config +from css_utils import Log, create_steam_symlink, Result, get_theme_path, store_read as util_store_read, store_write as util_store_write, store_or_file_config, is_steam_beta_active from css_inject import ALL_INJECTS, initialize_class_mappings from css_theme import CSS_LOADER_VER from css_remoteinstall import install @@ -34,7 +34,13 @@ async def fetch_class_mappings(css_translations_path : str, loader : Loader): return setting = util_store_read("beta_translations") - css_translations_url = "https://api.deckthemes.com/beta.json" if (setting == "1" or setting == "true") else "https://api.deckthemes.com/stable.json" + + if ((len(setting.strip()) < 0 or setting == "-1" or setting == "auto") and is_steam_beta_active()) or (setting == "1" or setting == "true"): + css_translations_url = "https://api.deckthemes.com/beta.json" + else: + css_translations_url = "https://api.deckthemes.com/stable.json" + + Log(f"Fetching CSS mappings from {css_translations_url}") try: async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(verify_ssl=False), timeout=aiohttp.ClientTimeout(total=2)) as session: From c66f1d119f74c440a8db6e42b5cf02e3595fcb10 Mon Sep 17 00:00:00 2001 From: Pablo Iglesias Date: Wed, 10 Apr 2024 10:01:55 +0200 Subject: [PATCH 08/13] =?UTF-8?q?Added=20fix=20for=20asus=20rog=20ally=20o?= =?UTF-8?q?n=20windows=20to=20prevent=20an=20error=20related=20wi=E2=80=A6?= =?UTF-8?q?=20(#114)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added fix for asus rog ally on windows to prevent an error related with websockets connection * refactor code to use PLATFORM_WIN --- css_browserhook.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/css_browserhook.py b/css_browserhook.py index c945536..eb4615d 100644 --- a/css_browserhook.py +++ b/css_browserhook.py @@ -1,6 +1,6 @@ import os, re, uuid, asyncio, json, aiohttp, time from typing import List -from css_utils import get_theme_path, Log, Result +from css_utils import get_theme_path, Log, Result, PLATFORM_WIN import css_inject MAX_QUEUE_SIZE = 500 @@ -414,7 +414,7 @@ async def health_check(self): while True: await asyncio.sleep(3) try: - async with aiohttp.ClientSession() as web: + async with aiohttp.ClientSession(trust_env=PLATFORM_WIN) as web: res = await web.get(f"http://127.0.0.1:8080/json/version", timeout=3) if (res.status != 200): From 5182dbecfb878ba240b7981728ebd865e406bbf6 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Wed, 10 Apr 2024 10:05:40 +0200 Subject: [PATCH 09/13] Fix beta detection on steam deck --- css_utils.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/css_utils.py b/css_utils.py index 9067182..a38c116 100644 --- a/css_utils.py +++ b/css_utils.py @@ -101,7 +101,17 @@ def get_steam_path() -> str: def is_steam_beta_active() -> bool: beta_path = os.path.join(get_steam_path(), "package", "beta") - return os.path.exists(beta_path) + if not os.path.exists(beta_path): + return False + + with open(beta_path, 'r') as fp: + content = fp.read().strip() + + stable_branches = [ + "steamdeck_stable", + ] + + return content not in stable_branches def create_steam_symlink() -> Result: return create_symlink(get_theme_path(), os.path.join(get_steam_path(), "steamui", "themes_custom")) From eae861456f5de2df08a8f6a2ecd9e6cf7ca68194 Mon Sep 17 00:00:00 2001 From: Beebles <102569435+beebls@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:32:13 -0600 Subject: [PATCH 10/13] update beta translation toggle to dropdown --- .../pythonMethods/pluginSettingsMethods.ts | 10 ++++-- src/backend/pythonMethods/storeUtils.ts | 20 +++++++++++ src/pages/settings/PluginSettings.tsx | 35 +++++++++++-------- 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/backend/pythonMethods/pluginSettingsMethods.ts b/src/backend/pythonMethods/pluginSettingsMethods.ts index 4663694..20f35bf 100644 --- a/src/backend/pythonMethods/pluginSettingsMethods.ts +++ b/src/backend/pythonMethods/pluginSettingsMethods.ts @@ -1,6 +1,6 @@ -import { toast } from "../../python"; +import { storeRead, toast } from "../../python"; import { server, globalState } from "../pythonRoot"; -import { booleanStoreRead } from "./storeUtils"; +import { booleanStoreRead, stringStoreRead } from "./storeUtils"; export function enableServer() { return server!.callPluginMethod("enable_server", {}); @@ -25,7 +25,7 @@ export async function getWatchState() { } export async function getBetaTranslationsState() { - return booleanStoreRead("beta_translations"); + return stringStoreRead("beta_translations"); } export function toggleWatchState(bool: boolean, onlyThisSession: boolean = false) { @@ -50,3 +50,7 @@ export function getHiddenMotd() { key: "hiddenMotd", }); } + +export function fetchClassMappings() { + return server!.callPluginMethod<{}>("fetch_class_mappings", {}); +} diff --git a/src/backend/pythonMethods/storeUtils.ts b/src/backend/pythonMethods/storeUtils.ts index a5789a0..585e75a 100644 --- a/src/backend/pythonMethods/storeUtils.ts +++ b/src/backend/pythonMethods/storeUtils.ts @@ -16,7 +16,27 @@ export async function booleanStoreWrite(key: string, value: boolean) { key, val: value ? "1" : "0", }); + if (!deckyRes.success) { + toast(`Error setting ${key}`, deckyRes.result); + } +} + +export async function stringStoreRead(key: string) { + const deckyRes = await server!.callPluginMethod<{ key: string }, string>("store_read", { + key, + }); if (!deckyRes.success) { toast(`Error fetching ${key}`, deckyRes.result); + return ""; + } + return deckyRes.result; +} +export async function stringStoreWrite(key: string, value: string) { + const deckyRes = await server!.callPluginMethod<{ key: string; val: string }>("store_write", { + key, + val: value, + }); + if (!deckyRes.success) { + toast(`Error setting ${key}`, deckyRes.result); } } diff --git a/src/pages/settings/PluginSettings.tsx b/src/pages/settings/PluginSettings.tsx index c8d86f0..6184f61 100644 --- a/src/pages/settings/PluginSettings.tsx +++ b/src/pages/settings/PluginSettings.tsx @@ -1,4 +1,4 @@ -import { Focusable, ToggleField } from "decky-frontend-lib"; +import { DropdownItem, Focusable, ToggleField } from "decky-frontend-lib"; import { useMemo, useState, useEffect } from "react"; import { useCssLoaderState } from "../../state"; import { toast } from "../../python"; @@ -9,15 +9,16 @@ import { enableServer, toggleWatchState, getBetaTranslationsState, + fetchClassMappings, } from "../../backend/pythonMethods/pluginSettingsMethods"; -import { booleanStoreWrite } from "../../backend/pythonMethods/storeUtils"; +import { booleanStoreWrite, stringStoreWrite } from "../../backend/pythonMethods/storeUtils"; import { disableUnminifyMode, enableUnminifyMode } from "../../deckyPatches/UnminifyMode"; export function PluginSettings() { const { navPatchInstance, unminifyModeOn, setGlobalState } = useCssLoaderState(); const [serverOn, setServerOn] = useState(false); const [watchOn, setWatchOn] = useState(false); - const [betaTranslationsOn, setBetaTranslationsOn] = useState(false); + const [betaTranslationsOn, setBetaTranslationsOn] = useState("-1"); const navPatchEnabled = useMemo(() => !!navPatchInstance, [navPatchInstance]); @@ -31,6 +32,10 @@ export function PluginSettings() { } async function fetchBetaTranslationsState() { const value = await getBetaTranslationsState(); + if (![!"0", "1", "-1"].includes(value)) { + setBetaTranslationsOn("-1"); + return; + } setBetaTranslationsOn(value); } @@ -60,23 +65,25 @@ export function PluginSettings() { await fetchServerState(); } - async function setBetaTranslations(enabled: boolean) { - await booleanStoreWrite("beta_translations", enabled); + async function setBetaTranslations(value: string) { + await stringStoreWrite("beta_translations", value); + await fetchClassMappings(); await fetchBetaTranslationsState(); - toast( - "Beta translations " + (enabled ? "enabled" : "disabled") + ".", - "Please restart your Deck to apply changes." - ); } return (
- setBetaTranslations(data.data)} /> From 085845a661a9aa3492235504c41d596f3e78f6c6 Mon Sep 17 00:00:00 2001 From: Beebles <102569435+beebls@users.noreply.github.com> Date: Thu, 11 Apr 2024 23:11:28 -0600 Subject: [PATCH 11/13] fatfinger --- src/pages/settings/PluginSettings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/PluginSettings.tsx b/src/pages/settings/PluginSettings.tsx index 6184f61..a929ded 100644 --- a/src/pages/settings/PluginSettings.tsx +++ b/src/pages/settings/PluginSettings.tsx @@ -32,7 +32,7 @@ export function PluginSettings() { } async function fetchBetaTranslationsState() { const value = await getBetaTranslationsState(); - if (![!"0", "1", "-1"].includes(value)) { + if (!["0", "1", "-1"].includes(value)) { setBetaTranslationsOn("-1"); return; } From cd81568dee335dcb7c6e73c3e207e008e1a2dd19 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Fri, 12 Apr 2024 21:26:37 +0200 Subject: [PATCH 12/13] less than 0 isn't 0 --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index e9e9492..dec1d1c 100644 --- a/main.py +++ b/main.py @@ -35,7 +35,7 @@ async def fetch_class_mappings(css_translations_path : str, loader : Loader): setting = util_store_read("beta_translations") - if ((len(setting.strip()) < 0 or setting == "-1" or setting == "auto") and is_steam_beta_active()) or (setting == "1" or setting == "true"): + if ((len(setting.strip()) <= 0 or setting == "-1" or setting == "auto") and is_steam_beta_active()) or (setting == "1" or setting == "true"): css_translations_url = "https://api.deckthemes.com/beta.json" else: css_translations_url = "https://api.deckthemes.com/stable.json" From d64e7980a9bc1816f4575878216e40019532132c Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Fri, 12 Apr 2024 22:18:17 +0200 Subject: [PATCH 13/13] Bump version --- css_utils.py | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/css_utils.py b/css_utils.py index a38c116..a5a0fb8 100644 --- a/css_utils.py +++ b/css_utils.py @@ -110,7 +110,7 @@ def is_steam_beta_active() -> bool: stable_branches = [ "steamdeck_stable", ] - + return content not in stable_branches def create_steam_symlink() -> Result: diff --git a/package.json b/package.json index 555dbbc..270bd5d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "SDH-CssLoader", - "version": "2.1.0", + "version": "2.1.1", "description": "A css loader", "scripts": { "build": "shx rm -rf dist && rollup -c",