import { hilog } from '@kit.PerformanceAnalysisKit'; import { formProvider, formBindingData } from '@kit.FormKit'; import { preferences } from '@kit.ArkData'; import { WidgetData, FormattedWidgetData, WidgetSize } from './WidgetTypes'; import { FormLayoutManager } from './FormLayoutManager'; import { PreferencesUtil } from '../utils/PreferencesUtil'; import { Context } from '@kit.AbilityKit'; // 定义支持的值类型 type SupportedValueType = string | number | boolean | Uint8Array; const TAG = 'DirectFormUpdateService'; /** * 表单状态数据接口 */ interface FormStateData extends Record { size: string; lastUpdate: number; lastSongId: string; } /** * 表单验证结果接口 */ interface FormValidationResult { formId: string; isValid: boolean; error: Error | null; } /** * 测试数据接口 */ interface TestFormData { test: string; } /** * 直接卡片更新服务 * 按照 HarmonyOS 官方推荐方式,通过持久化的 Form ID 直接更新卡片 */ export class DirectFormUpdateService { private static instance: DirectFormUpdateService | null = null; private layoutManager: FormLayoutManager = FormLayoutManager.getInstance(); private preferencesUtil: PreferencesUtil = PreferencesUtil.getInstance(); private appContext: Context | null = null; private constructor() {} public static getInstance(): DirectFormUpdateService { if (!DirectFormUpdateService.instance) { DirectFormUpdateService.instance = new DirectFormUpdateService(); } return DirectFormUpdateService.instance; } /** * 设置应用上下文 */ public setAppContext(context: Context): void { this.appContext = context; hilog.info(0x0000, TAG, '🎯 App context set for DirectFormUpdateService'); } /** * 更新所有卡片数据 */ public async updateAllForms(data: WidgetData): Promise { try { if (!this.appContext) { hilog.error(0x0000, TAG, '❌ App context not set, cannot update forms'); return; } hilog.info(0x0000, TAG, `🎯 Starting direct form update: isPlaying=${data.playState.isPlaying}, title=${data.currentSong.title}`); // 获取所有持久化的 Form ID const prefs = await this.preferencesUtil.getPreferences(this.appContext); const formIds = await this.preferencesUtil.getFormIds(prefs); if (formIds.length === 0) { hilog.info(0x0000, TAG, '📋 No forms found in persistence, skipping update'); return; } hilog.info(0x0000, TAG, `📋 Found ${formIds.length} forms to update: [${formIds.join(', ')}]`); // 为每个卡片创建单独的更新任务,添加详细日志 const updatePromises = formIds.map((formId, index) => { hilog.info(0x0000, TAG, `🚀 Creating update task ${index + 1}/${formIds.length} for form: ${formId}`); return this.updateSingleForm(formId, data, prefs); }); hilog.info(0x0000, TAG, `⏳ Executing ${updatePromises.length} parallel update tasks...`); // 更新每个卡片 const results = await Promise.allSettled(updatePromises); // 统计更新结果 const successCount = results.filter(result => result.status === 'fulfilled').length; const failureCount = results.filter(result => result.status === 'rejected').length; hilog.info(0x0000, TAG, `🎯 Form update completed: ${successCount} succeeded, ${failureCount} failed`); // 详细记录每个结果 results.forEach((result, index) => { const formId = formIds[index]; if (result.status === 'fulfilled') { hilog.info(0x0000, TAG, `✅ Form ${index + 1}/${formIds.length} (${formId}) updated successfully`); } else { const error = result.reason as Error; hilog.error(0x0000, TAG, `❌ Form ${index + 1}/${formIds.length} (${formId}) failed: ${error.message}`); } }); // 清理无效的 Form ID(16501001 错误表示 Form 不存在) if (failureCount > 0) { hilog.info(0x0000, TAG, `🧹 Starting cleanup of failed forms...`); await this.cleanupInvalidForms(prefs, formIds, results); // 重新获取清理后的 Form ID 列表 const remainingFormIds = await this.preferencesUtil.getFormIds(prefs); hilog.info(0x0000, TAG, `📋 After cleanup: ${remainingFormIds.length} forms remaining: [${remainingFormIds.join(', ')}]`); } } catch (error) { hilog.error(0x0000, TAG, `❌ Failed to update forms: ${error}`); } } /** * 更新单个卡片 */ private async updateSingleForm(formId: string, data: WidgetData, prefs: preferences.Preferences): Promise { try { hilog.info(0x0000, TAG, `🎯 [${formId}] Starting form update...`); // 获取卡片的当前状态(如果有保存的话) const formState = await this.preferencesUtil.getFormState(prefs, formId); const widgetSizeStr = (formState?.size as string) || 'medium'; // 默认使用 medium 尺寸 hilog.info(0x0000, TAG, `🎯 [${formId}] Widget size: ${widgetSizeStr}, formState: ${JSON.stringify(formState)}`); // 转换为 WidgetSize 类型 const widgetSize: WidgetSize = widgetSizeStr as WidgetSize; // 适配数据到卡片尺寸 const adaptedData = this.layoutManager.adaptDataForSize(data, widgetSize); hilog.info(0x0000, TAG, `🎯 [${formId}] Data adapted for size ${widgetSize}`); // 转换为 FormattedWidgetData const formattedData: FormattedWidgetData = { isPlaying: adaptedData.isPlaying, isPaused: adaptedData.isPaused, isLoading: adaptedData.isLoading, songTitle: adaptedData.songTitle, songArtist: adaptedData.songArtist, songAlbum: adaptedData.songAlbum, coverImage: adaptedData.coverImage, currentTime: adaptedData.currentTime, totalTime: adaptedData.totalTime, progressPercentage: adaptedData.progressPercentage, hasNext: adaptedData.hasNext, hasPrevious: adaptedData.hasPrevious, showProgress: adaptedData.showProgress, showCover: adaptedData.showCover, widgetSize: adaptedData.widgetSize, timestamp: Date.now(), imgName: adaptedData.imgName || '' }; hilog.info(0x0000, TAG, `🎯 [${formId}] Formatted data prepared: isPlaying=${formattedData.isPlaying}, title="${formattedData.songTitle}"`); // 创建 FormBindingData 并更新卡片 const formData = formBindingData.createFormBindingData(formattedData); hilog.info(0x0000, TAG, `🎯 [${formId}] FormBindingData created, calling formProvider.updateForm...`); await formProvider.updateForm(formId, formData); hilog.info(0x0000, TAG, `✅ [${formId}] Form updated successfully: isPlaying=${formattedData.isPlaying}, title="${formattedData.songTitle}"`); // 保存当前状态 const stateData: FormStateData = { size: widgetSizeStr, lastUpdate: Date.now(), lastSongId: data.currentSong.id }; await this.preferencesUtil.saveFormState(prefs, formId, stateData); hilog.info(0x0000, TAG, `💾 [${formId}] Form state saved`); } catch (error) { hilog.error(0x0000, TAG, `❌ [${formId}] Failed to update form: ${JSON.stringify(error)}`); throw new Error(`Failed to update form ${formId}: ${JSON.stringify(error)}`); // 重新抛出错误,让 Promise.allSettled 捕获 } } /** * 清理无效的 Form ID */ private async cleanupInvalidForms(prefs: preferences.Preferences, formIds: string[], results: PromiseSettledResult[]): Promise { try { const invalidFormIds: string[] = []; results.forEach((result: PromiseSettledResult, index: number) => { if (result.status === 'rejected') { const error = result.reason as Error; const errorStr = error.toString(); const formId = formIds[index]; hilog.warn(0x0000, TAG, `🔍 Analyzing error for form ${formId}: ${errorStr}`); // 检查是否是因为 Form 不存在导致的错误 // 16501001 是 Form 不存在的错误代码 if (errorStr.includes('form not exist') || errorStr.includes('16501001') || errorStr.includes('FormProvider') || errorStr.includes('invalid form')) { hilog.warn(0x0000, TAG, `🗑️ Form ${formId} appears to be invalid (error: ${errorStr}), marking for cleanup`); invalidFormIds.push(formId); } else { hilog.error(0x0000, TAG, `⚠️ Form ${formId} failed with unknown error: ${errorStr}`); } } }); if (invalidFormIds.length > 0) { hilog.info(0x0000, TAG, `🧹 Cleaning up ${invalidFormIds.length} invalid forms: [${invalidFormIds.join(', ')}]`); for (const invalidFormId of invalidFormIds) { hilog.info(0x0000, TAG, `🗑️ Removing invalid form ID: ${invalidFormId}`); await this.preferencesUtil.removeFormId(prefs, invalidFormId); } hilog.info(0x0000, TAG, `✅ Invalid forms cleaned up successfully. Remaining forms will be updated normally.`); } else { hilog.warn(0x0000, TAG, `⚠️ ${results.filter(r => r.status === 'rejected').length} forms failed but none appear to be invalid (may be temporary errors)`); } } catch (error) { hilog.error(0x0000, TAG, `❌ Failed to cleanup invalid forms: ${error}`); } } }