mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-07-11 16:32:02 +00:00
Refactor languages and fix hooks logic bugs.
This commit is contained in:
@@ -2,8 +2,6 @@ import { ConfirmModal, Navigation, QuickAccessTab } from 'decky-frontend-lib';
|
||||
import { FC, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const { t } = useTranslation('PluginInstallModal');
|
||||
|
||||
interface PluginInstallModalProps {
|
||||
artifact: string;
|
||||
version: string;
|
||||
@@ -16,6 +14,7 @@ interface PluginInstallModalProps {
|
||||
|
||||
const PluginInstallModal: FC<PluginInstallModalProps> = ({ artifact, version, hash, onOK, onCancel, closeModal }) => {
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<ConfirmModal
|
||||
bOKDisabled={loading}
|
||||
@@ -29,13 +28,15 @@ const PluginInstallModal: FC<PluginInstallModalProps> = ({ artifact, version, ha
|
||||
onCancel={async () => {
|
||||
await onCancel();
|
||||
}}
|
||||
strTitle={t('install.title', artifact)}
|
||||
strOKButtonText={loading ? t('install.button_processing') : t('install.button_idle')}
|
||||
strTitle={t('PluginInstallModal.install.title', artifact)}
|
||||
strOKButtonText={
|
||||
loading ? t('PluginInstallModal.install.button_processing') : t('PluginInstallModal.install.button_idle')
|
||||
}
|
||||
>
|
||||
{hash == 'False' ? (
|
||||
<h3 style={{ color: 'red' }}>!!!!NO HASH PROVIDED!!!!</h3>
|
||||
) : (
|
||||
t('install.desc', artifact, version)
|
||||
t('PluginInstallModal.install.desc', artifact, version)
|
||||
)}
|
||||
</ConfirmModal>
|
||||
);
|
||||
|
||||
@@ -9,19 +9,18 @@ import PluginList from './pages/plugin_list';
|
||||
|
||||
const DeveloperSettings = lazy(() => import('./pages/developer'));
|
||||
|
||||
const { t } = useTranslation('SettingsIndex');
|
||||
|
||||
export default function SettingsPage() {
|
||||
const [isDeveloper, setIsDeveloper] = useSetting<boolean>('developer.enabled', false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const pages = [
|
||||
{
|
||||
title: t('general_title'),
|
||||
title: t('SettingsIndex.general_title'),
|
||||
content: <GeneralSettings isDeveloper={isDeveloper} setIsDeveloper={setIsDeveloper} />,
|
||||
route: '/decky/settings/general',
|
||||
},
|
||||
{
|
||||
title: t('plugins_title'),
|
||||
title: t('SettingsIndex.plugins_title'),
|
||||
content: <PluginList />,
|
||||
route: '/decky/settings/plugins',
|
||||
},
|
||||
@@ -29,7 +28,7 @@ export default function SettingsPage() {
|
||||
|
||||
if (isDeveloper)
|
||||
pages.push({
|
||||
title: t('developer_title'),
|
||||
title: t('SettingsIndex.developer_title'),
|
||||
content: (
|
||||
<WithSuspense>
|
||||
<DeveloperSettings />
|
||||
@@ -38,5 +37,5 @@ export default function SettingsPage() {
|
||||
route: '/decky/settings/developer',
|
||||
});
|
||||
|
||||
return <SidebarNavigation title={t('settings_navbar') as string} showTitle pages={pages} />;
|
||||
return <SidebarNavigation title={t('SettingsIndex.settings_navbar') as string} showTitle pages={pages} />;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { callUpdaterMethod } from '../../../../updater';
|
||||
import { useSetting } from '../../../../utils/hooks/useSetting';
|
||||
|
||||
const logger = new Logger('BranchSelect');
|
||||
const { t } = useTranslation('BranchSelect');
|
||||
|
||||
enum UpdateBranch {
|
||||
Stable,
|
||||
@@ -16,12 +15,13 @@ enum UpdateBranch {
|
||||
}
|
||||
|
||||
const BranchSelect: FunctionComponent<{}> = () => {
|
||||
const { t } = useTranslation();
|
||||
const [selectedBranch, setSelectedBranch] = useSetting<UpdateBranch>('branch', UpdateBranch.Prerelease);
|
||||
|
||||
return (
|
||||
// Returns numerical values from 0 to 2 (with current branch setup as of 8/28/22)
|
||||
// 0 being stable, 1 being pre-release and 2 being nightly
|
||||
<Field label={t('update_channel.label')}>
|
||||
<Field label={t('BranchSelect.update_channel.label')}>
|
||||
<Dropdown
|
||||
rgOptions={Object.values(UpdateBranch)
|
||||
.filter((branch) => typeof branch == 'string')
|
||||
|
||||
@@ -6,12 +6,12 @@ import { useSetting } from '../../../../utils/hooks/useSetting';
|
||||
|
||||
export default function RemoteDebuggingSettings() {
|
||||
const [allowRemoteDebugging, setAllowRemoteDebugging] = useSetting<boolean>('cef_forward', false);
|
||||
const { t } = useTranslation('RemoteDebugging');
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Field
|
||||
label={t('remote_cef.label')}
|
||||
description={<span style={{ whiteSpace: 'pre-line' }}>{t('remote_cef.desc')}</span>}
|
||||
label={t('RemoteDebugging.remote_cef.label')}
|
||||
description={<span style={{ whiteSpace: 'pre-line' }}>{t('RemoteDebugging.remote_cef.desc')}</span>}
|
||||
icon={<FaBug style={{ display: 'block' }} />}
|
||||
>
|
||||
<Toggle
|
||||
|
||||
@@ -8,17 +8,17 @@ import { Store } from '../../../../store';
|
||||
import { useSetting } from '../../../../utils/hooks/useSetting';
|
||||
|
||||
const logger = new Logger('StoreSelect');
|
||||
const { t } = useTranslation('StoreSelect');
|
||||
|
||||
const StoreSelect: FunctionComponent<{}> = () => {
|
||||
const [selectedStore, setSelectedStore] = useSetting<Store>('store', Store.Default);
|
||||
const [selectedStoreURL, setSelectedStoreURL] = useSetting<string | null>('store-url', null);
|
||||
const { t } = useTranslation();
|
||||
|
||||
// Returns numerical values from 0 to 2 (with current branch setup as of 8/28/22)
|
||||
// 0 being Default, 1 being Testing and 2 being Custom
|
||||
return (
|
||||
<>
|
||||
<Field label={t('store_channel_label')}>
|
||||
<Field label={t('StoreSelect.store_channel_label')}>
|
||||
<Dropdown
|
||||
rgOptions={Object.values(Store)
|
||||
.filter((store) => typeof store == 'string')
|
||||
@@ -35,7 +35,7 @@ const StoreSelect: FunctionComponent<{}> = () => {
|
||||
</Field>
|
||||
{selectedStore == Store.Custom && (
|
||||
<Field
|
||||
label={t('custom_store_label')}
|
||||
label={t('StoreSelect.custom_store_label')}
|
||||
indentLevel={1}
|
||||
description={
|
||||
<TextField
|
||||
|
||||
@@ -21,10 +21,10 @@ import InlinePatchNotes from '../../../patchnotes/InlinePatchNotes';
|
||||
import WithSuspense from '../../../WithSuspense';
|
||||
|
||||
const MarkdownRenderer = lazy(() => import('../../../Markdown'));
|
||||
const { t } = useTranslation('Updater');
|
||||
|
||||
function PatchNotesModal({ versionInfo, closeModal }: { versionInfo: VerInfo | null; closeModal?: () => {} }) {
|
||||
const SP = findSP();
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Focusable onCancelButton={closeModal}>
|
||||
<FocusRing>
|
||||
@@ -47,7 +47,7 @@ function PatchNotesModal({ versionInfo, closeModal }: { versionInfo: VerInfo | n
|
||||
<MarkdownRenderer onDismiss={closeModal}>{versionInfo.all[id].body}</MarkdownRenderer>
|
||||
</WithSuspense>
|
||||
) : (
|
||||
t('no_patch_notes_desc')
|
||||
t('Updater.no_patch_notes_desc')
|
||||
)}
|
||||
</div>
|
||||
</Focusable>
|
||||
@@ -60,7 +60,7 @@ function PatchNotesModal({ versionInfo, closeModal }: { versionInfo: VerInfo | n
|
||||
initialColumn={0}
|
||||
autoFocus={true}
|
||||
fnGetColumnWidth={() => SP.innerWidth}
|
||||
name={t('decky_updates') as string}
|
||||
name={t('Updater.decky_updates') as string}
|
||||
/>
|
||||
</FocusRing>
|
||||
</Focusable>
|
||||
@@ -74,6 +74,8 @@ export default function UpdaterSettings() {
|
||||
const [updateProgress, setUpdateProgress] = useState<number>(-1);
|
||||
const [reloading, setReloading] = useState<boolean>(false);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
window.DeckyUpdater = {
|
||||
updateProgress: (i) => {
|
||||
@@ -97,11 +99,13 @@ export default function UpdaterSettings() {
|
||||
<Field
|
||||
onOptionsActionDescription={versionInfo?.all ? 'Patch Notes' : undefined}
|
||||
onOptionsButton={versionInfo?.all ? showPatchNotes : undefined}
|
||||
label={t('updates.label')}
|
||||
label={t('Updater.updates.label')}
|
||||
description={
|
||||
versionInfo && (
|
||||
<span style={{ whiteSpace: 'pre-line' }}>{`${t('updates.cur_version', { ver: versionInfo.current })}\n${
|
||||
versionInfo.updatable ? t('updates.lat_version', { ver: versionInfo.remote?.tag_name }) : ''
|
||||
<span style={{ whiteSpace: 'pre-line' }}>{`${t('Updater.updates.cur_version', {
|
||||
ver: versionInfo.current,
|
||||
})}\n${
|
||||
versionInfo.updatable ? t('Updater.updates.lat_version', { ver: versionInfo.remote?.tag_name }) : ''
|
||||
}`}</span>
|
||||
)
|
||||
}
|
||||
@@ -131,10 +135,10 @@ export default function UpdaterSettings() {
|
||||
}
|
||||
>
|
||||
{checkingForUpdates
|
||||
? t('updates.checking')
|
||||
? t('Updater.updates.checking')
|
||||
: !versionInfo?.remote || versionInfo?.remote?.tag_name == versionInfo?.current
|
||||
? t('updates.check_button')
|
||||
: t('updates.install_button')}
|
||||
? t('Updater.updates.check_button')
|
||||
: t('Updater.updates.install_button')}
|
||||
</DialogButton>
|
||||
) : (
|
||||
<ProgressBarWithInfo
|
||||
@@ -142,7 +146,7 @@ export default function UpdaterSettings() {
|
||||
bottomSeparator="none"
|
||||
nProgress={updateProgress}
|
||||
indeterminate={reloading}
|
||||
sOperationText={reloading ? t('updates.reloading') : t('updates.updating')}
|
||||
sOperationText={reloading ? t('Updater.updates.reloading') : t('Updater.updates.updating')}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function GeneralSettings({
|
||||
setIsDeveloper: (val: boolean) => void;
|
||||
}) {
|
||||
const [pluginURL, setPluginURL] = useState('');
|
||||
const { t } = useTranslation('SettingsGeneralIndex');
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -26,8 +26,8 @@ export default function GeneralSettings({
|
||||
<StoreSelect />
|
||||
<RemoteDebuggingSettings />
|
||||
<Field
|
||||
label={t('developer_mode.label')}
|
||||
description={<span style={{ whiteSpace: 'pre-line' }}>{t('developer_mode.desc')}</span>}
|
||||
label={t('SettingsGeneralIndex.developer_mode.label')}
|
||||
description={<span style={{ whiteSpace: 'pre-line' }}>{t('SettingsGeneralIndex.developer_mode.desc')}</span>}
|
||||
icon={<FaTools style={{ display: 'block' }} />}
|
||||
>
|
||||
<Toggle
|
||||
@@ -38,12 +38,12 @@ export default function GeneralSettings({
|
||||
/>
|
||||
</Field>
|
||||
<Field
|
||||
label={t('manual_plugin.label')}
|
||||
label={t('SettingsGeneralIndex.manual_plugin.label')}
|
||||
description={<TextField label={'URL'} value={pluginURL} onChange={(e) => setPluginURL(e?.target.value)} />}
|
||||
icon={<FaShapes style={{ display: 'block' }} />}
|
||||
>
|
||||
<DialogButton disabled={pluginURL.length == 0} onClick={() => installFromURL(pluginURL)}>
|
||||
{t('manual_plugin.button')}
|
||||
{t('SettingsGeneralIndex.manual_plugin.button')}
|
||||
</DialogButton>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useDeckyState } from '../../../DeckyState';
|
||||
|
||||
export default function PluginList() {
|
||||
const { plugins, updates } = useDeckyState();
|
||||
const { t } = useTranslation('PluginListIndex');
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
window.DeckyPluginLoader.checkPluginUpdates();
|
||||
@@ -17,7 +17,7 @@ export default function PluginList() {
|
||||
if (plugins.length === 0) {
|
||||
return (
|
||||
<div>
|
||||
<p>{t('list_no_plugin')}</p>
|
||||
<p>{t('PluginListIndex.list_no_plugin')}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -38,7 +38,7 @@ export default function PluginList() {
|
||||
onClick={() => requestPluginInstall(name, update)}
|
||||
>
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
{t('list_update_to', update.name)}
|
||||
{t('PluginListIndex.list_update_to', update.name)}
|
||||
<FaDownload style={{ paddingLeft: '2rem' }} />
|
||||
</div>
|
||||
</DialogButton>
|
||||
@@ -47,12 +47,12 @@ export default function PluginList() {
|
||||
style={{ height: '40px', width: '40px', padding: '10px 12px', minWidth: '40px' }}
|
||||
onClick={(e: MouseEvent) =>
|
||||
showContextMenu(
|
||||
<Menu label={t('list_plug_actions_label')}>
|
||||
<Menu label={t('PluginListIndex.list_plug_actions_label')}>
|
||||
<MenuItem onSelected={() => window.DeckyPluginLoader.importPlugin(name, version)}>
|
||||
{t('reload')}
|
||||
{t('PluginListIndex.reload')}
|
||||
</MenuItem>
|
||||
<MenuItem onSelected={() => window.DeckyPluginLoader.uninstallPlugin(name)}>
|
||||
{t('uninstall')}
|
||||
{t('PluginListIndex.uninstall')}
|
||||
</MenuItem>
|
||||
</Menu>,
|
||||
e.currentTarget ?? window,
|
||||
|
||||
@@ -15,12 +15,12 @@ interface PluginCardProps {
|
||||
plugin: StorePlugin;
|
||||
}
|
||||
|
||||
const { t } = useTranslation('PluginCard');
|
||||
|
||||
const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
|
||||
const [selectedOption, setSelectedOption] = useState<number>(0);
|
||||
const root: boolean = plugin.tags.some((tag) => tag === 'root');
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div
|
||||
className="deckyStoreCard"
|
||||
@@ -100,7 +100,7 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
|
||||
plugin.description
|
||||
) : (
|
||||
<span>
|
||||
<i style={{ color: '#666' }}>{t('plugin_no_desc')}</i>
|
||||
<i style={{ color: '#666' }}>{t('PluginCard.plugin_no_desc')}</i>
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
@@ -112,7 +112,7 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
|
||||
color: '#fee75c',
|
||||
}}
|
||||
>
|
||||
<i>{t('plugin_full_access')}</i>{' '}
|
||||
<i>{t('PluginCard.plugin_full_access')}</i>{' '}
|
||||
<a
|
||||
className="deckyStoreCardDescriptionRootLink"
|
||||
href="https://deckbrew.xyz/root"
|
||||
@@ -149,7 +149,7 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
|
||||
layout="below"
|
||||
onClick={() => requestPluginInstall(plugin.name, plugin.versions[selectedOption])}
|
||||
>
|
||||
<span className="deckyStoreCardInstallText">{t('plugin_install')}</span>
|
||||
<span className="deckyStoreCardInstallText">{t('PluginCard.plugin_install')}</span>
|
||||
</ButtonItem>
|
||||
</div>
|
||||
<div
|
||||
@@ -166,7 +166,7 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
|
||||
label: version.name,
|
||||
})) as SingleDropdownOption[]
|
||||
}
|
||||
menuLabel={t('plugin_version_label') as string}
|
||||
menuLabel={t('PluginCard.plugin_version_label') as string}
|
||||
selectedOption={selectedOption}
|
||||
onChange={({ data }) => setSelectedOption(data)}
|
||||
/>
|
||||
|
||||
@@ -16,8 +16,6 @@ import Logger from '../../logger';
|
||||
import { StorePlugin, getPluginList } from '../../store';
|
||||
import PluginCard from './PluginCard';
|
||||
|
||||
const { t } = useTranslation('Store');
|
||||
|
||||
const logger = new Logger('FilePicker');
|
||||
|
||||
const StorePage: FC<{}> = () => {
|
||||
@@ -28,6 +26,8 @@ const StorePage: FC<{}> = () => {
|
||||
return false;
|
||||
});
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const res = await getPluginList();
|
||||
@@ -57,13 +57,13 @@ const StorePage: FC<{}> = () => {
|
||||
}}
|
||||
tabs={[
|
||||
{
|
||||
title: t('store_tabs_title'),
|
||||
title: t('Store.store_tabs.title'),
|
||||
content: <BrowseTab children={{ data: data }} />,
|
||||
id: 'browse',
|
||||
renderTabAddon: () => <span className={TabCount}>{data.length}</span>,
|
||||
},
|
||||
{
|
||||
title: t('store_tabs.about'),
|
||||
title: t('Store.store_tabs.about'),
|
||||
content: <AboutTab />,
|
||||
id: 'about',
|
||||
},
|
||||
@@ -76,10 +76,12 @@ const StorePage: FC<{}> = () => {
|
||||
};
|
||||
|
||||
const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const sortOptions = useMemo(
|
||||
(): DropdownOption[] => [
|
||||
{ data: 1, label: t('store_tabs.alph_desc') },
|
||||
{ data: 2, label: t('store_tabs.alph_asce') },
|
||||
{ data: 1, label: t('Store.store_tabs.alph_desc') },
|
||||
{ data: 2, label: t('Store.store_tabs.alph_asce') },
|
||||
],
|
||||
[],
|
||||
);
|
||||
@@ -108,11 +110,11 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
|
||||
width: '47.5%',
|
||||
}}
|
||||
>
|
||||
<span className="DialogLabel">{t("store_sort.label")}</span>
|
||||
<span className="DialogLabel">{t("Store.store_sort.label")}</span>
|
||||
<Dropdown
|
||||
menuLabel={t("store_sort.label") as string}
|
||||
menuLabel={t("Store.store_sort.label") as string}
|
||||
rgOptions={sortOptions}
|
||||
strDefaultLabel={t("store_sort.label_def") as string}
|
||||
strDefaultLabel={t("Store.store_sort.label_def") as string}
|
||||
selectedOption={selectedSort}
|
||||
onChange={(e) => setSort(e.data)}
|
||||
/>
|
||||
@@ -125,11 +127,11 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
|
||||
marginLeft: 'auto',
|
||||
}}
|
||||
>
|
||||
<span className="DialogLabel">{t("store_filter.label")}</span>
|
||||
<span className="DialogLabel">{t("Store.store_filter.label")}</span>
|
||||
<Dropdown
|
||||
menuLabel={t("store_filter.label")}
|
||||
menuLabel={t("Store.store_filter.label")}
|
||||
rgOptions={filterOptions}
|
||||
strDefaultLabel={t("store_filter.label_def")}
|
||||
strDefaultLabel={t("Store.store_filter.label_def")}
|
||||
selectedOption={selectedFilter}
|
||||
onChange={(e) => setFilter(e.data)}
|
||||
/>
|
||||
@@ -139,7 +141,7 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
|
||||
<div style={{ justifyContent: 'center', display: 'flex' }}>
|
||||
<Focusable style={{ display: 'flex', alignItems: 'center', width: '96%' }}>
|
||||
<div style={{ width: '100%' }}>
|
||||
<TextField label={t("store_search.label")} value={searchFieldValue} onChange={(e) => setSearchValue(e.target.value)} />
|
||||
<TextField label={t("Store.store_search.label")} value={searchFieldValue} onChange={(e) => setSearchValue(e.target.value)} />
|
||||
</div>
|
||||
</Focusable>
|
||||
</div>
|
||||
@@ -154,11 +156,11 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
|
||||
maxWidth: '100%',
|
||||
}}
|
||||
>
|
||||
<span className="DialogLabel">{t('store_sort.label')}</span>
|
||||
<span className="DialogLabel">{t('Store.store_sort.label')}</span>
|
||||
<Dropdown
|
||||
menuLabel={t('store_sort.label') as string}
|
||||
menuLabel={t('Store.store_sort.label') as string}
|
||||
rgOptions={sortOptions}
|
||||
strDefaultLabel={t('store_sort.label_def') as string}
|
||||
strDefaultLabel={t('Store.store_sort.label_def') as string}
|
||||
selectedOption={selectedSort}
|
||||
onChange={(e) => setSort(e.data)}
|
||||
/>
|
||||
@@ -169,7 +171,7 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
|
||||
<Focusable style={{ display: 'flex', alignItems: 'center', width: '96%' }}>
|
||||
<div style={{ width: '100%' }}>
|
||||
<TextField
|
||||
label={t('store_search.label')}
|
||||
label={t('Store.store_search.label')}
|
||||
value={searchFieldValue}
|
||||
onChange={(e) => setSearchValue(e.target.value)}
|
||||
/>
|
||||
@@ -199,6 +201,8 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
|
||||
};
|
||||
|
||||
const AboutTab: FC<{}> = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -223,7 +227,7 @@ const AboutTab: FC<{}> = () => {
|
||||
/>
|
||||
<span className="deckyStoreAboutHeader">Testing</span>
|
||||
<span>
|
||||
{t('store_testing_cta')}{' '}
|
||||
{t('Store.store_testing_cta')}{' '}
|
||||
<a
|
||||
href="https://deckbrew.xyz/testing"
|
||||
target="_blank"
|
||||
@@ -234,10 +238,10 @@ const AboutTab: FC<{}> = () => {
|
||||
deckbrew.xyz/testing
|
||||
</a>
|
||||
</span>
|
||||
<span className="deckyStoreAboutHeader">{t('store_contrib.label')}</span>
|
||||
<span>{t('store_contrib.desc')}</span>
|
||||
<span className="deckyStoreAboutHeader">{t('store_source.label')}</span>
|
||||
<span>{t('store_source.desc')}</span>
|
||||
<span className="deckyStoreAboutHeader">{t('Store.store_contrib.label')}</span>
|
||||
<span>{t('Store.store_contrib.desc')}</span>
|
||||
<span className="deckyStoreAboutHeader">{t('Store.store_source.label')}</span>
|
||||
<span>{t('Store.store_source.desc')}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
staticClasses,
|
||||
updaterFieldClasses,
|
||||
} from 'decky-frontend-lib';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaReact } from 'react-icons/fa';
|
||||
|
||||
import Logger from './logger';
|
||||
@@ -58,9 +59,11 @@ export async function setShowValveInternal(show: boolean) {
|
||||
}
|
||||
|
||||
export async function setShouldConnectToReactDevTools(enable: boolean) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
window.DeckyPluginLoader.toaster.toast({
|
||||
title: (enable ? 'Enabling' : 'Disabling') + ' React DevTools',
|
||||
body: 'Reloading in 5 seconds',
|
||||
title: (enable ? t('Developer.enabling') : t('Developer.disabling')) + ' React DevTools',
|
||||
body: t('Developer.5secreload'),
|
||||
icon: <FaReact />,
|
||||
});
|
||||
await sleep(5000);
|
||||
|
||||
+10
-2
@@ -11,12 +11,20 @@ i18n
|
||||
load: 'languageOnly',
|
||||
debug: true,
|
||||
fallbackLng: 'en',
|
||||
lng: 'en',
|
||||
lng: 'it',
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
backend: {
|
||||
loadPath: 'http://127.0.0.1:1337/locales/{{lng}}/{{ns}}.json',
|
||||
loadPath: 'http://127.0.0.1:1337/locales/{{lng}}.json',
|
||||
requestOptions: {
|
||||
// used for fetch
|
||||
credentials: 'include',
|
||||
cache: 'no-cache',
|
||||
},
|
||||
customHeaders: {
|
||||
Authentication: window.deckyAuthToken,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@ const SettingsPage = lazy(() => import('./components/settings'));
|
||||
|
||||
const FilePicker = lazy(() => import('./components/modals/filepicker'));
|
||||
|
||||
const { t } = useTranslation('plugin-loader');
|
||||
|
||||
declare global {
|
||||
interface Window {}
|
||||
}
|
||||
@@ -103,10 +101,11 @@ class PluginLoader extends Logger {
|
||||
|
||||
public async notifyUpdates() {
|
||||
const versionInfo = await this.updateVersion();
|
||||
const { t } = useTranslation('PluginLoader');
|
||||
if (versionInfo?.remote && versionInfo?.remote?.tag_name != versionInfo?.current) {
|
||||
this.toaster.toast({
|
||||
title: 'Decky',
|
||||
body: t('decky_update_available', versionInfo?.remote?.tag_name),
|
||||
body: t('PluginLoader.decky_update_available', versionInfo?.remote?.tag_name),
|
||||
onClick: () => Router.Navigate('/decky/settings'),
|
||||
});
|
||||
this.deckyState.setHasLoaderUpdate(true);
|
||||
@@ -123,11 +122,12 @@ class PluginLoader extends Logger {
|
||||
|
||||
public async notifyPluginUpdates() {
|
||||
const updates = await this.checkPluginUpdates();
|
||||
const { t } = useTranslation();
|
||||
if (updates?.size > 0) {
|
||||
this.toaster.toast({
|
||||
title: 'Decky',
|
||||
//body: `Updates available for ${updates.size} plugin${updates.size > 1 ? 's' : ''}!`,
|
||||
body: t('plugin_update', updates.size.toString(10), { count: updates.size }),
|
||||
body: t('PluginLoader.plugin_update', updates.size.toString(10), { count: updates.size }),
|
||||
onClick: () => Router.Navigate('/decky/settings/plugins'),
|
||||
});
|
||||
}
|
||||
@@ -146,6 +146,7 @@ class PluginLoader extends Logger {
|
||||
}
|
||||
|
||||
public uninstallPlugin(name: string) {
|
||||
const { t } = useTranslation();
|
||||
showModal(
|
||||
<ConfirmModal
|
||||
onOK={async () => {
|
||||
@@ -154,10 +155,10 @@ class PluginLoader extends Logger {
|
||||
onCancel={() => {
|
||||
// do nothing
|
||||
}}
|
||||
strTitle={t('plugin_uninstall_title', name)}
|
||||
strOKButtonText={t('plugin_uninstall_button')}
|
||||
strTitle={t('PluginLoader.plugin_uninstall.title', name)}
|
||||
strOKButtonText={t('PluginLoader.plugin_uninstall.button')}
|
||||
>
|
||||
{t('plugin_uninstall_desc', name)}
|
||||
{t('PluginLoader.plugin_uninstall.desc', name)}
|
||||
</ConfirmModal>,
|
||||
);
|
||||
}
|
||||
@@ -233,6 +234,9 @@ class PluginLoader extends Logger {
|
||||
Authentication: window.deckyAuthToken,
|
||||
},
|
||||
});
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (res.ok) {
|
||||
try {
|
||||
let plugin_export = await eval(await res.text());
|
||||
@@ -243,14 +247,14 @@ class PluginLoader extends Logger {
|
||||
version: version,
|
||||
});
|
||||
} catch (e) {
|
||||
this.error(t('plugin_load_error', name), e);
|
||||
this.error(t('PluginLoader.plugin_load_error', name), e);
|
||||
const TheError: FC<{}> = () => (
|
||||
<>
|
||||
{t('error')}:{' '}
|
||||
<pre>
|
||||
<code>{e instanceof Error ? e.stack : JSON.stringify(e)}</code>
|
||||
</pre>
|
||||
<>{t('plugin_error_uninstall', <FaCog style={{ display: 'inline' }} />)}</>
|
||||
<>{t('PluginLoader.plugin_error_uninstall', <FaCog style={{ display: 'inline' }} />)}</>
|
||||
</>
|
||||
);
|
||||
this.plugins.push({
|
||||
@@ -260,7 +264,7 @@ class PluginLoader extends Logger {
|
||||
icon: <FaExclamationCircle />,
|
||||
});
|
||||
this.toaster.toast({
|
||||
title: t('error_loading_plugin_toast', name),
|
||||
title: t('PluginLoader.error_loading_plugin.toast', name),
|
||||
body: '' + e,
|
||||
icon: <FaExclamationCircle />,
|
||||
});
|
||||
@@ -296,12 +300,14 @@ class PluginLoader extends Logger {
|
||||
includeFiles?: boolean,
|
||||
regex?: RegExp,
|
||||
): Promise<{ path: string; realpath: string }> {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const Content = ({ closeModal }: { closeModal?: () => void }) => (
|
||||
// Purposely outside of the FilePicker component as lazy-loaded ModalRoots don't focus correctly
|
||||
<ModalRoot
|
||||
onCancel={() => {
|
||||
reject(t('file_picker_cancel_text'));
|
||||
reject(t('PluginLoader.file_picker_cancel_text'));
|
||||
closeModal?.();
|
||||
}}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user