mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 01:23:52 +00:00
move useI18n to i18n.ts
Since we are using the react-i18n babel loader plugin, useI18n can only be used once per file. Also we have to remember to add the istanbul ignore next comment each time we use it. By moving this to a common file, it can be easily copied and pasted when a new submodule is created and we don't have to remember the rules when calling it.
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
|
||||
import { AnchorButton, Button, Classes, Dialog } from '@blueprintjs/core';
|
||||
import { firmwareVersion } from '@pybricks/firmware';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
appName,
|
||||
@@ -17,7 +16,7 @@ import {
|
||||
} from '../app/constants';
|
||||
import LicenseDialog from '../licenses/LicenseDialog';
|
||||
import ExternalLinkIcon from '../utils/ExternalLinkIcon';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
import './about.scss';
|
||||
|
||||
@@ -29,8 +28,7 @@ const AboutDialog: React.VoidFunctionComponent<AboutDialogProps> = ({
|
||||
}) => {
|
||||
const [isLicenseDialogOpen, setIsLicenseDialogOpen] = useState(false);
|
||||
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
|
||||
// About dialog translation keys.
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Title = 'title',
|
||||
Description = 'description',
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
|
||||
import './activities.scss';
|
||||
import { Icon, Tab, Tabs } from '@blueprintjs/core';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import { useLocalStorage } from 'usehooks-ts';
|
||||
import Explorer from '../explorer/Explorer';
|
||||
import Settings from '../settings/Settings';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
/** Indicates the selected activity. */
|
||||
export enum Activity {
|
||||
@@ -24,8 +23,7 @@ export enum Activity {
|
||||
* React component that acts as a tab control to select activities.
|
||||
*/
|
||||
const Activities: React.VoidFunctionComponent = () => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
const [selectedActivity, setSelectedActivity] = useLocalStorage(
|
||||
'activities.selectedActivity',
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
//
|
||||
// Explorer translation keys.
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Title = 'title',
|
||||
Explorer = 'explorer',
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
|
||||
import './UnexpectedErrorAlert.scss';
|
||||
import { AnchorButton, Button, ButtonGroup, Collapse, Intent } from '@blueprintjs/core';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useState } from 'react';
|
||||
import { useId } from 'react-aria';
|
||||
import { CreateToast } from '../i18nToaster';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
type UnexpectedErrorAlertProps = {
|
||||
error: Error;
|
||||
@@ -16,8 +15,7 @@ type UnexpectedErrorAlertProps = {
|
||||
const UnexpectedErrorAlert: React.VoidFunctionComponent<UnexpectedErrorAlertProps> = ({
|
||||
error,
|
||||
}) => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const labelId = useId();
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Message = 'message',
|
||||
TechnicalInfo = 'technicalInfo',
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { Classes } from '@blueprintjs/core';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { OverlayContainer } from 'react-aria';
|
||||
import { useBoolean } from 'usehooks-ts';
|
||||
import { Button } from './Button';
|
||||
import HelpDialog from './HelpDialog';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
type HelpButtonProps = {
|
||||
/** The label of the control this button provides help for. */
|
||||
@@ -21,8 +20,7 @@ const HelpButton: React.VoidFunctionComponent<HelpButtonProps> = ({
|
||||
helpForLabel,
|
||||
content,
|
||||
}) => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
const {
|
||||
value: isDialogOpen,
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
POPOVER_ARROW_SVG_SIZE,
|
||||
Popover2Arrow,
|
||||
} from '@blueprintjs/popover2/lib/cjs/popover2Arrow';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import classNames from 'classnames';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import {
|
||||
@@ -21,7 +20,7 @@ import {
|
||||
useOverlay,
|
||||
} from 'react-aria';
|
||||
import { usePopper } from 'react-popper';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
type HelpDialogProps = {
|
||||
/** The title of the dialog. */
|
||||
@@ -45,8 +44,7 @@ const HelpDialog: React.FunctionComponent<HelpDialogProps> = ({
|
||||
onAnimationEnd,
|
||||
children,
|
||||
}) => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
// this is the dialog element and the popper element
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
HelpButtonLabel = 'helpButton.label',
|
||||
HelpButtonDescription = 'helpButton.description',
|
||||
|
||||
+7
-15
@@ -16,7 +16,6 @@ import {
|
||||
Text,
|
||||
} from '@blueprintjs/core';
|
||||
import { ContextMenu2, ResizeSensor2 } from '@blueprintjs/popover2';
|
||||
import { I18n, useI18n } from '@shopify/react-i18n';
|
||||
import tomorrowNightEightiesTheme from 'monaco-themes/themes/Tomorrow-Night-Eighties.json';
|
||||
import xcodeTheme from 'monaco-themes/themes/Xcode_default.json';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
@@ -34,7 +33,7 @@ import { useSelector } from '../reducers';
|
||||
import { useSettingIsShowDocsEnabled } from '../settings/hooks';
|
||||
import { isMacOS } from '../utils/os';
|
||||
import { editorActivateFile, editorCloseFile } from './actions';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
import * as pybricksMicroPython from './pybricksMicroPython';
|
||||
import { pybricksMicroPythonId } from './pybricksMicroPython';
|
||||
import { UntitledHintContribution } from './untitledHint';
|
||||
@@ -114,14 +113,12 @@ const EditorContextMenuItem: React.VoidFunctionComponent<
|
||||
type EditorContextMenuProps = {
|
||||
/** The editor. */
|
||||
editor: monaco.editor.IStandaloneCodeEditor | undefined;
|
||||
/** Translation context. */
|
||||
i18n: I18n;
|
||||
};
|
||||
|
||||
const EditorContextMenu: React.VoidFunctionComponent<EditorContextMenuProps> = ({
|
||||
editor,
|
||||
i18n,
|
||||
}) => {
|
||||
const i18n = useI18n();
|
||||
const selection = editor?.getSelection();
|
||||
const hasSelection = selection && !selection.isEmpty();
|
||||
|
||||
@@ -179,17 +176,13 @@ const EditorContextMenu: React.VoidFunctionComponent<EditorContextMenuProps> = (
|
||||
type EditorTabsProps = Readonly<{
|
||||
/** Called when the selected tab changes. */
|
||||
onChange?: () => void;
|
||||
/** Translation context. */
|
||||
i18n: I18n;
|
||||
}>;
|
||||
|
||||
const EditorTabs: React.VoidFunctionComponent<EditorTabsProps> = ({
|
||||
onChange,
|
||||
i18n,
|
||||
}) => {
|
||||
const EditorTabs: React.VoidFunctionComponent<EditorTabsProps> = ({ onChange }) => {
|
||||
const openFiles = useSelector((s) => s.editor.openFiles);
|
||||
const activeFile = useSelector((s) => s.editor.activeFile);
|
||||
const dispatch = useDispatch();
|
||||
const i18n = useI18n();
|
||||
|
||||
const handleChange = useCallback(
|
||||
(newTabId: TabId) => {
|
||||
@@ -301,8 +294,7 @@ const Editor: React.VFC = () => {
|
||||
const { toggleIsSettingShowDocsEnabled } = useSettingIsShowDocsEnabled();
|
||||
const { isDarkMode } = useTernaryDarkMode();
|
||||
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
const options = useMemo<monaco.editor.IStandaloneEditorConstructionOptions>(
|
||||
() => ({
|
||||
@@ -423,7 +415,7 @@ const Editor: React.VFC = () => {
|
||||
|
||||
return (
|
||||
<div className="pb-editor">
|
||||
<EditorTabs onChange={() => editor?.focus()} i18n={i18n} />
|
||||
<EditorTabs onChange={() => editor?.focus()} />
|
||||
<ResizeSensor2 onResize={() => editor?.layout()}>
|
||||
<ContextMenu2
|
||||
className="pb-editor-tabpanel"
|
||||
@@ -431,7 +423,7 @@ const Editor: React.VFC = () => {
|
||||
// NB: we have to create a new context menu each time it is
|
||||
// shown in order to get some state, like canUndo and canRedo
|
||||
// that don't have events to monitor changes.
|
||||
content={() => <EditorContextMenu editor={editor} i18n={i18n} />}
|
||||
content={() => <EditorContextMenu editor={editor} />}
|
||||
popoverProps={popoverProps}
|
||||
>
|
||||
<MonacoEditor
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
//
|
||||
// Editor translation keys.
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Placeholder = 'placeholder',
|
||||
Check = 'check',
|
||||
|
||||
+14
-32
@@ -12,7 +12,6 @@ import {
|
||||
IconName,
|
||||
useHotkeys,
|
||||
} from '@blueprintjs/core';
|
||||
import { I18n, useI18n } from '@shopify/react-i18n';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useId } from 'react-aria';
|
||||
import {
|
||||
@@ -41,7 +40,7 @@ import {
|
||||
} from './actions';
|
||||
import DeleteFileAlert from './deleteFileAlert/DeleteFileAlert';
|
||||
import DuplicateFileDialog from './duplicateFileDialog/DuplicateFileDialog';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
import NewFileWizard from './newFileWizard/NewFileWizard';
|
||||
|
||||
type ActionButtonProps = {
|
||||
@@ -91,14 +90,12 @@ type FileTreeItem = TreeItem<FileTreeItemData>;
|
||||
type ActionButtonGroupProps = {
|
||||
/** The name of the file (displayed to user) */
|
||||
item: TreeItem;
|
||||
/** Translation context. */
|
||||
i18n: I18n;
|
||||
};
|
||||
|
||||
const FileActionButtonGroup: React.VoidFunctionComponent<ActionButtonGroupProps> = ({
|
||||
item,
|
||||
i18n,
|
||||
}) => {
|
||||
const i18n = useI18n();
|
||||
const dispatch = useDispatch();
|
||||
const environment = useTreeEnvironment();
|
||||
|
||||
@@ -145,16 +142,12 @@ const FileActionButtonGroup: React.VoidFunctionComponent<ActionButtonGroupProps>
|
||||
);
|
||||
};
|
||||
|
||||
type HeaderProps = {
|
||||
/** Translation context. */
|
||||
i18n: I18n;
|
||||
};
|
||||
|
||||
const Header: React.VoidFunctionComponent<HeaderProps> = ({ i18n }) => {
|
||||
const Header: React.VoidFunctionComponent = () => {
|
||||
const archiveButtonId = useId();
|
||||
const exportButtonId = useId();
|
||||
const newButtonId = useId();
|
||||
const dispatch = useDispatch();
|
||||
const i18n = useI18n();
|
||||
|
||||
return (
|
||||
<Toolbar
|
||||
@@ -191,9 +184,10 @@ const Header: React.VoidFunctionComponent<HeaderProps> = ({ i18n }) => {
|
||||
|
||||
/**
|
||||
* Accessibility live descriptors.
|
||||
* @param i18n Translation context.
|
||||
*/
|
||||
function useLiveDescriptors(i18n: I18n): LiveDescriptors {
|
||||
function useLiveDescriptors(): LiveDescriptors {
|
||||
const i18n = useI18n();
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
introduction: `
|
||||
@@ -301,15 +295,10 @@ const renderTreeContainer: typeof renderers.renderTreeContainer = (props) => {
|
||||
return <div onKeyDown={handleKeyDown}>{renderers.renderTreeContainer(props)}</div>;
|
||||
};
|
||||
|
||||
type FileTreeProps = {
|
||||
/** Translation context. */
|
||||
i18n: I18n;
|
||||
};
|
||||
|
||||
const FileTree: React.VoidFunctionComponent<FileTreeProps> = ({ i18n }) => {
|
||||
const FileTree: React.VoidFunctionComponent = () => {
|
||||
const [focusedItem, setFocusedItem] = useState<TreeItemIndex>();
|
||||
const files = useFileStorageMetadata() ?? [];
|
||||
const liveDescriptors = useLiveDescriptors(i18n);
|
||||
const liveDescriptors = useLiveDescriptors();
|
||||
|
||||
const rootItemIndex = 'root';
|
||||
|
||||
@@ -326,12 +315,7 @@ const FileTree: React.VoidFunctionComponent<FileTreeProps> = ({ i18n }) => {
|
||||
icon: 'document',
|
||||
secondaryLabel: (
|
||||
<TreeItemContext.Consumer>
|
||||
{(item) => (
|
||||
<FileActionButtonGroup
|
||||
item={item}
|
||||
i18n={i18n}
|
||||
/>
|
||||
)}
|
||||
{(item) => <FileActionButtonGroup item={item} />}
|
||||
</TreeItemContext.Consumer>
|
||||
),
|
||||
},
|
||||
@@ -348,7 +332,7 @@ const FileTree: React.VoidFunctionComponent<FileTreeProps> = ({ i18n }) => {
|
||||
},
|
||||
} as Record<TreeItemIndex, FileTreeItem>,
|
||||
),
|
||||
[i18n, files],
|
||||
[files],
|
||||
);
|
||||
|
||||
const getItemTitle = useCallback((item: FileTreeItem) => item.data.fileName, []);
|
||||
@@ -361,6 +345,7 @@ const FileTree: React.VoidFunctionComponent<FileTreeProps> = ({ i18n }) => {
|
||||
);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const i18n = useI18n();
|
||||
|
||||
return (
|
||||
<ControlledTreeEnvironment<FileTreeItemData>
|
||||
@@ -388,14 +373,11 @@ const FileTree: React.VoidFunctionComponent<FileTreeProps> = ({ i18n }) => {
|
||||
};
|
||||
|
||||
const Explorer: React.VFC = () => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
|
||||
return (
|
||||
<div className="pb-explorer">
|
||||
<Header i18n={i18n} />
|
||||
<Header />
|
||||
<Divider />
|
||||
<FileTree i18n={i18n} />
|
||||
<FileTree />
|
||||
<NewFileWizard />
|
||||
<DuplicateFileDialog />
|
||||
<DeleteFileAlert />
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { CreateToast } from '../../i18nToaster';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
type FileInUseAlertProps = {
|
||||
fileName: string;
|
||||
@@ -14,8 +13,7 @@ type FileInUseAlertProps = {
|
||||
const FileInUseAlert: React.VoidFunctionComponent<FileInUseAlertProps> = ({
|
||||
fileName,
|
||||
}) => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
return <>{i18n.translate(I18nId.FileInUseMessage, { fileName })}</>;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
FileInUseMessage = 'fileInUse.message',
|
||||
}
|
||||
|
||||
@@ -2,18 +2,16 @@
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { Alert, Classes, Intent } from '@blueprintjs/core';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useSelector } from '../../reducers';
|
||||
import { deleteFileAlertDidAccept, deleteFileAlertDidCancel } from './actions';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
const DeleteFileAlert: React.VoidFunctionComponent = () => {
|
||||
const { isOpen, fileName } = useSelector((s) => s.explorer.deleteFileAlert);
|
||||
const dispatch = useDispatch();
|
||||
// istanbul ignore next: babel rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
// a11y: focus primary button when dialog is opened
|
||||
const handleOpened = useCallback((node: HTMLElement) => {
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Accept = 'action.accept',
|
||||
Cancel = 'action.cancel',
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { Button, Classes, Dialog } from '@blueprintjs/core';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useCallback, useRef, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useFileStorageMetadata } from '../../fileStorage/hooks';
|
||||
@@ -13,11 +12,10 @@ import {
|
||||
import { useSelector } from '../../reducers';
|
||||
import FileNameFormGroup from '../fileNameFormGroup/FileNameFormGroup';
|
||||
import { duplicateFileDialogDidAccept, duplicateFileDialogDidCancel } from './actions';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
const DuplicateFileDialog: React.VFC = () => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
const dispatch = useDispatch();
|
||||
const isOpen = useSelector((s) => s.explorer.duplicateFileDialog.isOpen);
|
||||
const oldName = useSelector((s) => s.explorer.duplicateFileDialog.fileName);
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Title = 'title',
|
||||
ActionAccept = 'action.accept',
|
||||
|
||||
@@ -2,16 +2,13 @@
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { Classes, FormGroup, InputGroup, Intent, Tag } from '@blueprintjs/core';
|
||||
import { I18n, useI18n } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { FileNameValidationResult } from '../../pybricksMicropython/lib';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
type FileNameHelpTextProps = {
|
||||
/** The result of the file name validation. */
|
||||
validation: FileNameValidationResult;
|
||||
/** Translation context. */
|
||||
i18n: I18n;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -19,8 +16,9 @@ type FileNameHelpTextProps = {
|
||||
*/
|
||||
const FileNameHelpText: React.VoidFunctionComponent<FileNameHelpTextProps> = ({
|
||||
validation,
|
||||
i18n,
|
||||
}) => {
|
||||
const i18n = useI18n();
|
||||
|
||||
switch (validation) {
|
||||
case FileNameValidationResult.IsOk:
|
||||
return <>{i18n.translate(I18nId.HelpTextIsOk)}</>;
|
||||
@@ -78,8 +76,7 @@ const FileNameFormGroup: React.VoidFunctionComponent<FileNameFormGroupProps> = (
|
||||
inputRef,
|
||||
onChange,
|
||||
}) => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
const fileNameIntent =
|
||||
validationResult === FileNameValidationResult.IsOk
|
||||
@@ -90,7 +87,7 @@ const FileNameFormGroup: React.VoidFunctionComponent<FileNameFormGroupProps> = (
|
||||
<FormGroup
|
||||
label={i18n.translate(I18nId.Label)}
|
||||
intent={fileNameIntent}
|
||||
subLabel={<FileNameHelpText validation={validationResult} i18n={i18n} />}
|
||||
subLabel={<FileNameHelpText validation={validationResult} />}
|
||||
>
|
||||
<InputGroup
|
||||
aria-label="File name"
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Label = 'label',
|
||||
HelpTextIsOk = 'helpText.isOk',
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
//
|
||||
// Explorer translation keys.
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
HeaderToolbarTitle = 'header.toolbar.title',
|
||||
HeaderToolbarExportAll = 'header.toolbar.exportAll',
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
Radio,
|
||||
RadioGroup,
|
||||
} from '@blueprintjs/core';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useCallback, useRef, useState } from 'react';
|
||||
import { useId } from 'react-aria';
|
||||
import { useDispatch } from 'react-redux';
|
||||
@@ -22,14 +21,13 @@ import {
|
||||
import { useSelector } from '../../reducers';
|
||||
import FileNameFormGroup from '../fileNameFormGroup/FileNameFormGroup';
|
||||
import { Hub, newFileWizardDidAccept, newFileWizardDidCancel } from './actions';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
// This should be set to the most commonly used hub.
|
||||
const defaultHub = Hub.Technic;
|
||||
|
||||
const NewFileWizard: React.VoidFunctionComponent = () => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const isOpen = useSelector((s) => s.explorer.newFileWizard.isOpen);
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Title = 'title',
|
||||
SmartHubLabel = 'smartHub.label',
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { Button, Classes, Dialog } from '@blueprintjs/core';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useCallback, useRef, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useFileStorageMetadata } from '../../fileStorage/hooks';
|
||||
@@ -13,11 +12,11 @@ import {
|
||||
import { useSelector } from '../../reducers';
|
||||
import FileNameFormGroup from '../fileNameFormGroup/FileNameFormGroup';
|
||||
import { renameFileDialogDidAccept, renameFileDialogDidCancel } from './actions';
|
||||
import { useI18n } from './i18n';
|
||||
import { I18nId } from './i18n';
|
||||
|
||||
const RenameFileDialog: React.VFC = () => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
const dispatch = useDispatch();
|
||||
const isOpen = useSelector((s) => s.explorer.renameFileDialog.isOpen);
|
||||
const oldName = useSelector((s) => s.explorer.renameFileDialog.fileName);
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Title = 'title',
|
||||
ActionRename = 'action.rename',
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
NonIdealState,
|
||||
Spinner,
|
||||
} from '@blueprintjs/core';
|
||||
import { I18n, useI18n } from '@shopify/react-i18n';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import {
|
||||
ControlledTreeEnvironment,
|
||||
@@ -23,7 +22,7 @@ import {
|
||||
import { useFetch } from 'usehooks-ts';
|
||||
import { appName } from '../app/constants';
|
||||
import { TreeItemData, renderers } from '../utils/tree-renderer';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
import './license.scss';
|
||||
|
||||
@@ -40,14 +39,12 @@ type LicenseList = ReadonlyArray<LicenseInfo>;
|
||||
type LicenseListPanelProps = {
|
||||
/** Called when item is clicked. */
|
||||
onItemClick(info?: LicenseInfo): void;
|
||||
/** Translation context. */
|
||||
i18n: I18n;
|
||||
};
|
||||
|
||||
const LicenseListPanel: React.VoidFunctionComponent<LicenseListPanelProps> = ({
|
||||
onItemClick,
|
||||
i18n,
|
||||
}) => {
|
||||
const i18n = useI18n();
|
||||
const { data, error } = useFetch<LicenseList>('static/oss-licenses.json');
|
||||
const [focusedItem, setFocusedItem] = useState<TreeItemIndex>();
|
||||
const [activeItem, setActiveItem] = useState<TreeItemIndex>();
|
||||
@@ -124,12 +121,12 @@ const LicenseListPanel: React.VoidFunctionComponent<LicenseListPanelProps> = ({
|
||||
type LicenseInfoPanelProps = {
|
||||
/** The license info to show or undefined if no license info is selected. */
|
||||
licenseInfo: LicenseInfo | undefined;
|
||||
/** Translation context. */
|
||||
i18n: I18n;
|
||||
};
|
||||
|
||||
const LicenseInfoPanel = React.forwardRef<HTMLDivElement, LicenseInfoPanelProps>(
|
||||
({ licenseInfo, i18n }, ref) => {
|
||||
({ licenseInfo }, ref) => {
|
||||
const i18n = useI18n();
|
||||
|
||||
return (
|
||||
<div className="pb-license-info" ref={ref}>
|
||||
{licenseInfo === undefined ? (
|
||||
@@ -182,9 +179,7 @@ const LicenseDialog: React.VoidFunctionComponent<LicenseDialogProps> = ({
|
||||
}) => {
|
||||
const [licenseInfo, setLicenseInfo] = useState<LicenseInfo | undefined>(undefined);
|
||||
const infoDiv = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
@@ -205,13 +200,8 @@ const LicenseDialog: React.VoidFunctionComponent<LicenseDialogProps> = ({
|
||||
infoDiv.current?.scrollTo(0, 0);
|
||||
setLicenseInfo(info);
|
||||
}}
|
||||
i18n={i18n}
|
||||
/>
|
||||
<LicenseInfoPanel
|
||||
licenseInfo={licenseInfo}
|
||||
ref={infoDiv}
|
||||
i18n={i18n}
|
||||
/>
|
||||
<LicenseInfoPanel licenseInfo={licenseInfo} ref={infoDiv} />
|
||||
</Callout>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
|
||||
// License dialog translation keys.
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Title = 'title',
|
||||
Description = 'description',
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
// provides translation for notification text
|
||||
|
||||
import { Replacements, useI18n } from '@shopify/react-i18n';
|
||||
import { Replacements } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
type NotificationActionProps = {
|
||||
messageId: I18nId;
|
||||
@@ -16,8 +16,7 @@ const NotificationAction: React.VoidFunctionComponent<NotificationActionProps> =
|
||||
messageId,
|
||||
replacements,
|
||||
}) => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
return <>{i18n.translate(messageId, replacements)}</>;
|
||||
};
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
// provides translation for notification text
|
||||
|
||||
import { Replacements, useI18n } from '@shopify/react-i18n';
|
||||
import { Replacements } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
type NotificationMessageProps = {
|
||||
messageId: I18nId;
|
||||
@@ -16,8 +16,7 @@ const NotificationMessage: React.VoidFunctionComponent<NotificationMessageProps>
|
||||
messageId,
|
||||
replacements,
|
||||
}) => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
let message = i18n.translate(messageId, replacements) as
|
||||
| React.ReactElement
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
//
|
||||
// Notification translation keys.
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
AppNoUpdateFound = 'app.noUpdateFound',
|
||||
BleUnexpectedError = 'ble.unexpectedError',
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
Label,
|
||||
Switch,
|
||||
} from '@blueprintjs/core';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useTernaryDarkMode } from 'usehooks-ts';
|
||||
@@ -36,7 +35,7 @@ import {
|
||||
useSettingHubName,
|
||||
useSettingIsShowDocsEnabled,
|
||||
} from './hooks';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
import './settings.scss';
|
||||
|
||||
const Settings: React.VoidFunctionComponent = () => {
|
||||
@@ -61,8 +60,7 @@ const Settings: React.VoidFunctionComponent = () => {
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
return (
|
||||
<div className="pb-settings">
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
//
|
||||
// Settings translation keys.
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Title = 'title',
|
||||
AppearanceTitle = 'appearance.title',
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
|
||||
import { Button, Intent, ProgressBar } from '@blueprintjs/core';
|
||||
import { Classes as Classes2, Popover2, Popover2Props } from '@blueprintjs/popover2';
|
||||
import { I18n, useI18n } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { BleConnectionState } from '../ble/reducers';
|
||||
import { useSelector } from '../reducers';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
import './status-bar.scss';
|
||||
|
||||
@@ -16,12 +15,8 @@ const commonPopoverProps: Partial<Popover2Props> = {
|
||||
placement: 'top',
|
||||
};
|
||||
|
||||
type HubInfoButtonProps = {
|
||||
/** Translation context. */
|
||||
i18n: I18n;
|
||||
};
|
||||
|
||||
const HubInfoButton: React.VoidFunctionComponent<HubInfoButtonProps> = ({ i18n }) => {
|
||||
const HubInfoButton: React.VoidFunctionComponent = () => {
|
||||
const i18n = useI18n();
|
||||
const deviceName = useSelector((s) => s.ble.deviceName);
|
||||
const deviceType = useSelector((s) => s.ble.deviceType);
|
||||
const deviceFirmwareVersion = useSelector((s) => s.ble.deviceFirmwareVersion);
|
||||
@@ -65,14 +60,8 @@ const HubInfoButton: React.VoidFunctionComponent<HubInfoButtonProps> = ({ i18n }
|
||||
);
|
||||
};
|
||||
|
||||
type BatteryIndicatorProps = {
|
||||
/** Translation context. */
|
||||
i18n: I18n;
|
||||
};
|
||||
|
||||
const BatteryIndicator: React.VoidFunctionComponent<BatteryIndicatorProps> = ({
|
||||
i18n,
|
||||
}) => {
|
||||
const BatteryIndicator: React.VoidFunctionComponent = () => {
|
||||
const i18n = useI18n();
|
||||
const charging = useSelector((s) => s.ble.deviceBatteryCharging);
|
||||
const lowBatteryWarning = useSelector((s) => s.ble.deviceLowBatteryWarning);
|
||||
|
||||
@@ -106,17 +95,14 @@ const BatteryIndicator: React.VoidFunctionComponent<BatteryIndicatorProps> = ({
|
||||
};
|
||||
|
||||
const StatusBar: React.VFC = (_props) => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
|
||||
const connection = useSelector((s) => s.ble.connection);
|
||||
|
||||
return (
|
||||
<div className="pb-status-bar" role="status" aria-live="off">
|
||||
{connection === BleConnectionState.Connected && (
|
||||
<>
|
||||
<HubInfoButton i18n={i18n} />
|
||||
<BatteryIndicator i18n={i18n} />
|
||||
<HubInfoButton />
|
||||
<BatteryIndicator />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
//
|
||||
// Status bar translation keys.
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
BatteryTitle = 'battery.title',
|
||||
BatteryLow = 'battery.low',
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
import { Menu, MenuDivider, MenuItem, ResizeSensor } from '@blueprintjs/core';
|
||||
import { ContextMenu2, ContextMenu2ContentProps } from '@blueprintjs/popover2';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useContext, useEffect, useMemo, useRef } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useTernaryDarkMode } from 'usehooks-ts';
|
||||
@@ -12,7 +11,7 @@ import { FitAddon } from 'xterm-addon-fit';
|
||||
import { isMacOS } from '../utils/os';
|
||||
import { TerminalContext } from './TerminalContext';
|
||||
import { receiveData } from './actions';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
import 'xterm/css/xterm.css';
|
||||
|
||||
@@ -54,8 +53,7 @@ function createContextMenu(
|
||||
xterm: XTerm,
|
||||
): (props: ContextMenu2ContentProps) => JSX.Element {
|
||||
const contextMenu = (_props: ContextMenu2ContentProps): JSX.Element => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
|
||||
return (
|
||||
<Menu>
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
//
|
||||
// Terminal translation keys.
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Copy = 'copy',
|
||||
Paste = 'paste',
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { toggleBluetooth } from '../../../ble/actions';
|
||||
@@ -11,7 +10,7 @@ import { useSelector } from '../../../reducers';
|
||||
import ActionButton, { ActionButtonProps } from '../../ActionButton';
|
||||
import connectedIcon from './connected.svg';
|
||||
import disconnectedIcon from './disconnected.svg';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
|
||||
type BluetoothButtonProps = Pick<ActionButtonProps, 'id'>;
|
||||
|
||||
@@ -23,8 +22,7 @@ const BluetoothButton: React.VoidFunctionComponent<BluetoothButtonProps> = ({ id
|
||||
bootloaderConnection === BootloaderConnectionState.Disconnected &&
|
||||
bleConnection === BleConnectionState.Disconnected;
|
||||
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Label = 'label',
|
||||
TooltipConnect = 'tooltip.connect',
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { BleConnectionState } from '../../../ble/reducers';
|
||||
@@ -14,7 +13,7 @@ import {
|
||||
useSettingHubName,
|
||||
} from '../../../settings/hooks';
|
||||
import OpenFileButton, { OpenFileButtonProps } from '../../../toolbar/OpenFileButton';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
import icon from './icon.svg';
|
||||
|
||||
type FlashButtonProps = Pick<OpenFileButtonProps, 'id'>;
|
||||
@@ -27,8 +26,7 @@ const FlashButton: React.VoidFunctionComponent<FlashButtonProps> = ({ id }) => {
|
||||
const [isSettingFlashCurrentProgramEnabled] = useSettingFlashCurrentProgram();
|
||||
const { hubName } = useSettingHubName();
|
||||
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Label = 'label',
|
||||
TooltipAction = 'tooltip.action',
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { repl } from '../../../hub/actions';
|
||||
import { HubRuntimeState } from '../../../hub/reducers';
|
||||
import { useSelector } from '../../../reducers';
|
||||
import ActionButton, { ActionButtonProps } from '../../ActionButton';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
import icon from './icon.svg';
|
||||
|
||||
type ReplButtonProps = Pick<ActionButtonProps, 'id'>;
|
||||
|
||||
const ReplButton: React.VoidFunctionComponent<ReplButtonProps> = ({ id }) => {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const enabled = useSelector((s) => s.hub.runtime === HubRuntimeState.Idle);
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Label = 'label',
|
||||
Tooltip = 'tooltip',
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { downloadAndRun } from '../../../hub/actions';
|
||||
import { HubRuntimeState } from '../../../hub/reducers';
|
||||
import { useSelector } from '../../../reducers';
|
||||
import ActionButton, { ActionButtonProps } from '../../ActionButton';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
import icon from './icon.svg';
|
||||
|
||||
type RunButtonProps = Pick<ActionButtonProps, 'id'>;
|
||||
@@ -19,8 +18,7 @@ const RunButton: React.VoidFunctionComponent<RunButtonProps> = ({ id }) => {
|
||||
const isEditorReady = useSelector((s) => s.editor.isReady);
|
||||
const keyboardShortcut = 'F5';
|
||||
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Label = 'label',
|
||||
TooltipAction = 'tooltip.action',
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { stop } from '../../../hub/actions';
|
||||
import { HubRuntimeState } from '../../../hub/reducers';
|
||||
import { useSelector } from '../../../reducers';
|
||||
import ActionButton, { ActionButtonProps } from '../../ActionButton';
|
||||
import { I18nId } from './i18n';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
import icon from './icon.svg';
|
||||
|
||||
type StopButtonProps = Pick<ActionButtonProps, 'id'>;
|
||||
@@ -17,8 +16,7 @@ const StopButton: React.VoidFunctionComponent<StopButtonProps> = ({ id }) => {
|
||||
const runtime = useSelector((s) => s.hub.runtime);
|
||||
const keyboardShortcut = 'F6';
|
||||
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useI18n();
|
||||
const i18n = useI18n();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Label = 'label',
|
||||
Tooltip = 'tooltip',
|
||||
|
||||
Reference in New Issue
Block a user