forked from NG-SD-Plugins/PowerTools
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
|
||||
|
||||
![plugin_demo](./extras/ui.png)
|
||||
![plugin_demo](./assets/ui.png)
|
||||
|
||||
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 subprocess
|
||||
|
||||
VERSION = "0.7.0"
|
||||
HOME_DIR = str(pathlib.Path(os.getcwd()).parent.parent.resolve())
|
||||
VERSION = "0.7.0-alpha-react"
|
||||
HOME_DIR = "/home/deck"
|
||||
DEFAULT_SETTINGS_LOCATION = HOME_DIR + "/.config/powertools/default_settings.json"
|
||||
LOG_LOCATION = "/tmp/powertools.log"
|
||||
FANTASTIC_INSTALL_DIR = HOME_DIR + "/homebrew/plugins/Fantastic"
|
||||
|
@ -127,10 +127,13 @@ class Plugin:
|
|||
CPU_COUNT = 8
|
||||
FAN_SPEEDS = [0, 1000, 2000, 3000, 4000, 5000, 6000]
|
||||
|
||||
gpu_power_values = [[-1, -1, -1], [1000000, 15000000, 29000000], [0, 15000000, 30000000]]
|
||||
|
||||
auto_fan = True
|
||||
persistent = True
|
||||
modified_settings = False
|
||||
current_gameid = None
|
||||
ready = False
|
||||
|
||||
async def get_version(self) -> str:
|
||||
return VERSION
|
||||
|
@ -139,6 +142,7 @@ class Plugin:
|
|||
|
||||
# call from main_view.html with setCPUs(count, smt)
|
||||
async def set_cpus(self, count, smt=True):
|
||||
logging.info(f"set_cpus({count}, {smt})")
|
||||
self.modified_settings = True
|
||||
cpu_count = len(self.cpus)
|
||||
self.smt = smt
|
||||
|
@ -165,9 +169,11 @@ class Plugin:
|
|||
for cpu in self.cpus:
|
||||
if(cpu.status()):
|
||||
online_count += 1
|
||||
logging.info(f"get_cpus() -> {online_count}")
|
||||
return online_count
|
||||
|
||||
async def get_smt(self) -> bool:
|
||||
logging.info(f"get_smt() -> {self.smt}")
|
||||
return self.smt
|
||||
|
||||
async def set_boost(self, enabled: bool) -> bool:
|
||||
|
@ -203,6 +209,24 @@ class Plugin:
|
|||
async def get_gpu_power(self, power_number: int) -> int:
|
||||
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
|
||||
|
||||
async def set_fan_tick(self, tick: int):
|
||||
|
@ -331,6 +355,9 @@ class Plugin:
|
|||
# called from main_view::onViewReady
|
||||
async def on_ready(self):
|
||||
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")
|
||||
|
||||
# persistence
|
||||
|
@ -439,7 +466,15 @@ class Plugin:
|
|||
self.current_gameid = None
|
||||
|
||||
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",
|
||||
"main_view_html": "main_view.html",
|
||||
"tile_view_html": "",
|
||||
"flags": ["root", "debug"],
|
||||
"publish": {
|
||||
"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
|
||||
import aiohttp
|
||||
|
||||
HOME_DIR = str(pathlib.Path(os.getcwd()).parent.parent.resolve())
|
||||
HOME_DIR = "/home/deck"
|
||||
SETTINGS_DIR = HOME_DIR + "/.config/powertools"
|
||||
|
||||
if not os.path.exists(SETTINGS_DIR):
|
||||
|
@ -60,6 +60,15 @@ class Server(web.Application):
|
|||
def game(self) -> GameInfo:
|
||||
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):
|
||||
logging.debug("Debug index page accessed")
|
||||
current_game = None if self.current_game is None else self.current_game.gameid
|
||||
|
@ -97,16 +106,13 @@ class Server(web.Application):
|
|||
except ValueError:
|
||||
return web.Response(text="WTF", status=400)
|
||||
if self.current_game.gameid == game_id:
|
||||
pass
|
||||
#self.current_game = None
|
||||
# TODO change settings to default
|
||||
self.current_game = None
|
||||
return web.Response(status=204, headers={"Access-Control-Allow-Origin": "*"})
|
||||
|
||||
async def on_game_exit_null(self, request):
|
||||
# ignored for now
|
||||
logging.info(f"on_game_exit_null")
|
||||
#self.current_game = None
|
||||
# TODO change settings to default
|
||||
self.current_game = None
|
||||
return web.Response(status=204, headers={"Access-Control-Allow-Origin": "*"})
|
||||
|
||||
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