| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- 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<string, SupportedValueType> {
- 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<void> {
- 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<void> {
- 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<void>[]): Promise<void> {
- try {
- const invalidFormIds: string[] = [];
- results.forEach((result: PromiseSettledResult<void>, 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}`);
- }
- }
- }
|