Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions frontend/components/ExtensionBar/ExtensionContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React, { JSX } from 'react';
import { createOptionsWindow } from '../../windowManagement';
import { Separator } from '../Separator';
import { useExtensionsBarStore } from '../stores/extensionsBarStore';
import { t } from '../../i18n';

function ExtensionContextMenu({ extension }: { readonly extension: Extension; }): JSX.Element {
const { setExtensionsOrder } = useExtensionsBarStore();
Expand All @@ -29,11 +30,11 @@ function ExtensionContextMenu({ extension }: { readonly extension: Extension; })
{extension.name}
</MenuItem>
<Separator />
{extension.options.hasOptions() && <MenuItem onClick={() => { createOptionsWindow(extension); }}>Options</MenuItem>}
<MenuItem onClick={() => { uninstallExtension(extension.id); }}>Remove extension</MenuItem>
<MenuItem onClick={unpin}>Unpin</MenuItem>
{extension.options.hasOptions() && <MenuItem onClick={() => { createOptionsWindow(extension); }}>{t('options')}</MenuItem>}
<MenuItem onClick={() => { uninstallExtension(extension.id); }}>{t('removeExtension')}</MenuItem>
<MenuItem onClick={unpin}>{t('unpin')}</MenuItem>
<Separator />
<MenuItem onClick={() => { openExtensionManagerPopup(`info/${extension.id}`); }}>Manage</MenuItem>
<MenuItem onClick={() => { openExtensionManagerPopup(`info/${extension.id}`); }}>{t('manage')}</MenuItem>
</Menu>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { openExtensionManagerPopup } from 'extensions-manager/ExtensionManagerPo
import React from 'react';
import { FaCog } from 'react-icons/fa';
import { LuPin, LuPinOff } from 'react-icons/lu';
import { t } from '../../i18n';

export function ManagerExtensionItem({ extension, pinned, pinExtension, unpinExtension }:
{ readonly extension: Extension; readonly pinned: boolean; pinExtension(extensionId: string): void; unpinExtension(extensionId: string): void; }): React.JSX.Element {
Expand All @@ -22,10 +23,10 @@ export function ManagerExtensionItem({ extension, pinned, pinExtension, unpinExt
icon={<img width={16} height={16} src={extension.action.iconUrl} alt={extension.name} />}
padding="standard"
>
<DialogButton onClick={handlePin} style={{ padding: '0 8px' }} title={pinned ? 'Unpin' : 'Pin'}>
<DialogButton onClick={handlePin} style={{ padding: '0 8px' }} title={pinned ? t('unpin') : t('pin')}>
{pinned ? <LuPinOff color="lightblue" /> : <LuPin />}
</DialogButton>
<DialogButton onClick={() => { openExtensionManagerPopup(`info/${extension.id}`); }} style={{ padding: '0 8px' }} title="Manage">
<DialogButton onClick={() => { openExtensionManagerPopup(`info/${extension.id}`); }} style={{ padding: '0 8px' }} title={t('manage')}>
<FaCog />
</DialogButton>
</Field>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import React, { useMemo } from 'react';
import { FaCog } from 'react-icons/fa';
import { useExtensionsStore } from 'stores/extensionsStore';
import { useExtensionsBarStore } from '../stores/extensionsBarStore';
import { t } from '../../i18n';
import { ManagerExtensionItem } from './ManagerExtensionItem';

export function ToolbarManagerContextMenu(): React.JSX.Element {
Expand Down Expand Up @@ -35,8 +36,8 @@ export function ToolbarManagerContextMenu(): React.JSX.Element {
<>
<Styles />
<div className="extendium-toolbar-manager-context-menu">
<Menu label="Extension">
<DialogHeader>Extensions</DialogHeader>
<Menu label={t('extensions')}>
<DialogHeader>{t('extensions')}</DialogHeader>
{enabledExtensions
.sort((a, b) => a.name.localeCompare(b.name))
.map(extension => (
Expand All @@ -49,7 +50,7 @@ export function ToolbarManagerContextMenu(): React.JSX.Element {
/>
))}
<div style={{ cursor: 'pointer' }} onClick={() => { openExtensionManagerPopup(); }}>
<Field icon={<FaCog />} label="Manage extensions" />
<Field icon={<FaCog />} label={t('manageExtensions')} />
</div>
</Menu>
</div>
Expand Down
11 changes: 6 additions & 5 deletions frontend/extensionInitialization.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { BROKEN_EXTENSION_IDS, INTERNAL_HOME_PAGE_URL } from 'constant';
import React from 'react';
import { mainWindow } from 'shared';
import { useExtensionsStore } from 'stores/extensionsStore';
import { t } from './i18n';

export async function initializeExtension(): Promise<void> {
const { setExtension, removeExtension } = useExtensionsStore.getState();
Expand Down Expand Up @@ -58,23 +59,23 @@ export async function initializeExtension(): Promise<void> {
function showBrokenExtensionWarning(extensionId: string, extensionName: string): void {
const dialog = showModal(
<ConfirmModal
strTitle="Unsupported extension installed"
strTitle={t('unsupportedTitle')}
bAlertDialog
bDisableBackgroundDismiss
bHideCloseIcon
strDescription={(
<>
<p>
We've automatically detected an extension ({extensionName}:{extensionId}) that is known to cause Steam to become unresponsive, crash or become fully bricked.
{t('unsupportedDesc1').replace('{extensionName}', extensionName).replace('{extensionId}', extensionId)}
</p>
<strong>
You WILL NEED to remove this extension to prevent potential issues with your Steam client.
{t('unsupportedDesc2')}
<br />
You can find more information about compatible extensions on the Extendium github page.
{t('unsupportedDesc3')}
</strong>
</>
)}
strOKButtonText="Uninstall extension"
strOKButtonText={t('uninstallBtn')}
onOK={() => {
uninstallExtension(extensionId).then(() => {
dialog.Close();
Expand Down
37 changes: 27 additions & 10 deletions frontend/extensionInstallationFailedDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ConfirmModal, showModal } from '@steambrew/client';
import { IgnoreInternalExtensionRequirement, InstallInternalExtension } from 'callables';
import React from 'react';
import { mainWindow } from 'shared';
import { t } from './i18n';

function openInExternalBrowser(event: React.MouseEvent<HTMLAnchorElement>): void {
event.preventDefault();
Expand All @@ -10,30 +11,46 @@ function openInExternalBrowser(event: React.MouseEvent<HTMLAnchorElement>): void
}

export function showExtensionInstallationFailedDialog(): void {
const readmeParts = t('failedDesc3').split('{readmeLink}');
const githubParts = t('failedDesc4').split('{githubLink}');
const firstPart = githubParts[0];
const rest = githubParts[1] ?? '';
const discordParts = rest.split('{discordLink}');

const dialog = showModal(
<ConfirmModal
strTitle="Extendium installation failed"
strTitle={t('failedTitle')}
strDescription={(
<>
<p>
Extendium needs a helper extension to work fully, but the automatic installation didn't complete successfully.
{t('failedDesc1')}
</p>
<p>
Without the helper extension, some extensions like Augmented Steam won't work properly.
{t('failedDesc2')}
</p>
<p>
You can try the automatic installation again, or manually install the helper extension
by following the step-by-step instructions in the readme <a href="https://github.com/BossSloth/extendium/blob/main/README.md#helper-extension" onClick={openInExternalBrowser}>here</a>.
{readmeParts[0]}
<a href="https://github.com/BossSloth/extendium/blob/main/README.md#helper-extension" onClick={openInExternalBrowser}>
{t('here')}
</a>
{readmeParts[1]}
</p>
<p>
If the problem persists, please check the plugin logs for more details and report this issue
on the <a href="https://github.com/BossSloth/extendium" onClick={openInExternalBrowser}>Extendium GitHub repository</a> or the <a href="https://discord.com/channels/1102739071085846623/1380854735183282309" onClick={openInExternalBrowser}>discord channel</a> with your log.
{firstPart}
<a href="https://github.com/BossSloth/extendium" onClick={openInExternalBrowser}>
{t('githubRepo')}
</a>
{discordParts[0]}
<a href="https://discord.com/channels/1102739071085846623/1380854735183282309" onClick={openInExternalBrowser}>
{t('discordChannel')}
</a>
{discordParts[1]}
</p>
</>
)}
strOKButtonText="Try installation again"
strMiddleButtonText="Ignore and don't show again"
strCancelButtonText="Understood, I will manually install it"
strOKButtonText={t('tryAgain')}
strMiddleButtonText={t('ignoreBtn')}
strCancelButtonText={t('understoodBtn')}
bDisableBackgroundDismiss
bHideCloseIcon
onOK={async () => {
Expand Down
27 changes: 18 additions & 9 deletions frontend/extensions-manager/ExtensionDetailInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { FaExclamationCircle } from 'react-icons/fa';
import { MdArrowBack, MdArrowForward, MdOpenInNew } from 'react-icons/md';
import { mainWindow } from 'shared';
import { createOptionsWindow } from 'windowManagement';
import { t } from '../i18n';

export function ExtensionDetailInfo({ extension }: { readonly extension: Extension | undefined; }): React.ReactNode {
const [views, setViews] = React.useState<Protocol.Target.TargetInfo[]>([]);
Expand All @@ -20,7 +21,7 @@ export function ExtensionDetailInfo({ extension }: { readonly extension: Extensi
<button onClick={() => { setManagerPopup({ route: null }); }} type="button" className="md-button">
<MdArrowBack />
</button>
Error in extension
{t('errorInExtension')}
</div>
</div>
);
Expand Down Expand Up @@ -53,6 +54,10 @@ export function ExtensionDetailInfo({ extension }: { readonly extension: Extensi
}
}, []);

const errorInstructions = t('errorInstructions');
const devmodeText = t('enableDevModeText');
const parts = errorInstructions.split('{devmodeLink}');

return (
<div className="extension-detail-info">
<div className="page-header">
Expand All @@ -64,23 +69,23 @@ export function ExtensionDetailInfo({ extension }: { readonly extension: Extensi
</div>

<div className="section">
<div className="heading">Description</div>
<div className="heading">{t('description')}</div>
<div className="content">{extension.description}</div>
</div>

<div className="section hr">
<div className="heading">Version</div>
<div className="heading">{t('version')}</div>
<div className="content">{extension.version}</div>
</div>

<div className="section hr">
<div className="heading">Id</div>
<div className="heading">{t('id')}</div>
<div className="content">{extension.id}</div>
</div>

{views.length > 0 && (
<div className="section hr">
<div className="heading">Inspect views</div>
<div className="heading">{t('inspectViews')}</div>
<div className="content">
<ul>
{views.map(view => (
Expand All @@ -105,10 +110,14 @@ export function ExtensionDetailInfo({ extension }: { readonly extension: Extensi
<div className="section hr" id="errors">
<div className="heading">
<FaExclamationCircle color="red" />
Errors
{t('errors')}
</div>
<div className="content">
<span style={{ marginBottom: '1rem' }}>For detailed error information, <a href="steam://devmode/enable" onClick={() => { initializeViews(); }}>enable dev mode</a> and open the console of the specified view in the list above</span>
<span style={{ marginBottom: '1rem' }}>
{parts[0]}
<a href="steam://devmode/enable" onClick={() => { initializeViews(); }}>{devmodeText}</a>
{parts[1]}
</span>
<ul>
{extension.logger.errors.map(error => (
<li key={error}><code>{error}</code></li>
Expand All @@ -120,13 +129,13 @@ export function ExtensionDetailInfo({ extension }: { readonly extension: Extensi

{extension.options.hasOptions() && (
<div className="section hr clickable-row" onClick={() => { createOptionsWindow(extension); }}>
<span>Extension options</span>
<span>{t('extensionOptions')}</span>
<button type="button"><MdOpenInNew /></button>
</div>
)}

<div className="section hr clickable-row" onClick={() => { fullyUninstallExtension(); }}>
<span>Remove extension</span>
<span>{t('removeExtension')}</span>
<button type="button"><MdArrowForward /></button>
</div>
</div>
Expand Down
7 changes: 4 additions & 3 deletions frontend/extensions-manager/ExtensionManagerComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import React from 'react';
import { useExtensionsStore } from 'stores/extensionsStore';
import { getExtensionCompatibility, type CompatibilityStatus } from '../extensionCompatibility';
import { useSettingsStore } from '../extensions-manager/Settings/settingsStore';
import { t } from '../i18n';

export function ExtensionManagerComponent({ extension }: { readonly extension: Extension; }): React.ReactNode {
const { setManagerPopup } = usePopupsStore();
Expand Down Expand Up @@ -59,7 +60,7 @@ export function ExtensionManagerComponent({ extension }: { readonly extension: E
<span
className="compatibility-pill"
style={{ backgroundColor: getCompatibilityColor(compatibility) }}
title={`Compatibility: ${compatibility}, click for compatibility list`}
title={t('clickForCompList').replace('{compatibility}', compatibility)}
onClick={() => { SteamClient.System.OpenInSystemBrowser(COMPATIBILITY_LIST_URL); }}
>
{compatibility}
Expand All @@ -72,8 +73,8 @@ export function ExtensionManagerComponent({ extension }: { readonly extension: E
</div>
</div>
<div className="extension-buttons">
<DialogButton onClick={() => { setManagerPopup({ route: `info/${extension.id}` }); }}>Details</DialogButton>
<DialogButton onClick={() => { fullyUninstallExtension(); }}>Remove</DialogButton>
<DialogButton onClick={() => { setManagerPopup({ route: `info/${extension.id}` }); }}>{t('details')}</DialogButton>
<DialogButton onClick={() => { fullyUninstallExtension(); }}>{t('remove')}</DialogButton>
<Toggle onChange={handleToggleChange} value={extension.enabled} />
</div>
</div>
Expand Down
5 changes: 3 additions & 2 deletions frontend/extensions-manager/ExtensionManagerPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useExtensionsStore } from 'stores/extensionsStore';
import { ExtensionDetailInfo } from './ExtensionDetailInfo';
import { ExtensionManagerRoot } from './ExtensionManagerRoot';
import { ExtendiumSettings } from './Settings/ExtendiumSettings';
import { t } from '../i18n';

function ExtensionManagerPopup(): React.ReactNode {
const { managerPopup, setManagerPopup } = usePopupsStore();
Expand All @@ -27,12 +28,12 @@ function ExtensionManagerPopup(): React.ReactNode {
} else if (managerPopup.route.startsWith('settings')) {
content = <ExtendiumSettings />;
} else {
content = <p>Error you somehow got to an undefined route please report this with this route &quot;<code>{managerPopup.route}</code>&quot;</p>;
content = <p>{t('undefinedRoute').replace('{route}', managerPopup.route ?? '')}</p>;
}

return (
<SteamDialog
strTitle="Extensions"
strTitle={t('extensions')}
onDismiss={() => { setManagerPopup({ open: false }); }}
popupWidth={1280}
popupHeight={mainWindow.innerHeight * 0.65}
Expand Down
5 changes: 3 additions & 2 deletions frontend/extensions-manager/ExtensionManagerRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React from 'react';
import { FaCog, FaStore } from 'react-icons/fa';
import { IoExtensionPuzzle } from 'react-icons/io5';
import { useExtensionsStore } from 'stores/extensionsStore';
import { t } from '../i18n';
import { ExtensionManagerComponent } from './ExtensionManagerComponent';

export function ExtensionManagerRoot(): React.ReactNode {
Expand All @@ -20,14 +21,14 @@ export function ExtensionManagerRoot(): React.ReactNode {
className={`span-icon ${settingsClasses.SettingsDialogButton}`}
>
<FaStore />
Install extension
{t('installExtension')}
</DialogButton>
<DialogButton
onClick={() => { OpenTargetPage('chrome://extensions'); }}
className={`span-icon ${settingsClasses.SettingsDialogButton}`}
>
<IoExtensionPuzzle />
Advanced extension management
{t('advancedExtManagement')}
</DialogButton>
<div style={{ display: 'flex', gap: '6px' }}>
<DialogButton
Expand Down
Loading