@@ -11,15 +11,14 @@ import {
1111 getDeviceBootloaderVersion ,
1212} from '@onekeyfe/hd-core' ;
1313import { serviceHardware } from '@/hardware' ;
14- import { setDevice } from '@/store/reducers/runtime' ;
14+ import { setDevice , setPageStatus } from '@/store/reducers/runtime' ;
1515import { RestartToHomeTip , ListTips , EmptyTips } from './TouchResource/Tips' ;
1616import ResourceButton from './TouchResource/Button' ;
1717
1818import ConfirmDialog from '../Modal' ;
1919import ReleaseInfo from './ReleaseInfo' ;
2020import BootloaderTips from './BootloaderTips' ;
2121import ProgressBar from './ProgressBar' ;
22- import BridgeReleaseDialog from './BridgeReleaseDialog' ;
2322import V3FirmwareConfirmUpdate from './V3FirmwareConfirmUpdate' ;
2423import V3ReleaseInfo from './V3ReleaseInfo' ;
2524
@@ -28,12 +27,20 @@ let isPollingUpdateDevice = false;
2827
2928const DeviceEventAlert : FC = ( ) => {
3029 const intl = useIntl ( ) ;
30+ const needsPermission = useSelector (
31+ ( state : RootState ) => state . runtime . needsBootloaderPermission
32+ ) ;
3133 const showPinAlert = useSelector (
3234 ( state : RootState ) => state . firmware . showPinAlert
3335 ) ;
3436 const showButtonAlert = useSelector (
3537 ( state : RootState ) => state . firmware . showButtonAlert
3638 ) ;
39+
40+ if ( needsPermission ) {
41+ return null ;
42+ }
43+
3744 return (
3845 < >
3946 { showPinAlert && (
@@ -95,6 +102,76 @@ const Description: FC<{ text: string; value: any }> = ({ text, value }) => (
95102 </ div >
96103) ;
97104
105+ const BootloaderStatusAlert : FC = ( ) => {
106+ const intl = useIntl ( ) ;
107+ const device = useSelector ( ( state : RootState ) => state . runtime . device ) ;
108+ const isBootLoader = device ?. features ?. bootloader_mode ;
109+
110+ if ( ! isBootLoader ) {
111+ return null ;
112+ }
113+
114+ // Bootloader mode - 提示用户当前处于可更新状态
115+ return (
116+ < div className = "my-2" >
117+ < Alert
118+ type = "info"
119+ title = { intl . formatMessage ( { id : 'TR_DEVICE_IN_BOOTLOADER_MODE' } ) }
120+ content = { intl . formatMessage ( { id : 'TR_DEVICE_READY_FOR_UPDATE' } ) }
121+ />
122+ </ div >
123+ ) ;
124+ } ;
125+
126+ const BootloaderPermissionPrompt : FC = ( ) => {
127+ const intl = useIntl ( ) ;
128+ const needsPermission = useSelector (
129+ ( state : RootState ) => state . runtime . needsBootloaderPermission
130+ ) ;
131+ const [ authorizing , setAuthorizing ] = useState ( false ) ;
132+
133+ if ( ! needsPermission ) {
134+ return null ;
135+ }
136+
137+ const handleAuthorize = async ( ) => {
138+ if ( authorizing ) {
139+ return ;
140+ }
141+ setAuthorizing ( true ) ;
142+ try {
143+ const success = await serviceHardware . promptBootloaderDeviceAccess ( ) ;
144+ if ( ! success ) {
145+ console . warn ( 'Bootloader 设备重新授权未完成,可提示用户再次尝试。' ) ;
146+ }
147+ } finally {
148+ setAuthorizing ( false ) ;
149+ }
150+ } ;
151+
152+ return (
153+ < div className = "my-2" >
154+ < Alert
155+ type = "warning"
156+ title = { intl . formatMessage ( { id : 'TR_BOOTLOADER_PERMISSION_REQUIRED' } ) }
157+ content = { intl . formatMessage ( {
158+ id : 'TR_BOOTLOADER_PERMISSION_REQUIRED_DESC' ,
159+ } ) }
160+ action = {
161+ < Button
162+ type = "primary"
163+ size = "sm"
164+ onClick = { handleAuthorize }
165+ loading = { authorizing }
166+ >
167+ { intl . formatMessage ( { id : 'TR_REAUTHORIZE_DEVICE' } ) }
168+ </ Button >
169+ }
170+ />
171+ </ div >
172+ ) ;
173+ } ;
174+
98175const RebootToBoard : FC = ( ) => {
99176 const intl = useIntl ( ) ;
100177 const device = useSelector ( ( state : RootState ) => state . runtime . device ) ;
@@ -128,23 +205,39 @@ const RebootToBoard: FC = () => {
128205 return null ;
129206} ;
130207
208+ const ReconnectDevice : FC = ( ) => {
209+ const intl = useIntl ( ) ;
210+ const dispatch = useDispatch ( ) ;
211+ const device = useSelector ( ( state : RootState ) => state . runtime . device ) ;
212+
213+ const handleReconnect = useCallback ( ( ) => {
214+ // Clear current device and return to search page
215+ dispatch ( setDevice ( null ) ) ;
216+ dispatch ( setPageStatus ( 'searching' ) ) ;
217+ } , [ dispatch ] ) ;
218+
219+ // Show reconnect button when no device is connected
220+ if ( ! device ) {
221+ return (
222+ < div className = "flex items-center justify-center py-4" >
223+ < Button type = "primary" size = "lg" onClick = { handleReconnect } >
224+ { intl . formatMessage ( { id : 'TR_RECONNECT_DEVICE' } ) }
225+ </ Button >
226+ </ div >
227+ ) ;
228+ }
229+
230+ return null ;
231+ } ;
232+
131233const ConfirmUpdate : FC = ( ) => {
132234 const intl = useIntl ( ) ;
133235 const device = useSelector ( ( state : RootState ) => state . runtime . device ) ;
134- const releaseMap = useSelector (
135- ( state : RootState ) => state . runtime . releaseMap
136- ) ;
137- const selectedReleaseInfo = useSelector (
138- ( state : RootState ) => state . runtime . selectedReleaseInfo
139- ) ;
140236 const selectedUploadType = useSelector (
141237 ( state : RootState ) => state . runtime . selectedUploadType
142238 ) ;
143239 const tabType = useSelector ( ( state : RootState ) => state . runtime . currentTab ) ;
144240 const [ confirmProtocol , setConfirmProtocol ] = useState ( false ) ;
145- const [ bridgeReleaseModalVisible , setBridgeReleaseModalVisible ] =
146- useState ( false ) ;
147- const [ bridgeReleaseVersion , setBridgeReleaseVersion ] = useState ( '' ) ;
148241 const [ isUpdating , setIsUpdating ] = useState ( false ) ;
149242 const onHandleInstall = useCallback ( async ( ) => {
150243 if ( isUpdating ) return ;
@@ -153,25 +246,6 @@ const ConfirmUpdate: FC = () => {
153246 }
154247 setIsUpdating ( true ) ;
155248 try {
156- if (
157- device ?. deviceType &&
158- ( selectedUploadType === 'firmware' || selectedUploadType === 'ble' )
159- ) {
160- const firmwareField = selectedReleaseInfo ?. firmwareField ;
161- if ( firmwareField ) {
162- const version =
163- releaseMap [ device . deviceType ] ?. [ firmwareField ] ?. [ 0 ] ?. version ;
164- const checkBridgeRelease = await serviceHardware . checkBridgeRelease (
165- version ?. join ( '.' ) ?? ''
166- ) ;
167- if ( checkBridgeRelease ?. shouldUpdate ) {
168- setBridgeReleaseVersion ( checkBridgeRelease . releaseVersion ) ;
169- setBridgeReleaseModalVisible ( true ) ;
170- return ;
171- }
172- }
173- }
174-
175249 if ( tabType === 'bootloader' ) {
176250 await serviceHardware . bootloaderUpdate ( ) ;
177251 } else {
@@ -182,14 +256,7 @@ const ConfirmUpdate: FC = () => {
182256 } finally {
183257 setIsUpdating ( false ) ;
184258 }
185- } , [
186- device ,
187- selectedUploadType ,
188- selectedReleaseInfo ,
189- releaseMap ,
190- tabType ,
191- isUpdating ,
192- ] ) ;
259+ } , [ tabType , isUpdating ] ) ;
193260
194261 return (
195262 < div className = "flex justify-center items-center flex-col" >
@@ -226,11 +293,6 @@ const ConfirmUpdate: FC = () => {
226293 { intl . formatMessage ( { id : 'TR_FIRMWARE_HEADING' } ) }
227294 </ Button >
228295 </ div >
229- < BridgeReleaseDialog
230- visible = { bridgeReleaseModalVisible }
231- setVisible = { setBridgeReleaseModalVisible }
232- version = { bridgeReleaseVersion }
233- />
234296 </ div >
235297 ) ;
236298} ;
@@ -355,8 +417,10 @@ export default function Firmware() {
355417 : 'TR_FIRMWARE_HEADING' ,
356418 } ) }
357419 </ h1 >
420+ < BootloaderPermissionPrompt />
358421 { ! showFirmwareUpdate ? (
359422 < >
423+ < ReconnectDevice />
360424 < div className = "flex flex-row-reverse" >
361425 < div className = "md:w-1/2 sm:w-full" >
362426 < Description
@@ -400,6 +464,7 @@ export default function Firmware() {
400464 < RebootToBoard />
401465 </ div >
402466 </ div >
467+ < BootloaderStatusAlert />
403468 { [ 'touch' , 'pro' ] . includes ( getDeviceType ( device ?. features ) ) && (
404469 < ConfirmDialog
405470 okCancel
0 commit comments