Keep OTA update button disabled while updating
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { View, Text, Image, Input, Button } from '@tarojs/components'
|
||||
import { useState } from 'react'
|
||||
import Taro, { useDidShow, useShareAppMessage } from '@tarojs/taro'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import Taro, { useDidHide, useDidShow, useShareAppMessage } from '@tarojs/taro'
|
||||
import { authorizeParentPhone, clearToken, getParent, getToken, Parent } from '@/services/auth'
|
||||
import { DEVICE_UNAVAILABLE_MESSAGE } from '@/services/api'
|
||||
import { getCurrentUserId } from '@/services/session'
|
||||
@@ -48,6 +48,22 @@ interface MenuItem {
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
const FIRMWARE_STATUS_POLL_INTERVAL_MS = 3000
|
||||
const FIRMWARE_UPDATE_IN_PROGRESS_STATUSES = new Set(['sent', 'accepted', 'updating'])
|
||||
const FIRMWARE_UPDATE_SUCCESS_STATUSES = new Set(['success', 'completed'])
|
||||
|
||||
function normalizeFirmwareUpdateStatus(status?: string | null): string {
|
||||
return String(status || '').trim().toLowerCase()
|
||||
}
|
||||
|
||||
function isFirmwareUpdateInProgress(status?: string | null): boolean {
|
||||
return FIRMWARE_UPDATE_IN_PROGRESS_STATUSES.has(normalizeFirmwareUpdateStatus(status))
|
||||
}
|
||||
|
||||
function isFirmwareUpdateSuccessful(status?: string | null): boolean {
|
||||
return FIRMWARE_UPDATE_SUCCESS_STATUSES.has(normalizeFirmwareUpdateStatus(status))
|
||||
}
|
||||
|
||||
export default function Sleep() {
|
||||
const systemBanner = useSystemBanner()
|
||||
const [loading, setLoading] = useState(true)
|
||||
@@ -89,11 +105,22 @@ export default function Sleep() {
|
||||
const [familyMemberDisplayName, setFamilyMemberDisplayName] = useState('')
|
||||
const [parentInfo, setParentInfo] = useState<Parent | null>(null)
|
||||
const [isAuthorizingPhone, setIsAuthorizingPhone] = useState(false)
|
||||
const firmwareStatusPollTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
const firmwareStatusPollDeviceIdRef = useRef('')
|
||||
const isFirmwareStatusPollingRef = useRef(false)
|
||||
|
||||
useDidShow(() => {
|
||||
void loadData()
|
||||
})
|
||||
|
||||
useDidHide(() => {
|
||||
stopFirmwareStatusPolling()
|
||||
})
|
||||
|
||||
useEffect(() => () => {
|
||||
stopFirmwareStatusPolling()
|
||||
}, [])
|
||||
|
||||
useShareAppMessage(() => {
|
||||
const targetName = currentChild?.child_name || binding?.device_id || '孩子'
|
||||
return {
|
||||
@@ -145,11 +172,92 @@ export default function Sleep() {
|
||||
|
||||
const currentChildName = currentChild?.child_name || '未设置'
|
||||
|
||||
function clearFirmwareStatusPollTimer() {
|
||||
if (firmwareStatusPollTimerRef.current) {
|
||||
clearTimeout(firmwareStatusPollTimerRef.current)
|
||||
firmwareStatusPollTimerRef.current = null
|
||||
}
|
||||
}
|
||||
|
||||
function stopFirmwareStatusPolling() {
|
||||
clearFirmwareStatusPollTimer()
|
||||
firmwareStatusPollDeviceIdRef.current = ''
|
||||
isFirmwareStatusPollingRef.current = false
|
||||
}
|
||||
|
||||
function scheduleFirmwareStatusPoll(deviceId: string) {
|
||||
clearFirmwareStatusPollTimer()
|
||||
firmwareStatusPollTimerRef.current = setTimeout(() => {
|
||||
void pollFirmwareStatus(deviceId)
|
||||
}, FIRMWARE_STATUS_POLL_INTERVAL_MS)
|
||||
}
|
||||
|
||||
function startFirmwareStatusPolling(deviceId: string) {
|
||||
const normalizedDeviceId = String(deviceId || '').trim()
|
||||
if (!normalizedDeviceId) return
|
||||
|
||||
firmwareStatusPollDeviceIdRef.current = normalizedDeviceId
|
||||
scheduleFirmwareStatusPoll(normalizedDeviceId)
|
||||
}
|
||||
|
||||
function syncFirmwareStatusPolling(deviceId: string, nextFirmwareStatus?: DeviceFirmwareStatus | null) {
|
||||
const normalizedDeviceId = String(deviceId || '').trim()
|
||||
if (!normalizedDeviceId) {
|
||||
stopFirmwareStatusPolling()
|
||||
return
|
||||
}
|
||||
|
||||
if (isFirmwareUpdateInProgress(nextFirmwareStatus?.update_status)) {
|
||||
startFirmwareStatusPolling(normalizedDeviceId)
|
||||
} else {
|
||||
stopFirmwareStatusPolling()
|
||||
}
|
||||
}
|
||||
|
||||
async function pollFirmwareStatus(deviceId: string) {
|
||||
const normalizedDeviceId = String(deviceId || '').trim()
|
||||
if (
|
||||
!normalizedDeviceId ||
|
||||
firmwareStatusPollDeviceIdRef.current !== normalizedDeviceId ||
|
||||
isFirmwareStatusPollingRef.current
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
isFirmwareStatusPollingRef.current = true
|
||||
try {
|
||||
const nextFirmwareStatus = await getDeviceFirmwareStatus(normalizedDeviceId)
|
||||
if (firmwareStatusPollDeviceIdRef.current !== normalizedDeviceId) return
|
||||
|
||||
setFirmwareStatus(nextFirmwareStatus)
|
||||
if (isFirmwareUpdateInProgress(nextFirmwareStatus?.update_status)) {
|
||||
scheduleFirmwareStatusPoll(normalizedDeviceId)
|
||||
return
|
||||
}
|
||||
|
||||
stopFirmwareStatusPolling()
|
||||
const nextStatus = normalizeFirmwareUpdateStatus(nextFirmwareStatus?.update_status)
|
||||
if (isFirmwareUpdateSuccessful(nextStatus)) {
|
||||
Taro.showToast({ title: '系统更新完成', icon: 'success' })
|
||||
} else if (nextStatus === 'failed') {
|
||||
Taro.showToast({ title: '系统更新失败,可重试', icon: 'none' })
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('[manage] firmware poll failed:', error)
|
||||
if (firmwareStatusPollDeviceIdRef.current === normalizedDeviceId) {
|
||||
scheduleFirmwareStatusPoll(normalizedDeviceId)
|
||||
}
|
||||
} finally {
|
||||
isFirmwareStatusPollingRef.current = false
|
||||
}
|
||||
}
|
||||
|
||||
const loadFirmwareStatus = async (deviceId?: string | null) => {
|
||||
const normalizedDeviceId = String(deviceId || '').trim()
|
||||
if (!normalizedDeviceId) {
|
||||
setFirmwareStatus(null)
|
||||
setIsLoadingFirmware(false)
|
||||
stopFirmwareStatusPolling()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -157,9 +265,13 @@ export default function Sleep() {
|
||||
try {
|
||||
const nextFirmwareStatus = await getDeviceFirmwareStatus(normalizedDeviceId)
|
||||
setFirmwareStatus(nextFirmwareStatus)
|
||||
syncFirmwareStatusPolling(normalizedDeviceId, nextFirmwareStatus)
|
||||
} catch (error: any) {
|
||||
console.error('[manage] firmware load failed:', error)
|
||||
setFirmwareStatus(null)
|
||||
if (firmwareStatusPollDeviceIdRef.current === normalizedDeviceId) {
|
||||
stopFirmwareStatusPolling()
|
||||
}
|
||||
Taro.showToast({
|
||||
title: error?.message || '系统更新状态加载失败',
|
||||
icon: 'none',
|
||||
@@ -551,7 +663,15 @@ export default function Sleep() {
|
||||
}
|
||||
|
||||
const handleStartFirmwareUpdate = () => {
|
||||
if (!binding?.device_id || !firmwareStatus?.can_update || isLoadingFirmware || isUpdatingFirmware) return
|
||||
if (
|
||||
!binding?.device_id ||
|
||||
!firmwareStatus?.can_update ||
|
||||
isLoadingFirmware ||
|
||||
isUpdatingFirmware ||
|
||||
isFirmwareUpdateInProgress(firmwareStatus.update_status)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
Taro.showModal({
|
||||
title: '系统更新',
|
||||
@@ -574,6 +694,7 @@ export default function Sleep() {
|
||||
|
||||
const nextFirmwareStatus = await startDeviceFirmwareUpdate(binding.device_id)
|
||||
setFirmwareStatus(nextFirmwareStatus)
|
||||
syncFirmwareStatusPolling(binding.device_id, nextFirmwareStatus)
|
||||
Taro.showToast({
|
||||
title: '更新指令已发送',
|
||||
icon: 'success',
|
||||
@@ -787,8 +908,25 @@ export default function Sleep() {
|
||||
familyInfo?.device_id === binding.device_id &&
|
||||
isFamilyOwner
|
||||
)
|
||||
const canUpdateFirmware = Boolean(binding?.device_id && firmwareStatus?.can_update && !isLoadingFirmware && !isUpdatingFirmware)
|
||||
const firmwareActionText = isLoadingFirmware ? '查询中' : isUpdatingFirmware ? '发送中' : '更新'
|
||||
const isFirmwareUpdatingByStatus = isFirmwareUpdateInProgress(firmwareStatus?.update_status)
|
||||
const canUpdateFirmware = Boolean(
|
||||
binding?.device_id &&
|
||||
firmwareStatus?.can_update &&
|
||||
!isLoadingFirmware &&
|
||||
!isUpdatingFirmware &&
|
||||
!isFirmwareUpdatingByStatus
|
||||
)
|
||||
const firmwareActionText = !binding?.device_id
|
||||
? '更新'
|
||||
: isLoadingFirmware
|
||||
? '查询中'
|
||||
: isUpdatingFirmware
|
||||
? '发送中'
|
||||
: isFirmwareUpdatingByStatus
|
||||
? '更新中'
|
||||
: firmwareStatus?.update_available
|
||||
? '更新'
|
||||
: '已最新'
|
||||
const roleValue = !binding?.device_id
|
||||
? '未绑定'
|
||||
: isLoadingRoles
|
||||
@@ -803,6 +941,10 @@ export default function Sleep() {
|
||||
? '绑定设备后可查看系统版本'
|
||||
: isLoadingFirmware
|
||||
? '正在查询当前设备版本'
|
||||
: isFirmwareUpdatingByStatus
|
||||
? '设备正在更新,请稍候'
|
||||
: normalizeFirmwareUpdateStatus(firmwareStatus?.update_status) === 'failed'
|
||||
? '更新失败,可重试'
|
||||
: firmwareStatus?.update_available
|
||||
? '发现可更新版本'
|
||||
: '当前设备版本状态'
|
||||
|
||||
Reference in New Issue
Block a user