React UI rewrite; port to new decky plugin framework
This commit is contained in:
parent
072053dcfc
commit
ef678ed122
18 changed files with 713 additions and 760 deletions
42
.gitignore
vendored
42
.gitignore
vendored
|
@ -1 +1,41 @@
|
||||||
*.png
|
lib-cov
|
||||||
|
*.seed
|
||||||
|
*.log
|
||||||
|
*.csv
|
||||||
|
*.dat
|
||||||
|
*.out
|
||||||
|
*.pid
|
||||||
|
*.gz
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
pids
|
||||||
|
logs
|
||||||
|
results
|
||||||
|
tmp
|
||||||
|
|
||||||
|
# Coverage reports
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# API keys and secrets
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Dependency directory
|
||||||
|
node_modules
|
||||||
|
bower_components
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
|
# Editors
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
# OS metadata
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Ignore built ts files
|
||||||
|
dist/
|
||||||
|
|
||||||
|
__pycache__/
|
||||||
|
|
||||||
|
/.yalc
|
||||||
|
yalc.lock
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# PowerTools
|
# PowerTools
|
||||||
|
|
||||||
![plugin_demo](./extras/ui.png)
|
![plugin_demo](./assets/ui.png)
|
||||||
|
|
||||||
Steam Deck power tweaks for power users.
|
Steam Deck power tweaks for power users.
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
BIN
assets/logo.png
Normal file
BIN
assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
assets/thumbnail.png
Normal file
BIN
assets/thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 290 KiB |
BIN
assets/ui.png
Normal file
BIN
assets/ui.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 156 KiB |
BIN
extras/ui.png
BIN
extras/ui.png
Binary file not shown.
Before Width: | Height: | Size: 202 KiB |
41
main.py
41
main.py
|
@ -5,8 +5,8 @@ import asyncio
|
||||||
import pathlib
|
import pathlib
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
VERSION = "0.7.0"
|
VERSION = "0.7.0-alpha-react"
|
||||||
HOME_DIR = str(pathlib.Path(os.getcwd()).parent.parent.resolve())
|
HOME_DIR = "/home/deck"
|
||||||
DEFAULT_SETTINGS_LOCATION = HOME_DIR + "/.config/powertools/default_settings.json"
|
DEFAULT_SETTINGS_LOCATION = HOME_DIR + "/.config/powertools/default_settings.json"
|
||||||
LOG_LOCATION = "/tmp/powertools.log"
|
LOG_LOCATION = "/tmp/powertools.log"
|
||||||
FANTASTIC_INSTALL_DIR = HOME_DIR + "/homebrew/plugins/Fantastic"
|
FANTASTIC_INSTALL_DIR = HOME_DIR + "/homebrew/plugins/Fantastic"
|
||||||
|
@ -127,10 +127,13 @@ class Plugin:
|
||||||
CPU_COUNT = 8
|
CPU_COUNT = 8
|
||||||
FAN_SPEEDS = [0, 1000, 2000, 3000, 4000, 5000, 6000]
|
FAN_SPEEDS = [0, 1000, 2000, 3000, 4000, 5000, 6000]
|
||||||
|
|
||||||
|
gpu_power_values = [[-1, -1, -1], [1000000, 15000000, 29000000], [0, 15000000, 30000000]]
|
||||||
|
|
||||||
auto_fan = True
|
auto_fan = True
|
||||||
persistent = True
|
persistent = True
|
||||||
modified_settings = False
|
modified_settings = False
|
||||||
current_gameid = None
|
current_gameid = None
|
||||||
|
ready = False
|
||||||
|
|
||||||
async def get_version(self) -> str:
|
async def get_version(self) -> str:
|
||||||
return VERSION
|
return VERSION
|
||||||
|
@ -139,6 +142,7 @@ class Plugin:
|
||||||
|
|
||||||
# call from main_view.html with setCPUs(count, smt)
|
# call from main_view.html with setCPUs(count, smt)
|
||||||
async def set_cpus(self, count, smt=True):
|
async def set_cpus(self, count, smt=True):
|
||||||
|
logging.info(f"set_cpus({count}, {smt})")
|
||||||
self.modified_settings = True
|
self.modified_settings = True
|
||||||
cpu_count = len(self.cpus)
|
cpu_count = len(self.cpus)
|
||||||
self.smt = smt
|
self.smt = smt
|
||||||
|
@ -165,9 +169,11 @@ class Plugin:
|
||||||
for cpu in self.cpus:
|
for cpu in self.cpus:
|
||||||
if(cpu.status()):
|
if(cpu.status()):
|
||||||
online_count += 1
|
online_count += 1
|
||||||
|
logging.info(f"get_cpus() -> {online_count}")
|
||||||
return online_count
|
return online_count
|
||||||
|
|
||||||
async def get_smt(self) -> bool:
|
async def get_smt(self) -> bool:
|
||||||
|
logging.info(f"get_smt() -> {self.smt}")
|
||||||
return self.smt
|
return self.smt
|
||||||
|
|
||||||
async def set_boost(self, enabled: bool) -> bool:
|
async def set_boost(self, enabled: bool) -> bool:
|
||||||
|
@ -203,6 +209,24 @@ class Plugin:
|
||||||
async def get_gpu_power(self, power_number: int) -> int:
|
async def get_gpu_power(self, power_number: int) -> int:
|
||||||
return read_gpu_ppt(power_number)
|
return read_gpu_ppt(power_number)
|
||||||
|
|
||||||
|
async def set_gpu_power_index(self, index: int, power_number: int) -> bool:
|
||||||
|
if index < 3 and index >= 0:
|
||||||
|
self.modified_settings = True
|
||||||
|
old_value = read_gpu_ppt(power_number)
|
||||||
|
if old_value not in self.gpu_power_values[power_number]:
|
||||||
|
self.gpu_power_values[power_number][1] = old_value
|
||||||
|
write_gpu_ppt(power_number, self.gpu_power_values[power_number][index])
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def get_gpu_power_index(self, power_number: int) -> int:
|
||||||
|
value = read_gpu_ppt(power_number)
|
||||||
|
if value not in self.gpu_power_values[power_number]:
|
||||||
|
#self.gpu_power_values[power_number][1] = value
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return self.gpu_power_values[power_number].index(value)
|
||||||
|
|
||||||
# Fan stuff
|
# Fan stuff
|
||||||
|
|
||||||
async def set_fan_tick(self, tick: int):
|
async def set_fan_tick(self, tick: int):
|
||||||
|
@ -331,6 +355,9 @@ class Plugin:
|
||||||
# called from main_view::onViewReady
|
# called from main_view::onViewReady
|
||||||
async def on_ready(self):
|
async def on_ready(self):
|
||||||
delta = time.time() - startup_time
|
delta = time.time() - startup_time
|
||||||
|
if self.ready:
|
||||||
|
logging.info(f"Front-end init called again {delta}s after startup")
|
||||||
|
return
|
||||||
logging.info(f"Front-end initialised {delta}s after startup")
|
logging.info(f"Front-end initialised {delta}s after startup")
|
||||||
|
|
||||||
# persistence
|
# persistence
|
||||||
|
@ -439,7 +466,15 @@ class Plugin:
|
||||||
self.current_gameid = None
|
self.current_gameid = None
|
||||||
|
|
||||||
async def get_per_game_profile(self) -> bool:
|
async def get_per_game_profile(self) -> bool:
|
||||||
return self.current_gameid is not None
|
return self.current_gameid is not None and current_game.has_settings()
|
||||||
|
|
||||||
|
async def on_game_start(self, game_id: int, data) -> bool:
|
||||||
|
pt_server.http_server.set_game(game_id, data)
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def on_game_stop(self, game_id: int) -> bool:
|
||||||
|
pt_server.http_server.unset_game(game_id)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
746
main_view.html
746
main_view.html
|
@ -1,746 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="/steam_resource/css/2.css">
|
|
||||||
<link rel="stylesheet" href="/steam_resource/css/39.css">
|
|
||||||
<link rel="stylesheet" href="/steam_resource/css/library.css">
|
|
||||||
<script src="/static/library.js"></script>
|
|
||||||
<script>
|
|
||||||
// Python functions
|
|
||||||
function getVersion() {
|
|
||||||
return call_plugin_method("get_version", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onViewReady() {
|
|
||||||
return call_plugin_method("on_ready", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setCPUs(value, smt) {
|
|
||||||
return call_plugin_method("set_cpus", {"count":value, "smt": smt});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCPUs() {
|
|
||||||
return call_plugin_method("get_cpus", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSMT() {
|
|
||||||
return call_plugin_method("get_smt", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setCPUBoost(value) {
|
|
||||||
return call_plugin_method("set_boost", {"enabled": value});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCPUBoost() {
|
|
||||||
return call_plugin_method("get_boost", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setMaxBoost(index) {
|
|
||||||
return call_plugin_method("set_max_boost", {"index": index});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMaxBoost() {
|
|
||||||
return call_plugin_method("get_max_boost", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setGPUPower(value, index) {
|
|
||||||
return call_plugin_method("set_gpu_power", {"value": value, "power_number": index});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getGPUPower(index) {
|
|
||||||
return call_plugin_method("get_gpu_power", {"power_number": index});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setFanTick(tick) {
|
|
||||||
return call_plugin_method("set_fan_tick", {"tick": tick});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFanTick() {
|
|
||||||
return call_plugin_method("get_fan_tick", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFantastic() {
|
|
||||||
return call_plugin_method("fantastic_installed", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getChargeNow() {
|
|
||||||
return call_plugin_method("get_charge_now", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getChargeFull() {
|
|
||||||
return call_plugin_method("get_charge_full", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getChargeDesign() {
|
|
||||||
return call_plugin_method("get_charge_design", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setPersistent(value) {
|
|
||||||
return call_plugin_method("set_persistent", {"enabled": value});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPersistent() {
|
|
||||||
return call_plugin_method("get_persistent", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setPerGameProfile(value) {
|
|
||||||
return call_plugin_method("set_per_game_profile", {"enabled": value});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPerGameProfile() {
|
|
||||||
return call_plugin_method("get_per_game_profile", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCurrentGame() {
|
|
||||||
return call_plugin_method("get_current_game", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
// other logic
|
|
||||||
|
|
||||||
async function onReady() {
|
|
||||||
await onViewReady();
|
|
||||||
|
|
||||||
// detect game starts and exits
|
|
||||||
console.log("Injecting game detection code into main window (SP)");
|
|
||||||
await execute_in_tab("SP", false,
|
|
||||||
`console.log("Hey PowerTools is over here now too!");
|
|
||||||
SteamClient.Apps.RegisterForGameActionStart((actionType, data) => {
|
|
||||||
console.log("start game", appStore.GetAppOverviewByGameID(data));
|
|
||||||
fetch("http://127.0.0.1:5030/on_game_start/" + data.toString(), {method: "POST", body: JSON.stringify(appStore.GetAppOverviewByGameID(data))}).then((_) => {});
|
|
||||||
});
|
|
||||||
// this seems to not run when I thought (runs right after ^^^, not when game exits)
|
|
||||||
/*SteamClient.Apps.RegisterForGameActionEnd((actionType, data) => {
|
|
||||||
if (data != null && data != undefined) {
|
|
||||||
console.log("stop game", appStore.GetAppOverviewByGameID(data));
|
|
||||||
fetch("http://127.0.0.1:5030/on_game_exit/" + data.toString(), {method: "POST", body: JSON.stringify(appStore.GetAppOverviewByGameID(data))}).then((_) => {});
|
|
||||||
} else {
|
|
||||||
console.log("stop game null");
|
|
||||||
fetch("http://127.0.0.1:5030/on_game_exit_null", {method: "POST", body:data}).then((_) => {});
|
|
||||||
}
|
|
||||||
});*/`
|
|
||||||
);
|
|
||||||
|
|
||||||
await updateCurrentGame();
|
|
||||||
/*let boostToggle = document.getElementById("boostToggle");
|
|
||||||
setToggleState(boostToggle, await getCPUBoost());
|
|
||||||
setToggleState(document.getElementById("smtToggle"), await getSMT());
|
|
||||||
selectNotch("cpuThreadsNotch", await getCPUs() - 1, 8);
|
|
||||||
selectNotch("frequencyNotch", await getMaxBoost(), 3);
|
|
||||||
await onReadyGPU();
|
|
||||||
let isFantasticInstalled = await getFantastic();
|
|
||||||
if (isFantasticInstalled) {
|
|
||||||
// Don't fight with Fantastic
|
|
||||||
let fanRoot = document.getElementById("fanRoot");
|
|
||||||
fanRoot.style.visibility = "hidden";
|
|
||||||
fanRoot.style.height = "0px";
|
|
||||||
} else {
|
|
||||||
selectNotch("fanNotch", await getFanTick(), 8);
|
|
||||||
}
|
|
||||||
await updateBatteryStats();
|
|
||||||
setToggleState(document.getElementById("persistToggle"), await getPersistent());
|
|
||||||
setToggleState(document.getElementById("gameProfileToggle"), await getPerGameProfile());
|
|
||||||
await updateCurrentGame();*/
|
|
||||||
// this is unimportant; always do it last
|
|
||||||
await updateVersion();
|
|
||||||
window.setInterval(function() {
|
|
||||||
updateBatteryStats().then(_ => {});
|
|
||||||
updateCurrentGame().then(_ => {});
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function reloadSettings() {
|
|
||||||
let boostToggle = document.getElementById("boostToggle");
|
|
||||||
setToggleState(boostToggle, await getCPUBoost());
|
|
||||||
setToggleState(document.getElementById("smtToggle"), await getSMT());
|
|
||||||
selectNotch("cpuThreadsNotch", await getCPUs() - 1, 8);
|
|
||||||
selectNotch("frequencyNotch", await getMaxBoost(), 3);
|
|
||||||
await onReadyGPU();
|
|
||||||
let isFantasticInstalled = await getFantastic();
|
|
||||||
if (isFantasticInstalled) {
|
|
||||||
// Don't fight with Fantastic
|
|
||||||
let fanRoot = document.getElementById("fanRoot");
|
|
||||||
fanRoot.style.visibility = "hidden";
|
|
||||||
fanRoot.style.height = "0px";
|
|
||||||
} else {
|
|
||||||
selectNotch("fanNotch", await getFanTick(), 8);
|
|
||||||
}
|
|
||||||
await updateBatteryStats();
|
|
||||||
setToggleState(document.getElementById("persistToggle"), await getPersistent());
|
|
||||||
setToggleState(document.getElementById("gameProfileToggle"), await getPerGameProfile());
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setCPUNotch(index) {
|
|
||||||
const ROOT_ID = "cpuThreadsNotch";
|
|
||||||
await setCPUs(index, getToggleState(document.getElementById("smtToggle")));
|
|
||||||
selectNotch(ROOT_ID, await getCPUs() - 1, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onSlideCPUNotch(e) {
|
|
||||||
const ROOT_ID = "cpuThreadsNotch";
|
|
||||||
let closest = closestNotch(e, ROOT_ID, 8);
|
|
||||||
await setCPUNotch(closest);
|
|
||||||
}
|
|
||||||
|
|
||||||
const TOGGLE_ON_CLASS = "gamepaddialog_On_3ld7T";
|
|
||||||
|
|
||||||
function setToggleState(toggle, state) {
|
|
||||||
if (state && !toggle.classList.contains(TOGGLE_ON_CLASS)) {
|
|
||||||
toggle.classList.add(TOGGLE_ON_CLASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!state && toggle.classList.contains(TOGGLE_ON_CLASS)) {
|
|
||||||
toggle.classList.remove(TOGGLE_ON_CLASS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getToggleState(toggle) {
|
|
||||||
return toggle.classList.contains(TOGGLE_ON_CLASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function toggleCPUBoost() {
|
|
||||||
let toggle = document.getElementById("boostToggle");
|
|
||||||
let isActive = getToggleState(toggle);
|
|
||||||
await setCPUBoost(!isActive);
|
|
||||||
setToggleState(toggle, !isActive);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function toggleCPUSMT() {
|
|
||||||
let toggle = document.getElementById("smtToggle");
|
|
||||||
let isActive = getToggleState(toggle);
|
|
||||||
let currentCPUs = await getCPUs();
|
|
||||||
if (currentCPUs == 4 && !isActive) {
|
|
||||||
// if all cores are running, enable all the threads as well
|
|
||||||
await setCPUs(8, !isActive);
|
|
||||||
} else {
|
|
||||||
await setCPUs(currentCPUs, !isActive);
|
|
||||||
}
|
|
||||||
|
|
||||||
setToggleState(toggle, !isActive);
|
|
||||||
selectNotch("cpuThreadsNotch", await getCPUs() - 1, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setBoostNotch(index) {
|
|
||||||
const ROOT_ID = "frequencyNotch";
|
|
||||||
await setMaxBoost(index);
|
|
||||||
selectNotch(ROOT_ID, await getMaxBoost(), 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onSlideBoostNotch(e) {
|
|
||||||
const ROOT_ID = "frequencyNotch";
|
|
||||||
let closest = closestNotch(e, ROOT_ID, 3);
|
|
||||||
await setBoostNotch(closest);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onSetFanNotch(index) {
|
|
||||||
const ROOT_ID = "fanNotch";
|
|
||||||
await setFanTick(index);
|
|
||||||
selectNotch(ROOT_ID, index, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onSlideFanNotch(e) {
|
|
||||||
const ROOT_ID = "fanNotch";
|
|
||||||
let closest = closestNotch(e, ROOT_ID, 8);
|
|
||||||
await onSetFanNotch(closest);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onReadyGPU() {
|
|
||||||
let power1_cap = await getGPUPower(1);
|
|
||||||
let power2_cap = await getGPUPower(2);
|
|
||||||
if (power1_cap <= 0) {
|
|
||||||
selectNotch("slowPPTNotch", 0, 3);
|
|
||||||
document.getElementById("slowPPTAutoDefault").innerText = "Default";
|
|
||||||
} else if (power1_cap > 15000000) {
|
|
||||||
selectNotch("slowPPTNotch", 2, 3);
|
|
||||||
document.getElementById("slowPPTAutoDefault").innerText = "Default";
|
|
||||||
} else {
|
|
||||||
selectNotch("slowPPTNotch", 1, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (power2_cap <= 0) {
|
|
||||||
selectNotch("fastPPTNotch", 0, 3);
|
|
||||||
document.getElementById("fastPPTAutoDefault").innerText = "Default";
|
|
||||||
} else if (power2_cap > 15000000) {
|
|
||||||
selectNotch("fastPPTNotch", 2, 3);
|
|
||||||
document.getElementById("fastPPTAutoDefault").innerText = "Default";
|
|
||||||
} else {
|
|
||||||
selectNotch("fastPPTNotch", 1, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onSetSlowPPTNotch(index) {
|
|
||||||
const ROOT_ID = "slowPPTNotch";
|
|
||||||
document.getElementById("slowPPTAutoDefault").innerText = "Default";
|
|
||||||
if (index == 0) {
|
|
||||||
await setGPUPower(0, 1);
|
|
||||||
} else if (index == 1) {
|
|
||||||
await setGPUPower(15000000, 1);
|
|
||||||
} else {
|
|
||||||
await setGPUPower(29000000, 1);
|
|
||||||
}
|
|
||||||
selectNotch(ROOT_ID, index, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onSlideSlowPPTNotch(e) {
|
|
||||||
const ROOT_ID = "slowPPTNotch";
|
|
||||||
let closest = closestNotch(e, ROOT_ID, 3);
|
|
||||||
onSetSlowPPTNotch(closest);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onSetFastPPTNotch(index) {
|
|
||||||
const ROOT_ID = "fastPPTNotch";
|
|
||||||
document.getElementById("fastPPTAutoDefault").innerText = "Default";
|
|
||||||
if (index == 0) {
|
|
||||||
await setGPUPower(0, 2);
|
|
||||||
} else if (index == 1) {
|
|
||||||
await setGPUPower(15000000, 2);
|
|
||||||
} else {
|
|
||||||
await setGPUPower(30000000, 2);
|
|
||||||
}
|
|
||||||
selectNotch(ROOT_ID, index, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onSlideFastPPTNotch(e) {
|
|
||||||
const ROOT_ID = "fastPPTNotch";
|
|
||||||
let closest = closestNotch(e, ROOT_ID, 3);
|
|
||||||
await onSetFastPPTNotch(closest);
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectNotch(rootId, index, elements) {
|
|
||||||
// WARNING: this yeets any style in div of slider
|
|
||||||
const ENABLED_CLASS = "gamepadslider_TickActive_1gnUV";
|
|
||||||
//console.log("Selecting notches up to " + index);
|
|
||||||
let root = document.getElementById(rootId);
|
|
||||||
root.style = "--normalized-slider-value:" + index/(elements-1) + ";";
|
|
||||||
for (let i = 0; i < elements; i++) {
|
|
||||||
let notch = document.getElementById(rootId + i);
|
|
||||||
if (notch.classList.contains(ENABLED_CLASS) && i > index) {
|
|
||||||
notch.classList.remove(ENABLED_CLASS);
|
|
||||||
} else if (!notch.classList.contains(ENABLED_CLASS) && i <= index) {
|
|
||||||
notch.classList.add(ENABLED_CLASS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function closestNotch(e, rootId, elements) {
|
|
||||||
let root = document.getElementById(rootId);
|
|
||||||
let val = e.x / root.scrollWidth;
|
|
||||||
let closest_notch = Math.round(val * elements);
|
|
||||||
if (closest_notch > elements) {
|
|
||||||
closest_notch = elements;
|
|
||||||
} else if (closest_notch < 0) {
|
|
||||||
closest_notch = 0;
|
|
||||||
}
|
|
||||||
return closest_notch
|
|
||||||
//selectNotch(closest_notch);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateBatteryStats() {
|
|
||||||
//console.log("Updating battery stats");
|
|
||||||
let batCapacityNow = document.getElementById("batCapacityNow");
|
|
||||||
let batCapacityFull = document.getElementById("batCapacityFull");
|
|
||||||
let chargeNow = await getChargeNow();
|
|
||||||
let chargeFull = await getChargeFull();
|
|
||||||
let chargeDesign = await getChargeDesign();
|
|
||||||
batCapacityNow.innerText = (7.7 * chargeNow / 1000000).toFixed(1).toString() + " Wh (" + (100 * chargeNow / chargeFull).toFixed(1).toString() + "%)";
|
|
||||||
batCapacityFull.innerText = (7.7 * chargeFull / 1000000).toFixed(1).toString() + " Wh (" + (100 * chargeFull / chargeDesign).toFixed(1).toString() + "%)";
|
|
||||||
}
|
|
||||||
|
|
||||||
async function togglePersist() {
|
|
||||||
let toggle = document.getElementById("persistToggle");
|
|
||||||
let isActive = getToggleState(toggle);
|
|
||||||
await setPersistent(!isActive);
|
|
||||||
setToggleState(toggle, !isActive);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function toggleGameProfile() {
|
|
||||||
let toggle = document.getElementById("gameProfileToggle");
|
|
||||||
let isActive = getToggleState(toggle);
|
|
||||||
await setPerGameProfile(!isActive);
|
|
||||||
setToggleState(toggle, await getPerGameProfile());
|
|
||||||
}
|
|
||||||
|
|
||||||
let lastGameName = "";
|
|
||||||
|
|
||||||
async function updateCurrentGame() {
|
|
||||||
let gameNow = document.getElementById("gameNow");
|
|
||||||
let gameNameNow = await getCurrentGame();
|
|
||||||
if (lastGameName != gameNameNow) {
|
|
||||||
setToggleState(document.getElementById("gameProfileToggle"), await getPerGameProfile());
|
|
||||||
await reloadSettings();
|
|
||||||
}
|
|
||||||
lastGameName = gameNameNow
|
|
||||||
gameNow.innerText = gameNameNow;
|
|
||||||
}
|
|
||||||
|
|
||||||
let versionCount = -1;
|
|
||||||
async function updateVersion() {
|
|
||||||
let version = await getVersion();
|
|
||||||
let target = document.getElementById("versionStr");
|
|
||||||
target.innerText = "v" + version;
|
|
||||||
if (versionCount >= 9) {
|
|
||||||
target.innerText += " by NGnius ;) ";
|
|
||||||
versionCount = 0;
|
|
||||||
} else {
|
|
||||||
versionCount += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style type="text/css" media="screen"></style>
|
|
||||||
</head>
|
|
||||||
<body onload="onReady()" style="/*margin:0px;padding:0px;*/overflow-x:hidden;margin:0px;">
|
|
||||||
<!-- Spacer (moves top out of shadow above it) -->
|
|
||||||
<div class="quickaccessmenu_TabGroupPanel_1QO7b">
|
|
||||||
<div class="quickaccesscontrols_PanelSection_2C0g0" style="margin-bottom:6px;">
|
|
||||||
<!--<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
</div>-->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- CPU -->
|
|
||||||
|
|
||||||
<!-- SMT toggle switch, roughly copied from https://github.com/SteamDeckHomebrew/ExtraSettingsPlugin/blob/main/main_view.html -->
|
|
||||||
<!-- Due to a bug in MangoHud, this has a warning for now -->
|
|
||||||
<div class="quickaccessmenu_TabGroupPanel_1QO7b Panel Focusable">
|
|
||||||
<div class="quickaccesscontrols_PanelSection_2C0g0" style="">
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_WithDescription_3bMIS gamepaddialog_ExtraPaddingOnChildrenBelow_5UO-_ gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable" style="--indent-level:0;" onclick="toggleCPUSMT()">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">
|
|
||||||
CPU SMT
|
|
||||||
</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div id="smtToggle" tabindex="0" class="gamepaddialog_Toggle_24G4g Focusable" >
|
|
||||||
<div class="gamepaddialog_ToggleRail_2JtC3"></div>
|
|
||||||
<div class="gamepaddialog_ToggleSwitch_3__OD"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepaddialog_FieldDescription_2OJfk">Enables odd-numbered CPUs</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- CPUs selector -->
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_WithChildrenBelow_1u5FT gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_InlineWrapShiftsChildrenBelow_pHUb6 gamepaddialog_WithBottomSeparatorStandard_3s1Rk gamepaddialog_ChildrenWidthFixed_1ugIU gamepaddialog_ExtraPaddingOnChildrenBelow_5UO-_ gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">Threads</div>
|
|
||||||
</div>
|
|
||||||
<div id="cpuThreadsNotch" class="gamepadslider_SliderControlAndNotches_1Cccx Focusable" tabindex="0" style="--normalized-slider-value:0.5;" onmousemove="onSlideCPUNotch(event)">
|
|
||||||
<div class="gamepadslider_SliderControl_3o137">
|
|
||||||
<div class="gamepadslider_SliderTrack_Mq25N gamepadslider_SliderHasNotches_2XiAy "></div>
|
|
||||||
<div class="gamepadslider_SliderHandleContainer_1pQZi">
|
|
||||||
<div class="gamepadslider_SliderHandle_2yVKj"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotchContainer_2N-a5 Panel Focusable">
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="cpuThreadsNotch0" class="gamepadslider_SliderNotchTick_Fv1Ht" onclick='setCPUNotch(1)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">1</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="cpuThreadsNotch1" class="gamepadslider_SliderNotchTick_Fv1Ht" onclick='setCPUNotch(2)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">2</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="cpuThreadsNotch2" class="gamepadslider_SliderNotchTick_Fv1Ht" onclick='setCPUNotch(3)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">3</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="cpuThreadsNotch3" class="gamepadslider_SliderNotchTick_Fv1Ht" onclick='setCPUNotch(4)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">4</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="cpuThreadsNotch4" class="gamepadslider_SliderNotchTick_Fv1Ht" onclick='setCPUNotch(5)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">5</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="cpuThreadsNotch5" class="gamepadslider_SliderNotchTick_Fv1Ht" onclick='setCPUNotch(6)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">6</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="cpuThreadsNotch6" class="gamepadslider_SliderNotchTick_Fv1Ht" onclick='setCPUNotch(7)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">7</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="cpuThreadsNotch7" class="gamepadslider_SliderNotchTick_Fv1Ht" onclick='setCPUNotch(8)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">8</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- CPU Boost toggle switch, roughly copied from https://github.com/SteamDeckHomebrew/ExtraSettingsPlugin/blob/main/main_view.html -->
|
|
||||||
<div class="quickaccesscontrols_PanelSection_2C0g0" style="">
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_WithDescription_3bMIS gamepaddialog_ExtraPaddingOnChildrenBelow_5UO-_ gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable" style="--indent-level:0;" onclick="toggleCPUBoost()">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">
|
|
||||||
CPU Boost
|
|
||||||
</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div id="boostToggle" tabindex="0" class="gamepaddialog_Toggle_24G4g Focusable">
|
|
||||||
<div class="gamepaddialog_ToggleRail_2JtC3"></div>
|
|
||||||
<div class="gamepaddialog_ToggleSwitch_3__OD"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepaddialog_FieldDescription_2OJfk">Allows the CPU to go above max frequency</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Frequency selector -->
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_WithChildrenBelow_1u5FT gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_InlineWrapShiftsChildrenBelow_pHUb6 gamepaddialog_WithBottomSeparatorStandard_3s1Rk gamepaddialog_ChildrenWidthFixed_1ugIU gamepaddialog_ExtraPaddingOnChildrenBelow_5UO-_ gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">Max Frequency</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div id="frequencyNotch" class="gamepadslider_SliderControlAndNotches_1Cccx Focusable" tabindex="0" style="--normalized-slider-value:0.5;" onmousemove="onSlideBoostNotch(event)">
|
|
||||||
<div class="gamepadslider_SliderControl_3o137">
|
|
||||||
<div class="gamepadslider_SliderTrack_Mq25N gamepadslider_SliderHasNotches_2XiAy "></div>
|
|
||||||
<div class="gamepadslider_SliderHandleContainer_1pQZi">
|
|
||||||
<div class="gamepadslider_SliderHandle_2yVKj"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotchContainer_2N-a5 Panel Focusable">
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="frequencyNotch0" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='setBoostNotch(0)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1" style="margin-left:2em;">1.7GHz</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="frequencyNotch1" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='setBoostNotch(1)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">2.4GHz</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="frequencyNotch2" class="gamepadslider_SliderNotchTick_Fv1Ht" onclick='setBoostNotch(2)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1" style="margin-right:2em;">2.8GHz</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="font-size:x-small;">
|
|
||||||
WARNING: This will change the CPU governor.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- GPU -->
|
|
||||||
|
|
||||||
<div class="quickaccesscontrols_PanelSection_2C0g0" style="">
|
|
||||||
|
|
||||||
<!-- SlowPPT power limit (number 1) -->
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_WithChildrenBelow_1u5FT gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_InlineWrapShiftsChildrenBelow_pHUb6 gamepaddialog_ChildrenWidthFixed_1ugIU gamepaddialog_ExtraPaddingOnChildrenBelow_5UO-_ gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">GPU SlowPPT Power</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div id="slowPPTNotch" class="gamepadslider_SliderControlAndNotches_1Cccx Focusable" tabindex="0" style="--normalized-slider-value:0.33;" onmousemove="onSlideSlowPPTNotch(event)">
|
|
||||||
<div class="gamepadslider_SliderControl_3o137">
|
|
||||||
<div class="gamepadslider_SliderTrack_Mq25N gamepadslider_SliderHasNotches_2XiAy "></div>
|
|
||||||
<div class="gamepadslider_SliderHandleContainer_1pQZi">
|
|
||||||
<div class="gamepadslider_SliderHandle_2yVKj"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotchContainer_2N-a5 Panel Focusable">
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="slowPPTNotch0" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetSlowPPTNotch(0)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">0</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="slowPPTNotch1" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetSlowPPTNotch(1)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1" id="slowPPTAutoDefault">Auto</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="slowPPTNotch2" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetSlowPPTNotch(2)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">Max</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- FastPPT power limit (number 2) -->
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_WithChildrenBelow_1u5FT gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_InlineWrapShiftsChildrenBelow_pHUb6 gamepaddialog_WithBottomSeparatorStandard_3s1Rk gamepaddialog_ChildrenWidthFixed_1ugIU gamepaddialog_ExtraPaddingOnChildrenBelow_5UO-_ gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">GPU FastPPT Power</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div id="fastPPTNotch" class="gamepadslider_SliderControlAndNotches_1Cccx Focusable" tabindex="0" style="--normalized-slider-value:0.33;" onmousemove="onSlideFastPPTNotch(event)">
|
|
||||||
<div class="gamepadslider_SliderControl_3o137">
|
|
||||||
<div class="gamepadslider_SliderTrack_Mq25N gamepadslider_SliderHasNotches_2XiAy "></div>
|
|
||||||
<div class="gamepadslider_SliderHandleContainer_1pQZi">
|
|
||||||
<div class="gamepadslider_SliderHandle_2yVKj"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotchContainer_2N-a5 Panel Focusable">
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="fastPPTNotch0" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetFastPPTNotch(0)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">0</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="fastPPTNotch1" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetFastPPTNotch(1)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1" id="fastPPTAutoDefault">Auto</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="fastPPTNotch2" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetFastPPTNotch(2)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">Max</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Fan RPM selector -->
|
|
||||||
<div class="quickaccesscontrols_PanelSection_2C0g0" style="" id="fanRoot">
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<!-- TODO: Make this non-notched slider when PluginLoader PR#41 is merged -->
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_WithChildrenBelow_1u5FT gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_InlineWrapShiftsChildrenBelow_pHUb6 gamepaddialog_WithBottomSeparatorStandard_3s1Rk gamepaddialog_ChildrenWidthFixed_1ugIU gamepaddialog_ExtraPaddingOnChildrenBelow_5UO-_ gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">Fan RPM</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepaddialog_FieldDescription_2OJfk" style="display:none;">Requires disabling updated fan control</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div id="fanNotch" class="gamepadslider_SliderControlAndNotches_1Cccx Focusable" tabindex="0" style="--normalized-slider-value:0.33;" onmousemove="onSlideFanNotch(event)">
|
|
||||||
<div class="gamepadslider_SliderControl_3o137">
|
|
||||||
<div class="gamepadslider_SliderTrack_Mq25N gamepadslider_SliderHasNotches_2XiAy "></div>
|
|
||||||
<div class="gamepadslider_SliderHandleContainer_1pQZi">
|
|
||||||
<div class="gamepadslider_SliderHandle_2yVKj"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotchContainer_2N-a5 Panel Focusable">
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="fanNotch0" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetFanNotch(0)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">0</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="fanNotch1" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetFanNotch(1)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">1K</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="fanNotch2" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetFanNotch(2)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">2K</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="fanNotch3" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetFanNotch(3)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">3K</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="fanNotch4" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetFanNotch(4)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">4K</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="fanNotch5" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetFanNotch(5)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">5K</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="fanNotch6" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetFanNotch(6)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">6K</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepadslider_SliderNotch_3x6ve">
|
|
||||||
<div id="fanNotch7" class="gamepadslider_SliderNotchTick_Fv1Ht gamepadslider_TickActive_j418S" onclick='onSetFanNotch(7)'></div>
|
|
||||||
<div class="gamepadslider_SliderNotchLabel_u_sH1">Auto</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="font-size:x-small;">
|
|
||||||
WARNING: This can cause component overheating.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Battery Info -->
|
|
||||||
<div class="quickaccesscontrols_PanelSection_2C0g0" style="" onclick="updateBatteryStats()" style="margin-bottom:0px;">
|
|
||||||
<div class="quickaccesscontrols_PanelSectionTitle_2iFf9">
|
|
||||||
<div class="quickaccesscontrols_Text_1hJkB">Battery</div>
|
|
||||||
</div>
|
|
||||||
<div class="Panel Focusable" tabindex="0">
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_InlineWrapShiftsChildrenBelow_pHUb6 gamepaddialog_WithBottomSeparatorStandard_3s1Rk gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable" style="--indent-level:0;">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">Now (Charge)</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div class="gamepaddialog_LabelFieldValue_5Mylh" id="batCapacityNow"> :'( (|-_-|) </div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_InlineWrapShiftsChildrenBelow_pHUb6 gamepaddialog_WithBottomSeparatorStandard_3s1Rk gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable" style="--indent-level:0;">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">Max (Design)</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div class="gamepaddialog_LabelFieldValue_5Mylh" id="batCapacityFull"> 9000+ (420%) </div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="quickaccesscontrols_PanelSection_2C0g0" style="">
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_WithDescription_3bMIS gamepaddialog_ExtraPaddingOnChildrenBelow_5UO-_ gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable" style="--indent-level:0;" onclick="togglePersist()">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">
|
|
||||||
Persistent
|
|
||||||
</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div id="persistToggle" tabindex="0" class="gamepaddialog_Toggle_24G4g Focusable">
|
|
||||||
<div class="gamepaddialog_ToggleRail_2JtC3"></div>
|
|
||||||
<div class="gamepaddialog_ToggleSwitch_3__OD"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="gamepaddialog_FieldDescription_2OJfk">Restores settings after an app or OS restart</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_WithDescription_3bMIS gamepaddialog_ExtraPaddingOnChildrenBelow_5UO-_ gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable" style="--indent-level:0;" onclick="toggleGameProfile()">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">
|
|
||||||
Use per-game profile
|
|
||||||
</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div id="gameProfileToggle" tabindex="0" class="gamepaddialog_Toggle_24G4g Focusable">
|
|
||||||
<div class="gamepaddialog_ToggleRail_2JtC3"></div>
|
|
||||||
<div class="gamepaddialog_ToggleSwitch_3__OD"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_InlineWrapShiftsChildrenBelow_pHUb6 gamepaddialog_WithBottomSeparatorStandard_3s1Rk gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable" style="--indent-level:0;">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">Now Playing</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div class="gamepaddialog_LabelFieldValue_5Mylh" id="gameNow"> the bongos </div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="quickaccesscontrols_PanelSectionRow_2VQ88" onclick="updateVersion()">
|
|
||||||
<div class="gamepaddialog_Field_S-_La gamepaddialog_WithFirstRow_qFXi6 gamepaddialog_VerticalAlignCenter_3XNvA gamepaddialog_InlineWrapShiftsChildrenBelow_pHUb6 gamepaddialog_WithBottomSeparatorStandard_3s1Rk gamepaddialog_StandardPadding_XRBFu gamepaddialog_HighlightOnFocus_wE4V6 Panel Focusable" style="--indent-level:0;">
|
|
||||||
<div class="gamepaddialog_FieldLabelRow_H9WOq">
|
|
||||||
<div class="gamepaddialog_FieldLabel_3b0U-">PowerTools</div>
|
|
||||||
<div class="gamepaddialog_FieldChildren_14_HB">
|
|
||||||
<div class="gamepaddialog_LabelFieldValue_5Mylh" id="versionStr"> v0.42.0 </div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
45
package.json
Normal file
45
package.json
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"name": "PowerTools",
|
||||||
|
"version": "0.7.0",
|
||||||
|
"description": "Power tweaks for power users",
|
||||||
|
"scripts": {
|
||||||
|
"build": "shx rm -rf dist && rollup -c",
|
||||||
|
"watch": "rollup -c -w",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/NGnius/PowerTools.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"plugin",
|
||||||
|
"utility",
|
||||||
|
"power-management",
|
||||||
|
"steam-deck",
|
||||||
|
"deck"
|
||||||
|
],
|
||||||
|
"author": "NGnius (Graham) <ngniusness@gmail.com>",
|
||||||
|
"license": "GPL-3.0",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/NGnius/PowerTools/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/NGnius/PowerTools#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-commonjs": "^21.1.0",
|
||||||
|
"@rollup/plugin-json": "^4.1.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^13.2.1",
|
||||||
|
"@rollup/plugin-replace": "^4.0.0",
|
||||||
|
"@rollup/plugin-typescript": "^8.3.2",
|
||||||
|
"@types/react": "16.14.0",
|
||||||
|
"@types/webpack": "^5.28.0",
|
||||||
|
"rollup": "^2.70.2",
|
||||||
|
"rollup-plugin-import-assets": "^1.1.1",
|
||||||
|
"shx": "^0.3.4",
|
||||||
|
"tslib": "^2.4.0",
|
||||||
|
"typescript": "^4.6.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"decky-frontend-lib": "*",
|
||||||
|
"react-icons": "^4.3.1"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "Power Tools",
|
"name": "PowerTools",
|
||||||
"author": "NGnius",
|
"author": "NGnius",
|
||||||
"main_view_html": "main_view.html",
|
|
||||||
"tile_view_html": "",
|
|
||||||
"flags": ["root", "debug"],
|
"flags": ["root", "debug"],
|
||||||
"publish": {
|
"publish": {
|
||||||
"discord_id": "106537989684887552",
|
"discord_id": "106537989684887552",
|
||||||
|
|
37
rollup.config.js
Normal file
37
rollup.config.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import commonjs from '@rollup/plugin-commonjs';
|
||||||
|
import json from '@rollup/plugin-json';
|
||||||
|
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
||||||
|
import replace from '@rollup/plugin-replace';
|
||||||
|
import typescript from '@rollup/plugin-typescript';
|
||||||
|
import { defineConfig } from 'rollup';
|
||||||
|
import importAssets from 'rollup-plugin-import-assets';
|
||||||
|
|
||||||
|
import { name } from "./plugin.json";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
input: './src/index.tsx',
|
||||||
|
plugins: [
|
||||||
|
commonjs(),
|
||||||
|
nodeResolve(),
|
||||||
|
typescript(),
|
||||||
|
json(),
|
||||||
|
replace({
|
||||||
|
preventAssignment: false,
|
||||||
|
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||||
|
}),
|
||||||
|
importAssets({
|
||||||
|
publicPath: `http://127.0.0.1:1337/plugins/${name}/`
|
||||||
|
})
|
||||||
|
],
|
||||||
|
context: 'window',
|
||||||
|
external: ['react', 'react-dom'],
|
||||||
|
output: {
|
||||||
|
file: 'dist/index.js',
|
||||||
|
globals: {
|
||||||
|
react: 'SP_REACT',
|
||||||
|
'react-dom': 'SP_REACTDOM',
|
||||||
|
},
|
||||||
|
format: 'iife',
|
||||||
|
exports: 'default',
|
||||||
|
},
|
||||||
|
});
|
18
server.py
18
server.py
|
@ -7,7 +7,7 @@ import pathlib
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
HOME_DIR = str(pathlib.Path(os.getcwd()).parent.parent.resolve())
|
HOME_DIR = "/home/deck"
|
||||||
SETTINGS_DIR = HOME_DIR + "/.config/powertools"
|
SETTINGS_DIR = HOME_DIR + "/.config/powertools"
|
||||||
|
|
||||||
if not os.path.exists(SETTINGS_DIR):
|
if not os.path.exists(SETTINGS_DIR):
|
||||||
|
@ -60,6 +60,15 @@ class Server(web.Application):
|
||||||
def game(self) -> GameInfo:
|
def game(self) -> GameInfo:
|
||||||
return self.current_game
|
return self.current_game
|
||||||
|
|
||||||
|
def set_game(self, game_id, data):
|
||||||
|
self.current_game = GameInfo(game_id, data)
|
||||||
|
|
||||||
|
def unset_game(self, game_id):
|
||||||
|
if self.current_game is None:
|
||||||
|
return
|
||||||
|
if game_id is None or self.current_game.gameid == game_id:
|
||||||
|
self.current_game = None
|
||||||
|
|
||||||
async def index(self, request):
|
async def index(self, request):
|
||||||
logging.debug("Debug index page accessed")
|
logging.debug("Debug index page accessed")
|
||||||
current_game = None if self.current_game is None else self.current_game.gameid
|
current_game = None if self.current_game is None else self.current_game.gameid
|
||||||
|
@ -97,16 +106,13 @@ class Server(web.Application):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return web.Response(text="WTF", status=400)
|
return web.Response(text="WTF", status=400)
|
||||||
if self.current_game.gameid == game_id:
|
if self.current_game.gameid == game_id:
|
||||||
pass
|
self.current_game = None
|
||||||
#self.current_game = None
|
|
||||||
# TODO change settings to default
|
|
||||||
return web.Response(status=204, headers={"Access-Control-Allow-Origin": "*"})
|
return web.Response(status=204, headers={"Access-Control-Allow-Origin": "*"})
|
||||||
|
|
||||||
async def on_game_exit_null(self, request):
|
async def on_game_exit_null(self, request):
|
||||||
# ignored for now
|
# ignored for now
|
||||||
logging.info(f"on_game_exit_null")
|
logging.info(f"on_game_exit_null")
|
||||||
#self.current_game = None
|
self.current_game = None
|
||||||
# TODO change settings to default
|
|
||||||
return web.Response(status=204, headers={"Access-Control-Allow-Origin": "*"})
|
return web.Response(status=204, headers={"Access-Control-Allow-Origin": "*"})
|
||||||
|
|
||||||
async def self_destruct(self, request):
|
async def self_destruct(self, request):
|
||||||
|
|
368
src/index.tsx
Executable file
368
src/index.tsx
Executable file
|
@ -0,0 +1,368 @@
|
||||||
|
import {
|
||||||
|
//ButtonItem,
|
||||||
|
definePlugin,
|
||||||
|
DialogButton,
|
||||||
|
//Menu,
|
||||||
|
//MenuItem,
|
||||||
|
PanelSection,
|
||||||
|
PanelSectionRow,
|
||||||
|
//Router,
|
||||||
|
ServerAPI,
|
||||||
|
//showContextMenu,
|
||||||
|
staticClasses,
|
||||||
|
Slider,
|
||||||
|
Toggle,
|
||||||
|
//NotchLabel
|
||||||
|
gamepadDialogClasses,
|
||||||
|
joinClassNames,
|
||||||
|
} from "decky-frontend-lib";
|
||||||
|
import { VFC, useState } from "react";
|
||||||
|
import { FaShip } from "react-icons/fa";
|
||||||
|
|
||||||
|
import * as python from "./python";
|
||||||
|
|
||||||
|
//import logo from "../assets/logo.png";
|
||||||
|
|
||||||
|
// interface AddMethodArgs {
|
||||||
|
// left: number;
|
||||||
|
// right: number;
|
||||||
|
// }
|
||||||
|
|
||||||
|
var firstTime: boolean = true;
|
||||||
|
var versionGlobal: string = "0.0.0-jank";
|
||||||
|
var periodicHook: NodeJS.Timer | null = null;
|
||||||
|
var lastGame: string = "";
|
||||||
|
var lifetimeHook: any = null;
|
||||||
|
var startHook: any = null;
|
||||||
|
|
||||||
|
var reload = function(){};
|
||||||
|
|
||||||
|
const Content: VFC<{ serverAPI: ServerAPI }> = ({serverAPI}) => {
|
||||||
|
// const [result, setResult] = useState<number | undefined>();
|
||||||
|
|
||||||
|
// const onClick = async () => {
|
||||||
|
// const result = await serverAPI.callPluginMethod<AddMethodArgs, number>(
|
||||||
|
// "add",
|
||||||
|
// {
|
||||||
|
// left: 2,
|
||||||
|
// right: 2,
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
// if (result.success) {
|
||||||
|
// setResult(result.result);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
python.setServer(serverAPI);
|
||||||
|
|
||||||
|
const [smtGlobal, setSMT] = useState<boolean>(true);
|
||||||
|
const [cpusGlobal, setCPUs] = useState<number>(8);
|
||||||
|
const [boostGlobal, setBoost] = useState<boolean>(true);
|
||||||
|
|
||||||
|
const [freqGlobal, setFreq] = useState<number>(8);
|
||||||
|
|
||||||
|
const [slowPPTGlobal, setSlowPPT] = useState<number>(1);
|
||||||
|
const [fastPPTGlobal, setFastPPT] = useState<number>(1);
|
||||||
|
|
||||||
|
const [chargeNowGlobal, setChargeNow] = useState<number>(40);
|
||||||
|
const [chargeFullGlobal, setChargeFull] = useState<number>(40);
|
||||||
|
const [chargeDesignGlobal, setChargeDesign] = useState<number>(40);
|
||||||
|
|
||||||
|
const [persistGlobal, setPersist] = useState<boolean>(false);
|
||||||
|
const [perGameProfileGlobal, setPerGameProfile] = useState<boolean>(false);
|
||||||
|
const [gameGlobal, setGame] = useState<string>("with your mom");
|
||||||
|
|
||||||
|
reload = function () {
|
||||||
|
python.execute(python.onViewReady());
|
||||||
|
|
||||||
|
python.resolve(python.getSMT(), setSMT);
|
||||||
|
python.resolve(python.getCPUs(), setCPUs);
|
||||||
|
python.resolve(python.getCPUBoost(), setBoost);
|
||||||
|
python.resolve(python.getMaxBoost(), setFreq);
|
||||||
|
|
||||||
|
python.resolve(python.getGPUPowerI(1), setSlowPPT);
|
||||||
|
python.resolve(python.getGPUPowerI(2), setFastPPT);
|
||||||
|
|
||||||
|
python.resolve(python.getPersistent(), setPersist);
|
||||||
|
python.resolve(python.getPerGameProfile(), setPerGameProfile);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (firstTime) {
|
||||||
|
firstTime = false;
|
||||||
|
|
||||||
|
reload(); // technically it's just load, not reload ;)
|
||||||
|
|
||||||
|
python.resolve(python.getChargeNow(), setChargeNow);
|
||||||
|
python.resolve(python.getChargeFull(), setChargeFull);
|
||||||
|
python.resolve(python.getChargeDesign(), setChargeDesign);
|
||||||
|
|
||||||
|
python.resolve(python.getCurrentGame(), setGame);
|
||||||
|
|
||||||
|
periodicHook = setInterval(function() {
|
||||||
|
python.resolve(python.getChargeNow(), setChargeNow);
|
||||||
|
python.resolve(python.getChargeFull(), setChargeFull);
|
||||||
|
python.resolve(python.getCurrentGame(), (game: string) => {
|
||||||
|
if (lastGame != game) {
|
||||||
|
setGame(game);
|
||||||
|
lastGame = game;
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
python.resolve(python.getVersion(), (v: string) => {versionGlobal = v;});
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
lifetimeHook = SteamClient.GameSessions.RegisterForAppLifetimeNotifications((update) => {
|
||||||
|
if (update.bRunning) {
|
||||||
|
console.log("AppID " + update.unAppID.toString() + " is now running");
|
||||||
|
} else {
|
||||||
|
console.log("AppID " + update.unAppID.toString() + " is no longer running");
|
||||||
|
python.execute(python.onGameStop(null));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//@ts-ignore
|
||||||
|
SteamClient.Apps.RegisterForGameActionStart((actionType, id) => {
|
||||||
|
//@ts-ignore
|
||||||
|
let gameInfo: any = appStore.GetAppOverviewByGameID(id);
|
||||||
|
python.execute(python.onGameStart(id, gameInfo));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const FieldWithSeparator = joinClassNames(gamepadDialogClasses.Field, gamepadDialogClasses.WithBottomSeparatorStandard);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PanelSection>
|
||||||
|
{/* CPU */}
|
||||||
|
<div className={staticClasses.PanelSectionTitle}>
|
||||||
|
CPU
|
||||||
|
</div>
|
||||||
|
<PanelSectionRow>
|
||||||
|
<Toggle
|
||||||
|
checked={smtGlobal}
|
||||||
|
label="SMT"
|
||||||
|
description="Enables odd-numbered CPUs"
|
||||||
|
onChange={(smt: boolean) => {
|
||||||
|
console.log("SMT is now " + smt.toString());
|
||||||
|
python.execute(python.setCPUs(cpusGlobal, smt));
|
||||||
|
python.resolve(python.getCPUs(), setCPUs);
|
||||||
|
python.resolve(python.getSMT(), setSMT);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</PanelSectionRow>
|
||||||
|
<PanelSectionRow>
|
||||||
|
<Slider
|
||||||
|
label="Threads"
|
||||||
|
value={cpusGlobal}
|
||||||
|
step={1}
|
||||||
|
max={smtGlobal? 8 : 4}
|
||||||
|
min={1}
|
||||||
|
showValue={true}
|
||||||
|
onChange={(cpus: number) => {
|
||||||
|
console.log("CPU slider is now " + cpus.toString());
|
||||||
|
if (cpus != cpusGlobal) {
|
||||||
|
python.execute(python.setCPUs(cpus, smtGlobal));
|
||||||
|
python.resolve(python.getCPUs(), setCPUs);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</PanelSectionRow>
|
||||||
|
<PanelSectionRow>
|
||||||
|
<Toggle
|
||||||
|
checked={boostGlobal}
|
||||||
|
label="Boost"
|
||||||
|
description="Allows the CPU to go above max frequency"
|
||||||
|
onChange={(boost: boolean) => {
|
||||||
|
console.log("Boost is now " + boost.toString());
|
||||||
|
python.execute(python.setCPUBoost(boost));
|
||||||
|
python.resolve(python.getCPUBoost(), setBoost);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</PanelSectionRow>
|
||||||
|
<PanelSectionRow>
|
||||||
|
<Slider
|
||||||
|
label="Max Frequency"
|
||||||
|
value={freqGlobal}
|
||||||
|
max={2}
|
||||||
|
min={0}
|
||||||
|
notchCount={3}
|
||||||
|
notchLabels={[
|
||||||
|
{notchIndex: 0, label: "1.7GHz"},
|
||||||
|
{notchIndex: 1, label: "2.4GHz"},
|
||||||
|
{notchIndex: 2, label: "2.8GHz"},
|
||||||
|
]}
|
||||||
|
notchTicksVisible={true}
|
||||||
|
onChange={(freq: number) => {
|
||||||
|
console.log("CPU slider is now " + freq.toString());
|
||||||
|
if (freq != freqGlobal) {
|
||||||
|
python.execute(python.setMaxBoost(freq));
|
||||||
|
python.resolve(python.getMaxBoost(), setFreq);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</PanelSectionRow>
|
||||||
|
{/* GPU */}
|
||||||
|
<div className={staticClasses.PanelSectionTitle}>
|
||||||
|
GPU
|
||||||
|
</div>
|
||||||
|
<PanelSectionRow>
|
||||||
|
{/* index: 1 */}
|
||||||
|
<Slider
|
||||||
|
label="SlowPPT Power"
|
||||||
|
value={slowPPTGlobal}
|
||||||
|
max={2}
|
||||||
|
min={0}
|
||||||
|
notchCount={3}
|
||||||
|
notchLabels={[
|
||||||
|
{notchIndex: 0, label: "Min"},
|
||||||
|
{notchIndex: 1, label: "Auto"},
|
||||||
|
{notchIndex: 2, label: "Max"},
|
||||||
|
]}
|
||||||
|
notchTicksVisible={true}
|
||||||
|
onChange={(ppt: number) => {
|
||||||
|
console.log("SlowPPT is now " + ppt.toString());
|
||||||
|
if (ppt != slowPPTGlobal) {
|
||||||
|
python.execute(python.setGPUPowerI(ppt, 1));
|
||||||
|
python.resolve(python.getGPUPowerI(1), setSlowPPT);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</PanelSectionRow>
|
||||||
|
<PanelSectionRow>
|
||||||
|
{/* index: 2 */}
|
||||||
|
<Slider
|
||||||
|
label="FastPPT Power"
|
||||||
|
value={fastPPTGlobal}
|
||||||
|
max={2}
|
||||||
|
min={0}
|
||||||
|
notchCount={3}
|
||||||
|
notchLabels={[
|
||||||
|
{notchIndex: 0, label: "Min"},
|
||||||
|
{notchIndex: 1, label: "Auto"},
|
||||||
|
{notchIndex: 2, label: "Max"},
|
||||||
|
]}
|
||||||
|
notchTicksVisible={true}
|
||||||
|
onChange={(ppt: number) => {
|
||||||
|
console.log("FastPPT is now " + ppt.toString());
|
||||||
|
if (ppt != fastPPTGlobal) {
|
||||||
|
python.execute(python.setGPUPowerI(ppt, 2));
|
||||||
|
python.resolve(python.getGPUPowerI(2), setFastPPT);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</PanelSectionRow>
|
||||||
|
{/* Battery */}
|
||||||
|
<div className={staticClasses.PanelSectionTitle}>
|
||||||
|
Battery
|
||||||
|
</div>
|
||||||
|
<PanelSectionRow>
|
||||||
|
<div className={FieldWithSeparator}>
|
||||||
|
<div className={gamepadDialogClasses.FieldLabelRow}>
|
||||||
|
<div className={gamepadDialogClasses.FieldLabel}>
|
||||||
|
Now (Charge)
|
||||||
|
</div>
|
||||||
|
<div className={gamepadDialogClasses.FieldChildren}>
|
||||||
|
{(7.7 * chargeNowGlobal / 1000000).toFixed(1).toString() + " Wh (" + (100 * chargeNowGlobal / chargeFullGlobal).toFixed(1).toString() + "%)"}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PanelSectionRow>
|
||||||
|
<PanelSectionRow>
|
||||||
|
<div className={FieldWithSeparator}>
|
||||||
|
<div className={gamepadDialogClasses.FieldLabelRow}>
|
||||||
|
<div className={gamepadDialogClasses.FieldLabel}>
|
||||||
|
Max (Design)
|
||||||
|
</div>
|
||||||
|
<div className={gamepadDialogClasses.FieldChildren}>
|
||||||
|
{(7.7 * chargeFullGlobal / 1000000).toFixed(1).toString() + " Wh (" + (100 * chargeFullGlobal / chargeDesignGlobal).toFixed(1).toString() + "%)"}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PanelSectionRow>
|
||||||
|
{/* Persistence */}
|
||||||
|
<PanelSectionRow>
|
||||||
|
<Toggle
|
||||||
|
checked={persistGlobal}
|
||||||
|
label="Persistent"
|
||||||
|
description="Restores settings after an app or OS restart"
|
||||||
|
onChange={(persist: boolean) => {
|
||||||
|
console.log("Persist is now " + persist.toString());
|
||||||
|
python.execute(python.setPersistent(persist));
|
||||||
|
python.resolve(python.getPersistent(), setPersist);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</PanelSectionRow>
|
||||||
|
<PanelSectionRow>
|
||||||
|
<Toggle
|
||||||
|
checked={perGameProfileGlobal}
|
||||||
|
label="Use per-game profile"
|
||||||
|
onChange={(p: boolean) => {
|
||||||
|
console.log("Per game profile is now " + p.toString());
|
||||||
|
python.execute(python.setPerGameProfile(p));
|
||||||
|
python.resolve(python.getPerGameProfile(), setPerGameProfile);
|
||||||
|
reload();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</PanelSectionRow>
|
||||||
|
<PanelSectionRow>
|
||||||
|
<div className={FieldWithSeparator}>
|
||||||
|
<div className={gamepadDialogClasses.FieldLabelRow}>
|
||||||
|
<div className={gamepadDialogClasses.FieldLabel}>
|
||||||
|
Now Playing
|
||||||
|
</div>
|
||||||
|
<div className={gamepadDialogClasses.FieldChildren}>
|
||||||
|
{gameGlobal}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PanelSectionRow>
|
||||||
|
{/* Version */}
|
||||||
|
<div className={staticClasses.PanelSectionTitle}>
|
||||||
|
Debug
|
||||||
|
</div>
|
||||||
|
<PanelSectionRow>
|
||||||
|
<div className={FieldWithSeparator}>
|
||||||
|
<div className={gamepadDialogClasses.FieldLabelRow}>
|
||||||
|
<div className={gamepadDialogClasses.FieldLabel}>
|
||||||
|
PowerTools
|
||||||
|
</div>
|
||||||
|
<div className={gamepadDialogClasses.FieldChildren}>
|
||||||
|
v{versionGlobal}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PanelSectionRow>
|
||||||
|
</PanelSection>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeckyPluginRouterTest: VFC = () => {
|
||||||
|
return (
|
||||||
|
<div style={{ marginTop: "50px", color: "white" }}>
|
||||||
|
Hello World!
|
||||||
|
<DialogButton onClick={() => {}}>
|
||||||
|
Go to Store
|
||||||
|
</DialogButton>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default definePlugin((serverApi: ServerAPI) => {
|
||||||
|
serverApi.routerHook.addRoute("/decky-plugin-test", DeckyPluginRouterTest, {
|
||||||
|
exact: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: <div className={staticClasses.Title}>PowerTools</div>,
|
||||||
|
content: <Content serverAPI={serverApi} />,
|
||||||
|
icon: <FaShip />,
|
||||||
|
onDismount() {
|
||||||
|
console.log("PowerTools shutting down");
|
||||||
|
clearInterval(periodicHook!);
|
||||||
|
lifetimeHook.unregister();
|
||||||
|
startHook.unregister();
|
||||||
|
serverApi.routerHook.removeRoute("/decky-plugin-test");
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
133
src/python.ts
Normal file
133
src/python.ts
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
import { ServerAPI } from "decky-frontend-lib";
|
||||||
|
|
||||||
|
var server: ServerAPI | undefined = undefined;
|
||||||
|
|
||||||
|
//import { useEffect } from "react";
|
||||||
|
|
||||||
|
export function resolve(promise: Promise<any>, setter: any) {
|
||||||
|
(async function () {
|
||||||
|
let data = await promise;
|
||||||
|
console.log("Got resolved", data);
|
||||||
|
if (data.success) {
|
||||||
|
setter(data.result);
|
||||||
|
} else {
|
||||||
|
console.log("Resolve failed:", data);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function execute(promise: Promise<any>) {
|
||||||
|
(async function () {
|
||||||
|
let data = await promise;
|
||||||
|
console.log("Got executed", data);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setServer(s: ServerAPI) {
|
||||||
|
server = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Python functions
|
||||||
|
export function getVersion(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_version", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onViewReady(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("on_ready", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setCPUs(value: number, smt: boolean): Promise<any> {
|
||||||
|
return server!.callPluginMethod("set_cpus", {"count":value, "smt": smt});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCPUs(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_cpus", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSMT(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_smt", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setCPUBoost(value: boolean): Promise<any> {
|
||||||
|
return server!.callPluginMethod("set_boost", {"enabled": value});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCPUBoost(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_boost", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setMaxBoost(index: number): Promise<any> {
|
||||||
|
return server!.callPluginMethod("set_max_boost", {"index": index});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMaxBoost(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_max_boost", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setGPUPower(value: number, index: number): Promise<any> {
|
||||||
|
return server!.callPluginMethod("set_gpu_power", {"value": value, "power_number": index});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGPUPower(index: number): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_gpu_power", {"power_number": index});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setGPUPowerI(value: number, index: number): Promise<any> {
|
||||||
|
return server!.callPluginMethod("set_gpu_power_index", {"index": value, "power_number": index});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGPUPowerI(index: number): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_gpu_power_index", {"power_number": index});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setFanTick(tick: number): Promise<any> {
|
||||||
|
return server!.callPluginMethod("set_fan_tick", {"tick": tick});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFanTick(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_fan_tick", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFantastic(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("fantastic_installed", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getChargeNow(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_charge_now", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getChargeFull(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_charge_full", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getChargeDesign(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_charge_design", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setPersistent(value: boolean): Promise<any> {
|
||||||
|
return server!.callPluginMethod("set_persistent", {"enabled": value});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPersistent(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_persistent", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setPerGameProfile(value: boolean): Promise<any> {
|
||||||
|
return server!.callPluginMethod("set_per_game_profile", {"enabled": value});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPerGameProfile(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_per_game_profile", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurrentGame(): Promise<any> {
|
||||||
|
return server!.callPluginMethod("get_current_game", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onGameStart(gameId: number, data: any): Promise<any> {
|
||||||
|
return server!.callPluginMethod("on_game_start", {"game_id": gameId, "data":data});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onGameStop(gameId: number | null): Promise<any> {
|
||||||
|
return server!.callPluginMethod("on_game_stop", {"game_id": gameId});
|
||||||
|
}
|
14
src/types.d.ts
vendored
Normal file
14
src/types.d.ts
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
declare module "*.svg" {
|
||||||
|
const content: string;
|
||||||
|
export default content;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "*.png" {
|
||||||
|
const content: string;
|
||||||
|
export default content;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "*.jpg" {
|
||||||
|
const content: string;
|
||||||
|
export default content;
|
||||||
|
}
|
23
tsconfig.json
Normal file
23
tsconfig.json
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "dist",
|
||||||
|
"module": "ESNext",
|
||||||
|
"target": "ES2020",
|
||||||
|
"jsx": "react",
|
||||||
|
"jsxFactory": "window.SP_REACT.createElement",
|
||||||
|
"declaration": false,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"strict": true,
|
||||||
|
"suppressImplicitAnyIndexErrors": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
Loading…
Reference in a new issue