mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-19 09:16:38 +00:00
Split drive selector from target selector
Change-type: patch Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
This commit is contained in:
parent
07befd0bd1
commit
377dfb8e22
@ -33,7 +33,7 @@ import {
|
|||||||
getDriveImageCompatibilityStatuses,
|
getDriveImageCompatibilityStatuses,
|
||||||
hasListDriveImageCompatibilityStatus,
|
hasListDriveImageCompatibilityStatus,
|
||||||
isDriveValid,
|
isDriveValid,
|
||||||
TargetStatus,
|
DriveStatus,
|
||||||
Image,
|
Image,
|
||||||
} from '../../../../shared/drive-constraints';
|
} from '../../../../shared/drive-constraints';
|
||||||
import { compatibility } from '../../../../shared/messages';
|
import { compatibility } from '../../../../shared/messages';
|
||||||
@ -49,7 +49,7 @@ import { logEvent, logException } from '../../modules/analytics';
|
|||||||
import { open as openExternal } from '../../os/open-external/services/open-external';
|
import { open as openExternal } from '../../os/open-external/services/open-external';
|
||||||
import { Modal, ScrollableFlex } from '../../styled-components';
|
import { Modal, ScrollableFlex } from '../../styled-components';
|
||||||
|
|
||||||
import TargetSVGIcon from '../../../assets/tgt.svg';
|
import DriveSVGIcon from '../../../assets/tgt.svg';
|
||||||
|
|
||||||
interface UsbbootDrive extends sourceDestination.UsbbootDrive {
|
interface UsbbootDrive extends sourceDestination.UsbbootDrive {
|
||||||
progress: number;
|
progress: number;
|
||||||
@ -64,26 +64,26 @@ interface DriverlessDrive {
|
|||||||
linkCTA: string;
|
linkCTA: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Target = scanner.adapters.DrivelistDrive | DriverlessDrive | UsbbootDrive;
|
type Drive = scanner.adapters.DrivelistDrive | DriverlessDrive | UsbbootDrive;
|
||||||
|
|
||||||
function isUsbbootDrive(drive: Target): drive is UsbbootDrive {
|
function isUsbbootDrive(drive: Drive): drive is UsbbootDrive {
|
||||||
return (drive as UsbbootDrive).progress !== undefined;
|
return (drive as UsbbootDrive).progress !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isDriverlessDrive(drive: Target): drive is DriverlessDrive {
|
function isDriverlessDrive(drive: Drive): drive is DriverlessDrive {
|
||||||
return (drive as DriverlessDrive).link !== undefined;
|
return (drive as DriverlessDrive).link !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isDrivelistDrive(
|
function isDrivelistDrive(
|
||||||
drive: Target,
|
drive: Drive,
|
||||||
): drive is scanner.adapters.DrivelistDrive {
|
): drive is scanner.adapters.DrivelistDrive {
|
||||||
return typeof (drive as scanner.adapters.DrivelistDrive).size === 'number';
|
return typeof (drive as scanner.adapters.DrivelistDrive).size === 'number';
|
||||||
}
|
}
|
||||||
|
|
||||||
const TargetsTable = styled(({ refFn, ...props }) => {
|
const DrivesTable = styled(({ refFn, ...props }) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table<Target> ref={refFn} {...props} />
|
<Table<Drive> ref={refFn} {...props} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})`
|
})`
|
||||||
@ -145,30 +145,37 @@ const InitProgress = styled(
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
interface TargetSelectorModalProps extends Omit<ModalProps, 'done'> {
|
export interface DriveSelectorProps
|
||||||
done: (targets: scanner.adapters.DrivelistDrive[]) => void;
|
extends Omit<ModalProps, 'done' | 'cancel'> {
|
||||||
|
multipleSelection?: boolean;
|
||||||
|
cancel: () => void;
|
||||||
|
done: (drives: scanner.adapters.DrivelistDrive[]) => void;
|
||||||
|
titleLabel: string;
|
||||||
|
emptyListLabel: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TargetSelectorModalState {
|
interface DriveSelectorState {
|
||||||
drives: Target[];
|
drives: Drive[];
|
||||||
image: Image;
|
image: Image;
|
||||||
missingDriversModal: { drive?: DriverlessDrive };
|
missingDriversModal: { drive?: DriverlessDrive };
|
||||||
selectedList: scanner.adapters.DrivelistDrive[];
|
selectedList: scanner.adapters.DrivelistDrive[];
|
||||||
showSystemDrives: boolean;
|
showSystemDrives: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TargetSelectorModal extends React.Component<
|
export class DriveSelector extends React.Component<
|
||||||
TargetSelectorModalProps,
|
DriveSelectorProps,
|
||||||
TargetSelectorModalState
|
DriveSelectorState
|
||||||
> {
|
> {
|
||||||
private unsubscribe: (() => void) | undefined;
|
private unsubscribe: (() => void) | undefined;
|
||||||
tableColumns: Array<TableColumn<Target>>;
|
multipleSelection: boolean;
|
||||||
|
tableColumns: Array<TableColumn<Drive>>;
|
||||||
|
|
||||||
constructor(props: TargetSelectorModalProps) {
|
constructor(props: DriveSelectorProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const defaultMissingDriversModalState: { drive?: DriverlessDrive } = {};
|
const defaultMissingDriversModalState: { drive?: DriverlessDrive } = {};
|
||||||
const selectedList = getSelectedDrives();
|
const selectedList = getSelectedDrives();
|
||||||
|
this.multipleSelection = !!this.props.multipleSelection;
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
drives: getDrives(),
|
drives: getDrives(),
|
||||||
@ -182,7 +189,7 @@ export class TargetSelectorModal extends React.Component<
|
|||||||
{
|
{
|
||||||
field: 'description',
|
field: 'description',
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
render: (description: string, drive: Target) => {
|
render: (description: string, drive: Drive) => {
|
||||||
return isDrivelistDrive(drive) && drive.isSystem ? (
|
return isDrivelistDrive(drive) && drive.isSystem ? (
|
||||||
<Flex alignItems="center">
|
<Flex alignItems="center">
|
||||||
<ExclamationTriangleSvg height="1em" fill="#fca321" />
|
<ExclamationTriangleSvg height="1em" fill="#fca321" />
|
||||||
@ -197,7 +204,7 @@ export class TargetSelectorModal extends React.Component<
|
|||||||
field: 'description',
|
field: 'description',
|
||||||
key: 'size',
|
key: 'size',
|
||||||
label: 'Size',
|
label: 'Size',
|
||||||
render: (_description: string, drive: Target) => {
|
render: (_description: string, drive: Drive) => {
|
||||||
if (isDrivelistDrive(drive) && drive.size !== null) {
|
if (isDrivelistDrive(drive) && drive.size !== null) {
|
||||||
return bytesToClosestUnit(drive.size);
|
return bytesToClosestUnit(drive.size);
|
||||||
}
|
}
|
||||||
@ -207,7 +214,7 @@ export class TargetSelectorModal extends React.Component<
|
|||||||
field: 'description',
|
field: 'description',
|
||||||
key: 'link',
|
key: 'link',
|
||||||
label: 'Location',
|
label: 'Location',
|
||||||
render: (_description: string, drive: Target) => {
|
render: (_description: string, drive: Drive) => {
|
||||||
return (
|
return (
|
||||||
<Txt>
|
<Txt>
|
||||||
{drive.displayName}
|
{drive.displayName}
|
||||||
@ -231,7 +238,7 @@ export class TargetSelectorModal extends React.Component<
|
|||||||
key: 'extra',
|
key: 'extra',
|
||||||
// Space as empty string would use the field name as label
|
// Space as empty string would use the field name as label
|
||||||
label: ' ',
|
label: ' ',
|
||||||
render: (_description: string, drive: Target) => {
|
render: (_description: string, drive: Drive) => {
|
||||||
if (isUsbbootDrive(drive)) {
|
if (isUsbbootDrive(drive)) {
|
||||||
return this.renderProgress(drive.progress);
|
return this.renderProgress(drive.progress);
|
||||||
} else if (isDrivelistDrive(drive)) {
|
} else if (isDrivelistDrive(drive)) {
|
||||||
@ -244,7 +251,7 @@ export class TargetSelectorModal extends React.Component<
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private driveShouldBeDisabled(drive: Target, image: any) {
|
private driveShouldBeDisabled(drive: Drive, image: any) {
|
||||||
return (
|
return (
|
||||||
isUsbbootDrive(drive) ||
|
isUsbbootDrive(drive) ||
|
||||||
isDriverlessDrive(drive) ||
|
isDriverlessDrive(drive) ||
|
||||||
@ -252,8 +259,8 @@ export class TargetSelectorModal extends React.Component<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDisplayedTargets(targets: Target[]): Target[] {
|
private getDisplayedDrives(drives: Drive[]): Drive[] {
|
||||||
return targets.filter((drive) => {
|
return drives.filter((drive) => {
|
||||||
return (
|
return (
|
||||||
isUsbbootDrive(drive) ||
|
isUsbbootDrive(drive) ||
|
||||||
isDriverlessDrive(drive) ||
|
isDriverlessDrive(drive) ||
|
||||||
@ -264,7 +271,7 @@ export class TargetSelectorModal extends React.Component<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDisabledTargets(drives: Target[], image: any): string[] {
|
private getDisabledDrives(drives: Drive[], image: any): string[] {
|
||||||
return drives
|
return drives
|
||||||
.filter((drive) => this.driveShouldBeDisabled(drive, image))
|
.filter((drive) => this.driveShouldBeDisabled(drive, image))
|
||||||
.map((drive) => drive.displayName);
|
.map((drive) => drive.displayName);
|
||||||
@ -279,7 +286,7 @@ export class TargetSelectorModal extends React.Component<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderStatuses(statuses: TargetStatus[]) {
|
private renderStatuses(statuses: DriveStatus[]) {
|
||||||
return (
|
return (
|
||||||
// the column render fn expects a single Element
|
// the column render fn expects a single Element
|
||||||
<>
|
<>
|
||||||
@ -324,12 +331,12 @@ export class TargetSelectorModal extends React.Component<
|
|||||||
const { cancel, done, ...props } = this.props;
|
const { cancel, done, ...props } = this.props;
|
||||||
const { selectedList, drives, image, missingDriversModal } = this.state;
|
const { selectedList, drives, image, missingDriversModal } = this.state;
|
||||||
|
|
||||||
const displayedTargets = this.getDisplayedTargets(drives);
|
const displayedDrives = this.getDisplayedDrives(drives);
|
||||||
const disabledTargets = this.getDisabledTargets(drives, image);
|
const disabledDrives = this.getDisabledDrives(drives, image);
|
||||||
const numberOfSystemDrives = drives.filter(
|
const numberOfSystemDrives = drives.filter(
|
||||||
(drive) => isDrivelistDrive(drive) && drive.isSystem,
|
(drive) => isDrivelistDrive(drive) && drive.isSystem,
|
||||||
).length;
|
).length;
|
||||||
const numberOfDisplayedSystemDrives = displayedTargets.filter(
|
const numberOfDisplayedSystemDrives = displayedDrives.filter(
|
||||||
(drive) => isDrivelistDrive(drive) && drive.isSystem,
|
(drive) => isDrivelistDrive(drive) && drive.isSystem,
|
||||||
).length;
|
).length;
|
||||||
const numberOfHiddenSystemDrives =
|
const numberOfHiddenSystemDrives =
|
||||||
@ -341,7 +348,7 @@ export class TargetSelectorModal extends React.Component<
|
|||||||
titleElement={
|
titleElement={
|
||||||
<Flex alignItems="baseline" mb={18}>
|
<Flex alignItems="baseline" mb={18}>
|
||||||
<Txt fontSize={24} align="left">
|
<Txt fontSize={24} align="left">
|
||||||
Select target
|
{this.props.titleLabel}
|
||||||
</Txt>
|
</Txt>
|
||||||
<Txt
|
<Txt
|
||||||
fontSize={11}
|
fontSize={11}
|
||||||
@ -372,45 +379,61 @@ export class TargetSelectorModal extends React.Component<
|
|||||||
alignItems="center"
|
alignItems="center"
|
||||||
width="100%"
|
width="100%"
|
||||||
>
|
>
|
||||||
<TargetSVGIcon width="40px" height="90px" />
|
<DriveSVGIcon width="40px" height="90px" />
|
||||||
<b>Plug a target drive</b>
|
<b>{this.props.emptyListLabel}</b>
|
||||||
</Flex>
|
</Flex>
|
||||||
) : (
|
) : (
|
||||||
<ScrollableFlex flexDirection="column" width="100%">
|
<ScrollableFlex
|
||||||
<TargetsTable
|
flexDirection="column"
|
||||||
refFn={(t: Table<Target>) => {
|
width="100%"
|
||||||
|
>
|
||||||
|
<DrivesTable
|
||||||
|
refFn={(t: Table<Drive>) => {
|
||||||
if (t !== null) {
|
if (t !== null) {
|
||||||
t.setRowSelection(selectedList);
|
t.setRowSelection(selectedList);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
columns={this.tableColumns}
|
columns={this.tableColumns}
|
||||||
data={displayedTargets}
|
data={displayedDrives}
|
||||||
disabledRows={disabledTargets}
|
disabledRows={disabledDrives}
|
||||||
rowKey="displayName"
|
rowKey="displayName"
|
||||||
onCheck={(rows: Target[]) => {
|
onCheck={(rows: Drive[]) => {
|
||||||
|
const newSelection = rows.filter(isDrivelistDrive);
|
||||||
|
if (this.multipleSelection) {
|
||||||
|
this.setState({
|
||||||
|
selectedList: newSelection,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedList: rows.filter(isDrivelistDrive),
|
selectedList: newSelection.slice(newSelection.length - 1),
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
onRowClick={(row: Target) => {
|
onRowClick={(row: Drive) => {
|
||||||
if (
|
if (
|
||||||
!isDrivelistDrive(row) ||
|
!isDrivelistDrive(row) ||
|
||||||
this.driveShouldBeDisabled(row, image)
|
this.driveShouldBeDisabled(row, image)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const newList = [...selectedList];
|
if (this.multipleSelection) {
|
||||||
const selectedIndex = selectedList.findIndex(
|
const newList = [...selectedList];
|
||||||
(target) => target.device === row.device,
|
const selectedIndex = selectedList.findIndex(
|
||||||
);
|
(drive) => drive.device === row.device,
|
||||||
if (selectedIndex === -1) {
|
);
|
||||||
newList.push(row);
|
if (selectedIndex === -1) {
|
||||||
} else {
|
newList.push(row);
|
||||||
// Deselect if selected
|
} else {
|
||||||
newList.splice(selectedIndex, 1);
|
// Deselect if selected
|
||||||
|
newList.splice(selectedIndex, 1);
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
selectedList: newList,
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedList: newList,
|
selectedList: [row],
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
@ -67,7 +67,7 @@ function DriveCompatibilityWarning({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TargetSelector(props: TargetSelectorProps) {
|
export function TargetSelectorButton(props: TargetSelectorProps) {
|
||||||
const targets = getSelectedDrives();
|
const targets = getSelectedDrives();
|
||||||
|
|
||||||
if (targets.length === 1) {
|
if (targets.length === 1) {
|
||||||
|
@ -19,6 +19,10 @@ import * as React from 'react';
|
|||||||
import { Flex } from 'rendition';
|
import { Flex } from 'rendition';
|
||||||
import { TargetSelector } from '../../components/target-selector/target-selector-button';
|
import { TargetSelector } from '../../components/target-selector/target-selector-button';
|
||||||
import { TargetSelectorModal } from '../../components/target-selector/target-selector-modal';
|
import { TargetSelectorModal } from '../../components/target-selector/target-selector-modal';
|
||||||
|
import {
|
||||||
|
DriveSelector,
|
||||||
|
DriveSelectorProps,
|
||||||
|
} from '../drive-selector/drive-selector';
|
||||||
import {
|
import {
|
||||||
isDriveSelected,
|
isDriveSelected,
|
||||||
getImage,
|
getImage,
|
||||||
@ -50,6 +54,16 @@ const getDriveSelectionStateSlice = () => ({
|
|||||||
image: getImage(),
|
image: getImage(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const TargetSelectorModal = (
|
||||||
|
props: Omit<DriveSelectorProps, 'titleLabel' | 'emptyListLabel'>,
|
||||||
|
) => (
|
||||||
|
<DriveSelector
|
||||||
|
titleLabel="Select target"
|
||||||
|
emptyListLabel="Plug a target drive"
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
export const selectAllTargets = (
|
export const selectAllTargets = (
|
||||||
modalTargets: scanner.adapters.DrivelistDrive[],
|
modalTargets: scanner.adapters.DrivelistDrive[],
|
||||||
) => {
|
) => {
|
||||||
@ -79,17 +93,17 @@ export const selectAllTargets = (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
interface DriveSelectorProps {
|
interface TargetSelectorProps {
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
hasDrive: boolean;
|
hasDrive: boolean;
|
||||||
flashing: boolean;
|
flashing: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DriveSelector = ({
|
export const TargetSelector = ({
|
||||||
disabled,
|
disabled,
|
||||||
hasDrive,
|
hasDrive,
|
||||||
flashing,
|
flashing,
|
||||||
}: DriveSelectorProps) => {
|
}: TargetSelectorProps) => {
|
||||||
// TODO: inject these from redux-connector
|
// TODO: inject these from redux-connector
|
||||||
const [
|
const [
|
||||||
{ showDrivesButton, driveListLabel, targets, image },
|
{ showDrivesButton, driveListLabel, targets, image },
|
||||||
@ -115,7 +129,7 @@ export const DriveSelector = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TargetSelector
|
<TargetSelectorButton
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
show={!hasDrive && showDrivesButton}
|
show={!hasDrive && showDrivesButton}
|
||||||
tooltip={driveListLabel}
|
tooltip={driveListLabel}
|
||||||
@ -138,7 +152,7 @@ export const DriveSelector = ({
|
|||||||
selectAllTargets(modalTargets);
|
selectAllTargets(modalTargets);
|
||||||
setShowTargetSelectorModal(false);
|
setShowTargetSelectorModal(false);
|
||||||
}}
|
}}
|
||||||
></TargetSelectorModal>
|
/>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
@ -24,7 +24,6 @@ import * as constraints from '../../../../shared/drive-constraints';
|
|||||||
import * as messages from '../../../../shared/messages';
|
import * as messages from '../../../../shared/messages';
|
||||||
import { ProgressButton } from '../../components/progress-button/progress-button';
|
import { ProgressButton } from '../../components/progress-button/progress-button';
|
||||||
import { SourceOptions } from '../../components/source-selector/source-selector';
|
import { SourceOptions } from '../../components/source-selector/source-selector';
|
||||||
import { TargetSelectorModal } from '../../components/target-selector/target-selector-modal';
|
|
||||||
import * as availableDrives from '../../models/available-drives';
|
import * as availableDrives from '../../models/available-drives';
|
||||||
import * as flashState from '../../models/flash-state';
|
import * as flashState from '../../models/flash-state';
|
||||||
import * as selection from '../../models/selection-state';
|
import * as selection from '../../models/selection-state';
|
||||||
@ -32,7 +31,10 @@ import * as analytics from '../../modules/analytics';
|
|||||||
import { scanner as driveScanner } from '../../modules/drive-scanner';
|
import { scanner as driveScanner } from '../../modules/drive-scanner';
|
||||||
import * as imageWriter from '../../modules/image-writer';
|
import * as imageWriter from '../../modules/image-writer';
|
||||||
import * as notification from '../../os/notification';
|
import * as notification from '../../os/notification';
|
||||||
import { selectAllTargets } from './DriveSelector';
|
import {
|
||||||
|
selectAllTargets,
|
||||||
|
TargetSelectorModal,
|
||||||
|
} from '../../components/target-selector/target-selector';
|
||||||
|
|
||||||
import FlashSvg from '../../../assets/flash.svg';
|
import FlashSvg from '../../../assets/flash.svg';
|
||||||
|
|
||||||
@ -333,7 +335,7 @@ export class FlashStep extends React.PureComponent<
|
|||||||
selectAllTargets(modalTargets);
|
selectAllTargets(modalTargets);
|
||||||
this.setState({ showDriveSelectorModal: false });
|
this.setState({ showDriveSelectorModal: false });
|
||||||
}}
|
}}
|
||||||
></TargetSelectorModal>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -44,7 +44,10 @@ import {
|
|||||||
|
|
||||||
import { bytesToClosestUnit } from '../../../../shared/units';
|
import { bytesToClosestUnit } from '../../../../shared/units';
|
||||||
|
|
||||||
import { DriveSelector, getDriveListLabel } from './DriveSelector';
|
import {
|
||||||
|
TargetSelector,
|
||||||
|
getDriveListLabel,
|
||||||
|
} from '../../components/target-selector/target-selector';
|
||||||
import { FlashStep } from './Flash';
|
import { FlashStep } from './Flash';
|
||||||
|
|
||||||
import EtcherSvg from '../../../assets/etcher.svg';
|
import EtcherSvg from '../../../assets/etcher.svg';
|
||||||
@ -252,7 +255,7 @@ export class MainPage extends React.Component<
|
|||||||
<Flex>
|
<Flex>
|
||||||
<StepBorder disabled={shouldDriveStepBeDisabled} left />
|
<StepBorder disabled={shouldDriveStepBeDisabled} left />
|
||||||
</Flex>
|
</Flex>
|
||||||
<DriveSelector
|
<TargetSelector
|
||||||
disabled={shouldDriveStepBeDisabled}
|
disabled={shouldDriveStepBeDisabled}
|
||||||
hasDrive={this.state.hasDrive}
|
hasDrive={this.state.hasDrive}
|
||||||
flashing={this.state.isFlashing}
|
flashing={this.state.isFlashing}
|
||||||
|
@ -276,7 +276,7 @@ export function hasListDriveImageCompatibilityStatus(
|
|||||||
return Boolean(getListDriveImageCompatibilityStatuses(drives, image).length);
|
return Boolean(getListDriveImageCompatibilityStatuses(drives, image).length);
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TargetStatus {
|
export interface DriveStatus {
|
||||||
message: string;
|
message: string;
|
||||||
type: number;
|
type: number;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user