mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-06-13 12:15:09 +03:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 66bcdfd84e | |||
| 8494f2ec3e | |||
| 52f25708ad | |||
| 24b02114cb | |||
| 651215723d | |||
| ca9831be05 | |||
| f7fd7b712f | |||
| 3859c0e483 | |||
| 2db92536fd | |||
| a6ffc8f04d | |||
| 4df8cb5026 | |||
| a86d473280 | |||
| 4d226b00fc | |||
| 8b16b156ed | |||
| 4029a43637 | |||
| 57f4555350 | |||
| bd87cc852b | |||
| 30d7c9bb81 | |||
| 890599c7bb | |||
| b8e48d2146 | |||
| da1db5a053 | |||
| 60353df7ed | |||
| 13b6ed5ad9 | |||
| 89bbbf6fe4 | |||
| fdc556edee | |||
| f87e794c3f | |||
| 56719df827 | |||
| 3c11bb71f6 | |||
| 413cec9244 | |||
| 935de1ad0c | |||
| 9542708c92 | |||
| b3c363c89f | |||
| 5f5e8ad5d7 | |||
| 6b6de2fcd5 |
+11
-6
@@ -129,7 +129,7 @@ class PluginBrowser:
|
||||
logger.warning(f"Plugin {name} not installed, skipping uninstallation")
|
||||
except Exception as e:
|
||||
logger.error(f"Plugin {name} in {plugin_dir} was not uninstalled")
|
||||
logger.error(f"Error at %s", exc_info=e)
|
||||
logger.error(f"Error at {str(e)}", exc_info=e)
|
||||
if self.loader.watcher:
|
||||
self.loader.watcher.disabled = False
|
||||
|
||||
@@ -239,10 +239,15 @@ class PluginBrowser:
|
||||
name (string): The name of the plugin
|
||||
"""
|
||||
hidden_plugins = self.settings.getSetting("hiddenPlugins", [])
|
||||
hidden_plugins.remove(name)
|
||||
self.settings.setSetting("hiddenPlugins", hidden_plugins)
|
||||
if name in hidden_plugins:
|
||||
hidden_plugins.remove(name)
|
||||
self.settings.setSetting("hiddenPlugins", hidden_plugins)
|
||||
|
||||
plugin_order = self.settings.getSetting("pluginOrder")
|
||||
plugin_order.remove(name)
|
||||
self.settings.setSetting("pluginOrder", plugin_order)
|
||||
|
||||
plugin_order = self.settings.getSetting("pluginOrder", [])
|
||||
|
||||
if name in plugin_order:
|
||||
plugin_order.remove(name)
|
||||
self.settings.setSetting("pluginOrder", plugin_order)
|
||||
|
||||
logger.debug("Removed any settings for plugin %s", name)
|
||||
|
||||
+1
-1
@@ -159,4 +159,4 @@ async def stop_systemd_unit(unit_name: str) -> bool:
|
||||
return await localplatform.service_stop(unit_name)
|
||||
|
||||
async def start_systemd_unit(unit_name: str) -> bool:
|
||||
return await localplatform.service_start(unit_name)
|
||||
return await localplatform.service_start(unit_name)
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
{
|
||||
"BranchSelect": {
|
||||
"update_channel": {
|
||||
"label": "Aktualizační kanál",
|
||||
"prerelease": "Předběžná vydání",
|
||||
"stable": "Stabilní",
|
||||
"testing": "Testování"
|
||||
}
|
||||
},
|
||||
"Developer": {
|
||||
"disabling": "Vypínám React DevTools",
|
||||
"enabling": "Zapínám React DevTools",
|
||||
"5secreload": "Znovu načtení za 5 vteřin"
|
||||
},
|
||||
"FilePickerIndex": {
|
||||
"folder": {
|
||||
"select": "Použít tuto složku"
|
||||
}
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "1 plugin je v tomto seznamu skrytý",
|
||||
"hidden_few": "{{count}} pluginů je v tomto seznamu skryto",
|
||||
"hidden_other": "{{count}} pluginů je v tomto seznamu skryto"
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "Skryto z nabídky rychlého přístupu"
|
||||
},
|
||||
"PluginCard": {
|
||||
"plugin_full_access": "Tento plugin má plný přístup k vašemu Steam Decku.",
|
||||
"plugin_install": "Instalovat",
|
||||
"plugin_no_desc": "Nebyl uveden žádný popis.",
|
||||
"plugin_version_label": "Verze pluginu"
|
||||
},
|
||||
"PluginInstallModal": {
|
||||
"install": {
|
||||
"button_idle": "Instalovat",
|
||||
"button_processing": "Instalování",
|
||||
"title": "Instalovat {{artifact}}",
|
||||
"desc": "Jste si jisti, že chcete nainstalovat {{artifact}} {{version}}?"
|
||||
},
|
||||
"no_hash": "Tento plugin nemá hash, instalujete jej na vlastní nebezpečí.",
|
||||
"reinstall": {
|
||||
"button_idle": "Přeinstalovat",
|
||||
"button_processing": "Přeinstalování",
|
||||
"title": "Přeinstalovat {{artifact}}",
|
||||
"desc": "Jste si jisti, že chcete přeinstalovat {{artifact}} {{version}}?"
|
||||
},
|
||||
"update": {
|
||||
"button_idle": "Aktualizovat",
|
||||
"button_processing": "Aktualizování",
|
||||
"desc": "Jste si jisti, že chcete aktualizovat {{artifact}} {{version}}?",
|
||||
"title": "Aktualizovat {{artifact}}"
|
||||
}
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"mixed_one": "Upravit 1 plugin",
|
||||
"mixed_few": "Upravit {{count}} pluginů",
|
||||
"mixed_other": "Upravit {{count}} pluginů",
|
||||
"reinstall_one": "Přeinstalovat 1 plugin",
|
||||
"reinstall_few": "Přeinstalovat {{count}} pluginů",
|
||||
"reinstall_other": "Přeinstalovat {{count}} pluginů",
|
||||
"install_one": "Instalovat 1 plugin",
|
||||
"install_few": "Instalovat {{count}} pluginů",
|
||||
"install_other": "Instalovat {{count}} pluginů",
|
||||
"update_one": "Aktualizovat 1 plugin",
|
||||
"update_few": "Aktualizovat {{count}} pluginů",
|
||||
"update_other": "Aktualizovat {{count}} pluginů"
|
||||
},
|
||||
"ok_button": {
|
||||
"idle": "Potvrdit",
|
||||
"loading": "Probíhá"
|
||||
},
|
||||
"description": {
|
||||
"install": "Instalovat {{name}} {{version}}",
|
||||
"update": "Aktualizovat {{name}} na {{version}}",
|
||||
"reinstall": "Přeinstalovat {{name}} {{version}}"
|
||||
},
|
||||
"confirm": "Jste si jisti, že chcete udělat následující úpravy?"
|
||||
},
|
||||
"PluginListIndex": {
|
||||
"no_plugin": "Nejsou nainstalovány žádné pluginy!",
|
||||
"plugin_actions": "Akce pluginu",
|
||||
"reinstall": "Přeinstalovat",
|
||||
"reload": "Znovu načíst",
|
||||
"uninstall": "Odinstalovat",
|
||||
"update_to": "Aktualizovat na {{name}}",
|
||||
"show": "Rychlý přístup: Zobrazit",
|
||||
"hide": "Rychlý přístup: Skrýt",
|
||||
"update_all_one": "Aktualizovat 1 plugin",
|
||||
"update_all_few": "Aktualizovat {{count}} pluginů",
|
||||
"update_all_other": "Aktualizovat {{count}} pluginů"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
"decky_update_available": "Aktualizace na {{tag_name}} dostupná!",
|
||||
"error": "Chyba",
|
||||
"plugin_load_error": {
|
||||
"message": "Chyba při načítání pluginu {{name}}",
|
||||
"toast": "Chyba při načítání {{name}}"
|
||||
},
|
||||
"plugin_uninstall": {
|
||||
"button": "Odinstalovat",
|
||||
"desc": "Opravdu chcete odinstalovat {{name}}?",
|
||||
"title": "Odinstalovat {{name}}"
|
||||
},
|
||||
"plugin_update_one": "Je dostupná aktualizace pro 1 plugin!",
|
||||
"plugin_update_few": "Jsou dostupné aktualizace pro {{count}} pluginů!",
|
||||
"plugin_update_other": "Jsou dostupné aktualizace pro {{count}} pluginů!",
|
||||
"plugin_error_uninstall": "Načítání {{name}} způsobilo chybu uvedenou výše. To obvykle znamená, že plugin vyžaduje aktualizaci SteamUI. Zkontrolujte, zda je aktualizace k dispozici, nebo zvažte odstranění pluginu v nastavení Decky v sekci Pluginy."
|
||||
},
|
||||
"SettingsDeveloperIndex": {
|
||||
"cef_console": {
|
||||
"button": "Otevřít konzoli",
|
||||
"label": "CEF konzole",
|
||||
"desc": "Otevře CEF konzoli. Užitečné pouze pro účely ladění. Věci zde jsou potenciálně nebezpečné a měly by být používány pouze v případě, že jste vývojář pluginů, nebo vás sem nějaký nasměroval."
|
||||
},
|
||||
"header": "Ostatní",
|
||||
"react_devtools": {
|
||||
"desc": "Umožňuje připojení k počítači, na kterém běží React DevTools. Změnou tohoto nastavení se znovu načte Steam. Před povolením nastavte IP adresu.",
|
||||
"ip_label": "IP adresa",
|
||||
"label": "Zapnout React DevTools"
|
||||
},
|
||||
"third_party_plugins": {
|
||||
"button_install": "Instalovat",
|
||||
"button_zip": "Procházet",
|
||||
"header": "Pluginy třetí strany",
|
||||
"label_desc": "URL",
|
||||
"label_url": "Instalovat plugin z URL",
|
||||
"label_zip": "Instalovat plugin ze ZIP souboru"
|
||||
},
|
||||
"toast_zip": {
|
||||
"body": "Instalace selhala! Podporovány jsou pouze soubory ZIP.",
|
||||
"title": "Decky"
|
||||
},
|
||||
"valve_internal": {
|
||||
"desc1": "Zapíná interní vývojářské menu Valve.",
|
||||
"desc2": "Nedotýkejte se ničeho v této nabídce, pokud nevíte, co děláte.",
|
||||
"label": "Zapnout Valve Internal"
|
||||
}
|
||||
},
|
||||
"RemoteDebugging": {
|
||||
"remote_cef": {
|
||||
"label": "Povolit vzdálené CEF ladění",
|
||||
"desc": "Umožní neověřený přístup k CEF ladění komukoli ve vaší síti"
|
||||
}
|
||||
},
|
||||
"SettingsGeneralIndex": {
|
||||
"about": {
|
||||
"decky_version": "Decky verze",
|
||||
"header": "O Decky"
|
||||
},
|
||||
"beta": {
|
||||
"header": "Účast v betě"
|
||||
},
|
||||
"developer_mode": {
|
||||
"desc": "Zapíná vývojářské nastavení Decky.",
|
||||
"label": "Vývojářský režim"
|
||||
},
|
||||
"other": {
|
||||
"header": "Ostatní"
|
||||
},
|
||||
"updates": {
|
||||
"header": "Aktualizace"
|
||||
}
|
||||
},
|
||||
"SettingsIndex": {
|
||||
"developer_title": "Vývojář",
|
||||
"general_title": "Obecné",
|
||||
"navbar_settings": "Nastavení Decky",
|
||||
"plugins_title": "Pluginy"
|
||||
},
|
||||
"Store": {
|
||||
"store_contrib": {
|
||||
"label": "Přispívání",
|
||||
"desc": "Pokud byste chtěli přispět do obchodu Decky Plugin Store, podívejte se na repozitář SteamDeckHomebrew/decky-plugin-template na GitHubu. Informace o vývoji a distribuci jsou k dispozici v README."
|
||||
},
|
||||
"store_filter": {
|
||||
"label": "Filtr",
|
||||
"label_def": "Vše"
|
||||
},
|
||||
"store_search": {
|
||||
"label": "Hledat"
|
||||
},
|
||||
"store_sort": {
|
||||
"label": "Seřadit",
|
||||
"label_def": "Naposledy aktualizováno (Nejnovější)"
|
||||
},
|
||||
"store_source": {
|
||||
"desc": "Veškerý zdrojový kód pluginu je dostupný v repozitáři SteamDeckHomebrew/decky-plugin-database na GitHubu.",
|
||||
"label": "Zdrojový kód"
|
||||
},
|
||||
"store_tabs": {
|
||||
"about": "O Decky Plugin Store",
|
||||
"alph_asce": "Abecedně (Z do A)",
|
||||
"alph_desc": "Abecedně (A do Z)",
|
||||
"title": "Procházet"
|
||||
},
|
||||
"store_testing_cta": "Zvažte prosím testování nových pluginů, pomůžete tím týmu Decky Loader!"
|
||||
},
|
||||
"StoreSelect": {
|
||||
"custom_store": {
|
||||
"label": "Vlastní obchod",
|
||||
"url_label": "URL"
|
||||
},
|
||||
"store_channel": {
|
||||
"custom": "Vlastní",
|
||||
"default": "Výchozí",
|
||||
"label": "Kanál obchodu",
|
||||
"testing": "Testování"
|
||||
}
|
||||
},
|
||||
"Updater": {
|
||||
"updates": {
|
||||
"lat_version": "Aktuální: běží na verzi {{ver}}",
|
||||
"reloading": "Znovu načítání",
|
||||
"updating": "Aktualizování",
|
||||
"check_button": "Zkontrolovat aktualizace",
|
||||
"checking": "Kontrolování",
|
||||
"cur_version": "Aktuální verze: {{ver}}",
|
||||
"install_button": "Instalovat aktualizaci",
|
||||
"label": "Aktualizace"
|
||||
},
|
||||
"decky_updates": "Aktualizace Decky",
|
||||
"patch_notes_desc": "Poznámky k verzi",
|
||||
"no_patch_notes_desc": "žádné poznámky pro tuto verzi"
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,9 @@
|
||||
"reinstall": "Neu installieren",
|
||||
"reload": "Neu laden",
|
||||
"uninstall": "Deinstallieren",
|
||||
"update_to": "Aktualisieren zu {{name}}"
|
||||
"update_to": "Aktualisieren zu {{name}}",
|
||||
"update_all_one": "",
|
||||
"update_all_other": ""
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
@@ -179,5 +181,21 @@
|
||||
"updating": "Aktualisiere"
|
||||
},
|
||||
"no_patch_notes_desc": "Für diese Version gibt es keine Patchnotizen"
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "",
|
||||
"hidden_other": ""
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"install_one": "",
|
||||
"install_other": "",
|
||||
"mixed_one": "",
|
||||
"mixed_other": "",
|
||||
"update_one": "",
|
||||
"update_other": "",
|
||||
"reinstall_one": "",
|
||||
"reinstall_other": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,9 @@
|
||||
"reinstall": "Επανεγκατάσταση",
|
||||
"reload": "Επαναφόρτωση",
|
||||
"uninstall": "Απεγκατάσταση",
|
||||
"update_to": "Ενημέρωση σε {{name}}"
|
||||
"update_to": "Ενημέρωση σε {{name}}",
|
||||
"update_all_one": "",
|
||||
"update_all_other": ""
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
@@ -84,7 +86,9 @@
|
||||
"button": "Απεγκατάσταση",
|
||||
"desc": "Σίγουρα θέλετε να απεγκαταστήσετε το {{name}};",
|
||||
"title": "Απεγκατάσταση {{name}}"
|
||||
}
|
||||
},
|
||||
"plugin_update_one": "",
|
||||
"plugin_update_other": ""
|
||||
},
|
||||
"RemoteDebugging": {
|
||||
"remote_cef": {
|
||||
@@ -176,5 +180,21 @@
|
||||
"folder": {
|
||||
"select": "Χρησιμοποιήστε αυτό το φάκελο"
|
||||
}
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "",
|
||||
"hidden_other": ""
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"mixed_one": "",
|
||||
"mixed_other": "",
|
||||
"update_one": "",
|
||||
"update_other": "",
|
||||
"reinstall_one": "",
|
||||
"reinstall_other": "",
|
||||
"install_one": "",
|
||||
"install_other": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,37 @@
|
||||
"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.",
|
||||
"unknown": "An unknown error occurred. The raw error is: {{raw_error}}"
|
||||
}
|
||||
},
|
||||
"FilePickerIndex": {
|
||||
"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": {
|
||||
"select": "Use this folder"
|
||||
"label": "Folder",
|
||||
"select": "Use this folder",
|
||||
"show_more": "Show more files"
|
||||
}
|
||||
},
|
||||
"PluginView": {
|
||||
@@ -53,7 +81,7 @@
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"mixed_one": "Modify 1 plugin",
|
||||
"mixed_one": "Modify {{count}} plugin",
|
||||
"mixed_other": "Modify {{count}} plugins",
|
||||
"update_one": "Update 1 plugin",
|
||||
"update_other": "Update {{count}} plugins",
|
||||
|
||||
@@ -214,5 +214,10 @@
|
||||
"label": "Canál de la tienda",
|
||||
"testing": "Pruebas"
|
||||
}
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "",
|
||||
"hidden_many": "",
|
||||
"hidden_other": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,12 +101,15 @@
|
||||
"reload": "Recharger",
|
||||
"uninstall": "Désinstaller",
|
||||
"update_to": "Mettre à jour vers {{name}}",
|
||||
"no_plugin": "Aucun plugin installé !"
|
||||
"no_plugin": "Aucun plugin installé !",
|
||||
"update_all_one": "",
|
||||
"update_all_many": "",
|
||||
"update_all_other": ""
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
"error": "Erreur",
|
||||
"plugin_error_uninstall": "Allez sur <0></0> dans le menu de Decky si vous voulez désinstaller ce plugin.",
|
||||
"plugin_error_uninstall": "Allez sur {{name}} dans le menu de Decky si vous voulez désinstaller ce plugin.",
|
||||
"plugin_load_error": {
|
||||
"message": "Erreur lors du chargement du plugin {{name}}",
|
||||
"toast": "Erreur lors du chargement de {{name}}"
|
||||
@@ -179,5 +182,26 @@
|
||||
"title": "Explorer"
|
||||
},
|
||||
"store_testing_cta": "Pensez à tester de nouveaux plugins pour aider l'équipe Decky Loader !"
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "",
|
||||
"hidden_many": "",
|
||||
"hidden_other": ""
|
||||
},
|
||||
"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": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,41 @@
|
||||
}
|
||||
},
|
||||
"Developer": {
|
||||
"5secreload": "Ricarico in 5 secondi",
|
||||
"5secreload": "Ricarico tra 5 secondi",
|
||||
"disabling": "Disabilito i tools di React",
|
||||
"enabling": "Abilito i tools di React"
|
||||
},
|
||||
"DropdownMultiselect": {
|
||||
"button": {
|
||||
"back": "Indietro"
|
||||
}
|
||||
},
|
||||
"FilePickerError": {
|
||||
"errors": {
|
||||
"file_not_found": "Il percorso specificato non è valido. Controllalo e prova a reinserirlo di nuovo.",
|
||||
"unknown": "È avvenuto un'errore sconosciuto. L'errore segnalato è {{raw_error}}"
|
||||
}
|
||||
},
|
||||
"FilePickerIndex": {
|
||||
"files": {
|
||||
"all_files": "Tutti i file",
|
||||
"file_type": "Tipo di file",
|
||||
"show_hidden": "Mostra nascosti"
|
||||
},
|
||||
"filter": {
|
||||
"created_asce": "Creazione (meno recente)",
|
||||
"created_desc": "Creazione (più recente)",
|
||||
"modified_asce": "Modifica (meno recente)",
|
||||
"modified_desc": "Modifica (più recente)",
|
||||
"name_asce": "Z-A",
|
||||
"name_desc": "A-Z",
|
||||
"size_asce": "Dimensione (più piccolo)",
|
||||
"size_desc": "Dimensione (più grande)"
|
||||
},
|
||||
"folder": {
|
||||
"select": "Usa questa cartella"
|
||||
"label": "Cartella",
|
||||
"select": "Usa questa cartella",
|
||||
"show_more": "Mostra più file"
|
||||
}
|
||||
},
|
||||
"PluginCard": {
|
||||
@@ -84,7 +112,7 @@
|
||||
"SettingsDeveloperIndex": {
|
||||
"header": "Altro",
|
||||
"react_devtools": {
|
||||
"desc": "Abilita la connessione ad un computer che esegue i DevTools di React. Cambiando questa impostazione ricaricherà Steam. Imposta l'indirizzo IP prima di abilitarlo.",
|
||||
"desc": "Abilita la connessione ad un computer che esegue i DevTools di React. Steam verrà ricaricato se lo stato cambia. Imposta il tuo indirizzo IP prima di abilitarlo.",
|
||||
"ip_label": "IP",
|
||||
"label": "Abilita i DevTools di React"
|
||||
},
|
||||
@@ -218,9 +246,9 @@
|
||||
}
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "Un plugin è nascosto in questa lista",
|
||||
"hidden_many": "Sono nascosti {{count}} plugin da questa lista",
|
||||
"hidden_other": "Sono nascosti {{count}} plugin da questa lista"
|
||||
"hidden_one": "Un plugin è nascosto dalla lista",
|
||||
"hidden_many": "Sono nascosti {{count}} plugin dalla lista",
|
||||
"hidden_other": "Sono nascosti {{count}} plugin dalla lista"
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "Nascosti dal menu di accesso rapido"
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
{
|
||||
"BranchSelect": {
|
||||
"update_channel": {
|
||||
"label": "업데이트 배포 채널",
|
||||
"stable": "안정판",
|
||||
"testing": "시험판",
|
||||
"prerelease": "사전 출시판"
|
||||
}
|
||||
},
|
||||
"Developer": {
|
||||
"disabling": "React DevTools 비활성화",
|
||||
"enabling": "React DevTools 활성화",
|
||||
"5secreload": "5초 내로 다시 로드 됩니다"
|
||||
},
|
||||
"FilePickerIndex": {
|
||||
"folder": {
|
||||
"select": "이 폴더 사용"
|
||||
}
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_other": "플러그인 {{count}}개 숨김"
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "빠른 액세스 메뉴에서 숨김"
|
||||
},
|
||||
"PluginCard": {
|
||||
"plugin_install": "설치",
|
||||
"plugin_no_desc": "플러그인 설명이 제공되지 않았습니다.",
|
||||
"plugin_version_label": "플러그인 버전",
|
||||
"plugin_full_access": "이 플러그인은 Steam Deck의 모든 접근 권한을 가집니다."
|
||||
},
|
||||
"PluginInstallModal": {
|
||||
"install": {
|
||||
"button_idle": "설치",
|
||||
"button_processing": "설치 중",
|
||||
"desc": "{{artifact}} {{version}}을(를) 설치하겠습니까?",
|
||||
"title": "{{artifact}} 설치"
|
||||
},
|
||||
"reinstall": {
|
||||
"button_idle": "재설치",
|
||||
"button_processing": "재설치 중",
|
||||
"desc": "{{artifact}} {{version}}을(를) 재설치하겠습니까?",
|
||||
"title": "{{artifact}} 재설치"
|
||||
},
|
||||
"update": {
|
||||
"button_idle": "업데이트",
|
||||
"button_processing": "업데이트 중",
|
||||
"title": "{{artifact}} 업데이트",
|
||||
"desc": "{{artifact}} {{version}} 업데이트를 설치하겠습니까?"
|
||||
},
|
||||
"no_hash": "이 플러그인은 해시 확인을 하지 않습니다, 설치에 따른 위험은 사용자가 감수해야 합니다."
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"mixed_other": "플러그인 {{count}}개 수정",
|
||||
"update_other": "플러그인 {{count}}개 업데이트",
|
||||
"reinstall_other": "플러그인 {{count}}개 재설치",
|
||||
"install_other": "플러그인 {{count}}개 설치"
|
||||
},
|
||||
"ok_button": {
|
||||
"idle": "확인",
|
||||
"loading": "작업 중"
|
||||
},
|
||||
"confirm": "해당 수정을 적용하겠습니까?",
|
||||
"description": {
|
||||
"install": "{{name}} {{version}} 플러그인 설치",
|
||||
"update": "{{name}}의 {{version}} 업데이트 설치",
|
||||
"reinstall": "{{name}} {{version}} 재설치"
|
||||
}
|
||||
},
|
||||
"PluginListIndex": {
|
||||
"plugin_actions": "플러그인 동작",
|
||||
"reinstall": "재설치",
|
||||
"reload": "다시 로드",
|
||||
"uninstall": "설치 제거",
|
||||
"show": "빠른 액세스 메뉴: 표시",
|
||||
"hide": "빠른 액세스 메뉴: 숨김",
|
||||
"update_all_other": "플러그인 {{count}}개 업데이트",
|
||||
"no_plugin": "설치된 플러그인이 없습니다!",
|
||||
"update_to": "{{name}}(으)로 업데이트"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
"decky_update_available": "{{tag_name}} 업데이트를 설치할 수 있습니다!",
|
||||
"error": "오류",
|
||||
"plugin_load_error": {
|
||||
"message": "{{name}} 플러그인 불러오기 오류",
|
||||
"toast": "{{name}} 불러오기 오류"
|
||||
},
|
||||
"plugin_uninstall": {
|
||||
"button": "설치 제거",
|
||||
"desc": "{{name}}을(를) 설치 제거하겠습니까?",
|
||||
"title": "{{name}} 설치 제거"
|
||||
},
|
||||
"plugin_update_other": "플러그인 {{count}}개를 업데이트 할 수 있습니다!",
|
||||
"plugin_error_uninstall": "{{name}} 플러그인을 불러올 때 위와 같은 예외가 발생했습니다. 이는 보통 SteamUI 최신 버전에 맞는 플러그인 업데이트가 필요할 때 발생합니다. Decky 설정의 플러그인 항목에서 업데이트가 있는지 확인하거나 설치 제거를 시도 해 보세요."
|
||||
},
|
||||
"RemoteDebugging": {
|
||||
"remote_cef": {
|
||||
"label": "리모트 CEF 디버그 허용",
|
||||
"desc": "네트워크의 모든 사용자에게 CEF 디버거에 대한 인증되지 않은 액세스 허용"
|
||||
}
|
||||
},
|
||||
"SettingsDeveloperIndex": {
|
||||
"cef_console": {
|
||||
"button": "콘솔 열기",
|
||||
"label": "CEF 콘솔",
|
||||
"desc": "CEF 콘솔을 엽니다. 디버그 전용입니다. 이 항목들은 위험 가능성이 있으므로 플러그인 개발자이거나 개발자의 가이드를 따를 경우에만 사용해야 합니다."
|
||||
},
|
||||
"header": "기타",
|
||||
"react_devtools": {
|
||||
"ip_label": "IP",
|
||||
"label": "React DevTools 활성화",
|
||||
"desc": "React DevTools를 실행하고 있는 컴퓨터에 연결을 활성화합니다. 이 설정을 변경하면 Steam이 다시 로드됩니다. 활성화하기 전에 IP 주소를 설정하세요."
|
||||
},
|
||||
"third_party_plugins": {
|
||||
"button_install": "설치",
|
||||
"button_zip": "검색",
|
||||
"header": "서드파티 플러그인",
|
||||
"label_desc": "URL",
|
||||
"label_url": "URL에서 플러그인 설치",
|
||||
"label_zip": "ZIP 파일에서 플러그인 설치"
|
||||
},
|
||||
"toast_zip": {
|
||||
"body": "설치를 실패했습니다! ZIP 파일만이 지원됩니다.",
|
||||
"title": "Decky"
|
||||
},
|
||||
"valve_internal": {
|
||||
"desc1": "Valve 내부 개발자 메뉴를 활성화합니다.",
|
||||
"label": "Valve 내부 개발자 메뉴 활성화",
|
||||
"desc2": "이 메뉴의 기능을 모른다면 어떤 것도 건드리지 마세요."
|
||||
}
|
||||
},
|
||||
"SettingsGeneralIndex": {
|
||||
"about": {
|
||||
"decky_version": "Decky 버전",
|
||||
"header": "정보"
|
||||
},
|
||||
"beta": {
|
||||
"header": "베타 참가"
|
||||
},
|
||||
"developer_mode": {
|
||||
"desc": "Decky의 개발자 설정을 활성화합니다.",
|
||||
"label": "개발자 모드"
|
||||
},
|
||||
"other": {
|
||||
"header": "기타"
|
||||
},
|
||||
"updates": {
|
||||
"header": "업데이트"
|
||||
}
|
||||
},
|
||||
"SettingsIndex": {
|
||||
"developer_title": "개발자",
|
||||
"general_title": "일반",
|
||||
"navbar_settings": "Decky 설정",
|
||||
"plugins_title": "플러그인"
|
||||
},
|
||||
"Store": {
|
||||
"store_contrib": {
|
||||
"desc": "Decky 플러그인 스토어에 기여하고 싶다면 SteamDeckHomebrew/decky-plugin-template Github 저장소를 확인하세요. 개발 및 배포에 대한 정보는 README에서 확인할 수 있습니다.",
|
||||
"label": "기여하기"
|
||||
},
|
||||
"store_filter": {
|
||||
"label": "필터",
|
||||
"label_def": "모두"
|
||||
},
|
||||
"store_search": {
|
||||
"label": "검색"
|
||||
},
|
||||
"store_sort": {
|
||||
"label": "정렬",
|
||||
"label_def": "최근 업데이트 순"
|
||||
},
|
||||
"store_source": {
|
||||
"desc": "모든 플러그인 소스 코드는 SteamDeckHomebrew/decky-plugin-database Github 저장소에서 확인할 수 있습니다.",
|
||||
"label": "소스 코드"
|
||||
},
|
||||
"store_tabs": {
|
||||
"about": "정보",
|
||||
"alph_asce": "알파벳순 (Z-A)",
|
||||
"alph_desc": "알파벳순 (A-Z)",
|
||||
"title": "검색"
|
||||
},
|
||||
"store_testing_cta": "새로운 플러그인을 테스트하여 Decky Loader 팀을 도와주세요!"
|
||||
},
|
||||
"StoreSelect": {
|
||||
"custom_store": {
|
||||
"label": "사용자 지정 스토어",
|
||||
"url_label": "URL"
|
||||
},
|
||||
"store_channel": {
|
||||
"custom": "사용자 지정",
|
||||
"label": "스토어 배포 채널",
|
||||
"default": "기본",
|
||||
"testing": "시험"
|
||||
}
|
||||
},
|
||||
"Updater": {
|
||||
"decky_updates": "Decky 업데이트",
|
||||
"no_patch_notes_desc": "이 버전에는 패치 노트가 없습니다",
|
||||
"patch_notes_desc": "패치 노트",
|
||||
"updates": {
|
||||
"check_button": "업데이트 확인",
|
||||
"checking": "확인 중",
|
||||
"cur_version": "현재 버전: {{ver}}",
|
||||
"install_button": "업데이트 설치",
|
||||
"label": "업데이트",
|
||||
"lat_version": "최신 상태: {{ver}} 실행 중",
|
||||
"reloading": "다시 로드 중",
|
||||
"updating": "업데이트 중"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
{
|
||||
"BranchSelect": {
|
||||
"update_channel": {
|
||||
"prerelease": "Pré-lançamento",
|
||||
"stable": "Estável",
|
||||
"testing": "Em Teste",
|
||||
"label": "Canal de Atualização"
|
||||
}
|
||||
},
|
||||
"Developer": {
|
||||
"5secreload": "Recarregando em 5 segundos",
|
||||
"enabling": "Habilitando React DevTools",
|
||||
"disabling": "Desabilitando React DevTools"
|
||||
},
|
||||
"FilePickerIndex": {
|
||||
"folder": {
|
||||
"select": "Use esta pasta"
|
||||
}
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "Oculto no menu de acesso rápido"
|
||||
},
|
||||
"PluginCard": {
|
||||
"plugin_full_access": "Este plugin tem acesso total ao seu Steam Deck.",
|
||||
"plugin_install": "Instalar",
|
||||
"plugin_no_desc": "Nenhuma descrição fornecida.",
|
||||
"plugin_version_label": "Versão do plugin"
|
||||
},
|
||||
"PluginInstallModal": {
|
||||
"install": {
|
||||
"button_idle": "Instalar",
|
||||
"button_processing": "Instalando",
|
||||
"desc": "Você tem certeza que deseja instalar {{artifact}} {{version}}?",
|
||||
"title": "Instalar {{artifact}}"
|
||||
},
|
||||
"reinstall": {
|
||||
"button_idle": "Reinstalar",
|
||||
"button_processing": "Reinstalando",
|
||||
"desc": "Tem certeza que voce deseja reinstalar {{artifact}} {{version}}?",
|
||||
"title": "Reinstalar {{artifact}}"
|
||||
},
|
||||
"update": {
|
||||
"button_idle": "Atualizar",
|
||||
"button_processing": "Atualizando",
|
||||
"desc": "Tem certeza que voce deseja atualizar {{artifact}} {{version}}?",
|
||||
"title": "Atualizar {{artifact}}"
|
||||
},
|
||||
"no_hash": "Este plugin não tem um hash, você o está instalando por sua conta em risco."
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"mixed_one": "Modificar 1 plugin",
|
||||
"mixed_many": "Modificar {{count}} plugins",
|
||||
"mixed_other": "Modificar {{count}} plugins",
|
||||
"update_one": "Atualizar 1 plugin",
|
||||
"update_many": "Atualizar {{count}} plugins",
|
||||
"update_other": "Atualizar {{count}} plugins",
|
||||
"install_one": "Instalar 1 plugin",
|
||||
"install_many": "Instalar {{count}} plugins",
|
||||
"install_other": "Instalar {{count}} plugins",
|
||||
"reinstall_one": "Reinstalar 1 plugin",
|
||||
"reinstall_many": "Reinstalar {{count}} plugins",
|
||||
"reinstall_other": "Reinstalar {{count}} plugins"
|
||||
},
|
||||
"ok_button": {
|
||||
"idle": "Confirmar",
|
||||
"loading": "Carregando"
|
||||
},
|
||||
"description": {
|
||||
"install": "Instalar {{name}} {{version}}",
|
||||
"update": "Atualizar {{name}} para {{version}}",
|
||||
"reinstall": "Reinstalar {{name}} {{version}}"
|
||||
},
|
||||
"confirm": "Tem certeza que deseja fazer as seguintes modificações?"
|
||||
},
|
||||
"PluginListIndex": {
|
||||
"no_plugin": "Nenhum plugin instalado!",
|
||||
"plugin_actions": "Ações do plugin",
|
||||
"reinstall": "Reinstalar",
|
||||
"reload": "Recarregar",
|
||||
"uninstall": "Desinstalar",
|
||||
"update_to": "Atualizar para {{name}}",
|
||||
"show": "Acesso Rápido: Mostrar",
|
||||
"update_all_one": "Atualizar 1 plugin",
|
||||
"update_all_many": "Atualizar {{count}} plugins",
|
||||
"update_all_other": "Atualizar {{count}} plugins",
|
||||
"hide": "Acesso Rápido: Ocultar"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
"error": "Erro",
|
||||
"plugin_load_error": {
|
||||
"message": "Erro ao carregar o plugin {{name}}",
|
||||
"toast": "Erro ao carregar {{name}}"
|
||||
},
|
||||
"plugin_uninstall": {
|
||||
"button": "Desinstalar",
|
||||
"desc": "Você tem certeza que deseja desinstalar {{name}}?",
|
||||
"title": "Desinstalar {{name}}"
|
||||
},
|
||||
"decky_update_available": "Atualização para {{tag_name}} disponível!",
|
||||
"plugin_error_uninstall": "Um erro aconteceu ao carregar {{name}}, como mostrado acima. Isso normalmente significa que o plugin precisa de uma atualização para a nova versão do SteamUI. Confira se existe uma atualização ou avalie a remoção do plugin nas configurações do Decky, na sessão de plugins.",
|
||||
"plugin_update_one": "Atualizações disponível para 1 plugin!",
|
||||
"plugin_update_many": "Atualizações disponíveis para {{count}} plugins!",
|
||||
"plugin_update_other": "Atualizações disponíveis para {{count}} plugins!"
|
||||
},
|
||||
"RemoteDebugging": {
|
||||
"remote_cef": {
|
||||
"label": "Permitir Depuração CEF Demota",
|
||||
"desc": "Permitir acesso não autenticato ao depurador CEF para qualquer um na sua rede"
|
||||
}
|
||||
},
|
||||
"SettingsDeveloperIndex": {
|
||||
"cef_console": {
|
||||
"button": "Abrir o Console",
|
||||
"label": "Console CEF",
|
||||
"desc": "Abre o Console CEF. Somente útil para fins de depuração. O material aqui é potencialmente perigoso e só deve ser usado se você for um desenvolvedor de plugin, ou direcionado até aqui por um."
|
||||
},
|
||||
"header": "Outros",
|
||||
"react_devtools": {
|
||||
"desc": "Habilita a conexão a um computador executando React DevTools. Alterar essa configuração irá recarregar a Steam. Defina o endereço IP antes de habilitar.",
|
||||
"ip_label": "IP",
|
||||
"label": "Habilitar React DevTools"
|
||||
},
|
||||
"third_party_plugins": {
|
||||
"button_install": "Instalar",
|
||||
"button_zip": "Navegar",
|
||||
"header": "Plugins de terceiros",
|
||||
"label_url": "Instalar Plugin a partir da URL",
|
||||
"label_zip": "Instalar Plugin a partir de um arquivo ZIP",
|
||||
"label_desc": "URL"
|
||||
},
|
||||
"toast_zip": {
|
||||
"title": "Decky",
|
||||
"body": "Falha na instalação! Somente arquivos ZIP são suportados."
|
||||
},
|
||||
"valve_internal": {
|
||||
"desc1": "Habilita o menu interno de desenvolvedor da Valve.",
|
||||
"desc2": "Não toque em nada neste menu, a não ser que você saiba o que está fazendo.",
|
||||
"label": "Habilitar Menu Interno da Valve"
|
||||
}
|
||||
},
|
||||
"SettingsGeneralIndex": {
|
||||
"about": {
|
||||
"decky_version": "Versão do Decky",
|
||||
"header": "Sobre"
|
||||
},
|
||||
"developer_mode": {
|
||||
"desc": "Habilita as configurações de desenvolvedor do Decky.",
|
||||
"label": "Modo Deselvolvedor"
|
||||
},
|
||||
"other": {
|
||||
"header": "Outros"
|
||||
},
|
||||
"updates": {
|
||||
"header": "Atualizações"
|
||||
},
|
||||
"beta": {
|
||||
"header": "Participação no Beta"
|
||||
}
|
||||
},
|
||||
"SettingsIndex": {
|
||||
"developer_title": "Desenvolvedor",
|
||||
"general_title": "Geral",
|
||||
"navbar_settings": "Configurações do Decky",
|
||||
"plugins_title": "Plugins"
|
||||
},
|
||||
"Store": {
|
||||
"store_contrib": {
|
||||
"label": "Contribuindo",
|
||||
"desc": "Se você deseja contribuir para a Loja de Plugins para o Decky, confira o repositório SteamDeckHomebrew/decky-plugin-template no GitHub. Informações sobre o desenvolvimento e distribuição estão disponíveis no README."
|
||||
},
|
||||
"store_filter": {
|
||||
"label": "Filtros",
|
||||
"label_def": "Todos"
|
||||
},
|
||||
"store_search": {
|
||||
"label": "Buscar"
|
||||
},
|
||||
"store_sort": {
|
||||
"label": "Ordenar",
|
||||
"label_def": "Último atualizado (Mais recente)"
|
||||
},
|
||||
"store_source": {
|
||||
"desc": "Todos os codigo fonte dos plugins estão disponíveis no repositório SteamDeckHomebrew/decky-plugin-database no GitHub.",
|
||||
"label": "Código Fonte"
|
||||
},
|
||||
"store_tabs": {
|
||||
"about": "Sobre",
|
||||
"alph_desc": "Alfabética (A - Z)",
|
||||
"title": "Navegar",
|
||||
"alph_asce": "Alfabética (Z - A)"
|
||||
},
|
||||
"store_testing_cta": "Por favor, considere testar os novos plugins para ajudar o time do Decky Loader!"
|
||||
},
|
||||
"StoreSelect": {
|
||||
"custom_store": {
|
||||
"label": "Loja Personalizada",
|
||||
"url_label": "URL"
|
||||
},
|
||||
"store_channel": {
|
||||
"custom": "Personalizada",
|
||||
"default": "Padrão",
|
||||
"label": "Canal da Loja",
|
||||
"testing": "Em Teste"
|
||||
}
|
||||
},
|
||||
"Updater": {
|
||||
"no_patch_notes_desc": "nenhuma nota de alteração para esta versão",
|
||||
"patch_notes_desc": "Notas de alteração",
|
||||
"updates": {
|
||||
"check_button": "Buscar Atualizações",
|
||||
"checking": "Buscando",
|
||||
"cur_version": "Versão atual: {{ver}}",
|
||||
"install_button": "Instalar Atualização",
|
||||
"label": "Atualizações",
|
||||
"lat_version": "Atualizado: rodando {{ver}}",
|
||||
"reloading": "Recarregando",
|
||||
"updating": "Atualizando"
|
||||
},
|
||||
"decky_updates": "Atualizações do Decky"
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "1 plugin está oculto nesta lista",
|
||||
"hidden_many": "{{count}} plugins estão ocultos nesta lista",
|
||||
"hidden_other": "{{count}} plugins estão ocultos nesta lista"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
{
|
||||
"FilePickerIndex": {
|
||||
"folder": {
|
||||
"select": "Usar esta pasta"
|
||||
}
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "1 plugin está oculto desta lista",
|
||||
"hidden_many": "{{count}} plugins estão ocultos desta lista",
|
||||
"hidden_other": "{{count}} plugins estão ocultos desta lista"
|
||||
},
|
||||
"PluginCard": {
|
||||
"plugin_full_access": "Este plugin tem acesso total à tua Steam Deck.",
|
||||
"plugin_install": "Instalar",
|
||||
"plugin_version_label": "Versão do plugin",
|
||||
"plugin_no_desc": "Não tem descrição."
|
||||
},
|
||||
"PluginInstallModal": {
|
||||
"install": {
|
||||
"button_idle": "Instalar",
|
||||
"button_processing": "Instalação em curso",
|
||||
"title": "Instalar {{artifact}}",
|
||||
"desc": "De certeza que queres instalar {{artifact}} {{version}}?"
|
||||
},
|
||||
"reinstall": {
|
||||
"button_idle": "Reinstalar",
|
||||
"button_processing": "Reinstalação em curso",
|
||||
"title": "Reinstalar {{artifact}}",
|
||||
"desc": "De certeza que queres reinstalar {{artifact}} {{version}}?"
|
||||
},
|
||||
"update": {
|
||||
"button_idle": "Actualizar",
|
||||
"button_processing": "Actualização em curso",
|
||||
"title": "Actualizar {{artifact}}",
|
||||
"desc": "De certeza que queres actualizar {{artifact}} {{version}}?"
|
||||
},
|
||||
"no_hash": "Este plugin não tem um hash, estás a instalá-lo por tua conta e risco."
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"mixed_one": "Alterar 1 plugin",
|
||||
"mixed_many": "Alterar {{count}} plugins",
|
||||
"mixed_other": "Alterar {{count}} plugins",
|
||||
"update_one": "Actualizar 1 plugin",
|
||||
"update_many": "Actualizar {{count}} plugins",
|
||||
"update_other": "Actualizar {{count}} plugins",
|
||||
"reinstall_one": "Reinstalar 1 plugin",
|
||||
"reinstall_many": "Reinstalar {{count}} plugins",
|
||||
"reinstall_other": "Reinstalar {{count}} plugins",
|
||||
"install_one": "Instalar 1 plugin",
|
||||
"install_many": "Instalar {{count}} plugins",
|
||||
"install_other": "Instalar {{count}} plugins"
|
||||
},
|
||||
"ok_button": {
|
||||
"idle": "Confirmar",
|
||||
"loading": "Em curso"
|
||||
},
|
||||
"description": {
|
||||
"install": "Instalar {{name}} {{version}}",
|
||||
"update": "Actualizar {{name}} para {{version}}",
|
||||
"reinstall": "Reinstalar {{name}} {{version}}"
|
||||
},
|
||||
"confirm": "De certeza que queres fazer as seguintes alterações?"
|
||||
},
|
||||
"PluginListIndex": {
|
||||
"no_plugin": "Nenhum plugin instalado!",
|
||||
"reinstall": "Reinstalar",
|
||||
"uninstall": "Desinstalar",
|
||||
"update_to": "Actualizar para {{name}}",
|
||||
"update_all_one": "Actualizar 1 plugin",
|
||||
"update_all_many": "Actualizar {{count}} plugins",
|
||||
"update_all_other": "Actualizar {{count}} plugins",
|
||||
"plugin_actions": "Operações de plugin",
|
||||
"reload": "Recarregar",
|
||||
"show": "Acesso rápido: Mostrar",
|
||||
"hide": "Acesso rápido: Ocultar"
|
||||
},
|
||||
"BranchSelect": {
|
||||
"update_channel": {
|
||||
"stable": "Estável",
|
||||
"testing": "Em teste",
|
||||
"label": "Canal de actualização",
|
||||
"prerelease": "Pré-lançamento"
|
||||
}
|
||||
},
|
||||
"Developer": {
|
||||
"5secreload": "Vai recarregar em 5 segundos",
|
||||
"disabling": "Desactivando React DevTools",
|
||||
"enabling": "Activando React DevTools"
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "Oculto do menu de acesso rápido"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
"error": "Erro",
|
||||
"plugin_load_error": {
|
||||
"message": "Erro ao carregar o plugin {{name}}",
|
||||
"toast": "Erro ao carregar {{name}}"
|
||||
},
|
||||
"plugin_uninstall": {
|
||||
"button": "Desinstalar",
|
||||
"title": "Desinstalar {{name}}",
|
||||
"desc": "De certeza que queres desinstalar {{name}}?"
|
||||
},
|
||||
"decky_update_available": "Está disponível uma nova versão de {{tag_name}} !",
|
||||
"plugin_update_one": "1 plugin tem actualizações disponíveis!",
|
||||
"plugin_update_many": "{{count}} plugins têm actualizações disponíveis!",
|
||||
"plugin_update_other": "{{count}} plugins têm actualizações disponíveis!",
|
||||
"plugin_error_uninstall": "Houve uma excepção ao carregar {{name}}, como mostrado em cima. Pode ter sido porque o plugin requere a última versão do SteamUI. Verifica se há uma actualização disponível ou desinstala o plugin nas definições do Decky."
|
||||
},
|
||||
"SettingsDeveloperIndex": {
|
||||
"cef_console": {
|
||||
"button": "Abrir consola",
|
||||
"label": "Consola CEF",
|
||||
"desc": "Abre a consola do CEF. Só é útil para efeitos de debugging. Pode ser perigosa e só deve ser usada se és um desenvolvedor de plugins, ou se foste aqui indicado por um desenvolvedor."
|
||||
},
|
||||
"header": "Outros",
|
||||
"react_devtools": {
|
||||
"desc": "Permite a conecção a um computador que está a correr React DevTools. Mudar esta definição vai recarregar o Steam. Define o endereço de IP antes de activar.",
|
||||
"ip_label": "IP",
|
||||
"label": "Activar React DevTools"
|
||||
},
|
||||
"third_party_plugins": {
|
||||
"button_install": "Instalar",
|
||||
"button_zip": "Navegar",
|
||||
"header": "Plugins de terceiros",
|
||||
"label_desc": "URl",
|
||||
"label_url": "Instalar plugin a partir dum URL",
|
||||
"label_zip": "Instalar plugin a partir dum ficheiro ZIP"
|
||||
},
|
||||
"toast_zip": {
|
||||
"title": "Decky",
|
||||
"body": "A instalação falhou! Só ficheiros ZIP são suportados."
|
||||
},
|
||||
"valve_internal": {
|
||||
"label": "Activar menu interno da Valve",
|
||||
"desc1": "Activa o menu interno de programador da Valve.",
|
||||
"desc2": "Não toques em nada deste menu se não souberes a sua função."
|
||||
}
|
||||
},
|
||||
"RemoteDebugging": {
|
||||
"remote_cef": {
|
||||
"desc": "Permitir acesso não autenticado ao debugger do CEF a qualquer pessoa na tua rede",
|
||||
"label": "Permitir debugging remoto do CEF"
|
||||
}
|
||||
},
|
||||
"SettingsGeneralIndex": {
|
||||
"about": {
|
||||
"decky_version": "Versão do Decky",
|
||||
"header": "Sobre"
|
||||
},
|
||||
"beta": {
|
||||
"header": "Participação na versão Beta"
|
||||
},
|
||||
"developer_mode": {
|
||||
"label": "Modo de programador",
|
||||
"desc": "Activa as definições de programador do Decky."
|
||||
},
|
||||
"other": {
|
||||
"header": "Outros"
|
||||
},
|
||||
"updates": {
|
||||
"header": "Actualizações"
|
||||
}
|
||||
},
|
||||
"SettingsIndex": {
|
||||
"developer_title": "Programador",
|
||||
"general_title": "Geral",
|
||||
"navbar_settings": "Definições do Decky",
|
||||
"plugins_title": "Plugins"
|
||||
},
|
||||
"Store": {
|
||||
"store_contrib": {
|
||||
"label": "Contribuir",
|
||||
"desc": "Se queres contribuir com um novo plugin, vai ao repositório SteamDeckHomebrew/decky-plugin-template no GitHub. No README, podes encontrar mais informação sobre desenvolvimento e distribuição."
|
||||
},
|
||||
"store_filter": {
|
||||
"label": "Filtro",
|
||||
"label_def": "Todos"
|
||||
},
|
||||
"store_search": {
|
||||
"label": "Procurar"
|
||||
},
|
||||
"store_sort": {
|
||||
"label": "Ordenar",
|
||||
"label_def": "Última actualização (mais recente)"
|
||||
},
|
||||
"store_source": {
|
||||
"label": "Código fonte",
|
||||
"desc": "O código fonte de cada plugin está disponível no repositório SteamDeckHomebrew/decky-plugin-database no GitHub."
|
||||
},
|
||||
"store_tabs": {
|
||||
"about": "Sobre",
|
||||
"alph_asce": "Alfabeticamente (Z-A)",
|
||||
"alph_desc": "Alfabeticamente (A-Z)",
|
||||
"title": "Navegar"
|
||||
},
|
||||
"store_testing_cta": "Testa novos plugins e ajuda a equipa do Decky Loader!"
|
||||
},
|
||||
"StoreSelect": {
|
||||
"custom_store": {
|
||||
"url_label": "URL",
|
||||
"label": "Loja personalizada"
|
||||
},
|
||||
"store_channel": {
|
||||
"custom": "Personalizada",
|
||||
"default": "Standard",
|
||||
"testing": "Em teste",
|
||||
"label": "Canal de loja"
|
||||
}
|
||||
},
|
||||
"Updater": {
|
||||
"decky_updates": "Actualizações do Decky",
|
||||
"no_patch_notes_desc": "sem registo de alterações desta versão",
|
||||
"patch_notes_desc": "Registo de alterações",
|
||||
"updates": {
|
||||
"check_button": "Procurar actualizações",
|
||||
"checking": "Busca de actualizações em curso",
|
||||
"cur_version": "Versão actual: {{ver}}",
|
||||
"label": "Actualizações",
|
||||
"lat_version": "Actualizado: a correr {{ver}}",
|
||||
"updating": "Actualização em curso",
|
||||
"reloading": "Recarregar",
|
||||
"install_button": "Instalar actualização"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"update_one": "",
|
||||
"update_few": "",
|
||||
"update_many": "",
|
||||
"reinstall_one": "",
|
||||
"reinstall_few": "",
|
||||
"reinstall_many": "",
|
||||
"install_one": "",
|
||||
"install_few": "",
|
||||
"install_many": "",
|
||||
"mixed_one": "",
|
||||
"mixed_few": "",
|
||||
"mixed_many": ""
|
||||
}
|
||||
},
|
||||
"PluginListIndex": {
|
||||
"update_all_one": "",
|
||||
"update_all_few": "",
|
||||
"update_all_many": ""
|
||||
},
|
||||
"PluginLoader": {
|
||||
"plugin_update_one": "",
|
||||
"plugin_update_few": "",
|
||||
"plugin_update_many": ""
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "",
|
||||
"hidden_few": "",
|
||||
"hidden_many": ""
|
||||
}
|
||||
}
|
||||
@@ -59,11 +59,15 @@
|
||||
"desc": "Je i sigurt që don ta çinstalojsh {{name}}?"
|
||||
},
|
||||
"error": "Gabim",
|
||||
"plugin_error_uninstall": "Ju lutem shko nga <0></0> në Decky menu nëse don ta çinstalojsh këtë shtese."
|
||||
"plugin_error_uninstall": "Ju lutem shko nga {{name}} në Decky menu nëse don ta çinstalojsh këtë shtese.",
|
||||
"plugin_update_one": "",
|
||||
"plugin_update_other": ""
|
||||
},
|
||||
"PluginListIndex": {
|
||||
"no_plugin": "Nuk ka shtesa të instaluar!",
|
||||
"uninstall": "Çinstalo"
|
||||
"uninstall": "Çinstalo",
|
||||
"update_all_one": "",
|
||||
"update_all_other": ""
|
||||
},
|
||||
"SettingsGeneralIndex": {
|
||||
"other": {
|
||||
@@ -111,5 +115,21 @@
|
||||
"updates": {
|
||||
"cur_version": "Versioni e tanishëme: {{ver}}"
|
||||
}
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"mixed_one": "",
|
||||
"mixed_other": "",
|
||||
"update_one": "",
|
||||
"update_other": "",
|
||||
"reinstall_one": "",
|
||||
"reinstall_other": "",
|
||||
"install_one": "",
|
||||
"install_other": ""
|
||||
}
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "",
|
||||
"hidden_other": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
{
|
||||
"BranchSelect": {
|
||||
"update_channel": {
|
||||
"prerelease": "Передреліз",
|
||||
"testing": "Тестовий",
|
||||
"label": "Канал оновлень",
|
||||
"stable": "Стабільний"
|
||||
}
|
||||
},
|
||||
"Developer": {
|
||||
"5secreload": "Перезавантаження за 5 секунд",
|
||||
"enabling": "Увімкнення React DevTools",
|
||||
"disabling": "Вимкнення React DevTools"
|
||||
},
|
||||
"FilePickerIndex": {
|
||||
"folder": {
|
||||
"select": "Використовувати цю папку"
|
||||
}
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "Приховано з меню швидкого доступу"
|
||||
},
|
||||
"PluginCard": {
|
||||
"plugin_full_access": "Цей плагін має повний доступ до вашого Steam Deck.",
|
||||
"plugin_install": "Встановити",
|
||||
"plugin_no_desc": "Опис не надано.",
|
||||
"plugin_version_label": "Версія плагіна"
|
||||
},
|
||||
"PluginInstallModal": {
|
||||
"install": {
|
||||
"button_idle": "Встановити",
|
||||
"button_processing": "Встановлення",
|
||||
"title": "Встановити {{artifact}}",
|
||||
"desc": "Ви впевнені, що хочете встановити {{artifact}} {{version}}?"
|
||||
},
|
||||
"reinstall": {
|
||||
"button_idle": "Перевстановити",
|
||||
"desc": "Ви впевнені, що хочете перевстановити {{artifact}} {{version}}?",
|
||||
"title": "Перевстановити {{artifact}}",
|
||||
"button_processing": "Перевстановлення"
|
||||
},
|
||||
"update": {
|
||||
"button_idle": "Оновити",
|
||||
"button_processing": "Оновлення",
|
||||
"title": "Оновити {{artifact}}",
|
||||
"desc": "Ви впевнені, що хочете оновити {{artifact}} {{version}}?"
|
||||
},
|
||||
"no_hash": "Цей плагін не має хешу, ви встановлюєте його на власний ризик."
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"mixed_one": "Модифікувати 1 плагін",
|
||||
"mixed_few": "Модифікувати {{count}} плагінів",
|
||||
"mixed_many": "",
|
||||
"reinstall_one": "Перевстановити 1 плагін",
|
||||
"reinstall_few": "Перевстановити {{count}} плагінів",
|
||||
"reinstall_many": "Перевстановити {{count}} плагінів",
|
||||
"update_one": "Оновити 1 плагін",
|
||||
"update_few": "Оновити {{count}} плагінів",
|
||||
"update_many": "Оновити {{count}} плагінів",
|
||||
"install_one": "Встановити 1 плагін",
|
||||
"install_few": "Встановити {{count}} плагінів",
|
||||
"install_many": "Встановити {{count}} плагінів"
|
||||
},
|
||||
"ok_button": {
|
||||
"idle": "Підтвердити",
|
||||
"loading": "Опрацювання"
|
||||
},
|
||||
"description": {
|
||||
"install": "Встановити {{name}} {{version}}",
|
||||
"update": "Оновити {{name}} до {{version}}",
|
||||
"reinstall": "Перевстановити {{name}} {{version}}"
|
||||
},
|
||||
"confirm": "Ви впевнені, що хочете застосувати такі модифікації?"
|
||||
},
|
||||
"PluginListIndex": {
|
||||
"no_plugin": "Плагінів не встановлено!",
|
||||
"plugin_actions": "Дії плагінів",
|
||||
"reinstall": "Перевстановити",
|
||||
"reload": "Перезавантажити",
|
||||
"update_to": "Оновити {{name}}",
|
||||
"show": "Швидкий доступ: Показати",
|
||||
"hide": "Швидкий доступ: Приховати",
|
||||
"uninstall": "Видалити",
|
||||
"update_all_one": "Оновити 1 плагін",
|
||||
"update_all_few": "Оновити {{count}} плагінів",
|
||||
"update_all_many": "Оновити {{count}} плагінів"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
"decky_update_available": "Доступне оновлення до {{tag_name}}!",
|
||||
"error": "Помилка",
|
||||
"plugin_load_error": {
|
||||
"message": "Помилка завантаження плагіна {{name}}",
|
||||
"toast": "Помилка завантаження {{name}}"
|
||||
},
|
||||
"plugin_uninstall": {
|
||||
"desc": "Ви впевнені, що хочете видалити {{name}}?",
|
||||
"title": "Видалити {{name}}",
|
||||
"button": "Видалення"
|
||||
},
|
||||
"plugin_error_uninstall": "Завантаження {{name}} спровокувало помилку показану вище. Зазвичай це означає, що плагін вимагає оновлення до нової версії SteamUI. Перевірте чи таке оновлення доступне або виконайте його видалення у налаштуваннях Decky, у секції Плагіни.",
|
||||
"plugin_update_one": "Доступне оновлення для 1 плагіна!",
|
||||
"plugin_update_few": "Доступне оновлення для {{count}} плагінів!",
|
||||
"plugin_update_many": "Доступне оновлення для {{count}} плагінів!"
|
||||
},
|
||||
"SettingsDeveloperIndex": {
|
||||
"cef_console": {
|
||||
"button": "Відкрити консоль",
|
||||
"label": "CEF-консоль",
|
||||
"desc": "Відкрити CEF-консоль. Корисно тільки для дебагу. Ця штука потенційно небезпечна і повинна використовувати виключно якщо ви розробник плагіна, або якщо розробник спрямував вас сюди."
|
||||
},
|
||||
"header": "Інше",
|
||||
"react_devtools": {
|
||||
"desc": "Вмикає доступ до компʼютера із запущеним React DevTools. Зміна цього налаштування перезавантажить Steam. Вкажіть IP перед увімкненням.",
|
||||
"label": "Увімкнути React DevTools",
|
||||
"ip_label": "IP"
|
||||
},
|
||||
"third_party_plugins": {
|
||||
"button_install": "Встановити",
|
||||
"header": "Сторонні плагіни",
|
||||
"label_desc": "URL",
|
||||
"label_url": "Встановити плагін з URL",
|
||||
"label_zip": "Встановити плагін з ZIP-файлу",
|
||||
"button_zip": "Огляд"
|
||||
},
|
||||
"toast_zip": {
|
||||
"title": "Decky",
|
||||
"body": "Помилка встановлення! Підтримуються лише ZIP-файли."
|
||||
},
|
||||
"valve_internal": {
|
||||
"desc1": "Вмикає внутрішнє розробницьке меню Valve.",
|
||||
"label": "Увімкнути Valve Internal",
|
||||
"desc2": "Нічого не торкайтесь у цьому меню, якщо не розумієте, що ви робите."
|
||||
}
|
||||
},
|
||||
"SettingsGeneralIndex": {
|
||||
"about": {
|
||||
"decky_version": "Версія Decky",
|
||||
"header": "Про нас"
|
||||
},
|
||||
"beta": {
|
||||
"header": "Участь у Beta"
|
||||
},
|
||||
"developer_mode": {
|
||||
"desc": "Вмикає розробницькі налаштування Decky.",
|
||||
"label": "Розробницький режим"
|
||||
},
|
||||
"other": {
|
||||
"header": "Інше"
|
||||
},
|
||||
"updates": {
|
||||
"header": "Оновлення"
|
||||
}
|
||||
},
|
||||
"SettingsIndex": {
|
||||
"developer_title": "Розробник",
|
||||
"general_title": "Загальне",
|
||||
"navbar_settings": "Налаштування Decky",
|
||||
"plugins_title": "Плагіни"
|
||||
},
|
||||
"Store": {
|
||||
"store_contrib": {
|
||||
"label": "Зробити внесок",
|
||||
"desc": "Якщо ви бажаєте додати щось у Decky Plugin Store, завітайте у репозиторій SteamDeckHomebrew/decky-plugin-template на GitHub. Інформація про розробку та поширення доступна у README."
|
||||
},
|
||||
"store_filter": {
|
||||
"label": "Фільтр",
|
||||
"label_def": "Усе"
|
||||
},
|
||||
"store_search": {
|
||||
"label": "Пошук"
|
||||
},
|
||||
"store_sort": {
|
||||
"label": "Сортування",
|
||||
"label_def": "Востаннє оновлені (Найновіші)"
|
||||
},
|
||||
"store_source": {
|
||||
"label": "Вихідний код",
|
||||
"desc": "Код усіх плагінів доступний у репозиторії SteamDeckHomebrew/decky-plugin-database на GitHub."
|
||||
},
|
||||
"store_tabs": {
|
||||
"about": "Інформація",
|
||||
"alph_asce": "За алфавітом (Z до A)",
|
||||
"alph_desc": "За алфавітом (A до Z)",
|
||||
"title": "Огляд"
|
||||
},
|
||||
"store_testing_cta": "Розгляньте можливість тестування нових плагінів, щоб допомогти команді Decky Loader!"
|
||||
},
|
||||
"StoreSelect": {
|
||||
"custom_store": {
|
||||
"label": "Власний магазин",
|
||||
"url_label": "URL"
|
||||
},
|
||||
"store_channel": {
|
||||
"custom": "Власний",
|
||||
"default": "За замовчуванням",
|
||||
"testing": "Тестування",
|
||||
"label": "Канал магазину"
|
||||
}
|
||||
},
|
||||
"Updater": {
|
||||
"decky_updates": "Оновлення Decky",
|
||||
"no_patch_notes_desc": "Немає нотаток до цієї версії",
|
||||
"patch_notes_desc": "Перелік змін",
|
||||
"updates": {
|
||||
"checking": "Перевірка",
|
||||
"cur_version": "Поточна версія: {{ver}}",
|
||||
"install_button": "Встановити оновлення",
|
||||
"label": "Оновлення",
|
||||
"reloading": "Перезавантаження",
|
||||
"updating": "Оновлення",
|
||||
"check_button": "Перевірити оновлення",
|
||||
"lat_version": "Оновлено: використовується {{ver}}"
|
||||
}
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_one": "{{count}} плагін приховано з цього списку",
|
||||
"hidden_few": "{{count}} плагінів приховано з цього списку",
|
||||
"hidden_many": "{{count}} плагінів приховано з цього списку"
|
||||
},
|
||||
"RemoteDebugging": {
|
||||
"remote_cef": {
|
||||
"desc": "Дозволити доступ до CEF-дебагера без аутентифікації для будь-кого у вашій мережі",
|
||||
"label": "Дозволити віддалений CEF-дебагінг"
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-10
@@ -21,7 +21,7 @@
|
||||
"plugin_install": "安装",
|
||||
"plugin_no_desc": "无描述提供。",
|
||||
"plugin_version_label": "插件版本",
|
||||
"plugin_full_access": "此插件可以完全访问你的 Steam Deck"
|
||||
"plugin_full_access": "此插件可以完全访问你的 Steam Deck。"
|
||||
},
|
||||
"PluginInstallModal": {
|
||||
"install": {
|
||||
@@ -42,7 +42,7 @@
|
||||
"desc": "你确定要更新 {{artifact}} {{version}} 吗?",
|
||||
"title": "更新 {{artifact}}"
|
||||
},
|
||||
"no_hash": "此插件没有哈希校验值,你需要自行承担安装风险"
|
||||
"no_hash": "此插件没有哈希校验值,你需要自行承担安装风险。"
|
||||
},
|
||||
"PluginListIndex": {
|
||||
"no_plugin": "没有安装插件!",
|
||||
@@ -51,7 +51,9 @@
|
||||
"reload": "重新加载",
|
||||
"uninstall": "卸载",
|
||||
"update_to": "更新 {{name}}",
|
||||
"update_all_other": "更新 {{count}} 个插件"
|
||||
"update_all_other": "更新 {{count}} 个插件",
|
||||
"show": "快速访问菜单:可见",
|
||||
"hide": "快速访问菜单:不可见"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
@@ -79,7 +81,7 @@
|
||||
"react_devtools": {
|
||||
"ip_label": "IP",
|
||||
"label": "启用 React DevTools",
|
||||
"desc": "允许连接到运行着 React DevTools 的计算机,更改此设置将重新加载Steam,请在启用前设置IP地址"
|
||||
"desc": "允许连接到运行着 React DevTools 的计算机,更改此设置将重新加载Steam,请在启用前设置IP地址。"
|
||||
},
|
||||
"third_party_plugins": {
|
||||
"button_install": "安装",
|
||||
@@ -91,11 +93,11 @@
|
||||
},
|
||||
"toast_zip": {
|
||||
"title": "Decky",
|
||||
"body": "安装失败!只有 ZIP 格式的插件被支持"
|
||||
"body": "安装失败!只有 ZIP 格式的插件被支持。"
|
||||
},
|
||||
"valve_internal": {
|
||||
"desc1": "启用 Valve 内部开发者菜单",
|
||||
"desc2": "除非你知道你在干什么,否则请不要修改此菜单中的任何内容",
|
||||
"desc1": "启用 Valve 内部开发者菜单。",
|
||||
"desc2": "除非你知道你在干什么,否则请不要修改此菜单中的任何内容。",
|
||||
"label": "启用 Valve 内部开发者"
|
||||
},
|
||||
"cef_console": {
|
||||
@@ -115,7 +117,7 @@
|
||||
},
|
||||
"developer_mode": {
|
||||
"label": "开发者模式",
|
||||
"desc": "启用 Decky 的开发者测试"
|
||||
"desc": "启用 Decky 的开发者测试。"
|
||||
},
|
||||
"other": {
|
||||
"header": "其他"
|
||||
@@ -133,7 +135,7 @@
|
||||
"Store": {
|
||||
"store_contrib": {
|
||||
"label": "贡献",
|
||||
"desc": "如果你想要提交你的插件到 Decky 插件商店,请访问 GitHub 上的 SteamDeckHomebrew/decky-plugin-template 存储库,关于开发和分发的相关信息,请查看 README 文件"
|
||||
"desc": "如果你想要提交你的插件到 Decky 插件商店,请访问 GitHub 上的 SteamDeckHomebrew/decky-plugin-template 存储库,关于开发和分发的相关信息,请查看 README 文件。"
|
||||
},
|
||||
"store_filter": {
|
||||
"label": "过滤器",
|
||||
@@ -148,7 +150,7 @@
|
||||
},
|
||||
"store_source": {
|
||||
"label": "源代码",
|
||||
"desc": "所有插件的源代码都可以在 GitHub 上的 SteamDeckHomebrew/decky-plugin-database 存储库中获得"
|
||||
"desc": "所有插件的源代码都可以在 GitHub 上的 SteamDeckHomebrew/decky-plugin-database 存储库中获得。"
|
||||
},
|
||||
"store_tabs": {
|
||||
"about": "关于",
|
||||
@@ -202,5 +204,11 @@
|
||||
"update": "更新 {{name}} to {{version}}",
|
||||
"reinstall": "重装 {{name}} {{version}}"
|
||||
}
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "快速访问菜单中不可见"
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_other": "此列表隐藏了 {{count}} 个插件"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
},
|
||||
"Developer": {
|
||||
"5secreload": "5 秒後重新載入",
|
||||
"disabling": "正在停用",
|
||||
"enabling": "正在啟用"
|
||||
"disabling": "正在停用 React DevTools",
|
||||
"enabling": "正在啟用 React DevTools"
|
||||
},
|
||||
"FilePickerIndex": {
|
||||
"folder": {
|
||||
@@ -50,7 +50,10 @@
|
||||
"uninstall": "解除安裝",
|
||||
"update_to": "更新到 {{name}}",
|
||||
"reinstall": "重新安裝",
|
||||
"reload": "重新載入"
|
||||
"reload": "重新載入",
|
||||
"show": "快速存取:顯示",
|
||||
"hide": "快速存取:隱藏",
|
||||
"update_all_other": "更新 {{count}} 個外掛程式"
|
||||
},
|
||||
"PluginLoader": {
|
||||
"decky_title": "Decky",
|
||||
@@ -97,7 +100,12 @@
|
||||
"ip_label": "IP",
|
||||
"label": "啟用 React DevTools"
|
||||
},
|
||||
"header": "其他"
|
||||
"header": "其他",
|
||||
"cef_console": {
|
||||
"button": "開啟控制台",
|
||||
"label": "CEF 控制台",
|
||||
"desc": "開啟 CEF 控制台。僅用於偵錯。這裡的東西有潛在的風險,只有當你是一個外掛程式開發者或者被外掛程式開發者引導到這裡時,才應該使用。"
|
||||
}
|
||||
},
|
||||
"SettingsGeneralIndex": {
|
||||
"about": {
|
||||
@@ -178,5 +186,29 @@
|
||||
"cur_version": "目前版本:{{ver}}",
|
||||
"updating": "正在更新"
|
||||
}
|
||||
},
|
||||
"PluginView": {
|
||||
"hidden_other": "{{count}} 個外掛程式已隱藏"
|
||||
},
|
||||
"PluginListLabel": {
|
||||
"hidden": "已從快速存取選單中移除"
|
||||
},
|
||||
"MultiplePluginsInstallModal": {
|
||||
"title": {
|
||||
"mixed_other": "修改 {{count}} 個外掛程式",
|
||||
"update_other": "更新 {{count}} 個外掛程式",
|
||||
"reinstall_other": "重新安裝 {{count}} 個外掛程式",
|
||||
"install_other": "安裝 {{count}} 個外掛程式"
|
||||
},
|
||||
"ok_button": {
|
||||
"idle": "確定",
|
||||
"loading": "執行中"
|
||||
},
|
||||
"confirm": "您確定要進行以下的修改嗎?",
|
||||
"description": {
|
||||
"install": "安裝 {{name}} {{version}}",
|
||||
"update": "更新 {{name}} 到 {{version}}",
|
||||
"reinstall": "重新安裝 {{name}} {{version}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+84
-21
@@ -1,16 +1,21 @@
|
||||
import uuid
|
||||
import os
|
||||
from json.decoder import JSONDecodeError
|
||||
from os.path import splitext
|
||||
import re
|
||||
from traceback import format_exc
|
||||
from stat import FILE_ATTRIBUTE_HIDDEN
|
||||
|
||||
from asyncio import sleep, start_server, gather, open_connection
|
||||
from aiohttp import ClientSession, web
|
||||
|
||||
from logging import getLogger
|
||||
from injector import inject_to_tab, get_gamepadui_tab, close_old_tabs, get_tab
|
||||
from pathlib import Path
|
||||
from localplatform import ON_WINDOWS
|
||||
import helpers
|
||||
import subprocess
|
||||
from localplatform import service_stop, service_start
|
||||
from localplatform import service_stop, service_start, get_home_path, get_username
|
||||
|
||||
class Utilities:
|
||||
def __init__(self, context) -> None:
|
||||
@@ -33,7 +38,8 @@ class Utilities:
|
||||
"filepicker_ls": self.filepicker_ls,
|
||||
"disable_rdt": self.disable_rdt,
|
||||
"enable_rdt": self.enable_rdt,
|
||||
"get_tab_id": self.get_tab_id
|
||||
"get_tab_id": self.get_tab_id,
|
||||
"get_user_info": self.get_user_info,
|
||||
}
|
||||
|
||||
self.logger = getLogger("Utilities")
|
||||
@@ -189,31 +195,82 @@ class Utilities:
|
||||
await service_stop(helpers.REMOTE_DEBUGGER_UNIT)
|
||||
return True
|
||||
|
||||
async def filepicker_ls(self, path, include_files=True):
|
||||
# def sorter(file): # Modification time
|
||||
# if os.path.isdir(os.path.join(path, file)) or os.path.isfile(os.path.join(path, file)):
|
||||
# return os.path.getmtime(os.path.join(path, file))
|
||||
# return 0
|
||||
# file_names = sorted(os.listdir(path), key=sorter, reverse=True) # TODO provide more sort options
|
||||
file_names = sorted(os.listdir(path)) # Alphabetical
|
||||
async def filepicker_ls(self,
|
||||
path : str | None = None,
|
||||
include_files: bool = True,
|
||||
include_folders: bool = True,
|
||||
include_ext: list[str] = [],
|
||||
include_hidden: bool = False,
|
||||
order_by: str = "name_asc",
|
||||
filter_for: str | None = None,
|
||||
page: int = 1,
|
||||
max: int = 1000):
|
||||
|
||||
if path == None:
|
||||
path = get_home_path()
|
||||
|
||||
files = []
|
||||
path = Path(path).resolve()
|
||||
|
||||
for file in file_names:
|
||||
full_path = os.path.join(path, file)
|
||||
is_dir = os.path.isdir(full_path)
|
||||
files, folders = [], []
|
||||
|
||||
if is_dir or include_files:
|
||||
files.append({
|
||||
"isdir": is_dir,
|
||||
"name": file,
|
||||
"realpath": os.path.realpath(full_path)
|
||||
})
|
||||
#Resolving all files/folders in the requested directory
|
||||
for file in path.iterdir():
|
||||
if file.exists():
|
||||
filest = file.stat()
|
||||
is_hidden = file.name.startswith('.')
|
||||
if ON_WINDOWS and not is_hidden:
|
||||
is_hidden = bool(filest.st_file_attributes & FILE_ATTRIBUTE_HIDDEN)
|
||||
if include_folders and file.is_dir():
|
||||
if (is_hidden and include_hidden) or not is_hidden:
|
||||
folders.append({"file": file, "filest": filest, "is_dir": True})
|
||||
elif include_files:
|
||||
# Handle requested extensions if present
|
||||
if 'all_files' in include_ext or splitext(file.name)[1].lstrip('.') in include_ext:
|
||||
if (is_hidden and include_hidden) or not is_hidden:
|
||||
files.append({"file": file, "filest": filest, "is_dir": False})
|
||||
# Filter logic
|
||||
if filter_for is not None:
|
||||
try:
|
||||
if re.compile(filter_for):
|
||||
files = filter(lambda file: re.search(filter_for, file.name) != None, files)
|
||||
except re.error:
|
||||
files = filter(lambda file: file.name.find(filter_for) != -1, files)
|
||||
|
||||
# Ordering logic
|
||||
ord_arg = order_by.split("_")
|
||||
ord = ord_arg[0]
|
||||
rev = True if ord_arg[1] == "asc" else False
|
||||
match ord:
|
||||
case 'name':
|
||||
files.sort(key=lambda x: x['file'].name.casefold(), reverse = rev)
|
||||
folders.sort(key=lambda x: x['file'].name.casefold(), reverse = rev)
|
||||
case 'modified':
|
||||
files.sort(key=lambda x: x['filest'].st_mtime, reverse = not rev)
|
||||
folders.sort(key=lambda x: x['filest'].st_mtime, reverse = not rev)
|
||||
case 'created':
|
||||
files.sort(key=lambda x: x['filest'].st_ctime, reverse = not rev)
|
||||
folders.sort(key=lambda x: x['filest'].st_ctime, reverse = not rev)
|
||||
case 'size':
|
||||
files.sort(key=lambda x: x['filest'].st_size, reverse = not rev)
|
||||
# Folders has no file size, order by name instead
|
||||
folders.sort(key=lambda x: x['file'].name.casefold())
|
||||
|
||||
#Constructing the final file list, folders first
|
||||
all = [{
|
||||
"isdir": x['is_dir'],
|
||||
"name": str(x['file'].name),
|
||||
"realpath": str(x['file']),
|
||||
"size": x['filest'].st_size,
|
||||
"modified": x['filest'].st_mtime,
|
||||
"created": x['filest'].st_ctime,
|
||||
} for x in folders + files ]
|
||||
|
||||
return {
|
||||
"realpath": os.path.realpath(path),
|
||||
"files": files
|
||||
"realpath": str(path),
|
||||
"files": all[(page-1)*max:(page)*max],
|
||||
"total": len(all),
|
||||
}
|
||||
|
||||
|
||||
# Based on https://stackoverflow.com/a/46422554/13174603
|
||||
def start_rdt_proxy(self, ip, port):
|
||||
@@ -289,5 +346,11 @@ class Utilities:
|
||||
await tab.evaluate_js("location.reload();", False, True, False)
|
||||
self.logger.info("React DevTools disabled")
|
||||
|
||||
async def get_user_info(self) -> dict:
|
||||
return {
|
||||
"username": get_username(),
|
||||
"path": get_home_path()
|
||||
}
|
||||
|
||||
async def get_tab_id(self, name):
|
||||
return (await get_tab(name)).id
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"@types/react-router": "5.1.18",
|
||||
"@types/webpack": "^5.28.1",
|
||||
"husky": "^8.0.3",
|
||||
"i18next-parser": "^7.9.0",
|
||||
"i18next-parser": "^8.0.0",
|
||||
"import-sort-style-module": "^6.0.0",
|
||||
"inquirer": "^8.2.5",
|
||||
"prettier": "^2.8.8",
|
||||
@@ -33,8 +33,8 @@
|
||||
"rollup-plugin-delete": "^2.0.0",
|
||||
"rollup-plugin-external-globals": "^0.6.1",
|
||||
"rollup-plugin-polyfill-node": "^0.10.2",
|
||||
"rollup-plugin-visualizer": "^5.9.0",
|
||||
"tslib": "^2.5.2",
|
||||
"rollup-plugin-visualizer": "^5.9.2",
|
||||
"tslib": "^2.5.3",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"importSort": {
|
||||
@@ -45,11 +45,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"decky-frontend-lib": "3.21.1",
|
||||
"i18next": "^22.5.0",
|
||||
"filesize": "^10.0.7",
|
||||
"i18next": "^23.1.0",
|
||||
"i18next-http-backend": "^2.2.1",
|
||||
"react-file-icon": "^1.3.0",
|
||||
"react-i18next": "^12.3.1",
|
||||
"react-icons": "^4.8.0",
|
||||
"react-icons": "^4.9.0",
|
||||
"react-markdown": "^8.0.7",
|
||||
"remark-gfm": "^3.0.1"
|
||||
}
|
||||
|
||||
Generated
+359
-341
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,12 @@ interface PublicDeckyState {
|
||||
hasLoaderUpdate?: boolean;
|
||||
isLoaderUpdating: boolean;
|
||||
versionInfo: VerInfo | null;
|
||||
userInfo: UserInfo | null;
|
||||
}
|
||||
|
||||
export interface UserInfo {
|
||||
username: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export class DeckyState {
|
||||
@@ -24,6 +30,7 @@ export class DeckyState {
|
||||
private _hasLoaderUpdate: boolean = false;
|
||||
private _isLoaderUpdating: boolean = false;
|
||||
private _versionInfo: VerInfo | null = null;
|
||||
private _userInfo: UserInfo | null = null;
|
||||
|
||||
public eventBus = new EventTarget();
|
||||
|
||||
@@ -37,6 +44,7 @@ export class DeckyState {
|
||||
hasLoaderUpdate: this._hasLoaderUpdate,
|
||||
isLoaderUpdating: this._isLoaderUpdating,
|
||||
versionInfo: this._versionInfo,
|
||||
userInfo: this._userInfo,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -85,6 +93,11 @@ export class DeckyState {
|
||||
this.notifyUpdate();
|
||||
}
|
||||
|
||||
setUserInfo(userInfo: UserInfo) {
|
||||
this._userInfo = userInfo;
|
||||
this.notifyUpdate();
|
||||
}
|
||||
|
||||
private notifyUpdate() {
|
||||
this.eventBus.dispatchEvent(new Event('update'));
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { FC, createContext, useContext, useState } from 'react';
|
||||
|
||||
const QuickAccessVisibleState = createContext<boolean>(true);
|
||||
const QuickAccessVisibleState = createContext<boolean>(false);
|
||||
|
||||
export const useQuickAccessVisible = () => useContext(QuickAccessVisibleState);
|
||||
|
||||
export const QuickAccessVisibleStateProvider: FC<{ initial: boolean; tab: any }> = ({ children, initial, tab }) => {
|
||||
export const QuickAccessVisibleStateProvider: FC<{ tab: any }> = ({ children, tab }) => {
|
||||
const initial = tab.initialVisibility;
|
||||
const [visible, setVisible] = useState<boolean>(initial);
|
||||
const [prev, setPrev] = useState<boolean>(initial);
|
||||
// HACK but i can't think of a better way to do this
|
||||
tab.qAMVisibilitySetter = setVisible;
|
||||
if (initial != prev) {
|
||||
setPrev(initial);
|
||||
setVisible(initial);
|
||||
}
|
||||
tab.qAMVisibilitySetter = (val: boolean) => {
|
||||
if (val != visible) setVisible(val);
|
||||
};
|
||||
|
||||
return <QuickAccessVisibleState.Provider value={visible}>{children}</QuickAccessVisibleState.Provider>;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import {
|
||||
DialogButton,
|
||||
DialogCheckbox,
|
||||
DialogCheckboxProps,
|
||||
Marquee,
|
||||
Menu,
|
||||
MenuItem,
|
||||
findModuleChild,
|
||||
showContextMenu,
|
||||
} from 'decky-frontend-lib';
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaChevronDown } from 'react-icons/fa';
|
||||
|
||||
const dropDownControlButtonClass = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
for (const prop in m) {
|
||||
if (m[prop]?.toString()?.includes('gamepaddropdown_DropDownControlButton')) {
|
||||
return m[prop];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const DropdownMultiselectItem: FC<
|
||||
{
|
||||
value: any;
|
||||
onSelect: (checked: boolean, value: any) => void;
|
||||
checked: boolean;
|
||||
} & DialogCheckboxProps
|
||||
> = ({ value, onSelect, checked: defaultChecked, ...rest }) => {
|
||||
const [checked, setChecked] = useState(defaultChecked);
|
||||
|
||||
useEffect(() => {
|
||||
onSelect?.(checked, value);
|
||||
}, [checked, onSelect, value]);
|
||||
|
||||
return (
|
||||
<MenuItem bInteractableItem onClick={() => setChecked((x) => !x)}>
|
||||
<DialogCheckbox
|
||||
style={{ marginBottom: 0, padding: 0 }}
|
||||
className="decky_DropdownMultiselectItem_DialogCheckbox"
|
||||
bottomSeparator="none"
|
||||
{...rest}
|
||||
onClick={() => setChecked((x) => !x)}
|
||||
onChange={(checked) => setChecked(checked)}
|
||||
controlled
|
||||
checked={checked}
|
||||
/>
|
||||
</MenuItem>
|
||||
);
|
||||
};
|
||||
|
||||
const DropdownMultiselect: FC<{
|
||||
items: {
|
||||
label: string;
|
||||
value: string;
|
||||
}[];
|
||||
selected: string[];
|
||||
onSelect: (selected: any[]) => void;
|
||||
label: string;
|
||||
}> = ({ label, items, selected, onSelect }) => {
|
||||
const [itemsSelected, setItemsSelected] = useState<any>(selected);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleItemSelect = useCallback((checked, value) => {
|
||||
setItemsSelected((x: any) =>
|
||||
checked ? [...x.filter((y: any) => y !== value), value] : x.filter((y: any) => y !== value),
|
||||
);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
onSelect(itemsSelected);
|
||||
}, [itemsSelected, onSelect]);
|
||||
|
||||
return (
|
||||
<DialogButton
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
maxWidth: '100%',
|
||||
}}
|
||||
className={dropDownControlButtonClass}
|
||||
onClick={(evt) => {
|
||||
evt.preventDefault();
|
||||
showContextMenu(
|
||||
<Menu label={label} cancelText={t('DropdownMultiselect.button.back') as string}>
|
||||
<style>
|
||||
{`
|
||||
/* Inherit color from ".basiccontextmenu" */
|
||||
.decky_DropdownMultiselectItem_DialogCheckbox > .DialogToggle_Label {
|
||||
color: inherit;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
<div style={{ marginTop: '10px' }}>{/*FIXME: Hack for missing padding under label menu*/}</div>
|
||||
{items.map((x) => (
|
||||
<DropdownMultiselectItem
|
||||
key={x.value}
|
||||
label={x.label}
|
||||
value={x.value}
|
||||
checked={itemsSelected.includes(x.value)}
|
||||
onSelect={handleItemSelect}
|
||||
/>
|
||||
))}
|
||||
</Menu>,
|
||||
evt.currentTarget ?? window,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Marquee>
|
||||
{selected.length > 0
|
||||
? selected.map((x: any) => items[items.findIndex((v) => v.value === x)].label).join(', ')
|
||||
: '…'}
|
||||
</Marquee>
|
||||
<div style={{ flexGrow: 1, minWidth: '1ch' }} />
|
||||
<FaChevronDown style={{ height: '1em', flex: '0 0 1em' }} />
|
||||
</DialogButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default DropdownMultiselect;
|
||||
@@ -0,0 +1,51 @@
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IconContext } from 'react-icons';
|
||||
import { FaExclamationTriangle, FaQuestionCircle } from 'react-icons/fa';
|
||||
|
||||
export enum FileErrorTypes {
|
||||
FileNotFound,
|
||||
Unknown,
|
||||
None,
|
||||
}
|
||||
|
||||
interface FilePickerErrorProps {
|
||||
error: FileErrorTypes;
|
||||
rawError?: string;
|
||||
}
|
||||
|
||||
const FilePickerError: FC<FilePickerErrorProps> = ({ error, rawError = null }) => {
|
||||
const [icon, setIcon] = useState<JSX.Element>(<FaQuestionCircle />);
|
||||
const [text, setText] = useState<string | null>(null);
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
switch (error) {
|
||||
case FileErrorTypes.FileNotFound:
|
||||
setText(t('FilePickerError.errors.file_not_found'));
|
||||
setIcon(<FaExclamationTriangle />);
|
||||
break;
|
||||
case FileErrorTypes.Unknown:
|
||||
setText(t('FilePickerError.errors.unknown', { raw_error: rawError }));
|
||||
setIcon(<FaQuestionCircle />);
|
||||
break;
|
||||
case FileErrorTypes.None:
|
||||
setText(null);
|
||||
setIcon(<div></div>);
|
||||
break;
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={{ paddingTop: '50px', textAlign: 'center', height: '100%' }}>
|
||||
<IconContext.Provider value={{ className: 'fileError', size: '128px' }}>
|
||||
<div style={{ alignSelf: 'center', alignContent: 'center' }}>{icon}</div>
|
||||
</IconContext.Provider>
|
||||
<p style={{ height: '32px', paddingTop: '25px', alignSelf: 'flex-start', textAlign: 'center' }}>{text}</p>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FilePickerError;
|
||||
@@ -0,0 +1,46 @@
|
||||
import { FC } from 'react';
|
||||
import { Translation } from 'react-i18next';
|
||||
|
||||
export enum SortOptions {
|
||||
name_desc = 'name_desc',
|
||||
name_asc = 'name_asc',
|
||||
modified_desc = 'modified_desc',
|
||||
modified_asc = 'modified_asc',
|
||||
created_desc = 'created_desc',
|
||||
created_asc = 'created_asc',
|
||||
size_desc = 'size_desc',
|
||||
size_asc = 'size_asc',
|
||||
}
|
||||
|
||||
interface TSortOptionsProps {
|
||||
trans_part: SortOptions;
|
||||
}
|
||||
|
||||
const TSortOptions: FC<TSortOptionsProps> = ({ trans_part }) => {
|
||||
return (
|
||||
<Translation>
|
||||
{(t, {}) => {
|
||||
switch (trans_part) {
|
||||
case SortOptions.name_desc:
|
||||
return t('FilePickerIndex.filter.name_desc');
|
||||
case SortOptions.name_asc:
|
||||
return t('FilePickerIndex.filter.name_asce');
|
||||
case SortOptions.modified_desc:
|
||||
return t('FilePickerIndex.filter.modified_desc');
|
||||
case SortOptions.modified_asc:
|
||||
return t('FilePickerIndex.filter.modified_asce');
|
||||
case SortOptions.created_desc:
|
||||
return t('FilePickerIndex.filter.created_desc');
|
||||
case SortOptions.created_asc:
|
||||
return t('FilePickerIndex.filter.created_asce');
|
||||
case SortOptions.size_desc:
|
||||
return t('FilePickerIndex.filter.size_desc');
|
||||
case SortOptions.size_asc:
|
||||
return t('FilePickerIndex.filter.size_asce');
|
||||
}
|
||||
}}
|
||||
</Translation>
|
||||
);
|
||||
};
|
||||
|
||||
export default TSortOptions;
|
||||
@@ -38,7 +38,7 @@ const imageStyle = {
|
||||
color: '#d18f00',
|
||||
};
|
||||
|
||||
const imageExtList = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'tif', 'tiff'];
|
||||
const imageExtList = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'tif', 'tiff', 'apng', 'tga'];
|
||||
|
||||
styleDef.push([imageStyle, imageExtList]);
|
||||
|
||||
|
||||
@@ -1,11 +1,26 @@
|
||||
import { DialogButton, Focusable, SteamSpinner, TextField } from 'decky-frontend-lib';
|
||||
import { useEffect } from 'react';
|
||||
import { FunctionComponent, useState } from 'react';
|
||||
import {
|
||||
ControlsList,
|
||||
DialogBody,
|
||||
DialogButton,
|
||||
DialogControlsSection,
|
||||
DialogFooter,
|
||||
Dropdown,
|
||||
Focusable,
|
||||
Marquee,
|
||||
SteamSpinner,
|
||||
TextField,
|
||||
ToggleField,
|
||||
} from 'decky-frontend-lib';
|
||||
import { filesize } from 'filesize';
|
||||
import { FunctionComponent, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { FileIcon, defaultStyles } from 'react-file-icon';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaArrowUp, FaFolder } from 'react-icons/fa';
|
||||
|
||||
import Logger from '../../../logger';
|
||||
import DropdownMultiselect from '../DropdownMultiselect';
|
||||
import FilePickerError, { FileErrorTypes } from './FilePickerError';
|
||||
import TSortOption, { SortOptions } from './i18n/TSortOptions';
|
||||
import { styleDefObj } from './iconCustomizations';
|
||||
|
||||
const logger = new Logger('FilePicker');
|
||||
@@ -13,27 +28,89 @@ const logger = new Logger('FilePicker');
|
||||
export interface FilePickerProps {
|
||||
startPath: string;
|
||||
includeFiles?: boolean;
|
||||
regex?: RegExp;
|
||||
includeFolders?: boolean;
|
||||
filter?: RegExp | ((file: File) => boolean);
|
||||
validFileExtensions?: string[];
|
||||
allowAllFiles?: boolean;
|
||||
defaultHidden?: boolean;
|
||||
max?: number;
|
||||
onSubmit: (val: { path: string; realpath: string }) => void;
|
||||
closeModal?: () => void;
|
||||
}
|
||||
|
||||
interface File {
|
||||
export interface File {
|
||||
isdir: boolean;
|
||||
ishidden: boolean;
|
||||
name: string;
|
||||
realpath: string;
|
||||
size: number;
|
||||
modified: number;
|
||||
created: number;
|
||||
}
|
||||
|
||||
interface FileListing {
|
||||
realpath: string;
|
||||
files: File[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
const sortOptions = [
|
||||
{
|
||||
data: SortOptions.name_desc,
|
||||
label: <TSortOption trans_part={SortOptions.name_desc} />,
|
||||
},
|
||||
{
|
||||
data: SortOptions.name_asc,
|
||||
label: <TSortOption trans_part={SortOptions.name_asc} />,
|
||||
},
|
||||
{
|
||||
data: SortOptions.modified_desc,
|
||||
label: <TSortOption trans_part={SortOptions.modified_desc} />,
|
||||
},
|
||||
{
|
||||
data: SortOptions.modified_asc,
|
||||
label: <TSortOption trans_part={SortOptions.modified_asc} />,
|
||||
},
|
||||
{
|
||||
data: SortOptions.created_desc,
|
||||
label: <TSortOption trans_part={SortOptions.created_desc} />,
|
||||
},
|
||||
{
|
||||
data: SortOptions.created_asc,
|
||||
label: <TSortOption trans_part={SortOptions.created_asc} />,
|
||||
},
|
||||
{
|
||||
data: SortOptions.size_desc,
|
||||
label: <TSortOption trans_part={SortOptions.size_desc} />,
|
||||
},
|
||||
{
|
||||
data: SortOptions.size_asc,
|
||||
label: <TSortOption trans_part={SortOptions.size_asc} />,
|
||||
},
|
||||
];
|
||||
|
||||
function getList(
|
||||
path: string,
|
||||
includeFiles: boolean = true,
|
||||
includeFiles: boolean,
|
||||
includeFolders: boolean = true,
|
||||
includeExt: string[] | null = null,
|
||||
includeHidden: boolean = false,
|
||||
orderBy: SortOptions = SortOptions.name_desc,
|
||||
filterFor: RegExp | ((file: File) => boolean) | null = null,
|
||||
pageNumber: number = 1,
|
||||
max: number = 1000,
|
||||
): Promise<{ result: FileListing | string; success: boolean }> {
|
||||
return window.DeckyPluginLoader.callServerMethod('filepicker_ls', { path, include_files: includeFiles });
|
||||
return window.DeckyPluginLoader.callServerMethod('filepicker_ls', {
|
||||
path,
|
||||
include_files: includeFiles,
|
||||
include_folders: includeFolders,
|
||||
include_ext: includeExt ? includeExt : [],
|
||||
include_hidden: includeHidden,
|
||||
order_by: orderBy,
|
||||
filter_for: filterFor,
|
||||
page: pageNumber,
|
||||
max: max,
|
||||
});
|
||||
}
|
||||
|
||||
const iconStyles = {
|
||||
@@ -44,126 +121,240 @@ const iconStyles = {
|
||||
const FilePicker: FunctionComponent<FilePickerProps> = ({
|
||||
startPath,
|
||||
includeFiles = true,
|
||||
regex,
|
||||
filter = undefined,
|
||||
includeFolders = true,
|
||||
validFileExtensions = undefined,
|
||||
allowAllFiles = true,
|
||||
defaultHidden = false, // false by default makes sense for most users
|
||||
max = 1000,
|
||||
onSubmit,
|
||||
closeModal,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
if (startPath.endsWith('/')) startPath = startPath.substring(0, startPath.length - 1); // remove trailing path
|
||||
|
||||
if (startPath !== '/' && startPath.endsWith('/')) startPath = startPath.substring(0, startPath.length - 1); // remove trailing path
|
||||
const [path, setPath] = useState<string>(startPath);
|
||||
const [listing, setListing] = useState<FileListing>({ files: [], realpath: path });
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [listing, setListing] = useState<FileListing>({ files: [], realpath: path, total: 0 });
|
||||
const [files, setFiles] = useState<File[]>([]);
|
||||
const [error, setError] = useState<FileErrorTypes>(FileErrorTypes.None);
|
||||
const [rawError, setRawError] = useState<string | null>(null);
|
||||
const [page, setPage] = useState<number>(1);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [showHidden, setShowHidden] = useState<boolean>(defaultHidden);
|
||||
const [sort, setSort] = useState<SortOptions>(SortOptions.name_desc);
|
||||
const [selectedExts, setSelectedExts] = useState<string[] | undefined>(validFileExtensions);
|
||||
|
||||
const validExtsOptions = useMemo(() => {
|
||||
let validExt: { label: string; value: string }[] = [];
|
||||
if (validFileExtensions) {
|
||||
if (allowAllFiles) {
|
||||
validExt.push({ label: t('FilePickerIndex.files.all_files'), value: 'all_files' });
|
||||
}
|
||||
validExt.push(...validFileExtensions.map((x) => ({ label: x, value: x })));
|
||||
}
|
||||
return validExt;
|
||||
}, [validFileExtensions, allowAllFiles]);
|
||||
|
||||
function isSelectionValid(validExts: string[], selection: string[]) {
|
||||
if (validExts.some((el) => selection.includes(el))) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const handleExtsSelect = useCallback((val: any) => {
|
||||
// unselect other options if "All Files" is checked
|
||||
if (allowAllFiles && val.includes('all_files')) {
|
||||
setSelectedExts(['all_files']);
|
||||
} else if (validFileExtensions && isSelectionValid(validFileExtensions, val)) {
|
||||
// If at least one extension is still selected, then assign this selection to the selected values
|
||||
setSelectedExts(val);
|
||||
} else {
|
||||
// Else do nothing
|
||||
setSelectedExts(selectedExts);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (error) setError(null);
|
||||
setLoading(true);
|
||||
const listing = await getList(path, includeFiles);
|
||||
const listing = await getList(
|
||||
path,
|
||||
includeFiles,
|
||||
includeFolders,
|
||||
selectedExts,
|
||||
showHidden,
|
||||
sort,
|
||||
filter,
|
||||
page,
|
||||
max,
|
||||
);
|
||||
if (!listing.success) {
|
||||
setListing({ files: [], realpath: path });
|
||||
setListing({ files: [], realpath: path, total: 0 });
|
||||
setLoading(false);
|
||||
setError(listing.result as string);
|
||||
logger.error(listing.result);
|
||||
const theError = listing.result as string;
|
||||
switch (theError) {
|
||||
case theError.match(/\[Errno\s2.*/i)?.input:
|
||||
case theError.match(/\[WinError\s3.*/i)?.input:
|
||||
setError(FileErrorTypes.FileNotFound);
|
||||
break;
|
||||
default:
|
||||
setRawError(theError);
|
||||
setError(FileErrorTypes.Unknown);
|
||||
break;
|
||||
}
|
||||
logger.debug(theError);
|
||||
return;
|
||||
} else {
|
||||
setRawError(null);
|
||||
setError(FileErrorTypes.None);
|
||||
setFiles((listing.result as FileListing).files);
|
||||
}
|
||||
setLoading(false);
|
||||
setListing(listing.result as FileListing);
|
||||
logger.log('reloaded', path, listing);
|
||||
})();
|
||||
}, [path]);
|
||||
}, [error, path, includeFiles, includeFolders, showHidden, sort, selectedExts, page]);
|
||||
|
||||
return (
|
||||
<div className="deckyFilePicker">
|
||||
<Focusable style={{ display: 'flex', flexDirection: 'row', paddingBottom: '10px' }}>
|
||||
<DialogButton
|
||||
style={{
|
||||
minWidth: 'unset',
|
||||
width: '40px',
|
||||
flexGrow: '0',
|
||||
borderRadius: 'unset',
|
||||
margin: '0',
|
||||
padding: '10px',
|
||||
}}
|
||||
onClick={() => {
|
||||
const newPathArr = path.split('/');
|
||||
newPathArr.pop();
|
||||
let newPath = newPathArr.join('/');
|
||||
if (newPath == '') newPath = '/';
|
||||
setPath(newPath);
|
||||
}}
|
||||
>
|
||||
<FaArrowUp />
|
||||
</DialogButton>
|
||||
<div style={{ flexGrow: '1', width: '100%' }}>
|
||||
<TextField
|
||||
value={path}
|
||||
onChange={(e) => {
|
||||
e.target.value && setPath(e.target.value);
|
||||
}}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
</Focusable>
|
||||
<Focusable style={{ display: 'flex', flexDirection: 'column', height: '60vh', overflow: 'scroll' }}>
|
||||
{loading && <SteamSpinner style={{ height: '100%' }} />}
|
||||
{!loading &&
|
||||
listing.files
|
||||
.filter((file) => (includeFiles || file.isdir) && (!regex || regex.test(file.name)))
|
||||
.map((file) => {
|
||||
let extension = file.realpath.split('.').pop() as string;
|
||||
return (
|
||||
<DialogButton
|
||||
style={{ borderRadius: 'unset', margin: '0', padding: '10px' }}
|
||||
onClick={() => {
|
||||
const fullPath = `${path}${path.endsWith('/') ? '' : '/'}${file.name}`;
|
||||
if (file.isdir) setPath(fullPath);
|
||||
else {
|
||||
onSubmit({ path: fullPath, realpath: file.realpath });
|
||||
closeModal?.();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'flex-start' }}>
|
||||
{file.isdir ? (
|
||||
<FaFolder style={iconStyles} />
|
||||
) : (
|
||||
<div style={iconStyles}>
|
||||
{file.realpath.includes('.') ? (
|
||||
<FileIcon {...defaultStyles[extension]} {...styleDefObj[extension]} extension={''} />
|
||||
) : (
|
||||
<FileIcon />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<span
|
||||
<>
|
||||
<DialogBody className="deckyFilePicker">
|
||||
<DialogControlsSection>
|
||||
<Focusable flow-children="right" style={{ display: 'flex', marginBottom: '1em' }}>
|
||||
<DialogButton
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
minWidth: 'unset',
|
||||
width: '40px',
|
||||
borderRadius: 'unset',
|
||||
margin: '0',
|
||||
padding: '10px',
|
||||
}}
|
||||
onClick={() => {
|
||||
const newPathArr = path.split('/');
|
||||
const lastPath = newPathArr.pop();
|
||||
//If I have a single / with spaces, pop the array twice
|
||||
if (lastPath?.match(/^\/\s*$/) != null) newPathArr.pop();
|
||||
let newPath = newPathArr.join('/');
|
||||
if (newPath == '') newPath = '/';
|
||||
setPath(newPath);
|
||||
}}
|
||||
>
|
||||
<FaArrowUp />
|
||||
</DialogButton>
|
||||
<div style={{ width: '100%' }}>
|
||||
<TextField
|
||||
value={path}
|
||||
onChange={(e) => {
|
||||
e.target.value && setPath(e.target.value);
|
||||
}}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
</Focusable>
|
||||
<ControlsList alignItems="center" spacing="standard">
|
||||
<ToggleField
|
||||
highlightOnFocus={false}
|
||||
label={t('FilePickerIndex.files.show_hidden')}
|
||||
bottomSeparator="none"
|
||||
checked={showHidden}
|
||||
onChange={() => setShowHidden((x) => !x)}
|
||||
/>
|
||||
<Dropdown rgOptions={sortOptions} selectedOption={sort} onChange={(x) => setSort(x.data)} />
|
||||
{validFileExtensions && (
|
||||
<DropdownMultiselect
|
||||
label={t('FilePickerIndex.files.file_type')}
|
||||
items={validExtsOptions}
|
||||
selected={selectedExts ? selectedExts : []}
|
||||
onSelect={handleExtsSelect}
|
||||
/>
|
||||
)}
|
||||
</ControlsList>
|
||||
</DialogControlsSection>
|
||||
<DialogControlsSection style={{ marginTop: '1em' }}>
|
||||
<Focusable
|
||||
style={{ display: 'flex', gap: '.25em', flexDirection: 'column', height: '60vh', overflow: 'scroll' }}
|
||||
>
|
||||
{loading && error === FileErrorTypes.None && <SteamSpinner style={{ height: '100%' }} />}
|
||||
{!loading &&
|
||||
error === FileErrorTypes.None &&
|
||||
files.map((file) => {
|
||||
const extension = file.realpath.split('.').pop() as string;
|
||||
return (
|
||||
<DialogButton
|
||||
key={`${file.realpath}${file.name}`}
|
||||
style={{ borderRadius: 'unset', margin: '0', padding: '10px' }}
|
||||
onClick={() => {
|
||||
const fullPath = `${path}${path.endsWith('/') ? '' : '/'}${file.name}`;
|
||||
if (file.isdir) setPath(fullPath);
|
||||
else {
|
||||
onSubmit({ path: fullPath, realpath: file.realpath });
|
||||
closeModal?.();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'flex-start' }}>
|
||||
{file.isdir ? (
|
||||
<FaFolder style={iconStyles} />
|
||||
) : (
|
||||
<div style={iconStyles}>
|
||||
{file.realpath.includes('.') ? (
|
||||
<FileIcon {...defaultStyles[extension]} {...styleDefObj[extension]} extension={''} />
|
||||
) : (
|
||||
<FileIcon />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<Marquee>{file.name}</Marquee>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
textOverflow: 'ellipsis',
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
opacity: 0.5,
|
||||
fontSize: '.6em',
|
||||
textAlign: 'left',
|
||||
lineHeight: 1,
|
||||
marginTop: '.5em',
|
||||
}}
|
||||
>
|
||||
{file.name}
|
||||
</span>
|
||||
</div>
|
||||
</DialogButton>
|
||||
);
|
||||
})}
|
||||
{error}
|
||||
</Focusable>
|
||||
{file.isdir ? t('FilePickerIndex.folder.label') : filesize(file.size, { standard: 'iec' })}
|
||||
<span style={{ marginLeft: 'auto' }}>{new Date(file.modified * 1000).toLocaleString()}</span>
|
||||
</div>
|
||||
</DialogButton>
|
||||
);
|
||||
})}
|
||||
{error !== FileErrorTypes.None && <FilePickerError error={error} rawError={rawError ? rawError : ''} />}
|
||||
</Focusable>
|
||||
</DialogControlsSection>
|
||||
</DialogBody>
|
||||
{!loading && !error && !includeFiles && (
|
||||
<DialogButton
|
||||
className="Primary"
|
||||
style={{ marginTop: '10px', alignSelf: 'flex-end' }}
|
||||
onClick={() => {
|
||||
onSubmit({ path, realpath: listing.realpath });
|
||||
closeModal?.();
|
||||
}}
|
||||
>
|
||||
{t('FilePickerIndex.folder.select')}
|
||||
</DialogButton>
|
||||
<DialogFooter>
|
||||
<DialogButton
|
||||
className="Primary"
|
||||
style={{ marginTop: '10px', alignSelf: 'flex-end' }}
|
||||
onClick={() => {
|
||||
onSubmit({ path, realpath: listing.realpath });
|
||||
closeModal?.();
|
||||
}}
|
||||
>
|
||||
{t('FilePickerIndex.folder.select')}
|
||||
</DialogButton>
|
||||
</DialogFooter>
|
||||
)}
|
||||
</div>
|
||||
{page * max < listing.total && (
|
||||
<DialogFooter>
|
||||
<DialogButton
|
||||
className="Primary"
|
||||
style={{ marginTop: '10px', alignSelf: 'flex-end' }}
|
||||
onClick={() => {
|
||||
setPage(page + 1);
|
||||
}}
|
||||
>
|
||||
{t('FilePickerIndex.folder.show_more')}
|
||||
</DialogButton>
|
||||
</DialogFooter>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -13,26 +13,24 @@ import { useTranslation } from 'react-i18next';
|
||||
import { FaFileArchive, FaLink, FaReact, FaSteamSymbol, FaTerminal } from 'react-icons/fa';
|
||||
|
||||
import { setShouldConnectToReactDevTools, setShowValveInternal } from '../../../../developer';
|
||||
import Logger from '../../../../logger';
|
||||
import { installFromURL } from '../../../../store';
|
||||
import { useSetting } from '../../../../utils/hooks/useSetting';
|
||||
import { getSetting } from '../../../../utils/settings';
|
||||
import RemoteDebuggingSettings from '../general/RemoteDebugging';
|
||||
|
||||
const installFromZip = () => {
|
||||
window.DeckyPluginLoader.openFilePicker('/home/deck', true).then((val) => {
|
||||
const logger = new Logger('DeveloperIndex');
|
||||
|
||||
const installFromZip = async () => {
|
||||
const path = await getSetting<string>('user_info.user_home', '');
|
||||
if (path === '') {
|
||||
logger.error('The default path has not been found!');
|
||||
return;
|
||||
}
|
||||
window.DeckyPluginLoader.openFilePicker(path, true, undefined, true, ['zip', 'rar'], false, true).then((val) => {
|
||||
const url = `file://${val.path}`;
|
||||
console.log(`Installing plugin locally from ${url}`);
|
||||
|
||||
if (url.endsWith('.zip')) {
|
||||
installFromURL(url);
|
||||
} else {
|
||||
window.DeckyPluginLoader.toaster.toast({
|
||||
//title: t('SettingsDeveloperIndex.toast_zip.title'),
|
||||
title: 'Decky',
|
||||
//body: t('SettingsDeveloperIndex.toast_zip.body'),
|
||||
body: 'Installation failed! Only ZIP files are supported.',
|
||||
onClick: installFromZip,
|
||||
});
|
||||
}
|
||||
installFromURL(url);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { findModuleChild, sleep } from 'decky-frontend-lib';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaReact } from 'react-icons/fa';
|
||||
|
||||
import Logger from './logger';
|
||||
|
||||
@@ -12,8 +12,9 @@ import {
|
||||
import { FC, lazy } from 'react';
|
||||
import { FaExclamationCircle, FaPlug } from 'react-icons/fa';
|
||||
|
||||
import { DeckyState, DeckyStateContextProvider, useDeckyState } from './components/DeckyState';
|
||||
import { DeckyState, DeckyStateContextProvider, UserInfo, useDeckyState } from './components/DeckyState';
|
||||
import LegacyPlugin from './components/LegacyPlugin';
|
||||
import { File } from './components/modals/filepicker';
|
||||
import { deinitFilepickerPatches, initFilepickerPatches } from './components/modals/filepicker/patches';
|
||||
import MultiplePluginsInstallModal from './components/modals/MultiplePluginsInstallModal';
|
||||
import PluginInstallModal from './components/modals/PluginInstallModal';
|
||||
@@ -31,7 +32,7 @@ import TabsHook from './tabs-hook';
|
||||
import OldTabsHook from './tabs-hook.old';
|
||||
import Toaster from './toaster';
|
||||
import { VerInfo, callUpdaterMethod } from './updater';
|
||||
import { getSetting } from './utils/settings';
|
||||
import { getSetting, setSetting } from './utils/settings';
|
||||
import TranslationHelper, { TranslationClass } from './utils/TranslationHelper';
|
||||
|
||||
const StorePage = lazy(() => import('./components/store/Store'));
|
||||
@@ -99,9 +100,17 @@ class PluginLoader extends Logger {
|
||||
|
||||
initFilepickerPatches();
|
||||
|
||||
this.getUserInfo();
|
||||
|
||||
this.updateVersion();
|
||||
}
|
||||
|
||||
public async getUserInfo() {
|
||||
const userInfo = (await this.callServerMethod('get_user_info')).result as UserInfo;
|
||||
setSetting('user_info.user_name', userInfo.username);
|
||||
setSetting('user_info.user_home', userInfo.path);
|
||||
}
|
||||
|
||||
public async updateVersion() {
|
||||
const versionInfo = (await callUpdaterMethod('get_version')).result as VerInfo;
|
||||
this.deckyState.setVersionInfo(versionInfo);
|
||||
@@ -268,6 +277,7 @@ class PluginLoader extends Logger {
|
||||
Authentication: window.deckyAuthToken,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
try {
|
||||
let plugin_export = await eval(await res.text());
|
||||
@@ -352,7 +362,12 @@ class PluginLoader extends Logger {
|
||||
openFilePicker(
|
||||
startPath: string,
|
||||
includeFiles?: boolean,
|
||||
regex?: RegExp,
|
||||
filter?: RegExp | ((file: File) => boolean),
|
||||
includeFolders?: boolean,
|
||||
extensions?: string[],
|
||||
showHiddenFiles?: boolean,
|
||||
allowAllFiles?: boolean,
|
||||
max?: number,
|
||||
): Promise<{ path: string; realpath: string }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const Content = ({ closeModal }: { closeModal?: () => void }) => (
|
||||
@@ -367,9 +382,14 @@ class PluginLoader extends Logger {
|
||||
<FilePicker
|
||||
startPath={startPath}
|
||||
includeFiles={includeFiles}
|
||||
regex={regex}
|
||||
includeFolders={includeFolders}
|
||||
filter={filter}
|
||||
validFileExtensions={extensions}
|
||||
allowAllFiles={allowAllFiles}
|
||||
defaultHidden={showHiddenFiles}
|
||||
onSubmit={resolve}
|
||||
closeModal={closeModal}
|
||||
max={max}
|
||||
/>
|
||||
</WithSuspense>
|
||||
</ModalRoot>
|
||||
|
||||
@@ -128,7 +128,13 @@ class TabsHook extends Logger {
|
||||
let deckyTabAmount = existingTabs.reduce((prev: any, cur: any) => (cur.decky ? prev + 1 : prev), 0);
|
||||
if (deckyTabAmount == this.tabs.length) {
|
||||
for (let tab of existingTabs) {
|
||||
if (tab?.decky && tab?.qAMVisibilitySetter) tab?.qAMVisibilitySetter(visible);
|
||||
if (tab?.decky) {
|
||||
if (tab?.qAMVisibilitySetter) {
|
||||
tab?.qAMVisibilitySetter(visible);
|
||||
} else {
|
||||
tab.initialVisibility = visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -138,12 +144,9 @@ class TabsHook extends Logger {
|
||||
title,
|
||||
tab: icon,
|
||||
decky: true,
|
||||
initialVisibility: visible,
|
||||
};
|
||||
tab.panel = (
|
||||
<QuickAccessVisibleStateProvider initial={visible} tab={tab}>
|
||||
{content}
|
||||
</QuickAccessVisibleStateProvider>
|
||||
);
|
||||
tab.panel = <QuickAccessVisibleStateProvider tab={tab}>{content}</QuickAccessVisibleStateProvider>;
|
||||
existingTabs.push(tab);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user