mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-06-24 12:09:13 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5053a52f32 | |||
| 5bfc53231d | |||
| 2b4e3318ca | |||
| b84dcd99ad | |||
| 34fb7bb538 | |||
| 4a7e9a5f3d | |||
| 8e8e6a2bd1 | |||
| 55a95e04b5 | |||
| 49d1e33c14 | |||
| 922d0c4153 | |||
| ecf480059b | |||
| 7d6b8805df | |||
| 0dce3a8cbe | |||
| 9503d5cee0 |
@@ -42,7 +42,7 @@ body:
|
||||
label: SteamOS version
|
||||
# description: Can be found with `uname -a`
|
||||
# placeholder: "Linux steamdeck 5.13.0-valve36-1-neptune #1 SMP PREEMPT Mon, 19 Dec 2022 23:39:41 +0000 x86_64 GNU/Linux"
|
||||
placeholder: "SteamOS 3.4.3 Stable"
|
||||
placeholder: "SteamOS 3.5.7 Stable"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -67,8 +67,18 @@ body:
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Logs
|
||||
label: Backend Logs
|
||||
description: Please reboot your deck (if possible) when attempting to recreate the issue, then run ``cd ~ && journalctl -b0 -u plugin_loader.service > deckylog.txt``. This will save the log file to ``~`` aka ``/home/deck``. Please upload the file here
|
||||
placeholder: deckylog.txt
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Frontend Logs
|
||||
description: Please copy from your deck ~/.steam/steam/logs/cef_log.txt and ~/.steam/steam/logs/cef_log.previous.txt. Make sure to scrub your Steam username as it may appear in these logs.
|
||||
placeholder: cef_log.txt
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
|
||||
+267
-261
@@ -1,264 +1,270 @@
|
||||
{
|
||||
"BranchSelect": {
|
||||
"update_channel": {
|
||||
"label": "Update Channel",
|
||||
"prerelease": "Prerelease",
|
||||
"stable": "Stable",
|
||||
"testing": "Testing"
|
||||
"BranchSelect": {
|
||||
"update_channel": {
|
||||
"label": "Update Channel",
|
||||
"prerelease": "Prerelease",
|
||||
"stable": "Stable",
|
||||
"testing": "Testing"
|
||||
}
|
||||
},
|
||||
"Developer": {
|
||||
"5secreload": "Reloading in 5 seconds",
|
||||
"disabling": "Disabling React DevTools",
|
||||
"enabling": "Enabling React DevTools"
|
||||
},
|
||||
"DropdownMultiselect": {
|
||||
"button": {
|
||||
"back": "Back"
|
||||
}
|
||||
},
|
||||
"FilePickerError": {
|
||||
"errors": {
|
||||
"file_not_found": "The path specified is not valid. Please check it and reenter it correctly.",
|
||||
"perm_denied": "You do not have access to the specified directory. Please check if your user (deck on Steam Deck) has the corresponding permission to access the specified folder/file.",
|
||||
"unknown": "An unknown error occurred. The raw error is: {{raw_error}}"
|
||||
}
|
||||
},
|
||||
"FilePickerIndex": {
|
||||
"file": {
|
||||
"select": "Select this file"
|
||||
},
|
||||
"files": {
|
||||
"all_files": "All Files",
|
||||
"file_type": "File Type",
|
||||
"show_hidden": "Show Hidden Files"
|
||||
},
|
||||
"filter": {
|
||||
"created_asce": "Created (Oldest)",
|
||||
"created_desc": "Created (Newest)",
|
||||
"modified_asce": "Modified (Oldest)",
|
||||
"modified_desc": "Modified (Newest)",
|
||||
"name_asce": "Z-A",
|
||||
"name_desc": "A-Z",
|
||||
"size_asce": "Size (Smallest)",
|
||||
"size_desc": "Size (Largest)"
|
||||
},
|
||||
"folder": {
|
||||
"label": "Folder",
|
||||
"select": "Use this folder",
|
||||
"show_more": "Show more files"
|
||||
}
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"confirm": "Are you sure you want to make the following modifications?",
|
||||
"description": {
|
||||
"install": "Install {{name}} {{version}}",
|
||||
"reinstall": "Reinstall {{name}} {{version}}",
|
||||
"update": "Update {{name}} to {{version}}"
|
||||
},
|
||||
"ok_button": {
|
||||
"idle": "Confirm",
|
||||
"loading": "Working"
|
||||
},
|
||||
"title": {
|
||||
"install_one": "Install 1 plugin",
|
||||
"install_other": "Install {{count}} plugins",
|
||||
"mixed_one": "Modify {{count}} plugin",
|
||||
"mixed_other": "Modify {{count}} plugins",
|
||||
"reinstall_one": "Reinstall 1 plugin",
|
||||
"reinstall_other": "Reinstall {{count}} plugins",
|
||||
"update_one": "Update 1 plugin",
|
||||
"update_other": "Update {{count}} plugins"
|
||||
}
|
||||
},
|
||||
"PluginCard": {
|
||||
"plugin_full_access": "This plugin has full access to your Steam Deck.",
|
||||
"plugin_install": "Install",
|
||||
"plugin_no_desc": "No description provided.",
|
||||
"plugin_version_label": "Plugin Version"
|
||||
},
|
||||
"PluginInstallModal": {
|
||||
"install": {
|
||||
"button_idle": "Install",
|
||||
"button_processing": "Installing",
|
||||
"desc": "Are you sure you want to install {{artifact}} {{version}}?",
|
||||
"title": "Install {{artifact}}"
|
||||
},
|
||||
"no_hash": "This plugin does not have a hash, you are installing it at your own risk.",
|
||||
"reinstall": {
|
||||
"button_idle": "Reinstall",
|
||||
"button_processing": "Reinstalling",
|
||||
"desc": "Are you sure you want to reinstall {{artifact}} {{version}}?",
|
||||
"title": "Reinstall {{artifact}}"
|
||||
},
|
||||
"update": {
|
||||
"button_idle": "Update",
|
||||
"button_processing": "Updating",
|
||||
"desc": "Are you sure you want to update {{artifact}} {{version}}?",
|
||||
"title": "Update {{artifact}}"
|
||||
}
|
||||
},
|
||||
"PluginListIndex": {
|
||||
"freeze": "Freeze updates",
|
||||
"hide": "Quick access: Hide",
|
||||
"no_plugin": "No plugins installed!",
|
||||
"plugin_actions": "Plugin Actions",
|
||||
"reinstall": "Reinstall",
|
||||
"reload": "Reload",
|
||||
"show": "Quick access: Show",
|
||||
"unfreeze": "Allow updates",
|
||||
"uninstall": "Uninstall",
|
||||
"update_all_one": "Update 1 plugin",
|
||||
"update_all_other": "Update {{count}} plugins",
|
||||
"update_to": "Update to {{name}}"
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "Hidden from the quick access menu"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
"decky_update_available": "Update to {{tag_name}} available!",
|
||||
"error": "Error",
|
||||
"plugin_error_uninstall": "Loading {{name}} caused an exception as shown above. This usually means that the plugin requires an update for the new version of SteamUI. Check if an update is present or evaluate its removal in the Decky settings, in the Plugins section.",
|
||||
"plugin_load_error": {
|
||||
"message": "Error loading plugin {{name}}",
|
||||
"toast": "Error loading {{name}}"
|
||||
},
|
||||
"plugin_uninstall": {
|
||||
"button": "Uninstall",
|
||||
"desc": "Are you sure you want to uninstall {{name}}?",
|
||||
"title": "Uninstall {{name}}"
|
||||
},
|
||||
"plugin_update_one": "Updates available for 1 plugin!",
|
||||
"plugin_update_other": "Updates available for {{count}} plugins!"
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "1 plugin is hidden from this list",
|
||||
"hidden_other": "{{count}} plugins are hidden from this list"
|
||||
},
|
||||
"RemoteDebugging": {
|
||||
"remote_cef": {
|
||||
"desc": "Allow unauthenticated access to the CEF debugger to anyone in your network",
|
||||
"label": "Allow Remote CEF Debugging"
|
||||
}
|
||||
},
|
||||
"SettingsDeveloperIndex": {
|
||||
"cef_console": {
|
||||
"button": "Open Console",
|
||||
"desc": "Opens the CEF Console. Only useful for debugging purposes. Stuff here is potentially dangerous and should only be used if you are a plugin dev, or are directed here by one.",
|
||||
"label": "CEF Console"
|
||||
},
|
||||
"header": "Other",
|
||||
"react_devtools": {
|
||||
"desc": "Enables connection to a computer running React DevTools. Changing this setting will reload Steam. Set the IP address before enabling.",
|
||||
"ip_label": "IP",
|
||||
"label": "Enable React DevTools"
|
||||
},
|
||||
"third_party_plugins": {
|
||||
"button_install": "Install",
|
||||
"button_zip": "Browse",
|
||||
"header": "Third-Party Plugins",
|
||||
"label_desc": "URL",
|
||||
"label_url": "Install Plugin from URL",
|
||||
"label_zip": "Install Plugin from ZIP File"
|
||||
},
|
||||
"valve_internal": {
|
||||
"desc1": "Enables the Valve internal developer menu.",
|
||||
"desc2": "Do not touch anything in this menu unless you know what it does.",
|
||||
"label": "Enable Valve Internal"
|
||||
}
|
||||
},
|
||||
"SettingsGeneralIndex": {
|
||||
"about": {
|
||||
"decky_version": "Decky Version",
|
||||
"header": "About"
|
||||
},
|
||||
"beta": {
|
||||
"header": "Beta participation"
|
||||
},
|
||||
"developer_mode": {
|
||||
"label": "Developer mode"
|
||||
},
|
||||
"notifications": {
|
||||
"decky_updates_label": "Decky update available",
|
||||
"header": "Notifications",
|
||||
"plugin_updates_label": "Plugin updates available"
|
||||
},
|
||||
"other": {
|
||||
"header": "Other"
|
||||
},
|
||||
"updates": {
|
||||
"header": "Updates"
|
||||
}
|
||||
},
|
||||
"SettingsIndex": {
|
||||
"developer_title": "Developer",
|
||||
"general_title": "General",
|
||||
"plugins_title": "Plugins",
|
||||
"testing_title": "Testing"
|
||||
},
|
||||
"Store": {
|
||||
"store_contrib": {
|
||||
"desc": "If you would like to contribute to the Decky Plugin Store, check the SteamDeckHomebrew/decky-plugin-template repository on GitHub. Information on development and distribution is available in the README.",
|
||||
"label": "Contributing"
|
||||
},
|
||||
"store_filter": {
|
||||
"label": "Filter",
|
||||
"label_def": "All"
|
||||
},
|
||||
"store_search": {
|
||||
"label": "Search"
|
||||
},
|
||||
"store_sort": {
|
||||
"label": "Sort",
|
||||
"label_def": "Last Updated (Newest)"
|
||||
},
|
||||
"store_source": {
|
||||
"desc": "All plugin source code is available on SteamDeckHomebrew/decky-plugin-database repository on GitHub.",
|
||||
"label": "Source Code"
|
||||
},
|
||||
"store_tabs": {
|
||||
"about": "About",
|
||||
"alph_asce": "Alphabetical (Z to A)",
|
||||
"alph_desc": "Alphabetical (A to Z)",
|
||||
"date_asce": "Oldest First",
|
||||
"date_desc": "Newest First",
|
||||
"downloads_asce": "Least Downloaded First",
|
||||
"downloads_desc": "Most Downloaded First",
|
||||
"title": "Browse"
|
||||
},
|
||||
"store_testing_cta": "Please consider testing new plugins to help the Decky Loader team!",
|
||||
"store_testing_warning": {
|
||||
"desc": "You can use this store channel to test bleeding-edge plugin versions. Be sure to leave feedback on GitHub so the plugin can be updated for all users.",
|
||||
"label": "Welcome to the Testing Store Channel"
|
||||
}
|
||||
},
|
||||
"StoreSelect": {
|
||||
"custom_store": {
|
||||
"label": "Custom Store",
|
||||
"url_label": "URL"
|
||||
},
|
||||
"store_channel": {
|
||||
"custom": "Custom",
|
||||
"default": "Default",
|
||||
"label": "Store Channel",
|
||||
"testing": "Testing"
|
||||
}
|
||||
},
|
||||
"TitleView": {
|
||||
"decky_store_desc": "Open Decky Store",
|
||||
"settings_desc": "Open Decky Settings"
|
||||
},
|
||||
"Updater": {
|
||||
"decky_updates": "Decky Updates",
|
||||
"no_patch_notes_desc": "no patch notes for this version",
|
||||
"patch_notes_desc": "Patch Notes",
|
||||
"updates": {
|
||||
"check_button": "Check For Updates",
|
||||
"checking": "Checking",
|
||||
"cur_version": "Current version: {{ver}}",
|
||||
"install_button": "Install Update",
|
||||
"label": "Updates",
|
||||
"lat_version": "Up to date: running {{ver}}",
|
||||
"reloading": "Reloading",
|
||||
"updating": "Updating"
|
||||
}
|
||||
},
|
||||
"Testing": {
|
||||
"download": "Download"
|
||||
}
|
||||
},
|
||||
"Developer": {
|
||||
"5secreload": "Reloading in 5 seconds",
|
||||
"disabling": "Disabling React DevTools",
|
||||
"enabling": "Enabling React DevTools"
|
||||
},
|
||||
"DropdownMultiselect": {
|
||||
"button": {
|
||||
"back": "Back"
|
||||
}
|
||||
},
|
||||
"FilePickerError": {
|
||||
"errors": {
|
||||
"file_not_found": "The path specified is not valid. Please check it and reenter it correctly.",
|
||||
"perm_denied": "You do not have access to the specified directory. Please check if your user (deck on Steam Deck) has the corresponding permission to access the specified folder/file.",
|
||||
"unknown": "An unknown error occurred. The raw error is: {{raw_error}}"
|
||||
}
|
||||
},
|
||||
"FilePickerIndex": {
|
||||
"file": {
|
||||
"select": "Select this file"
|
||||
},
|
||||
"files": {
|
||||
"all_files": "All Files",
|
||||
"file_type": "File Type",
|
||||
"show_hidden": "Show Hidden Files"
|
||||
},
|
||||
"filter": {
|
||||
"created_asce": "Created (Oldest)",
|
||||
"created_desc": "Created (Newest)",
|
||||
"modified_asce": "Modified (Oldest)",
|
||||
"modified_desc": "Modified (Newest)",
|
||||
"name_asce": "Z-A",
|
||||
"name_desc": "A-Z",
|
||||
"size_asce": "Size (Smallest)",
|
||||
"size_desc": "Size (Largest)"
|
||||
},
|
||||
"folder": {
|
||||
"label": "Folder",
|
||||
"select": "Use this folder",
|
||||
"show_more": "Show more files"
|
||||
}
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"confirm": "Are you sure you want to make the following modifications?",
|
||||
"description": {
|
||||
"install": "Install {{name}} {{version}}",
|
||||
"reinstall": "Reinstall {{name}} {{version}}",
|
||||
"update": "Update {{name}} to {{version}}"
|
||||
},
|
||||
"ok_button": {
|
||||
"idle": "Confirm",
|
||||
"loading": "Working"
|
||||
},
|
||||
"title": {
|
||||
"install_one": "Install 1 plugin",
|
||||
"install_other": "Install {{count}} plugins",
|
||||
"mixed_one": "Modify {{count}} plugin",
|
||||
"mixed_other": "Modify {{count}} plugins",
|
||||
"reinstall_one": "Reinstall 1 plugin",
|
||||
"reinstall_other": "Reinstall {{count}} plugins",
|
||||
"update_one": "Update 1 plugin",
|
||||
"update_other": "Update {{count}} plugins"
|
||||
}
|
||||
},
|
||||
"PluginCard": {
|
||||
"plugin_full_access": "This plugin has full access to your Steam Deck.",
|
||||
"plugin_install": "Install",
|
||||
"plugin_no_desc": "No description provided.",
|
||||
"plugin_version_label": "Plugin Version"
|
||||
},
|
||||
"PluginInstallModal": {
|
||||
"install": {
|
||||
"button_idle": "Install",
|
||||
"button_processing": "Installing",
|
||||
"desc": "Are you sure you want to install {{artifact}} {{version}}?",
|
||||
"title": "Install {{artifact}}"
|
||||
},
|
||||
"no_hash": "This plugin does not have a hash, you are installing it at your own risk.",
|
||||
"reinstall": {
|
||||
"button_idle": "Reinstall",
|
||||
"button_processing": "Reinstalling",
|
||||
"desc": "Are you sure you want to reinstall {{artifact}} {{version}}?",
|
||||
"title": "Reinstall {{artifact}}"
|
||||
},
|
||||
"update": {
|
||||
"button_idle": "Update",
|
||||
"button_processing": "Updating",
|
||||
"desc": "Are you sure you want to update {{artifact}} {{version}}?",
|
||||
"title": "Update {{artifact}}"
|
||||
}
|
||||
},
|
||||
"PluginListIndex": {
|
||||
"hide": "Quick access: Hide",
|
||||
"no_plugin": "No plugins installed!",
|
||||
"plugin_actions": "Plugin Actions",
|
||||
"reinstall": "Reinstall",
|
||||
"reload": "Reload",
|
||||
"show": "Quick access: Show",
|
||||
"uninstall": "Uninstall",
|
||||
"update_all_one": "Update 1 plugin",
|
||||
"update_all_other": "Update {{count}} plugins",
|
||||
"update_to": "Update to {{name}}"
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "Hidden from the quick access menu"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
"decky_update_available": "Update to {{tag_name}} available!",
|
||||
"error": "Error",
|
||||
"plugin_error_uninstall": "Loading {{name}} caused an exception as shown above. This usually means that the plugin requires an update for the new version of SteamUI. Check if an update is present or evaluate its removal in the Decky settings, in the Plugins section.",
|
||||
"plugin_load_error": {
|
||||
"message": "Error loading plugin {{name}}",
|
||||
"toast": "Error loading {{name}}"
|
||||
},
|
||||
"plugin_uninstall": {
|
||||
"button": "Uninstall",
|
||||
"desc": "Are you sure you want to uninstall {{name}}?",
|
||||
"title": "Uninstall {{name}}"
|
||||
},
|
||||
"plugin_update_one": "Updates available for 1 plugin!",
|
||||
"plugin_update_other": "Updates available for {{count}} plugins!"
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "1 plugin is hidden from this list",
|
||||
"hidden_other": "{{count}} plugins are hidden from this list"
|
||||
},
|
||||
"RemoteDebugging": {
|
||||
"remote_cef": {
|
||||
"desc": "Allow unauthenticated access to the CEF debugger to anyone in your network",
|
||||
"label": "Allow Remote CEF Debugging"
|
||||
}
|
||||
},
|
||||
"SettingsDeveloperIndex": {
|
||||
"cef_console": {
|
||||
"button": "Open Console",
|
||||
"desc": "Opens the CEF Console. Only useful for debugging purposes. Stuff here is potentially dangerous and should only be used if you are a plugin dev, or are directed here by one.",
|
||||
"label": "CEF Console"
|
||||
},
|
||||
"header": "Other",
|
||||
"react_devtools": {
|
||||
"desc": "Enables connection to a computer running React DevTools. Changing this setting will reload Steam. Set the IP address before enabling.",
|
||||
"ip_label": "IP",
|
||||
"label": "Enable React DevTools"
|
||||
},
|
||||
"third_party_plugins": {
|
||||
"button_install": "Install",
|
||||
"button_zip": "Browse",
|
||||
"header": "Third-Party Plugins",
|
||||
"label_desc": "URL",
|
||||
"label_url": "Install Plugin from URL",
|
||||
"label_zip": "Install Plugin from ZIP File"
|
||||
},
|
||||
"valve_internal": {
|
||||
"desc1": "Enables the Valve internal developer menu.",
|
||||
"desc2": "Do not touch anything in this menu unless you know what it does.",
|
||||
"label": "Enable Valve Internal"
|
||||
}
|
||||
},
|
||||
"SettingsGeneralIndex": {
|
||||
"about": {
|
||||
"decky_version": "Decky Version",
|
||||
"header": "About"
|
||||
},
|
||||
"beta": {
|
||||
"header": "Beta participation"
|
||||
},
|
||||
"developer_mode": {
|
||||
"label": "Developer mode"
|
||||
},
|
||||
"notifications": {
|
||||
"decky_updates_label": "Decky update available",
|
||||
"header": "Notifications",
|
||||
"plugin_updates_label": "Plugin updates available"
|
||||
},
|
||||
"other": {
|
||||
"header": "Other"
|
||||
},
|
||||
"updates": {
|
||||
"header": "Updates"
|
||||
}
|
||||
},
|
||||
"SettingsIndex": {
|
||||
"developer_title": "Developer",
|
||||
"general_title": "General",
|
||||
"plugins_title": "Plugins"
|
||||
},
|
||||
"Store": {
|
||||
"store_contrib": {
|
||||
"desc": "If you would like to contribute to the Decky Plugin Store, check the SteamDeckHomebrew/decky-plugin-template repository on GitHub. Information on development and distribution is available in the README.",
|
||||
"label": "Contributing"
|
||||
},
|
||||
"store_filter": {
|
||||
"label": "Filter",
|
||||
"label_def": "All"
|
||||
},
|
||||
"store_search": {
|
||||
"label": "Search"
|
||||
},
|
||||
"store_sort": {
|
||||
"label": "Sort",
|
||||
"label_def": "Last Updated (Newest)"
|
||||
},
|
||||
"store_source": {
|
||||
"desc": "All plugin source code is available on SteamDeckHomebrew/decky-plugin-database repository on GitHub.",
|
||||
"label": "Source Code"
|
||||
},
|
||||
"store_tabs": {
|
||||
"about": "About",
|
||||
"alph_asce": "Alphabetical (Z to A)",
|
||||
"alph_desc": "Alphabetical (A to Z)",
|
||||
"date_asce": "Oldest First",
|
||||
"date_desc": "Newest First",
|
||||
"downloads_asce": "Least Downloaded First",
|
||||
"downloads_desc": "Most Downloaded First",
|
||||
"title": "Browse"
|
||||
},
|
||||
"store_testing_cta": "Please consider testing new plugins to help the Decky Loader team!",
|
||||
"store_testing_warning": {
|
||||
"desc": "You can use this store channel to test bleeding-edge plugin versions. Be sure to leave feedback on GitHub so the plugin can be updated for all users.",
|
||||
"label": "Welcome to the Testing Store Channel"
|
||||
}
|
||||
},
|
||||
"StoreSelect": {
|
||||
"custom_store": {
|
||||
"label": "Custom Store",
|
||||
"url_label": "URL"
|
||||
},
|
||||
"store_channel": {
|
||||
"custom": "Custom",
|
||||
"default": "Default",
|
||||
"label": "Store Channel",
|
||||
"testing": "Testing"
|
||||
}
|
||||
},
|
||||
"TitleView": {
|
||||
"decky_store_desc": "Open Decky Store",
|
||||
"settings_desc": "Open Decky Settings"
|
||||
},
|
||||
"Updater": {
|
||||
"decky_updates": "Decky Updates",
|
||||
"no_patch_notes_desc": "no patch notes for this version",
|
||||
"patch_notes_desc": "Patch Notes",
|
||||
"updates": {
|
||||
"check_button": "Check For Updates",
|
||||
"checking": "Checking",
|
||||
"cur_version": "Current version: {{ver}}",
|
||||
"install_button": "Install Update",
|
||||
"label": "Updates",
|
||||
"lat_version": "Up to date: running {{ver}}",
|
||||
"reloading": "Reloading",
|
||||
"updating": "Updating"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+68
-21
@@ -56,12 +56,32 @@
|
||||
},
|
||||
"Developer": {
|
||||
"5secreload": "Rechargement dans 5 secondes",
|
||||
"disabling": "Désactivation",
|
||||
"enabling": "Activation"
|
||||
"disabling": "Désactivation des React DevTools",
|
||||
"enabling": "Activation des React DevTools"
|
||||
},
|
||||
"FilePickerIndex": {
|
||||
"folder": {
|
||||
"select": "Utiliser ce dossier"
|
||||
"select": "Utiliser ce dossier",
|
||||
"label": "Dossier",
|
||||
"show_more": "Afficher plus de fichiers"
|
||||
},
|
||||
"files": {
|
||||
"show_hidden": "Afficher les fichiers cachés",
|
||||
"all_files": "Tout les fichiers",
|
||||
"file_type": "Type de fichier"
|
||||
},
|
||||
"file": {
|
||||
"select": "Sélectionner ce fichier"
|
||||
},
|
||||
"filter": {
|
||||
"created_desc": "Création (Plus récent)",
|
||||
"modified_asce": "Modifié (Plus vieux)",
|
||||
"modified_desc": "Modifié (Plus récent)",
|
||||
"created_asce": "Création (Plus vieux)",
|
||||
"name_asce": "Z-A",
|
||||
"name_desc": "A-Z",
|
||||
"size_asce": "Taille (Plus petit)",
|
||||
"size_desc": "Taille (Plus grand)"
|
||||
}
|
||||
},
|
||||
"PluginCard": {
|
||||
@@ -98,9 +118,11 @@
|
||||
"uninstall": "Désinstaller",
|
||||
"update_to": "Mettre à jour vers {{name}}",
|
||||
"no_plugin": "Aucun plugin installé !",
|
||||
"update_all_one": "",
|
||||
"update_all_many": "",
|
||||
"update_all_other": ""
|
||||
"update_all_one": "Mettre à jour 1 plugin",
|
||||
"update_all_many": "Mettre à jour {{count}} plugins",
|
||||
"update_all_other": "Mettre à jour {{count}} plugins",
|
||||
"show": "Accès Rapide : Afficher",
|
||||
"hide": "Accès rapide : Cacher"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
@@ -116,9 +138,9 @@
|
||||
"title": "Désinstaller {{name}}",
|
||||
"desc": "Êtes-vous sûr.e de vouloir désinstaller {{name}} ?"
|
||||
},
|
||||
"plugin_update_one": "",
|
||||
"plugin_update_many": "",
|
||||
"plugin_update_other": ""
|
||||
"plugin_update_one": "Mise à jour disponible pour 1 plugin !",
|
||||
"plugin_update_many": "Mises à jour disponible pour {{count}} plugins !",
|
||||
"plugin_update_other": "Mises à jour disponible pour {{count}} plugins !"
|
||||
},
|
||||
"RemoteDebugging": {
|
||||
"remote_cef": {
|
||||
@@ -184,18 +206,43 @@
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"reinstall_one": "",
|
||||
"reinstall_many": "",
|
||||
"reinstall_other": "",
|
||||
"install_one": "",
|
||||
"install_many": "",
|
||||
"install_other": "",
|
||||
"mixed_one": "",
|
||||
"mixed_many": "",
|
||||
"mixed_other": "",
|
||||
"update_one": "",
|
||||
"update_many": "",
|
||||
"update_other": ""
|
||||
"reinstall_one": "Réinstaller 1 plugin",
|
||||
"reinstall_many": "Réinstaller {{count}} plugins",
|
||||
"reinstall_other": "Réinstaller {{count}} plugins",
|
||||
"install_one": "Installer 1 plugin",
|
||||
"install_many": "Installer {{count}} plugins",
|
||||
"install_other": "Installer {{count}} plugins",
|
||||
"mixed_one": "Modifier {{count}} plugin",
|
||||
"mixed_many": "Modifier {{count}} plugins",
|
||||
"mixed_other": "Modifier {{count}} plugins",
|
||||
"update_one": "Mettre à jour 1 plugin",
|
||||
"update_many": "Mettre à jour {{count}} plugins",
|
||||
"update_other": "Mettre à jour {{count}} plugins"
|
||||
},
|
||||
"confirm": "Êtes-vous sûr de vouloir apporter les modifications suivantes ?",
|
||||
"description": {
|
||||
"install": "Installer {{name}} {{version}}",
|
||||
"update": "Mettre à jour {{name}} à {{version}}",
|
||||
"reinstall": "Réinstaller {{name}} {{version}}"
|
||||
},
|
||||
"ok_button": {
|
||||
"idle": "Confirmer",
|
||||
"loading": "En cours"
|
||||
}
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "Caché du menu d'accès rapide"
|
||||
},
|
||||
"FilePickerError": {
|
||||
"errors": {
|
||||
"perm_denied": "Vous n'avez pas accès au dossier spécifié. Veuillez vérifier que votre utilisateur (deck sur un Steam Deck) possède les permissions requises pour accéder au dossier/fichier spécifié.",
|
||||
"file_not_found": "Le chemin spécifié n'est pas valide. Veuillez vérifier et essayer à nouveau.",
|
||||
"unknown": "Une erreur inconnue est survenue. L'erreur est : {{raw_error}}"
|
||||
}
|
||||
},
|
||||
"DropdownMultiselect": {
|
||||
"button": {
|
||||
"back": "Retour"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,9 @@
|
||||
"update_all_one": "Aggiorna un plugin",
|
||||
"update_all_many": "Aggiorna {{count}} plugins",
|
||||
"update_all_other": "Aggiorna {{count}} plugins",
|
||||
"update_to": "Aggiorna a {{name}}"
|
||||
"update_to": "Aggiorna a {{name}}",
|
||||
"unfreeze": "Permetti aggiornamenti",
|
||||
"freeze": "Congela aggiornamenti"
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "Nascosto dal menu di accesso rapido"
|
||||
@@ -199,7 +201,8 @@
|
||||
"SettingsIndex": {
|
||||
"developer_title": "Sviluppatore",
|
||||
"general_title": "Generali",
|
||||
"plugins_title": "Plugins"
|
||||
"plugins_title": "Plugins",
|
||||
"testing_title": "Testing"
|
||||
},
|
||||
"Store": {
|
||||
"store_contrib": {
|
||||
@@ -225,7 +228,11 @@
|
||||
"about": "Riguardo a",
|
||||
"alph_asce": "Alfabetico (Z a A)",
|
||||
"alph_desc": "Alfabetico (A a Z)",
|
||||
"title": "Sfoglia"
|
||||
"title": "Sfoglia",
|
||||
"date_desc": "Per più recente",
|
||||
"date_asce": "Per più vecchio",
|
||||
"downloads_desc": "Per più scaricato",
|
||||
"downloads_asce": "Per meno scaricato"
|
||||
},
|
||||
"store_testing_cta": "Valuta la possibilità di testare nuovi plugin per aiutare il team di Decky Loader!",
|
||||
"store_testing_warning": {
|
||||
@@ -263,5 +270,8 @@
|
||||
"TitleView": {
|
||||
"settings_desc": "Apri le impostazioni di Decky",
|
||||
"decky_store_desc": "Apri lo store di Decky"
|
||||
},
|
||||
"Testing": {
|
||||
"download": "Scarica"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
"update_to": "{{name}} を更新"
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "クイックアクセスメニューから非表示にします"
|
||||
"hidden": "クイックアクセスメニューから表示されません"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"error": "エラー",
|
||||
@@ -124,7 +124,7 @@
|
||||
},
|
||||
"third_party_plugins": {
|
||||
"button_install": "インストール",
|
||||
"button_zip": "ブラウズ",
|
||||
"button_zip": "開く",
|
||||
"header": "サードパーティプラグイン",
|
||||
"label_desc": "URL",
|
||||
"label_url": "URLからプラグインをインストール",
|
||||
@@ -138,7 +138,7 @@
|
||||
"header": "その他"
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_other": "{{count}} 個のプラグインがこのリストから非表示になります"
|
||||
"hidden_other": "{{count}} 個のプラグインがこのリストから非表示になっています"
|
||||
},
|
||||
"SettingsGeneralIndex": {
|
||||
"about": {
|
||||
|
||||
+105
-88
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"BranchSelect": {
|
||||
"update_channel": {
|
||||
"prerelease": "Vooruitgave",
|
||||
"prerelease": "Prerelease",
|
||||
"stable": "Stabiel",
|
||||
"label": "Update Kanaal",
|
||||
"testing": "Test"
|
||||
"label": "Updatekanaal",
|
||||
"testing": "Testing"
|
||||
}
|
||||
},
|
||||
"Developer": {
|
||||
"5secreload": "Herlaad in 5 seconden",
|
||||
"disabling": "Uitschakelen React DevTools",
|
||||
"enabling": "Inschakelen React DevTools"
|
||||
"5secreload": "Bezig met herstarten in 5 seconden",
|
||||
"disabling": "Bezig met uitschakelen van React DevTools",
|
||||
"enabling": "Bezig met inschakelen van React DevTools"
|
||||
},
|
||||
"DropdownMultiselect": {
|
||||
"button": {
|
||||
@@ -19,30 +19,34 @@
|
||||
},
|
||||
"FilePickerError": {
|
||||
"errors": {
|
||||
"unknown": "Een onbekende fout is opgetreden. De ruwe fout is: {{raw_error}}",
|
||||
"file_not_found": "Het opgegeven pad is niet geldig. Controleer het en voer het opnieuw correct in."
|
||||
"unknown": "Er is een onbekende fout opgetreden. De foutmelding is: {{raw_error}}",
|
||||
"file_not_found": "Het opgegeven pad is niet geldig. Controleer het en voer het opnieuw correct in.",
|
||||
"perm_denied": "U heeft geen toegang tot de opgegeven map. Controleer of uw gebruiker (deck op Steam Deck) de juiste permissies heeft om toegang te krijgen tot de opgegeven map/het opgegeven bestand."
|
||||
}
|
||||
},
|
||||
"FilePickerIndex": {
|
||||
"files": {
|
||||
"all_files": "Alle bestanden",
|
||||
"file_type": "Bestandstype",
|
||||
"show_hidden": "Toon verborgen bestanden"
|
||||
"show_hidden": "Verborgen bestanden tonen"
|
||||
},
|
||||
"filter": {
|
||||
"created_desc": "Gecreëerd ( Nieuwste)",
|
||||
"modified_asce": "Veranderd (Oudste)",
|
||||
"modified_desc": "Veranderd (Nieuwste)",
|
||||
"name_asce": "Z-A",
|
||||
"name_desc": "A-Z",
|
||||
"size_asce": "Grootte (Kleinste)",
|
||||
"size_desc": "Grootte (Grootste)",
|
||||
"created_asce": "Gecreëerd (Oudste)"
|
||||
"created_desc": "Aanmaakdatum (nieuwste)",
|
||||
"modified_asce": "Gewijzigd op (oudste)",
|
||||
"modified_desc": "Gewijzigd op (nieuwste)",
|
||||
"name_asce": "Naam (Z-A)",
|
||||
"name_desc": "Naam (A-Z)",
|
||||
"size_asce": "Grootte (kleinste)",
|
||||
"size_desc": "Grootte (grootste)",
|
||||
"created_asce": "Aanmaakdatum (oudste)"
|
||||
},
|
||||
"folder": {
|
||||
"label": "Map",
|
||||
"select": "Gebruik deze map",
|
||||
"show_more": "Toon meer bestanden"
|
||||
"select": "Deze map gebruiken",
|
||||
"show_more": "Meer bestanden tonen"
|
||||
},
|
||||
"file": {
|
||||
"select": "Dit bestand selecteren"
|
||||
}
|
||||
},
|
||||
"PluginView": {
|
||||
@@ -50,13 +54,13 @@
|
||||
"hidden_other": "{{count}} plug-ins zijn verborgen in deze lijst"
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "Verborgen in het snelmenu"
|
||||
"hidden": "Verborgen in snelle toegang"
|
||||
},
|
||||
"PluginCard": {
|
||||
"plugin_install": "Installeren",
|
||||
"plugin_no_desc": "Geen beschrijving gegeven.",
|
||||
"plugin_version_label": "Plugin Versie",
|
||||
"plugin_full_access": "Deze plug-in heeft volledige toegang tot je Steam Deck."
|
||||
"plugin_version_label": "Plug-inversie",
|
||||
"plugin_full_access": "Deze plug-in heeft volledige toegang tot uw Steam Deck."
|
||||
},
|
||||
"PluginInstallModal": {
|
||||
"install": {
|
||||
@@ -65,59 +69,59 @@
|
||||
"title": "Installeer {{artifact}}",
|
||||
"desc": "Weet je zeker dat je {{artifact}} {{version}} wilt installeren?"
|
||||
},
|
||||
"no_hash": "Deze plug-in heeft geen hash, u installeert deze op eigen risico.",
|
||||
"no_hash": "Deze plug-in heeft geen hash, je installeert deze op eigen risico.",
|
||||
"reinstall": {
|
||||
"button_idle": "Herinstalleren",
|
||||
"button_processing": "Bezig te herinstalleren",
|
||||
"button_idle": "Opnieuw installeren",
|
||||
"button_processing": "Bezig met opnieuw te installeren",
|
||||
"desc": "Weet je zeker dat je {{artifact}} {{version}} opnieuw wilt installeren?",
|
||||
"title": "Installeer {{artifact}} opnieuw"
|
||||
},
|
||||
"update": {
|
||||
"button_idle": "Update",
|
||||
"button_processing": "Bezig met updaten",
|
||||
"button_idle": "Bijwerken",
|
||||
"button_processing": "Bezig met bijwerken",
|
||||
"title": "{{artifact}} bijwerken",
|
||||
"desc": "Weet je zeker dat je {{artifact}} {{version}} wilt updaten?"
|
||||
"desc": "Weet je zeker dat je {{artifact}} {{version}} wilt bijwerken?"
|
||||
}
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"mixed_one": "Wijzig {{count}} plug-in",
|
||||
"mixed_other": "Pas {{count}} plug-ins aan",
|
||||
"update_one": "1 plugin bijwerken",
|
||||
"update_other": "{{count}} plug-ins bijwerken",
|
||||
"install_one": "Installeer 1 plugin",
|
||||
"install_other": "Installeer {{count}} plugins",
|
||||
"reinstall_one": "1 plugin opnieuw installeren",
|
||||
"reinstall_other": "{{count}} plugins opnieuw installeren"
|
||||
"mixed_one": "Wijzig 1 plug-in",
|
||||
"mixed_other": "Wijzig {{count}} plug-ins",
|
||||
"update_one": "Werk 1 plug-in bij",
|
||||
"update_other": "Werk {{count}} plug-ins bij",
|
||||
"install_one": "Installeer 1 plug-in",
|
||||
"install_other": "Installeer {{count}} plug-ins",
|
||||
"reinstall_one": "Installeer 1 plug-in opnieuw",
|
||||
"reinstall_other": "Installeer {{count}} plug-ins opnieuw"
|
||||
},
|
||||
"ok_button": {
|
||||
"idle": "Bevestigen",
|
||||
"loading": "Werkend"
|
||||
"loading": "Bezig"
|
||||
},
|
||||
"confirm": "Weet u zeker dat u de volgende wijzigingen wilt aanbrengen?",
|
||||
"confirm": "Weet je zeker dat je de volgende wijzigingen wilt aanbrengen?",
|
||||
"description": {
|
||||
"install": "Installeer {{name}} {{version}}",
|
||||
"update": "Update {{name}} naar {{version}}",
|
||||
"reinstall": "Installeer opnieuw {{name}} {{version}}"
|
||||
"update": "Werk {{name}} bij naar {{version}}",
|
||||
"reinstall": "Installeer {{name}} {{version}} opnieuw"
|
||||
}
|
||||
},
|
||||
"PluginListIndex": {
|
||||
"no_plugin": "Geen plugins geïnstalleerd!",
|
||||
"plugin_actions": "Plugin Acties",
|
||||
"reload": "Herladen",
|
||||
"no_plugin": "Geen plug-ins geïnstalleerd!",
|
||||
"plugin_actions": "Plug-inacties",
|
||||
"reload": "Herstarten",
|
||||
"uninstall": "Verwijderen",
|
||||
"update_to": "Update naar {{name}}",
|
||||
"hide": "Snelle toegang: Verberg",
|
||||
"update_all_one": "Update 1 plugin",
|
||||
"update_all_other": "Update {{count}} plugins",
|
||||
"update_to": "Bijwerken naar {{name}}",
|
||||
"hide": "Verberg in snelle toegang",
|
||||
"update_all_one": "Werk 1 plug-in bij",
|
||||
"update_all_other": "Werk {{count}} plug-ins bij",
|
||||
"reinstall": "Opnieuw installeren",
|
||||
"show": "Snelle toegang: Toon"
|
||||
"show": "Toon in snelle toegang"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
"error": "Fout",
|
||||
"plugin_load_error": {
|
||||
"message": "Fout bij het laden van plugin {{name}}",
|
||||
"message": "Fout bij het laden van plug-in {{name}}",
|
||||
"toast": "Fout bij het laden van {{name}}"
|
||||
},
|
||||
"plugin_uninstall": {
|
||||
@@ -125,65 +129,70 @@
|
||||
"desc": "Weet je zeker dat je {{name}} wilt verwijderen?",
|
||||
"title": "Verwijder {{name}}"
|
||||
},
|
||||
"plugin_update_one": "Updates beschikbaar voor 1 plugin!",
|
||||
"plugin_update_other": "Updates beschikbaar voor {{count}} plugins!",
|
||||
"plugin_update_one": "Updates beschikbaar voor 1 plug-in!",
|
||||
"plugin_update_other": "Updates beschikbaar voor {{count}} plug-ins!",
|
||||
"decky_update_available": "Update naar {{tag_name}} beschikbaar!",
|
||||
"plugin_error_uninstall": "Het laden van {{name}} veroorzaakte een uitzondering zoals hierboven weergegeven. Dit betekent meestal dat de plug-in een update vereist voor de nieuwe versie van SteamUI. Controleer of er een update aanwezig is of evalueer de verwijdering ervan in de Decky-instellingen, in het gedeelte Plug-ins."
|
||||
"plugin_error_uninstall": "Het laden van {{name}} veroorzaakte een fout zoals hierboven weergegeven. Dit betekent meestal dat de plug-in moet worden bijgewerkt voor de nieuwe versie van SteamUI. Controleer of er een update aanwezig is of evalueer de verwijdering ervan in de Decky-instellingen, in het gedeelte Plug-ins."
|
||||
},
|
||||
"RemoteDebugging": {
|
||||
"remote_cef": {
|
||||
"desc": "Sta ongeauthenticeerde toegang tot de CEF-foutopsporing toe aan iedereen in uw netwerk",
|
||||
"label": "Externe CEF-foutopsporing toestaan"
|
||||
"desc": "Sta ongeauthenticeerde toegang tot de CEF-debugger toe aan iedereen in uw netwerk",
|
||||
"label": "Externe CEF-debugging toestaan"
|
||||
}
|
||||
},
|
||||
"SettingsDeveloperIndex": {
|
||||
"cef_console": {
|
||||
"button": "Console openen",
|
||||
"label": "CEF Bedieningsscherm",
|
||||
"desc": "Opent de CEF-console. Alleen nuttig voor foutopsporingsdoeleinden. Dingen hier zijn potentieel gevaarlijk en mogen alleen worden gebruikt als u een ontwikkelaar van plug-ins bent, of hier door een ontwikkelaar naartoe wordt geleid."
|
||||
"label": "CEF-console",
|
||||
"desc": "Opent de CEF-console. Alleen nuttig voor foutopsporingsdoeleinden. Dingen hier zijn potentieel gevaarlijk en mogen alleen worden gebruikt als je een ontwikkelaar van plug-ins bent, of hier door een ontwikkelaar naartoe wordt geleid."
|
||||
},
|
||||
"header": "Andere",
|
||||
"header": "Overige",
|
||||
"react_devtools": {
|
||||
"ip_label": "IP",
|
||||
"label": "Aanzetten React DevTools",
|
||||
"desc": "Maakt verbinding met een computer met React DevTools mogelijk. Als je deze instelling wijzigt, wordt Steam opnieuw geladen. Stel het IP-adres in voordat u het inschakelt."
|
||||
"ip_label": "IP-adres",
|
||||
"label": "React DevTools inschakelen",
|
||||
"desc": "Maakt verbinding met een computer met React DevTools mogelijk. Als je deze instelling wijzigt, wordt Steam opnieuw geladen. Stel het IP-adres in voordat je het inschakelt."
|
||||
},
|
||||
"third_party_plugins": {
|
||||
"header": "Plug-ins van derden",
|
||||
"label_desc": "URL",
|
||||
"label_url": "Installeer Plugin van URL",
|
||||
"label_zip": "Installeer Plugin van Zip bestand",
|
||||
"label_url": "Installeer plug-in via een URL",
|
||||
"label_zip": "Installeer plug-in via een ZIP-bestand",
|
||||
"button_install": "Installeren",
|
||||
"button_zip": "Bladeren"
|
||||
},
|
||||
"valve_internal": {
|
||||
"desc1": "Schakelt het interne ontwikkelaarsmenu van Valve in.",
|
||||
"desc2": "Raak niets in dit menu aan tenzij u weet wat het doet.",
|
||||
"desc2": "Pas niets in dit menu aan, tenzij je weet wat het doet.",
|
||||
"label": "Valve Internal inschakelen"
|
||||
}
|
||||
},
|
||||
"SettingsGeneralIndex": {
|
||||
"about": {
|
||||
"decky_version": "Decky versie",
|
||||
"decky_version": "Decky-versie",
|
||||
"header": "Over"
|
||||
},
|
||||
"beta": {
|
||||
"header": "Beta deelname"
|
||||
"header": "Beta-deelname"
|
||||
},
|
||||
"developer_mode": {
|
||||
"label": "Ontwikkelaars modus"
|
||||
"label": "Ontwikkelaarsmodus"
|
||||
},
|
||||
"other": {
|
||||
"header": "Overige"
|
||||
},
|
||||
"updates": {
|
||||
"header": "Nieuwe Versies"
|
||||
"header": "Updates"
|
||||
},
|
||||
"notifications": {
|
||||
"decky_updates_label": "Wanneer er een Decky-update beschikbaar is",
|
||||
"header": "Meldingen",
|
||||
"plugin_updates_label": "Wanneer er plug-in-updates beschikbaar zijn"
|
||||
}
|
||||
},
|
||||
"SettingsIndex": {
|
||||
"developer_title": "Ontwikkelaar",
|
||||
"general_title": "Algemeen",
|
||||
"plugins_title": "Plugins"
|
||||
"plugins_title": "Plug-ins"
|
||||
},
|
||||
"Store": {
|
||||
"store_filter": {
|
||||
@@ -191,14 +200,14 @@
|
||||
"label_def": "Alles"
|
||||
},
|
||||
"store_search": {
|
||||
"label": "Zoek"
|
||||
"label": "Zoeken"
|
||||
},
|
||||
"store_sort": {
|
||||
"label": "Sorteren",
|
||||
"label_def": "Laatste Geupdate (Nieuwste)"
|
||||
"label_def": "Laatst bijgewerkt (nieuwste)"
|
||||
},
|
||||
"store_source": {
|
||||
"label": "Bron Code",
|
||||
"label": "Broncode",
|
||||
"desc": "Alle broncode van de plug-in is beschikbaar in de SteamDeckHomebrew/decky-plugin-database-repository op GitHub."
|
||||
},
|
||||
"store_tabs": {
|
||||
@@ -207,37 +216,45 @@
|
||||
"alph_desc": "Alfabetisch (A naar Z)",
|
||||
"title": "Bladeren"
|
||||
},
|
||||
"store_testing_cta": "Overweeg alsjeblieft om nieuwe plug-ins te testen om het Decky Loader-team te helpen!",
|
||||
"store_testing_cta": "Overweeg om nieuwe plug-ins te testen om het Decky Loader-team te helpen!",
|
||||
"store_contrib": {
|
||||
"desc": "Als je wilt bijdragen aan de Decky Plugin winkel, kijk dan in de SteamDeckHomebrew/decky-plugin-template repository op GitHub. Informatie over ontwikkeling en distributie is beschikbaar in de README.",
|
||||
"label": "Bijdragende"
|
||||
"desc": "Als je wilt bijdragen aan de Decky Plugin Store, kijk dan in de SteamDeckHomebrew/decky-plugin-template repository op GitHub. Informatie over ontwikkeling en distributie is beschikbaar in de README.",
|
||||
"label": "Bijdragen"
|
||||
},
|
||||
"store_testing_warning": {
|
||||
"label": "Welkom bij het Testing-winkelkanaal",
|
||||
"desc": "Je kunt dit winkelkanaal gebruiken om nog in ontwikkeling zijnde plug-inversies te testen. Zorg ervoor dat je feedback geeft op GitHub, zodat de plug-in voor alle gebruikers kan worden bijgewerkt."
|
||||
}
|
||||
},
|
||||
"StoreSelect": {
|
||||
"custom_store": {
|
||||
"label": "Aangepassingen winkel",
|
||||
"label": "Aangepaste winkel",
|
||||
"url_label": "URL"
|
||||
},
|
||||
"store_channel": {
|
||||
"custom": "Aanpassingen",
|
||||
"custom": "Aangepast",
|
||||
"default": "Standaard",
|
||||
"label": "Winkel Kanaal",
|
||||
"testing": "Testen"
|
||||
"label": "Winkelkanaal",
|
||||
"testing": "Testing"
|
||||
}
|
||||
},
|
||||
"Updater": {
|
||||
"patch_notes_desc": "Correctie opmerkingen",
|
||||
"patch_notes_desc": "Patch-opmerkingen",
|
||||
"updates": {
|
||||
"check_button": "Controleer op updates",
|
||||
"checking": "Controleren",
|
||||
"check_button": "Op updates controleren",
|
||||
"checking": "Bezig met controleren op updates",
|
||||
"cur_version": "Huidige versie: {{ver}}",
|
||||
"install_button": "Installeer Update",
|
||||
"label": "Update",
|
||||
"lat_version": "Up-to-date: loopt {{ver}}",
|
||||
"reloading": "Herstarten",
|
||||
"updating": "Aan het updaten"
|
||||
"install_button": "Bijwerken",
|
||||
"label": "Updates",
|
||||
"lat_version": "Bijwerkt: versie {{ver}}",
|
||||
"reloading": "Bezig met herstarten",
|
||||
"updating": "Bezig met bijwerken"
|
||||
},
|
||||
"decky_updates": "Decky Nieuwe Versies",
|
||||
"no_patch_notes_desc": "geen correctie-opmerkingen voor deze versie"
|
||||
"decky_updates": "Decky-updates",
|
||||
"no_patch_notes_desc": "geen patch-opmerkingen voor deze versie"
|
||||
},
|
||||
"TitleView": {
|
||||
"decky_store_desc": "Decky Store openen",
|
||||
"settings_desc": "Decky-instellingen openen"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,9 @@
|
||||
"reinstall": "Reinstalacja",
|
||||
"show": "Szybki dostęp: Pokaż",
|
||||
"uninstall": "Odinstaluj",
|
||||
"update_to": "Zaktualizuj do {{name}}"
|
||||
"update_to": "Zaktualizuj do {{name}}",
|
||||
"unfreeze": "Odblokuj aktualizacje",
|
||||
"freeze": "Zablokuj aktualizacje"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
@@ -199,7 +201,8 @@
|
||||
"SettingsIndex": {
|
||||
"developer_title": "Deweloper",
|
||||
"general_title": "Ogólne",
|
||||
"plugins_title": "Pluginy"
|
||||
"plugins_title": "Pluginy",
|
||||
"testing_title": "Testowanie"
|
||||
},
|
||||
"Store": {
|
||||
"store_contrib": {
|
||||
@@ -225,7 +228,11 @@
|
||||
"alph_asce": "Alfabetycznie (od Z do A)",
|
||||
"alph_desc": "Alfabetycznie (od A do Z)",
|
||||
"title": "Przeglądaj",
|
||||
"about": "Informacje"
|
||||
"about": "Informacje",
|
||||
"date_desc": "Od najnowszych",
|
||||
"downloads_desc": "Najwięcej pobrań",
|
||||
"downloads_asce": "Najmniej pobrań",
|
||||
"date_asce": "Od najstarszych"
|
||||
},
|
||||
"store_testing_cta": "Rozważ przetestowanie nowych pluginów, aby pomóc zespołowi Decky Loader!",
|
||||
"store_testing_warning": {
|
||||
@@ -263,5 +270,8 @@
|
||||
"TitleView": {
|
||||
"settings_desc": "Otwórz ustawienia Decky",
|
||||
"decky_store_desc": "Otwórz sklep Decky"
|
||||
},
|
||||
"Testing": {
|
||||
"download": "Pobierz"
|
||||
}
|
||||
}
|
||||
|
||||
+29
-8
@@ -10,6 +10,7 @@ from hashlib import sha256
|
||||
from io import BytesIO
|
||||
from logging import getLogger
|
||||
from os import R_OK, W_OK, path, listdir, access, mkdir
|
||||
from re import sub
|
||||
from shutil import rmtree
|
||||
from time import time
|
||||
from zipfile import ZipFile
|
||||
@@ -137,7 +138,7 @@ class PluginBrowser:
|
||||
# logger.debug("current plugins: %s", snapshot_string)
|
||||
if name in self.plugins:
|
||||
logger.debug("Plugin %s was found", name)
|
||||
self.plugins[name].stop()
|
||||
self.plugins[name].stop(uninstall=True)
|
||||
logger.debug("Plugin %s was stopped", name)
|
||||
del self.plugins[name]
|
||||
logger.debug("Plugin %s was removed from the dictionary", name)
|
||||
@@ -162,12 +163,6 @@ class PluginBrowser:
|
||||
current_plugin_order = self.settings.getSetting("pluginOrder")[:]
|
||||
if self.loader.watcher:
|
||||
self.loader.watcher.disabled = True
|
||||
try:
|
||||
pluginFolderPath = self.find_plugin_folder(name)
|
||||
if pluginFolderPath:
|
||||
isInstalled = True
|
||||
except:
|
||||
logger.error(f"Failed to determine if {name} is already installed, continuing anyway.")
|
||||
|
||||
# Check if the file is a local file or a URL
|
||||
if artifact.startswith("file://"):
|
||||
@@ -198,6 +193,28 @@ class PluginBrowser:
|
||||
if res.status != 200:
|
||||
logger.error(f"Server did not accept install count increment request. code: {res.status}")
|
||||
|
||||
if res_zip and version == "dev":
|
||||
with ZipFile(res_zip) as plugin_zip:
|
||||
plugin_json_list = [file for file in plugin_zip.namelist() if file.endswith("/plugin.json") and file.count("/") == 1]
|
||||
|
||||
if len(plugin_json_list) == 0:
|
||||
logger.fatal("No plugin.json found in plugin ZIP")
|
||||
return
|
||||
|
||||
elif len(plugin_json_list) > 1:
|
||||
logger.fatal("Multiple plugin.json found in plugin ZIP")
|
||||
return
|
||||
|
||||
else:
|
||||
name = sub(r"/.+$", "", plugin_json_list[0])
|
||||
|
||||
try:
|
||||
pluginFolderPath = self.find_plugin_folder(name)
|
||||
if pluginFolderPath:
|
||||
isInstalled = True
|
||||
except:
|
||||
logger.error(f"Failed to determine if {name} is already installed, continuing anyway.")
|
||||
|
||||
# Check to make sure we got the file
|
||||
if res_zip is None:
|
||||
logger.fatal(f"Could not fetch {artifact}")
|
||||
@@ -272,12 +289,16 @@ class PluginBrowser:
|
||||
Args:
|
||||
name (string): The name of the plugin
|
||||
"""
|
||||
frozen_plugins = self.settings.getSetting("frozenPlugins", [])
|
||||
if name in frozen_plugins:
|
||||
frozen_plugins.remove(name)
|
||||
self.settings.setSetting("frozenPlugins", frozen_plugins)
|
||||
|
||||
hidden_plugins = self.settings.getSetting("hiddenPlugins", [])
|
||||
if name in hidden_plugins:
|
||||
hidden_plugins.remove(name)
|
||||
self.settings.setSetting("hiddenPlugins", hidden_plugins)
|
||||
|
||||
|
||||
plugin_order = self.settings.getSetting("pluginOrder", [])
|
||||
|
||||
if name in plugin_order:
|
||||
|
||||
@@ -156,6 +156,12 @@ async def service_start(service_name : str) -> bool:
|
||||
res = run(cmd, stdout=PIPE, stderr=STDOUT)
|
||||
return res.returncode == 0
|
||||
|
||||
async def restart_webhelper() -> bool:
|
||||
logger.info("Restarting steamwebhelper")
|
||||
# TODO move to pkill
|
||||
res = run(["killall", "-s", "SIGTERM", "steamwebhelper"], stdout=DEVNULL, stderr=DEVNULL)
|
||||
return res.returncode == 0
|
||||
|
||||
def get_privileged_path() -> str:
|
||||
path = os.getenv("PRIVILEGED_PATH")
|
||||
|
||||
|
||||
+6
-6
@@ -2,9 +2,9 @@
|
||||
import sys
|
||||
from typing import Dict
|
||||
from .localplatform import (chmod, chown, service_stop, service_start,
|
||||
ON_WINDOWS, get_log_level, get_live_reload,
|
||||
ON_WINDOWS, ON_LINUX, get_log_level, get_live_reload,
|
||||
get_server_port, get_server_host, get_chown_plugin_path,
|
||||
get_privileged_path)
|
||||
get_privileged_path, restart_webhelper)
|
||||
if hasattr(sys, '_MEIPASS'):
|
||||
chmod(sys._MEIPASS, 755) # type: ignore
|
||||
# Full imports
|
||||
@@ -158,10 +158,10 @@ class PluginManager:
|
||||
async def inject_javascript(self, tab: Tab, first: bool=False, request: Request|None=None):
|
||||
logger.info("Loading Decky frontend!")
|
||||
try:
|
||||
if first:
|
||||
if await tab.has_global_var("deckyHasLoaded", False):
|
||||
await close_old_tabs()
|
||||
await tab.evaluate_js("try{if (window.deckyHasLoaded){setTimeout(() => location.reload(), 100)}else{window.deckyHasLoaded = true;(async()=>{try{while(!window.SP_REACT){await new Promise(r => setTimeout(r, 10))};await import('http://localhost:1337/frontend/index.js')}catch(e){console.error(e)};})();}}catch(e){console.error(e)}", False, False, False)
|
||||
# if first:
|
||||
if ON_LINUX and await tab.has_global_var("deckyHasLoaded", False):
|
||||
await restart_webhelper()
|
||||
await tab.evaluate_js("try{if (window.deckyHasLoaded){setTimeout(() => SteamClient.Browser.RestartJSContext(), 100)}else{window.deckyHasLoaded = true;(async()=>{try{while(!window.webpackChunksteamui){await new Promise(r => setTimeout(r, 10))};await import('http://localhost:1337/frontend/index.js')}catch(e){console.error(e)};})();}}catch(e){console.error(e)}", False, False, False)
|
||||
except:
|
||||
logger.info("Failed to inject JavaScript into tab\n" + format_exc())
|
||||
pass
|
||||
|
||||
+21
-4
@@ -78,7 +78,7 @@ class PluginWrapper:
|
||||
|
||||
# append the plugin's `py_modules` to the recognized python paths
|
||||
syspath.append(path.join(environ["DECKY_PLUGIN_DIR"], "py_modules"))
|
||||
|
||||
|
||||
#TODO: FIX IN A LESS CURSED WAY
|
||||
keys = [key.replace("src.", "") for key in sysmodules if key.startswith("src.")]
|
||||
for key in keys:
|
||||
@@ -113,12 +113,29 @@ class PluginWrapper:
|
||||
self.log.error("Failed to unload " + self.name + "!\n" + format_exc())
|
||||
exit(0)
|
||||
|
||||
async def _uninstall(self):
|
||||
try:
|
||||
self.log.info("Attempting to uninstall with plugin " + self.name + "'s \"_uninstall\" function.\n")
|
||||
if hasattr(self.Plugin, "_uninstall"):
|
||||
await self.Plugin._uninstall(self.Plugin)
|
||||
self.log.info("Uninstalled " + self.name + "\n")
|
||||
else:
|
||||
self.log.info("Could not find \"_uninstall\" in " + self.name + "'s main.py" + "\n")
|
||||
except:
|
||||
self.log.error("Failed to uninstall " + self.name + "!\n" + format_exc())
|
||||
exit(0)
|
||||
|
||||
async def _on_new_message(self, message : str) -> str|None:
|
||||
data = loads(message)
|
||||
|
||||
if "stop" in data:
|
||||
self.log.info("Calling Loader unload function.")
|
||||
await self._unload()
|
||||
|
||||
if data.get('uninstall'):
|
||||
self.log.info("Calling Loader uninstall function.")
|
||||
await self._uninstall()
|
||||
|
||||
get_event_loop().stop()
|
||||
while get_event_loop().is_running():
|
||||
await sleep(0)
|
||||
@@ -141,12 +158,12 @@ class PluginWrapper:
|
||||
multiprocessing.Process(target=self._init).start()
|
||||
return self
|
||||
|
||||
def stop(self):
|
||||
def stop(self, uninstall: bool = False):
|
||||
if self.passive:
|
||||
return
|
||||
|
||||
async def _(self: PluginWrapper):
|
||||
await self.socket.write_single_line(dumps({ "stop": True }, ensure_ascii=False))
|
||||
await self.socket.write_single_line(dumps({ "stop": True, "uninstall": uninstall }, ensure_ascii=False))
|
||||
await self.socket.close_socket_connection()
|
||||
|
||||
get_event_loop().create_task(_(self))
|
||||
@@ -155,7 +172,7 @@ class PluginWrapper:
|
||||
if self.passive:
|
||||
raise RuntimeError("This plugin is passive (aka does not implement main.py)")
|
||||
async with self.method_call_lock:
|
||||
# reader, writer =
|
||||
# reader, writer =
|
||||
await self.socket.get_socket_connection()
|
||||
|
||||
await self.socket.write_single_line(dumps({ "method": method_name, "args": kwargs }, ensure_ascii=False))
|
||||
|
||||
+114
-40
@@ -1,20 +1,29 @@
|
||||
from __future__ import annotations
|
||||
import os
|
||||
import shutil
|
||||
from asyncio import sleep
|
||||
from json.decoder import JSONDecodeError
|
||||
from logging import getLogger
|
||||
import os
|
||||
from os import getcwd, path, remove
|
||||
from typing import TYPE_CHECKING, List, TypedDict
|
||||
if TYPE_CHECKING:
|
||||
from .main import PluginManager
|
||||
from .localplatform import chmod, service_restart, ON_LINUX, get_keep_systemd_service, get_selinux
|
||||
import shutil
|
||||
from typing import List, TYPE_CHECKING, TypedDict
|
||||
import zipfile
|
||||
|
||||
from aiohttp import ClientSession, web
|
||||
|
||||
from . import helpers
|
||||
from .injector import get_gamepadui_tab
|
||||
from .localplatform import (
|
||||
ON_LINUX,
|
||||
ON_WINDOWS,
|
||||
chmod,
|
||||
get_keep_systemd_service,
|
||||
get_selinux,
|
||||
service_restart,
|
||||
)
|
||||
from .settings import SettingsManager
|
||||
if TYPE_CHECKING:
|
||||
from .main import PluginManager
|
||||
|
||||
|
||||
logger = getLogger("Updater")
|
||||
|
||||
@@ -25,6 +34,12 @@ class RemoteVer(TypedDict):
|
||||
tag_name: str
|
||||
prerelease: bool
|
||||
assets: List[RemoteVerAsset]
|
||||
class TestingVersion(TypedDict):
|
||||
id: int
|
||||
name: str
|
||||
link: str
|
||||
head_sha: str
|
||||
|
||||
|
||||
class Updater:
|
||||
def __init__(self, context: PluginManager) -> None:
|
||||
@@ -36,7 +51,9 @@ class Updater:
|
||||
"get_version": self.get_version,
|
||||
"do_update": self.do_update,
|
||||
"do_restart": self.do_restart,
|
||||
"check_for_updates": self.check_for_updates
|
||||
"check_for_updates": self.check_for_updates,
|
||||
"get_testing_versions": self.get_testing_versions,
|
||||
"download_testing_version": self.download_testing_version
|
||||
}
|
||||
self.remoteVer: RemoteVer | None = None
|
||||
self.allRemoteVers: List[RemoteVer] = []
|
||||
@@ -150,6 +167,53 @@ class Updater:
|
||||
pass
|
||||
await sleep(60 * 60 * 6) # 6 hours
|
||||
|
||||
async def download_decky_binary(self, download_url: str, version: str, is_zip: bool = False):
|
||||
download_filename = "PluginLoader" if ON_LINUX else "PluginLoader.exe"
|
||||
download_temp_filename = download_filename + ".new"
|
||||
tab = await get_gamepadui_tab()
|
||||
await tab.open_websocket()
|
||||
|
||||
async with ClientSession() as web:
|
||||
logger.debug("Downloading binary")
|
||||
async with web.request("GET", download_url, ssl=helpers.get_ssl_context(), allow_redirects=True) as res:
|
||||
total = int(res.headers.get('content-length', 0))
|
||||
with open(path.join(getcwd(), download_temp_filename), "wb") as out:
|
||||
progress = 0
|
||||
raw = 0
|
||||
async for c in res.content.iter_chunked(512):
|
||||
out.write(c)
|
||||
if total != 0:
|
||||
raw += len(c)
|
||||
new_progress = round((raw / total) * 100)
|
||||
if progress != new_progress:
|
||||
self.context.loop.create_task(tab.evaluate_js(f"window.DeckyUpdater.updateProgress({new_progress})", False, False, False))
|
||||
progress = new_progress
|
||||
|
||||
with open(path.join(getcwd(), ".loader.version"), "w", encoding="utf-8") as out:
|
||||
out.write(version)
|
||||
|
||||
if ON_LINUX:
|
||||
remove(path.join(getcwd(), download_filename))
|
||||
if (is_zip):
|
||||
with zipfile.ZipFile(path.join(getcwd(), download_temp_filename), 'r') as file:
|
||||
file.getinfo(download_filename).filename = download_filename + ".unzipped"
|
||||
file.extract(download_filename)
|
||||
remove(path.join(getcwd(), download_temp_filename))
|
||||
shutil.move(path.join(getcwd(), download_filename + ".unzipped"), path.join(getcwd(), download_filename))
|
||||
else:
|
||||
shutil.move(path.join(getcwd(), download_temp_filename), path.join(getcwd(), download_filename))
|
||||
|
||||
chmod(path.join(getcwd(), download_filename), 777, False)
|
||||
if get_selinux():
|
||||
from asyncio.subprocess import create_subprocess_exec
|
||||
process = await create_subprocess_exec("chcon", "-t", "bin_t", path.join(getcwd(), download_filename))
|
||||
logger.info(f"Setting the executable flag with chcon returned {await process.wait()}")
|
||||
|
||||
logger.info("Updated loader installation.")
|
||||
await tab.evaluate_js("window.DeckyUpdater.finish()", False, False)
|
||||
await self.do_restart()
|
||||
await tab.close_websocket()
|
||||
|
||||
async def do_update(self):
|
||||
logger.debug("Starting update.")
|
||||
try:
|
||||
@@ -161,7 +225,6 @@ class Updater:
|
||||
version = self.remoteVer["tag_name"]
|
||||
download_url = None
|
||||
download_filename = "PluginLoader" if ON_LINUX else "PluginLoader.exe"
|
||||
download_temp_filename = download_filename + ".new"
|
||||
|
||||
for x in self.remoteVer["assets"]:
|
||||
if x["name"] == download_filename:
|
||||
@@ -174,8 +237,6 @@ class Updater:
|
||||
service_url = self.get_service_url()
|
||||
logger.debug("Retrieved service URL")
|
||||
|
||||
tab = await get_gamepadui_tab()
|
||||
await tab.open_websocket()
|
||||
async with ClientSession() as web:
|
||||
if ON_LINUX and not get_keep_systemd_service():
|
||||
logger.debug("Downloading systemd service")
|
||||
@@ -203,36 +264,49 @@ class Updater:
|
||||
os.mkdir(path.join(getcwd(), ".systemd"))
|
||||
shutil.move(service_file_path, path.join(getcwd(), ".systemd")+"/plugin_loader.service")
|
||||
|
||||
logger.debug("Downloading binary")
|
||||
async with web.request("GET", download_url, ssl=helpers.get_ssl_context(), allow_redirects=True) as res:
|
||||
total = int(res.headers.get('content-length', 0))
|
||||
with open(path.join(getcwd(), download_temp_filename), "wb") as out:
|
||||
progress = 0
|
||||
raw = 0
|
||||
async for c in res.content.iter_chunked(512):
|
||||
out.write(c)
|
||||
raw += len(c)
|
||||
new_progress = round((raw / total) * 100)
|
||||
if progress != new_progress:
|
||||
self.context.loop.create_task(tab.evaluate_js(f"window.DeckyUpdater.updateProgress({new_progress})", False, False, False))
|
||||
progress = new_progress
|
||||
|
||||
with open(path.join(getcwd(), ".loader.version"), "w", encoding="utf-8") as out:
|
||||
out.write(version)
|
||||
|
||||
if ON_LINUX:
|
||||
remove(path.join(getcwd(), download_filename))
|
||||
shutil.move(path.join(getcwd(), download_temp_filename), path.join(getcwd(), download_filename))
|
||||
chmod(path.join(getcwd(), download_filename), 777, False)
|
||||
if get_selinux():
|
||||
from asyncio.subprocess import create_subprocess_exec
|
||||
process = await create_subprocess_exec("chcon", "-t", "bin_t", path.join(getcwd(), download_filename))
|
||||
logger.info(f"Setting the executable flag with chcon returned {await process.wait()}")
|
||||
|
||||
logger.info("Updated loader installation.")
|
||||
await tab.evaluate_js("window.DeckyUpdater.finish()", False, False)
|
||||
await self.do_restart()
|
||||
await tab.close_websocket()
|
||||
await self.download_decky_binary(download_url, version)
|
||||
|
||||
async def do_restart(self):
|
||||
await service_restart("plugin_loader")
|
||||
|
||||
async def get_testing_versions(self) -> List[TestingVersion]:
|
||||
result: List[TestingVersion] = []
|
||||
async with ClientSession() as web:
|
||||
async with web.request("GET", "https://api.github.com/repos/SteamDeckHomebrew/decky-loader/pulls",
|
||||
headers={'X-GitHub-Api-Version': '2022-11-28'}, params={'state':'open'}, ssl=helpers.get_ssl_context()) as res:
|
||||
open_prs = await res.json()
|
||||
for pr in open_prs:
|
||||
result.append({
|
||||
"id": int(pr['number']),
|
||||
"name": pr['title'],
|
||||
"link": pr['html_url'],
|
||||
"head_sha": pr['head']['sha'],
|
||||
})
|
||||
return result
|
||||
|
||||
async def download_testing_version(self, pr_id: int, sha_id: str):
|
||||
down_id = ''
|
||||
#Get all the associated workflow run for the given sha_id code hash
|
||||
async with ClientSession() as web:
|
||||
async with web.request("GET", "https://api.github.com/repos/SteamDeckHomebrew/decky-loader/actions/runs",
|
||||
headers={'X-GitHub-Api-Version': '2022-11-28'}, params={'event':'pull_request', 'head_sha': sha_id}, ssl=helpers.get_ssl_context()) as res:
|
||||
works = await res.json()
|
||||
#Iterate over the workflow_run to get the two builds if they exists
|
||||
for work in works['workflow_runs']:
|
||||
if ON_WINDOWS and work['name'] == 'Builder Win':
|
||||
down_id=work['id']
|
||||
break
|
||||
elif ON_LINUX and work['name'] == 'Builder':
|
||||
down_id=work['id']
|
||||
break
|
||||
if down_id != '':
|
||||
async with ClientSession() as web:
|
||||
async with web.request("GET", f"https://api.github.com/repos/SteamDeckHomebrew/decky-loader/actions/runs/{down_id}/artifacts",
|
||||
headers={'X-GitHub-Api-Version': '2022-11-28'}, ssl=helpers.get_ssl_context()) as res:
|
||||
jresp = await res.json()
|
||||
#If the request found at least one artifact to download...
|
||||
if int(jresp['total_count']) != 0:
|
||||
# this assumes that the artifact we want is the first one!
|
||||
down_link = f"https://nightly.link/SteamDeckHomebrew/decky-loader/actions/artifacts/{jresp['artifacts'][0]['id']}.zip"
|
||||
#Then fetch it and restart itself
|
||||
await self.download_decky_binary(down_link, f'PR-{pr_id}' , True)
|
||||
|
||||
@@ -360,7 +360,7 @@ class Utilities:
|
||||
tab = await get_gamepadui_tab()
|
||||
self.rdt_script_id = None
|
||||
await close_old_tabs()
|
||||
await tab.evaluate_js("location.reload();", False, True, False)
|
||||
await tab.evaluate_js("SteamClient.Browser.RestartJSContext();", False, True, False)
|
||||
self.logger.info("React DevTools disabled")
|
||||
|
||||
async def get_user_info(self) -> Dict[str, str]:
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"i18next-parser": "^8.0.0",
|
||||
"import-sort-style-module": "^6.0.0",
|
||||
"inquirer": "^8.2.5",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-import-sort": "^0.0.7",
|
||||
"react": "16.14.0",
|
||||
"react-dom": "16.14.0",
|
||||
@@ -44,7 +44,7 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"decky-frontend-lib": "3.24.5",
|
||||
"decky-frontend-lib": "3.25.0",
|
||||
"filesize": "^10.0.7",
|
||||
"i18next": "^23.2.1",
|
||||
"i18next-http-backend": "^2.2.1",
|
||||
|
||||
Generated
+12
-14
@@ -6,8 +6,8 @@ settings:
|
||||
|
||||
dependencies:
|
||||
decky-frontend-lib:
|
||||
specifier: 3.24.5
|
||||
version: 3.24.5
|
||||
specifier: 3.25.0
|
||||
version: 3.25.0
|
||||
filesize:
|
||||
specifier: ^10.0.7
|
||||
version: 10.0.7
|
||||
@@ -77,11 +77,11 @@ devDependencies:
|
||||
specifier: ^8.2.5
|
||||
version: 8.2.5
|
||||
prettier:
|
||||
specifier: ^2.8.8
|
||||
version: 2.8.8
|
||||
specifier: ^3.2.5
|
||||
version: 3.2.5
|
||||
prettier-plugin-import-sort:
|
||||
specifier: ^0.0.7
|
||||
version: 0.0.7(prettier@2.8.8)
|
||||
version: 0.0.7(prettier@3.2.5)
|
||||
react:
|
||||
specifier: 16.14.0
|
||||
version: 16.14.0
|
||||
@@ -1482,8 +1482,8 @@ packages:
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
|
||||
/decky-frontend-lib@3.24.5:
|
||||
resolution: {integrity: sha512-eYlbKDOOcIBPI0b76Rqvlryq2ym/QNiry4xf2pFrXmBa1f95dflqbQAb2gTq9uHEa5gFmeV4lUcMPGJ3M14Xqw==}
|
||||
/decky-frontend-lib@3.25.0:
|
||||
resolution: {integrity: sha512-2lBoHS2AIRmuluq/bGdHBz+uyToQE7k3K/vDq1MQbDZ4eC+8CGDuh2T8yZOj3D0yjGP2MdikNNAWPA9Z5l2qDg==}
|
||||
dev: false
|
||||
|
||||
/decode-named-character-reference@1.0.2:
|
||||
@@ -3108,7 +3108,7 @@ packages:
|
||||
engines: {node: '>=8.6'}
|
||||
dev: true
|
||||
|
||||
/prettier-plugin-import-sort@0.0.7(prettier@2.8.8):
|
||||
/prettier-plugin-import-sort@0.0.7(prettier@3.2.5):
|
||||
resolution: {integrity: sha512-O0KlUSq+lwvh+UiN3wZDT6wWkf7TNxTVv2/XXE5KqpRNbFJq3nRg2ftzBYFFO8QGpdWIrOB0uCTCtFjIxmVKQw==}
|
||||
peerDependencies:
|
||||
prettier: '>= 2.0'
|
||||
@@ -3117,14 +3117,14 @@ packages:
|
||||
import-sort-config: 6.0.0
|
||||
import-sort-parser-babylon: 6.0.0
|
||||
import-sort-parser-typescript: 6.0.0
|
||||
prettier: 2.8.8
|
||||
prettier: 3.2.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/prettier@2.8.8:
|
||||
resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
/prettier@3.2.5:
|
||||
resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
@@ -3200,7 +3200,6 @@ packages:
|
||||
prop-types: 15.8.1
|
||||
react: 16.14.0
|
||||
scheduler: 0.19.1
|
||||
bundledDependencies: false
|
||||
|
||||
/react-file-icon@1.3.0(react-dom@16.14.0)(react@16.14.0):
|
||||
resolution: {integrity: sha512-wxl/WwSX5twQKVXloPHbS71iZQUKO84KgZ44Kh7vYZGu1qH2kagx+RSTNfk/+IHtXfjPWPNIHPGi2Y8S94N1CQ==}
|
||||
@@ -3284,7 +3283,6 @@ packages:
|
||||
loose-envify: 1.4.0
|
||||
object-assign: 4.1.1
|
||||
prop-types: 15.8.1
|
||||
bundledDependencies: false
|
||||
|
||||
/readable-stream@2.3.8:
|
||||
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { VerInfo } from '../updater';
|
||||
interface PublicDeckyState {
|
||||
plugins: Plugin[];
|
||||
pluginOrder: string[];
|
||||
frozenPlugins: string[];
|
||||
hiddenPlugins: string[];
|
||||
activePlugin: Plugin | null;
|
||||
updates: PluginUpdateMapping | null;
|
||||
@@ -26,6 +27,7 @@ export interface UserInfo {
|
||||
export class DeckyState {
|
||||
private _plugins: Plugin[] = [];
|
||||
private _pluginOrder: string[] = [];
|
||||
private _frozenPlugins: string[] = [];
|
||||
private _hiddenPlugins: string[] = [];
|
||||
private _activePlugin: Plugin | null = null;
|
||||
private _updates: PluginUpdateMapping | null = null;
|
||||
@@ -41,6 +43,7 @@ export class DeckyState {
|
||||
return {
|
||||
plugins: this._plugins,
|
||||
pluginOrder: this._pluginOrder,
|
||||
frozenPlugins: this._frozenPlugins,
|
||||
hiddenPlugins: this._hiddenPlugins,
|
||||
activePlugin: this._activePlugin,
|
||||
updates: this._updates,
|
||||
@@ -67,6 +70,11 @@ export class DeckyState {
|
||||
this.notifyUpdate();
|
||||
}
|
||||
|
||||
setFrozenPlugins(frozenPlugins: string[]) {
|
||||
this._frozenPlugins = frozenPlugins;
|
||||
this.notifyUpdate();
|
||||
}
|
||||
|
||||
setHiddenPlugins(hiddenPlugins: string[]) {
|
||||
this._hiddenPlugins = hiddenPlugins;
|
||||
this.notifyUpdate();
|
||||
|
||||
@@ -30,11 +30,14 @@ const DeckyToaster: FC<DeckyToasterProps> = () => {
|
||||
// not actually node but TS is shit
|
||||
let interval: NodeJS.Timer | null;
|
||||
if (renderedToast) {
|
||||
interval = setTimeout(() => {
|
||||
interval = null;
|
||||
console.log('clear toast', renderedToast.data);
|
||||
removeToast(renderedToast.data);
|
||||
}, (renderedToast.data.duration || 5e3) + 1000);
|
||||
interval = setTimeout(
|
||||
() => {
|
||||
interval = null;
|
||||
console.log('clear toast', renderedToast.data);
|
||||
removeToast(renderedToast.data);
|
||||
},
|
||||
(renderedToast.data.duration || 5e3) + 1000,
|
||||
);
|
||||
console.log('set int', interval);
|
||||
}
|
||||
return () => {
|
||||
|
||||
@@ -15,8 +15,9 @@ const PluginUninstallModal: FC<PluginUninstallModalProps> = ({ name, title, butt
|
||||
closeModal={closeModal}
|
||||
onOK={async () => {
|
||||
await window.DeckyPluginLoader.callServerMethod('uninstall_plugin', { name });
|
||||
// uninstalling a plugin resets the hidden setting for it server-side
|
||||
// uninstalling a plugin resets the frozen and hidden setting for it server-side
|
||||
// we invalidate here so if you re-install it, you won't have an out-of-date hidden filter
|
||||
await window.DeckyPluginLoader.frozenPluginsService.invalidate();
|
||||
await window.DeckyPluginLoader.hiddenPluginsService.invalidate();
|
||||
}}
|
||||
strTitle={title}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { SidebarNavigation } from 'decky-frontend-lib';
|
||||
import { lazy } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaCode, FaPlug } from 'react-icons/fa';
|
||||
import { FaCode, FaFlask, FaPlug } from 'react-icons/fa';
|
||||
|
||||
import { useSetting } from '../../utils/hooks/useSetting';
|
||||
import DeckyIcon from '../DeckyIcon';
|
||||
@@ -10,6 +10,7 @@ import GeneralSettings from './pages/general';
|
||||
import PluginList from './pages/plugin_list';
|
||||
|
||||
const DeveloperSettings = lazy(() => import('./pages/developer'));
|
||||
const TestingMenu = lazy(() => import('./pages/testing'));
|
||||
|
||||
export default function SettingsPage() {
|
||||
const [isDeveloper, setIsDeveloper] = useSetting<boolean>('developer.enabled', false);
|
||||
@@ -24,7 +25,7 @@ export default function SettingsPage() {
|
||||
},
|
||||
{
|
||||
title: t('SettingsIndex.plugins_title'),
|
||||
content: <PluginList />,
|
||||
content: <PluginList isDeveloper={isDeveloper} />,
|
||||
route: '/decky/settings/plugins',
|
||||
icon: <FaPlug />,
|
||||
},
|
||||
@@ -39,6 +40,17 @@ export default function SettingsPage() {
|
||||
icon: <FaCode />,
|
||||
visible: isDeveloper,
|
||||
},
|
||||
{
|
||||
title: t('SettingsIndex.testing_title'),
|
||||
content: (
|
||||
<WithSuspense>
|
||||
<TestingMenu />
|
||||
</WithSuspense>
|
||||
),
|
||||
route: '/decky/settings/testing',
|
||||
icon: <FaFlask />,
|
||||
visible: isDeveloper,
|
||||
},
|
||||
];
|
||||
|
||||
return <SidebarNavigation pages={pages} />;
|
||||
|
||||
@@ -8,10 +8,15 @@ import { useSetting } from '../../../../utils/hooks/useSetting';
|
||||
|
||||
const logger = new Logger('BranchSelect');
|
||||
|
||||
enum UpdateBranch {
|
||||
export enum UpdateBranch {
|
||||
Stable,
|
||||
Prerelease,
|
||||
Testing,
|
||||
}
|
||||
|
||||
enum LessUpdateBranch {
|
||||
Stable,
|
||||
Prerelease,
|
||||
// Testing,
|
||||
}
|
||||
|
||||
const BranchSelect: FunctionComponent<{}> = () => {
|
||||
@@ -24,11 +29,11 @@ const BranchSelect: FunctionComponent<{}> = () => {
|
||||
const [selectedBranch, setSelectedBranch] = useSetting<UpdateBranch>('branch', UpdateBranch.Stable);
|
||||
|
||||
return (
|
||||
// Returns numerical values from 0 to 2 (with current branch setup as of 8/28/22)
|
||||
// 0 being stable, 1 being pre-release and 2 being nightly
|
||||
// Returns numerical values from 0 to 2 (with current branch setup as of 6/16/23)
|
||||
// 0 being stable, 1 being pre-release and 2 being testing (not a branch!)
|
||||
<Field label={t('BranchSelect.update_channel.label')} childrenContainerWidth={'fixed'}>
|
||||
<Dropdown
|
||||
rgOptions={Object.values(UpdateBranch)
|
||||
rgOptions={Object.values(selectedBranch == UpdateBranch.Testing ? UpdateBranch : LessUpdateBranch)
|
||||
.filter((branch) => typeof branch == 'number')
|
||||
.map((branch) => ({
|
||||
label: tBranches[branch as number],
|
||||
|
||||
@@ -135,8 +135,8 @@ export default function UpdaterSettings() {
|
||||
{checkingForUpdates
|
||||
? t('Updater.updates.checking')
|
||||
: !versionInfo?.remote || versionInfo?.remote?.tag_name == versionInfo?.current
|
||||
? t('Updater.updates.check_button')
|
||||
: t('Updater.updates.install_button')}
|
||||
? t('Updater.updates.check_button')
|
||||
: t('Updater.updates.install_button')}
|
||||
</DialogButton>
|
||||
) : (
|
||||
<ProgressBarWithInfo
|
||||
|
||||
@@ -1,18 +1,34 @@
|
||||
import { FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaEyeSlash } from 'react-icons/fa';
|
||||
import { FaEyeSlash, FaLock } from 'react-icons/fa';
|
||||
|
||||
interface PluginListLabelProps {
|
||||
frozen: boolean;
|
||||
hidden: boolean;
|
||||
name: string;
|
||||
version?: string;
|
||||
}
|
||||
|
||||
const PluginListLabel: FC<PluginListLabelProps> = ({ name, hidden, version }) => {
|
||||
const PluginListLabel: FC<PluginListLabelProps> = ({ name, frozen, hidden, version }) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>
|
||||
<div>{version ? `${name} - ${version}` : name}</div>
|
||||
<div>
|
||||
{name}
|
||||
{version && (
|
||||
<>
|
||||
{' - '}
|
||||
<span style={{ color: frozen ? '#67707b' : 'inherit' }}>
|
||||
{frozen && (
|
||||
<>
|
||||
<FaLock />{' '}
|
||||
</>
|
||||
)}
|
||||
{version}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{hidden && (
|
||||
<div
|
||||
style={{
|
||||
|
||||
@@ -33,7 +33,16 @@ async function reinstallPlugin(pluginName: string, currentVersion?: string) {
|
||||
}
|
||||
}
|
||||
|
||||
type PluginTableData = PluginData & { name: string; hidden: boolean; onHide(): void; onShow(): void };
|
||||
type PluginTableData = PluginData & {
|
||||
name: string;
|
||||
frozen: boolean;
|
||||
onFreeze(): void;
|
||||
onUnfreeze(): void;
|
||||
hidden: boolean;
|
||||
onHide(): void;
|
||||
onShow(): void;
|
||||
isDeveloper: boolean;
|
||||
};
|
||||
|
||||
function PluginInteractables(props: { entry: ReorderableEntry<PluginTableData> }) {
|
||||
const { t } = useTranslation();
|
||||
@@ -43,7 +52,7 @@ function PluginInteractables(props: { entry: ReorderableEntry<PluginTableData> }
|
||||
return null;
|
||||
}
|
||||
|
||||
const { name, update, version, onHide, onShow, hidden } = props.entry.data;
|
||||
const { name, update, version, onHide, onShow, hidden, onFreeze, onUnfreeze, frozen, isDeveloper } = props.entry.data;
|
||||
|
||||
const showCtxMenu = (e: MouseEvent | GamepadEvent) => {
|
||||
showContextMenu(
|
||||
@@ -84,6 +93,11 @@ function PluginInteractables(props: { entry: ReorderableEntry<PluginTableData> }
|
||||
) : (
|
||||
<MenuItem onSelected={onHide}>{t('PluginListIndex.hide')}</MenuItem>
|
||||
)}
|
||||
{frozen ? (
|
||||
<MenuItem onSelected={onUnfreeze}>{t('PluginListIndex.unfreeze')}</MenuItem>
|
||||
) : (
|
||||
isDeveloper && <MenuItem onSelected={onFreeze}>{t('PluginListIndex.freeze')}</MenuItem>
|
||||
)}
|
||||
</Menu>,
|
||||
e.currentTarget ?? window,
|
||||
);
|
||||
@@ -138,8 +152,8 @@ type PluginData = {
|
||||
version?: string;
|
||||
};
|
||||
|
||||
export default function PluginList() {
|
||||
const { plugins, updates, pluginOrder, setPluginOrder, hiddenPlugins } = useDeckyState();
|
||||
export default function PluginList({ isDeveloper }: { isDeveloper: boolean }) {
|
||||
const { plugins, updates, pluginOrder, setPluginOrder, frozenPlugins, hiddenPlugins } = useDeckyState();
|
||||
const [_, setPluginOrderSetting] = useSetting<string[]>(
|
||||
'pluginOrder',
|
||||
plugins.map((plugin) => plugin.name),
|
||||
@@ -151,21 +165,27 @@ export default function PluginList() {
|
||||
}, []);
|
||||
|
||||
const [pluginEntries, setPluginEntries] = useState<ReorderableEntry<PluginTableData>[]>([]);
|
||||
const frozenPluginsService = window.DeckyPluginLoader.frozenPluginsService;
|
||||
const hiddenPluginsService = window.DeckyPluginLoader.hiddenPluginsService;
|
||||
|
||||
useEffect(() => {
|
||||
setPluginEntries(
|
||||
plugins.map(({ name, version }) => {
|
||||
const frozen = frozenPlugins.includes(name);
|
||||
const hidden = hiddenPlugins.includes(name);
|
||||
|
||||
return {
|
||||
label: <PluginListLabel name={name} hidden={hidden} version={version} />,
|
||||
label: <PluginListLabel name={name} frozen={frozen} hidden={hidden} version={version} />,
|
||||
position: pluginOrder.indexOf(name),
|
||||
data: {
|
||||
name,
|
||||
frozen,
|
||||
hidden,
|
||||
isDeveloper,
|
||||
version,
|
||||
update: updates?.get(name),
|
||||
onFreeze: () => frozenPluginsService.update([...frozenPlugins, name]),
|
||||
onUnfreeze: () => frozenPluginsService.update(frozenPlugins.filter((pluginName) => name !== pluginName)),
|
||||
onHide: () => hiddenPluginsService.update([...hiddenPlugins, name]),
|
||||
onShow: () => hiddenPluginsService.update(hiddenPlugins.filter((pluginName) => name !== pluginName)),
|
||||
},
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import { DialogBody, DialogButton, DialogControlsSection, Focusable, Navigation } from 'decky-frontend-lib';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaDownload, FaInfo } from 'react-icons/fa';
|
||||
|
||||
import { callUpdaterMethod } from '../../../../updater';
|
||||
import { setSetting } from '../../../../utils/settings';
|
||||
import { UpdateBranch } from '../general/BranchSelect';
|
||||
|
||||
interface TestingVersion {
|
||||
id: number;
|
||||
name: string;
|
||||
link: string;
|
||||
head_sha: string;
|
||||
}
|
||||
|
||||
export default function TestingVersionList() {
|
||||
const { t } = useTranslation();
|
||||
const [testingVersions, setTestingVersions] = useState<TestingVersion[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
setTestingVersions((await callUpdaterMethod('get_testing_versions')).result);
|
||||
})();
|
||||
}, []);
|
||||
|
||||
if (testingVersions.length === 0) {
|
||||
return (
|
||||
<div>
|
||||
<p>No open PRs found</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DialogBody>
|
||||
<DialogControlsSection>
|
||||
<ul style={{ listStyleType: 'none', padding: '0' }}>
|
||||
{testingVersions.map((version) => {
|
||||
return (
|
||||
<li style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', paddingBottom: '10px' }}>
|
||||
<span>
|
||||
{version.name} <span style={{ opacity: '50%' }}>{'#' + version.id}</span>
|
||||
</span>
|
||||
<Focusable style={{ height: '40px', marginLeft: 'auto', display: 'flex' }}>
|
||||
<DialogButton
|
||||
style={{ height: '40px', minWidth: '60px', marginRight: '10px' }}
|
||||
onClick={() => {
|
||||
callUpdaterMethod('download_testing_version', { pr_id: version.id, sha_id: version.head_sha });
|
||||
setSetting('branch', UpdateBranch.Testing);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
minWidth: '150px',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{t('Testing.download')}
|
||||
<FaDownload style={{ paddingLeft: '1rem' }} />
|
||||
</div>
|
||||
</DialogButton>
|
||||
<DialogButton
|
||||
style={{
|
||||
height: '40px',
|
||||
width: '40px',
|
||||
padding: '10px 12px',
|
||||
minWidth: '40px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
onClick={() => Navigation.NavigateToExternalWeb(version.link)}
|
||||
>
|
||||
<FaInfo />
|
||||
</DialogButton>
|
||||
</Focusable>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</DialogControlsSection>
|
||||
</DialogBody>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import { DeckyState } from './components/DeckyState';
|
||||
import { PluginUpdateMapping } from './store';
|
||||
import { getSetting, setSetting } from './utils/settings';
|
||||
|
||||
/**
|
||||
* A Service class for managing the state and actions related to the frozen plugins feature.
|
||||
*
|
||||
* It's mostly responsible for sending setting updates to the server and keeping the local state in sync.
|
||||
*/
|
||||
export class FrozenPluginService {
|
||||
constructor(private deckyState: DeckyState) {}
|
||||
|
||||
init() {
|
||||
getSetting<string[]>('frozenPlugins', []).then((frozenPlugins) => {
|
||||
this.deckyState.setFrozenPlugins(frozenPlugins);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the new frozen plugins list to the server and persists it locally in the decky state
|
||||
*
|
||||
* @param frozenPlugins The new list of frozen plugins
|
||||
*/
|
||||
async update(frozenPlugins: string[]) {
|
||||
await setSetting('frozenPlugins', frozenPlugins);
|
||||
this.deckyState.setFrozenPlugins(frozenPlugins);
|
||||
|
||||
// Remove pending updates for frozen plugins
|
||||
const updates = this.deckyState.publicState().updates;
|
||||
|
||||
if (updates) {
|
||||
const filteredUpdates = new Map() as PluginUpdateMapping;
|
||||
updates.forEach((v, k) => {
|
||||
if (!frozenPlugins.includes(k)) {
|
||||
filteredUpdates.set(k, v);
|
||||
}
|
||||
});
|
||||
|
||||
this.deckyState.setUpdates(filteredUpdates);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the state of frozen plugins in the local state
|
||||
*/
|
||||
async invalidate() {
|
||||
this.deckyState.setFrozenPlugins(await getSetting('frozenPlugins', []));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,16 @@
|
||||
// Sets up DFL, then loads start.ts which starts up the loader
|
||||
interface Window {
|
||||
SP_REACTDOM: any;
|
||||
}
|
||||
(async () => {
|
||||
if (!window.SP_REACT) {
|
||||
console.debug('Setting up React globals...');
|
||||
// deliberate partial import
|
||||
const DFLWebpack = await import('decky-frontend-lib/dist/webpack');
|
||||
// TODO move these finds to dfl in v4
|
||||
window.SP_REACT = DFLWebpack.findModule((m) => m.Component && m.PureComponent && m.useLayoutEffect);
|
||||
window.SP_REACTDOM = DFLWebpack.findModule((m) => m.createPortal && m.createRoot);
|
||||
}
|
||||
console.debug('Setting up decky-frontend-lib...');
|
||||
window.DFL = await import('decky-frontend-lib');
|
||||
await import('./start');
|
||||
|
||||
@@ -22,6 +22,7 @@ import PluginUninstallModal from './components/modals/PluginUninstallModal';
|
||||
import NotificationBadge from './components/NotificationBadge';
|
||||
import PluginView from './components/PluginView';
|
||||
import WithSuspense from './components/WithSuspense';
|
||||
import { FrozenPluginService } from './frozen-plugins-service';
|
||||
import { HiddenPluginsService } from './hidden-plugins-service';
|
||||
import Logger from './logger';
|
||||
import { NotificationService } from './notification-service';
|
||||
@@ -49,6 +50,7 @@ class PluginLoader extends Logger {
|
||||
public toaster: Toaster = new Toaster();
|
||||
private deckyState: DeckyState = new DeckyState();
|
||||
|
||||
public frozenPluginsService = new FrozenPluginService(this.deckyState);
|
||||
public hiddenPluginsService = new HiddenPluginsService(this.deckyState);
|
||||
public notificationService = new NotificationService(this.deckyState);
|
||||
|
||||
@@ -144,7 +146,9 @@ class PluginLoader extends Logger {
|
||||
}
|
||||
|
||||
public async checkPluginUpdates() {
|
||||
const updates = await checkForUpdates(this.plugins);
|
||||
const frozenPlugins = this.deckyState.publicState().frozenPlugins;
|
||||
|
||||
const updates = await checkForUpdates(this.plugins.filter((p) => !frozenPlugins.includes(p.name)));
|
||||
this.deckyState.setUpdates(updates);
|
||||
return updates;
|
||||
}
|
||||
@@ -224,6 +228,7 @@ class PluginLoader extends Logger {
|
||||
this.deckyState.setPluginOrder(pluginOrder);
|
||||
});
|
||||
|
||||
this.frozenPluginsService.init();
|
||||
this.hiddenPluginsService.init();
|
||||
this.notificationService.init();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import reloadFix from './reload';
|
||||
// import reloadFix from './reload';
|
||||
import restartFix from './restart';
|
||||
let fixes: Function[] = [];
|
||||
|
||||
@@ -7,6 +7,6 @@ export function deinitSteamFixes() {
|
||||
}
|
||||
|
||||
export async function initSteamFixes() {
|
||||
fixes.push(await reloadFix());
|
||||
// fixes.push(await reloadFix());
|
||||
fixes.push(await restartFix());
|
||||
}
|
||||
|
||||
@@ -40,7 +40,8 @@ class TabsHook extends Logger {
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
typeof currentNode?.memoizedProps?.visible == 'boolean' &&
|
||||
(typeof currentNode?.memoizedProps?.visible == 'boolean' ||
|
||||
typeof currentNode?.memoizedProps?.active == 'boolean') &&
|
||||
currentNode?.type?.toString()?.includes('QuickAccessMenuBrowserView')
|
||||
) {
|
||||
this.log(`QAM root was found in ${iters} recursion cycles`);
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
Patch,
|
||||
ToastData,
|
||||
afterPatch,
|
||||
findClass,
|
||||
findInReactTree,
|
||||
findModuleChild,
|
||||
getReactRoot,
|
||||
@@ -48,16 +49,20 @@ class Toaster extends Logger {
|
||||
// ));
|
||||
let instance: any;
|
||||
const tree = getReactRoot(document.getElementById('root') as any);
|
||||
const toasterClass1 = findClass('GamepadToastPlaceholder');
|
||||
const toasterClass2 = findClass('ToastPlaceholder');
|
||||
const toasterClass3 = findClass('ToastPopup');
|
||||
const toasterClass4 = findClass('GamepadToastPopup');
|
||||
const findToasterRoot = (currentNode: any, iters: number): any => {
|
||||
if (iters >= 80) {
|
||||
// currently 66
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
currentNode?.memoizedProps?.className?.startsWith?.('gamepadtoasts_GamepadToastPlaceholder') ||
|
||||
currentNode?.memoizedProps?.className?.startsWith?.('toastmanager_ToastPlaceholder') ||
|
||||
currentNode?.memoizedProps?.className?.startsWith?.('toastmanager_ToastPopup') ||
|
||||
currentNode?.memoizedProps?.className?.startsWith?.('gamepadtoasts_GamepadToastPopup')
|
||||
currentNode?.memoizedProps?.className?.startsWith?.(toasterClass1) ||
|
||||
currentNode?.memoizedProps?.className?.startsWith?.(toasterClass2) ||
|
||||
currentNode?.memoizedProps?.className?.startsWith?.(toasterClass3) ||
|
||||
currentNode?.memoizedProps?.className?.startsWith?.(toasterClass4)
|
||||
) {
|
||||
this.log(`Toaster root was found in ${iters} recursion cycles`);
|
||||
return currentNode;
|
||||
|
||||
Reference in New Issue
Block a user