Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
7 changes: 6 additions & 1 deletion config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,12 @@ module.exports = function (webpackEnv) {
// its runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/^$/, /\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
exclude: [
/^$/,
/\.(js|mjs|jsx|ts|tsx|cjs)$/,
/\.html$/,
/\.json$/,
],
type: 'asset/resource',
},
// ** STOP ** Are you adding a new loader?
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
"@headlessui/react": "^1.7.2",
"@heroicons/react": "^2.0.11",
"@noble/hashes": "^1.1.3",
"@onekeyfe/hd-core": "1.1.15",
"@onekeyfe/hd-shared": "1.1.15",
"@onekeyfe/hd-web-sdk": "1.1.15",
"@onekeyfe/hd-common-connect-sdk": "1.1.16",
"@onekeyfe/hd-core": "1.1.16",
"@onekeyfe/hd-shared": "1.1.16",
"@onekeyfe/ui-components": "^1.0.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
"@reduxjs/toolkit": "^1.8.5",
Expand Down Expand Up @@ -185,8 +185,8 @@
"sha.js": "2.4.12",
"cipher-base": "1.0.6",
"@babel/traverse": "7.28.4",
"base-x":"3.0.11",
"base-x": "3.0.11",
"cross-spawn": "7.0.6",
"webpack-dev-middleware":"5.3.4"
"webpack-dev-middleware": "5.3.4"
}
}
151 changes: 108 additions & 43 deletions src/components/Firmware/Firmware.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@ import {
getDeviceBootloaderVersion,
} from '@onekeyfe/hd-core';
import { serviceHardware } from '@/hardware';
import { setDevice } from '@/store/reducers/runtime';
import { setDevice, setPageStatus } from '@/store/reducers/runtime';
import { RestartToHomeTip, ListTips, EmptyTips } from './TouchResource/Tips';
import ResourceButton from './TouchResource/Button';

import ConfirmDialog from '../Modal';
import ReleaseInfo from './ReleaseInfo';
import BootloaderTips from './BootloaderTips';
import ProgressBar from './ProgressBar';
import BridgeReleaseDialog from './BridgeReleaseDialog';
import V3FirmwareConfirmUpdate from './V3FirmwareConfirmUpdate';
import V3ReleaseInfo from './V3ReleaseInfo';

Expand All @@ -28,12 +27,20 @@ let isPollingUpdateDevice = false;

const DeviceEventAlert: FC = () => {
const intl = useIntl();
const needsPermission = useSelector(
(state: RootState) => state.runtime.needsBootloaderPermission
);
const showPinAlert = useSelector(
(state: RootState) => state.firmware.showPinAlert
);
const showButtonAlert = useSelector(
(state: RootState) => state.firmware.showButtonAlert
);

if (needsPermission) {
return null;
}

return (
<>
{showPinAlert && (
Expand Down Expand Up @@ -95,6 +102,76 @@ const Description: FC<{ text: string; value: any }> = ({ text, value }) => (
</div>
);

const BootloaderStatusAlert: FC = () => {
const intl = useIntl();
const device = useSelector((state: RootState) => state.runtime.device);
const isBootLoader = device?.features?.bootloader_mode;

if (!isBootLoader) {
return null;
}

// Bootloader mode - 提示用户当前处于可更新状态
return (
<div className="my-2">
<Alert
type="info"
title={intl.formatMessage({ id: 'TR_DEVICE_IN_BOOTLOADER_MODE' })}
content={intl.formatMessage({ id: 'TR_DEVICE_READY_FOR_UPDATE' })}
/>
</div>
);
};

const BootloaderPermissionPrompt: FC = () => {
const intl = useIntl();
const needsPermission = useSelector(
(state: RootState) => state.runtime.needsBootloaderPermission
);
const [authorizing, setAuthorizing] = useState(false);

if (!needsPermission) {
return null;
}

const handleAuthorize = async () => {
if (authorizing) {
return;
}
setAuthorizing(true);
try {
const success = await serviceHardware.promptBootloaderDeviceAccess();
if (!success) {
console.warn('Bootloader 设备重新授权未完成,可提示用户再次尝试。');
}
} finally {
setAuthorizing(false);
}
};

return (
<div className="my-2">
<Alert
type="warning"
title={intl.formatMessage({ id: 'TR_BOOTLOADER_PERMISSION_REQUIRED' })}
content={intl.formatMessage({
id: 'TR_BOOTLOADER_PERMISSION_REQUIRED_DESC',
})}
action={
<Button
type="primary"
size="sm"
onClick={handleAuthorize}
loading={authorizing}
>
{intl.formatMessage({ id: 'TR_REAUTHORIZE_DEVICE' })}
</Button>
}
/>
</div>
);
};

const RebootToBoard: FC = () => {
const intl = useIntl();
const device = useSelector((state: RootState) => state.runtime.device);
Expand Down Expand Up @@ -128,23 +205,39 @@ const RebootToBoard: FC = () => {
return null;
};

const ReconnectDevice: FC = () => {
const intl = useIntl();
const dispatch = useDispatch();
const device = useSelector((state: RootState) => state.runtime.device);

const handleReconnect = useCallback(() => {
// Clear current device and return to search page
dispatch(setDevice(null));
dispatch(setPageStatus('searching'));
}, [dispatch]);

// Show reconnect button when no device is connected
if (!device) {
return (
<div className="flex items-center justify-center py-4">
<Button type="primary" size="lg" onClick={handleReconnect}>
{intl.formatMessage({ id: 'TR_RECONNECT_DEVICE' })}
</Button>
</div>
);
}

return null;
};

const ConfirmUpdate: FC = () => {
const intl = useIntl();
const device = useSelector((state: RootState) => state.runtime.device);
const releaseMap = useSelector(
(state: RootState) => state.runtime.releaseMap
);
const selectedReleaseInfo = useSelector(
(state: RootState) => state.runtime.selectedReleaseInfo
);
const selectedUploadType = useSelector(
(state: RootState) => state.runtime.selectedUploadType
);
const tabType = useSelector((state: RootState) => state.runtime.currentTab);
const [confirmProtocol, setConfirmProtocol] = useState(false);
const [bridgeReleaseModalVisible, setBridgeReleaseModalVisible] =
useState(false);
const [bridgeReleaseVersion, setBridgeReleaseVersion] = useState('');
const [isUpdating, setIsUpdating] = useState(false);
const onHandleInstall = useCallback(async () => {
if (isUpdating) return;
Expand All @@ -153,25 +246,6 @@ const ConfirmUpdate: FC = () => {
}
setIsUpdating(true);
try {
if (
device?.deviceType &&
(selectedUploadType === 'firmware' || selectedUploadType === 'ble')
) {
const firmwareField = selectedReleaseInfo?.firmwareField;
if (firmwareField) {
const version =
releaseMap[device.deviceType]?.[firmwareField]?.[0]?.version;
const checkBridgeRelease = await serviceHardware.checkBridgeRelease(
version?.join('.') ?? ''
);
if (checkBridgeRelease?.shouldUpdate) {
setBridgeReleaseVersion(checkBridgeRelease.releaseVersion);
setBridgeReleaseModalVisible(true);
return;
}
}
}

if (tabType === 'bootloader') {
await serviceHardware.bootloaderUpdate();
} else {
Expand All @@ -182,14 +256,7 @@ const ConfirmUpdate: FC = () => {
} finally {
setIsUpdating(false);
}
}, [
device,
selectedUploadType,
selectedReleaseInfo,
releaseMap,
tabType,
isUpdating,
]);
}, [tabType, isUpdating]);

return (
<div className="flex justify-center items-center flex-col">
Expand Down Expand Up @@ -226,11 +293,6 @@ const ConfirmUpdate: FC = () => {
{intl.formatMessage({ id: 'TR_FIRMWARE_HEADING' })}
</Button>
</div>
<BridgeReleaseDialog
visible={bridgeReleaseModalVisible}
setVisible={setBridgeReleaseModalVisible}
version={bridgeReleaseVersion}
/>
</div>
);
};
Expand Down Expand Up @@ -355,8 +417,10 @@ export default function Firmware() {
: 'TR_FIRMWARE_HEADING',
})}
</h1>
<BootloaderPermissionPrompt />
{!showFirmwareUpdate ? (
<>
<ReconnectDevice />
<div className="flex flex-row-reverse">
<div className="md:w-1/2 sm:w-full">
<Description
Expand Down Expand Up @@ -400,6 +464,7 @@ export default function Firmware() {
<RebootToBoard />
</div>
</div>
<BootloaderStatusAlert />
{['touch', 'pro'].includes(getDeviceType(device?.features)) && (
<ConfirmDialog
okCancel
Expand Down
4 changes: 0 additions & 4 deletions src/components/Firmware/V3UploadLocalFirmware.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,6 @@ const V3UploadLocalFirmware: React.FC = () => {
{intl.formatMessage({ id: 'TR_LOCAL_FIRMWARE_UPLOAD' }) ||
'本地固件上传'}
</h3>
<p className="text-sm text-gray-500">
{intl.formatMessage({ id: 'TR_LOCAL_FIRMWARE_DESCRIPTION' }) ||
'选择本地固件文件进行更新。上传前请确保文件来源可靠。'}
</p>

<div className="mt-5 grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-2">
{getAllV3ComponentTypes().map((componentType) => {
Expand Down
Loading