mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-06-17 08:47:49 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c947548064 | |||
| 19d5527bdf | |||
| ef51b96f08 | |||
| 617916e8e5 | |||
| 6c4a4d0a44 | |||
| bedcb0fb71 | |||
| 2461f52ca7 | |||
| 3c00eb8cf4 | |||
| 21e1d8504a | |||
| ba93c4add2 | |||
| 61fea41c8a | |||
| e40d3e4db5 | |||
| bbad6bf2be | |||
| 4e04455163 | |||
| 314292b042 | |||
| a264f36966 | |||
| 60c8c5db42 | |||
| 852c52c59a |
@@ -109,7 +109,7 @@ jobs:
|
||||
printf "OUT: ${OUT}\n"
|
||||
elif [[ ! "$VERSION" =~ "-pre" ]]; then
|
||||
printf "previous tag is a release, bumping by a patch\n"
|
||||
OUT=$(semver bump minor "$VERSION")
|
||||
OUT=$(semver bump patch "$VERSION")
|
||||
printf "OUT: ${OUT}\n"
|
||||
fi
|
||||
echo "vOUT: v$OUT"
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
# Plugin Loader [](https://discord.gg/ZU74G2NJzk)
|
||||
# Decky Loader [](https://discord.gg/ZU74G2NJzk)
|
||||
|
||||

|
||||
|
||||
Keep an eye on the [Wiki](https://deckbrew.xyz) for more information about Plugin Loader, documentation + tools for plugin development and more.
|
||||
Keep an eye on the [Wiki](https://deckbrew.xyz) for more information about Decky Loader, documentation + tools for plugin development and more.
|
||||
|
||||
## Installation
|
||||
1. Go into the Steam Deck Settings
|
||||
2. Under System -> System Settings toggle `Enable Developer Mode`
|
||||
3. Scroll the sidebar all the way down and click on `Developer`
|
||||
4. Under Miscellaneous, enable `CEF Remote Debugging`
|
||||
5. Click on the `STEAM` button and select `Power` -> `Switch to Desktop`
|
||||
6. Make sure you have a password set with the "passwd" command in terminal to install it ([YouTube Guide](https://www.youtube.com/watch?v=1vOMYGj22rQ)).
|
||||
7. Open a terminal and paste the following command into it:
|
||||
5. Confirm dialog and wait for system reboot
|
||||
6. Click on the `STEAM` button and select `Power` -> `Switch to Desktop`
|
||||
7. Make sure you have a password set with the "passwd" command in terminal to install it ([YouTube Guide](https://www.youtube.com/watch?v=1vOMYGj22rQ)).
|
||||
8. Open a terminal ("Konsole" is the pre-installed terminal application) and paste the following command into it:
|
||||
- For the latest release:
|
||||
- `curl -L https://github.com/SteamDeckHomebrew/decky-loader/raw/main/dist/install_release.sh | sh`
|
||||
- For the latest pre-release:
|
||||
- `curl -L https://github.com/SteamDeckHomebrew/decky-loader/raw/main/dist/install_prerelease.sh | sh`
|
||||
- For testers/plugin developers:
|
||||
- `curl -L https://github.com/SteamDeckHomebrew/decky-loader/raw/main/dist/install_prerelease.sh | sh`
|
||||
- [Wiki Link](https://deckbrew.xyz/en/loader-dev/development)
|
||||
- For the legacy version (unsupported):
|
||||
- `curl -L https://github.com/SteamDeckHomebrew/decky-loader/raw/legacy/dist/install_release.sh | sh`
|
||||
7. Done! Reboot back into Gaming mode and enjoy your plugins!
|
||||
9. Done! Reboot back into Gaming mode and enjoy your plugins!
|
||||
|
||||
### Install/Uninstall Plugins
|
||||
- Using the shopping bag button in the top right corner, you can go to the offical ["Plugin Store"](https://plugins.deckbrew.xyz/)
|
||||
- Using the shopping bag button in the top right corner of the plugin menu, you can go to the offical Plugin Store ([Web Preview](https://beta.deckbrew.xyz/)).
|
||||
- Simply copy the plugin's folder into `~/homebrew/plugins`
|
||||
- Use the settings menu to uninstall plugins, this will not remove any files made in different directories by plugins.
|
||||
|
||||
@@ -41,8 +42,8 @@ Keep an eye on the [Wiki](https://deckbrew.xyz) for more information about Plugi
|
||||
- There is no complete plugin development documentation yet. However a good starting point is the [Plugin Template](https://github.com/SteamDeckHomebrew/decky-plugin-template) repository.
|
||||
|
||||
## [Contribution](https://deckbrew.xyz/en/loader-dev/development)
|
||||
- Please consult the [Wiki](https://deckbrew.xyz/en/loader-dev/development) for installing development versions of PluginLoader.
|
||||
- This is also useful for Plugin Developers looking to target new but unreleased versions of PluginLoader.
|
||||
- Please consult the [Wiki](https://deckbrew.xyz/en/loader-dev/development) for installing development versions of Decky Loader.
|
||||
- This is also useful for Plugin Developers looking to target new but unreleased versions of Decky Loader.
|
||||
- [Here's how to get the Steam Deck UI on your enviroment of choice.](https://youtu.be/1IAbZte8e7E?t=112)
|
||||
- (The video shows Windows usage but unless you're using Arch WSL/cygwin this script is unsupported on Windows.)
|
||||
|
||||
|
||||
+3
-4
@@ -48,10 +48,9 @@ class PluginBrowser:
|
||||
return False
|
||||
return True
|
||||
|
||||
async def _download_remote_binaries_for_plugin_with_name(self, plugin_name):
|
||||
async def _download_remote_binaries_for_plugin_with_name(self, pluginBasePath):
|
||||
rv = False
|
||||
try:
|
||||
pluginBasePath = path.join(self.plugin_path, plugin_name)
|
||||
packageJsonPath = path.join(pluginBasePath, 'package.json')
|
||||
pluginBinPath = path.join(pluginBasePath, 'bin')
|
||||
|
||||
@@ -143,10 +142,10 @@ class PluginBrowser:
|
||||
logger.debug("Unzipping...")
|
||||
ret = self._unzip_to_plugin_dir(res_zip, name, hash)
|
||||
if ret:
|
||||
ret = await self._download_remote_binaries_for_plugin_with_name(name)
|
||||
plugin_dir = self.find_plugin_folder(name)
|
||||
ret = await self._download_remote_binaries_for_plugin_with_name(plugin_dir)
|
||||
if ret:
|
||||
logger.info(f"Installed {name} (Version: {version})")
|
||||
plugin_dir = self.find_plugin_folder(name)
|
||||
if name in self.loader.plugins:
|
||||
self.loader.plugins[name].stop()
|
||||
self.loader.plugins.pop(name, None)
|
||||
|
||||
Vendored
+7
-2
@@ -13,8 +13,13 @@ sudo -u $SUDO_USER mkdir -p "${HOMEBREW_FOLDER}/services"
|
||||
sudo -u $SUDO_USER mkdir -p "${HOMEBREW_FOLDER}/plugins"
|
||||
|
||||
# Download latest release and install it
|
||||
curl -L https://github.com/SteamDeckHomebrew/PluginLoader/releases/latest/download/PluginLoader --output "${HOMEBREW_FOLDER}/services/PluginLoader"
|
||||
chmod +x "${HOMEBREW_FOLDER}/services/PluginLoader"
|
||||
RELEASE=$(curl -s 'https://api.github.com/repos/SteamDeckHomebrew/decky-loader/releases' | jq -r "first(.[] | select(.prerelease == "false"))")
|
||||
read VERSION DOWNLOADURL < <(echo $(jq -r '.tag_name, .assets[].browser_download_url' <<< ${RELEASE}))
|
||||
|
||||
printf "Installing version %s...\n" "${VERSION}"
|
||||
curl -L $DOWNLOADURL --output ${HOMEBREW_FOLDER}/services/PluginLoader
|
||||
chmod +x ${HOMEBREW_FOLDER}/services/PluginLoader
|
||||
echo $VERSION > ${HOMEBREW_FOLDER}/services/.loader.version
|
||||
|
||||
systemctl --user stop plugin_loader 2> /dev/null
|
||||
systemctl --user disable plugin_loader 2> /dev/null
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "decky_frontend",
|
||||
"version": "0.0.1",
|
||||
"version": "2.1.1",
|
||||
"private": true,
|
||||
"license": "GPLV2",
|
||||
"scripts": {
|
||||
|
||||
@@ -24,6 +24,7 @@ const Markdown: FunctionComponent<MarkdownProps> = (props) => {
|
||||
aRef?.current?.click();
|
||||
props.onDismiss?.();
|
||||
}}
|
||||
style={{ display: 'inline' }}
|
||||
>
|
||||
<a ref={aRef} {...nodeProps.node.properties}>
|
||||
{nodeProps.children}
|
||||
|
||||
@@ -32,8 +32,8 @@ const PluginView: VFC = () => {
|
||||
.map(({ name, icon }) => (
|
||||
<PanelSectionRow key={name}>
|
||||
<ButtonItem layout="below" onClick={() => setActivePlugin(name)}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<div>{icon}</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
{icon}
|
||||
<div>{name}</div>
|
||||
<NotificationBadge show={updates?.has(name)} style={{ top: '-5px', right: '-5px' }} />
|
||||
</div>
|
||||
|
||||
@@ -21,6 +21,7 @@ const PluginInstallModal: FC<PluginInstallModalProps> = ({ artifact, version, ha
|
||||
setLoading(true);
|
||||
await onOK();
|
||||
setTimeout(() => Router.OpenQuickAccessMenu(QuickAccessTab.Decky), 250);
|
||||
setTimeout(() => window.DeckyPluginLoader.checkPluginUpdates(), 1000);
|
||||
}}
|
||||
onCancel={async () => {
|
||||
await onCancel();
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
import { ConfirmModal, ModalRoot, QuickAccessTab, Router, showModal, sleep, staticClasses } from 'decky-frontend-lib';
|
||||
import {
|
||||
ConfirmModal,
|
||||
ModalRoot,
|
||||
Patch,
|
||||
QuickAccessTab,
|
||||
Router,
|
||||
callOriginal,
|
||||
findModuleChild,
|
||||
replacePatch,
|
||||
showModal,
|
||||
sleep,
|
||||
staticClasses,
|
||||
} from 'decky-frontend-lib';
|
||||
import { lazy } from 'react';
|
||||
import { FaPlug } from 'react-icons/fa';
|
||||
|
||||
@@ -39,6 +51,8 @@ class PluginLoader extends Logger {
|
||||
// stores a list of plugin names which requested to be reloaded
|
||||
private pluginReloadQueue: { name: string; version?: string }[] = [];
|
||||
|
||||
private focusWorkaroundPatch?: Patch;
|
||||
|
||||
constructor() {
|
||||
super(PluginLoader.name);
|
||||
this.log('Initialized');
|
||||
@@ -83,6 +97,38 @@ class PluginLoader extends Logger {
|
||||
initFilepickerPatches();
|
||||
|
||||
this.updateVersion();
|
||||
|
||||
const self = this;
|
||||
|
||||
try {
|
||||
// TODO remove all of this once Valve fixes the bug
|
||||
const focusManager = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return false;
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.prototype?.TakeFocus) return m[prop];
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
this.focusWorkaroundPatch = replacePatch(focusManager.prototype, 'TakeFocus', function () {
|
||||
// @ts-ignore
|
||||
const classList = this.m_node?.m_element.classList;
|
||||
if (
|
||||
// @ts-ignore
|
||||
(this.m_node?.m_element && classList.contains(staticClasses.TabGroupPanel)) ||
|
||||
classList.contains('FriendsListTab') ||
|
||||
classList.contains('FriendsTabList') ||
|
||||
classList.contains('FriendsListAndChatsSteamDeck')
|
||||
) {
|
||||
self.debug('Intercepted friends re-focus');
|
||||
return true;
|
||||
}
|
||||
|
||||
return callOriginal;
|
||||
});
|
||||
} catch (e) {
|
||||
this.error('Friends focus patch failed', e);
|
||||
}
|
||||
}
|
||||
|
||||
public async updateVersion() {
|
||||
@@ -167,6 +213,7 @@ class PluginLoader extends Logger {
|
||||
this.routerHook.removeRoute('/decky/store');
|
||||
this.routerHook.removeRoute('/decky/settings');
|
||||
deinitFilepickerPatches();
|
||||
this.focusWorkaroundPatch?.unpatch();
|
||||
}
|
||||
|
||||
public unloadPlugin(name: string) {
|
||||
|
||||
@@ -101,6 +101,7 @@ class TabsHook extends Logger {
|
||||
});
|
||||
this.cNode = scrollRoot;
|
||||
this.cNode.stateNode.forceUpdate();
|
||||
this.log('Finished initial injection');
|
||||
})();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ class Toaster extends Logger {
|
||||
|
||||
async init() {
|
||||
let instance: any;
|
||||
|
||||
while (true) {
|
||||
instance = findInReactTree(
|
||||
(document.getElementById('root') as any)._reactRootContainer._internalRoot.current,
|
||||
|
||||
Reference in New Issue
Block a user