Keep OTA update button disabled while updating

This commit is contained in:
stu2not
2026-06-11 17:50:39 +08:00
parent 57291c81fc
commit 9d1537bd5d

View File

@@ -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
? '发现可更新版本'
: '当前设备版本状态'