diff --git a/main.py b/main.py
index 9767bbb..a644d75 100644
--- a/main.py
+++ b/main.py
@@ -35,6 +35,9 @@ async def _main(self):
async def get_settings(self):
results = settings.get_settings()
+ if results.get("chargeLimitEnabled", False):
+ legion_space.set_charge_limit(True)
+
try:
results['pluginVersionNum'] = f'{decky_plugin.DECKY_PLUGIN_VERSION}'
@@ -141,6 +144,13 @@ async def set_power_led(self, enabled):
legion_space.set_power_light(enabled)
+ async def set_charge_limit(self, enabled):
+ try:
+ settings.set_setting('chargeLimitEnabled', enabled)
+
+ legion_space.set_charge_limit(enabled)
+ except Exception as e:
+ decky_plugin.logger.error(f'error while setting charge limit {e}')
async def remap_button(self, button: str, action: str):
decky_plugin.logger.info(f"remap_button {button} {action}")
diff --git a/py_modules/legion_space.py b/py_modules/legion_space.py
index e3ee3bc..17fd7fa 100644
--- a/py_modules/legion_space.py
+++ b/py_modules/legion_space.py
@@ -139,8 +139,13 @@ def get_charge_limit():
# off
# echo '\_SB.GZFD.WMAE 0 0x12 {0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00}' | sudo tee /proc/acpi/call
# 80% charge limit
-def set_charging_limit(enabled: bool):
- if enabled:
+def set_charge_limit(enabled: bool):
+
+ current_charge_limit = get_charge_limit()
+
+ # decky_plugin.logger.info(f'charge limit {current_charge_limit} {current_charge_limit == 0}')
+
+ if enabled and current_charge_limit == 0:
return call(
r"\_SB.GZFD.WMAE",
[
@@ -160,7 +165,7 @@ def set_charging_limit(enabled: bool):
),
],
)
- else:
+ elif not enabled and current_charge_limit == 1:
return call(
r"\_SB.GZFD.WMAE",
[
@@ -180,6 +185,8 @@ def set_charging_limit(enabled: bool):
),
],
)
+ # no changes required
+ return True
def call(method: str, args: Sequence[bytes | int], risky: bool = True):
cmd = method
diff --git a/src/backend/utils.tsx b/src/backend/utils.tsx
index 6baab26..1df1da9 100644
--- a/src/backend/utils.tsx
+++ b/src/backend/utils.tsx
@@ -7,7 +7,8 @@ export enum ServerAPIMethods {
REMAP_BUTTON = 'remap_button',
LOG_INFO = 'log_info',
GET_SETTINGS = 'get_settings',
- SET_POWER_LED = 'set_power_led'
+ SET_POWER_LED = 'set_power_led',
+ SET_CHARGE_LIMIT = 'set_charge_limit'
}
const createRgbOn =
@@ -46,6 +47,13 @@ const createSetPowerLed =
});
};
+const createSetChargeLimit =
+ (serverAPI: ServerAPI) => async (enabled: boolean) => {
+ await serverAPI.callPluginMethod(ServerAPIMethods.SET_CHARGE_LIMIT, {
+ enabled
+ });
+ };
+
const createGetSettings = (serverAPI: ServerAPI) => async () => {
return await serverAPI.callPluginMethod(ServerAPIMethods.GET_SETTINGS, {});
};
@@ -73,7 +81,8 @@ export const createServerApiHelpers = (serverAPI: ServerAPI) => {
remapButton: createRemapButtons(serverAPI),
logInfo: createLogInfo(serverAPI),
getSettings: createGetSettings(serverAPI),
- setPowerLed: createSetPowerLed(serverAPI)
+ setPowerLed: createSetPowerLed(serverAPI),
+ setChargeLimit: createSetChargeLimit(serverAPI)
};
};
diff --git a/src/hooks/ui.tsx b/src/hooks/ui.tsx
new file mode 100644
index 0000000..d84a2a5
--- /dev/null
+++ b/src/hooks/ui.tsx
@@ -0,0 +1,13 @@
+import { useDispatch, useSelector } from 'react-redux';
+import { selectChargeLimitEnabled, uiSlice } from '../redux-modules/uiSlice';
+
+export const useChargeLimitEnabled = () => {
+ const chargeLimitEnabled = useSelector(selectChargeLimitEnabled);
+ const dispatch = useDispatch();
+
+ const setChargeLimit = (enabled: boolean) => {
+ return dispatch(uiSlice.actions.setChargeLimit(enabled));
+ };
+
+ return { chargeLimitEnabled, setChargeLimit };
+};
diff --git a/src/index.tsx b/src/index.tsx
index 826abc8..3bedea4 100755
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,4 +1,11 @@
-import { definePlugin, ServerAPI, staticClasses } from 'decky-frontend-lib';
+import {
+ definePlugin,
+ PanelSection,
+ PanelSectionRow,
+ ServerAPI,
+ staticClasses,
+ ToggleField
+} from 'decky-frontend-lib';
import { memo, VFC } from 'react';
import RemapButtons from './components/controller/RemapButtons';
@@ -13,14 +20,25 @@ import logo from '../assets/Icon.png';
import FanPanel from './components/fan/FanPanel';
import ErrorBoundary from './components/ErrorBoundary';
import OtaUpdates from './components/OtaUpdates';
+import { useChargeLimitEnabled } from './hooks/ui';
const Content: VFC<{ serverAPI?: ServerAPI }> = memo(() => {
const loading = useSelector(getInitialLoading);
+ const { chargeLimitEnabled, setChargeLimit } = useChargeLimitEnabled();
if (loading) {
return null;
}
return (
<>
+
+
+
+
+
diff --git a/src/redux-modules/store.tsx b/src/redux-modules/store.tsx
index ce96ad4..da9d8ea 100644
--- a/src/redux-modules/store.tsx
+++ b/src/redux-modules/store.tsx
@@ -1,6 +1,6 @@
import { configureStore } from '@reduxjs/toolkit';
import { rgbSlice, saveRgbSettingsMiddleware } from './rgbSlice';
-import { uiSlice } from './uiSlice';
+import { uiSlice, uiSliceMiddleware } from './uiSlice';
import {
controllerSlice,
saveControllerSettingsMiddleware
@@ -17,6 +17,7 @@ export const store = configureStore({
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat([
+ uiSliceMiddleware,
saveRgbSettingsMiddleware,
saveControllerSettingsMiddleware,
saveFanSettingsMiddleware
diff --git a/src/redux-modules/uiSlice.tsx b/src/redux-modules/uiSlice.tsx
index a61befe..dbffb65 100644
--- a/src/redux-modules/uiSlice.tsx
+++ b/src/redux-modules/uiSlice.tsx
@@ -2,13 +2,19 @@ import { createSlice } from '@reduxjs/toolkit';
import type { PayloadAction } from '@reduxjs/toolkit';
import { setCurrentGameId, setInitialState } from './extraActions';
import { RootState } from './store';
-import { extractDisplayName, logInfo } from '../backend/utils';
+import {
+ createServerApiHelpers,
+ extractDisplayName,
+ getServerApi,
+ logInfo
+} from '../backend/utils';
// import type { RootState } from './store';
type UiStateType = {
initialLoading: boolean;
currentGameId: undefined | string;
currentDisplayName: undefined | string;
+ chargeLimitEnabled?: boolean;
pluginVersionNum?: string;
};
@@ -27,6 +33,9 @@ export const uiSlice = createSlice({
reducers: {
setInitialLoading: (state, action: PayloadAction) => {
state.initialLoading = action.payload;
+ },
+ setChargeLimit(state, action: PayloadAction) {
+ state.chargeLimitEnabled = action.payload;
}
},
extraReducers: (builder) => {
@@ -35,6 +44,9 @@ export const uiSlice = createSlice({
if (action.payload?.pluginVersionNum) {
state.pluginVersionNum = `${action.payload.pluginVersionNum}`;
}
+ if (action.payload?.chargeLimitEnabled) {
+ state.chargeLimitEnabled = Boolean(action.payload?.chargeLimitEnabled);
+ }
});
builder.addCase(setCurrentGameId, (state, action) => {
if (action?.payload) {
@@ -55,3 +67,22 @@ export const selectCurrentGameId = (state: RootState) =>
export const selectCurrentGameDisplayName = (state: RootState) =>
state.ui?.currentDisplayName || 'default';
+
+export const selectChargeLimitEnabled = (state: RootState) =>
+ Boolean(state.ui?.chargeLimitEnabled);
+
+export const uiSliceMiddleware =
+ (store: any) => (next: any) => (action: any) => {
+ const { type } = action;
+ const serverApi = getServerApi();
+
+ const result = next(action);
+
+ if (type === uiSlice.actions.setChargeLimit.type && serverApi) {
+ const { setChargeLimit } = createServerApiHelpers(serverApi);
+
+ setChargeLimit(action.payload);
+ }
+
+ return result;
+ };