|
@@ -12,14 +12,6 @@ import { WidgetCommand, WidgetControlParams, WidgetData, WidgetSize, FormattedWi
|
|
|
import { FormLayoutManager } from '../common/widget/FormLayoutManager';
|
|
import { FormLayoutManager } from '../common/widget/FormLayoutManager';
|
|
|
import { GlobalWidgetManager } from '../common/widget/GlobalWidgetManager';
|
|
import { GlobalWidgetManager } from '../common/widget/GlobalWidgetManager';
|
|
|
import { WidgetSizeAdapter, SizeChangeListener } from '../common/widget/WidgetSizeAdapter';
|
|
import { WidgetSizeAdapter, SizeChangeListener } from '../common/widget/WidgetSizeAdapter';
|
|
|
-import { WidgetConfigManager, UserPreferences } from '../common/widget/WidgetConfigManager';
|
|
|
|
|
-import { ThemeSyncService, ThemeChangeListener, ThemeChangeEvent, ThemeInfo } from '../common/widget/ThemeSyncService';
|
|
|
|
|
-import {
|
|
|
|
|
- UserPreferencesService,
|
|
|
|
|
- PreferencesChangeListener,
|
|
|
|
|
- PreferencesChangeEvent
|
|
|
|
|
-} from '../common/widget/UserPreferencesService';
|
|
|
|
|
-import { ObjectUtils } from '../common/widget/ObjectUtils';
|
|
|
|
|
import {
|
|
import {
|
|
|
PLAY_PAUSE_EVENT,
|
|
PLAY_PAUSE_EVENT,
|
|
|
NEXT_SONG_EVENT,
|
|
NEXT_SONG_EVENT,
|
|
@@ -43,7 +35,6 @@ const TAG = 'Heanup';
|
|
|
interface WidgetSettingsParams extends Record<string, Object> {
|
|
interface WidgetSettingsParams extends Record<string, Object> {
|
|
|
formId: string;
|
|
formId: string;
|
|
|
currentSize: string;
|
|
currentSize: string;
|
|
|
- currentConfig: string;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -52,7 +43,6 @@ interface WidgetSettingsParams extends Record<string, Object> {
|
|
|
interface WidgetConfigParams extends Record<string, Object> {
|
|
interface WidgetConfigParams extends Record<string, Object> {
|
|
|
formId: string;
|
|
formId: string;
|
|
|
configType: string;
|
|
configType: string;
|
|
|
- configValue: string;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -94,27 +84,24 @@ function copyWidgetData(target: ExtendedWidgetData, overrides: Partial<ExtendedW
|
|
|
* 支持多尺寸适配和UI重构
|
|
* 支持多尺寸适配和UI重构
|
|
|
*/
|
|
*/
|
|
|
export default class EntryFormAbility extends FormExtensionAbility
|
|
export default class EntryFormAbility extends FormExtensionAbility
|
|
|
-implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
|
|
|
|
+implements SizeChangeListener {
|
|
|
private widgetDataManager: WidgetDataManager | null = null;
|
|
private widgetDataManager: WidgetDataManager | null = null;
|
|
|
private playerControlService: PlayerControlService = new PlayerControlService();
|
|
private playerControlService: PlayerControlService = new PlayerControlService();
|
|
|
private layoutManager: FormLayoutManager = FormLayoutManager.getInstance();
|
|
private layoutManager: FormLayoutManager = FormLayoutManager.getInstance();
|
|
|
private sizeAdapter: WidgetSizeAdapter = WidgetSizeAdapter.getInstance();
|
|
private sizeAdapter: WidgetSizeAdapter = WidgetSizeAdapter.getInstance();
|
|
|
- private configManager: WidgetConfigManager = WidgetConfigManager.getInstance();
|
|
|
|
|
- private themeSyncService: ThemeSyncService = ThemeSyncService.getInstance();
|
|
|
|
|
- private userPreferencesService: UserPreferencesService = UserPreferencesService.getInstance();
|
|
|
|
|
private globalWidgetManager: GlobalWidgetManager = GlobalWidgetManager.getInstance();
|
|
private globalWidgetManager: GlobalWidgetManager = GlobalWidgetManager.getInstance();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 使用实例变量而不是静态变量,确保每个进程都能正确设置监听器
|
|
// 使用实例变量而不是静态变量,确保每个进程都能正确设置监听器
|
|
|
private globalListenerSetup: boolean = false;
|
|
private globalListenerSetup: boolean = false;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 防抖机制:避免短时间内重复更新
|
|
// 防抖机制:避免短时间内重复更新
|
|
|
private lastUpdateTime: number = 0;
|
|
private lastUpdateTime: number = 0;
|
|
|
private updateDebounceDelay: number = 100; // 100ms防抖延迟
|
|
private updateDebounceDelay: number = 100; // 100ms防抖延迟
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 进程启动时间,用于检测进程重启
|
|
// 进程启动时间,用于检测进程重启
|
|
|
private processStartTime: number = Date.now();
|
|
private processStartTime: number = Date.now();
|
|
|
private lastHealthCheck: number = 0;
|
|
private lastHealthCheck: number = 0;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 图片下载缓存
|
|
// 图片下载缓存
|
|
|
private downloadingImages: Map<string, Promise<string | null>> = new Map();
|
|
private downloadingImages: Map<string, Promise<string | null>> = new Map();
|
|
|
private imageCache: Map<string, string> = new Map(); // url -> fileName映射
|
|
private imageCache: Map<string, string> = new Map(); // url -> fileName映射
|
|
@@ -124,12 +111,12 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
*/
|
|
*/
|
|
|
private initializeServices(): void {
|
|
private initializeServices(): void {
|
|
|
hilog.info(0x0000, TAG, 'Heanup EntryFormAbility initializeServices called');
|
|
hilog.info(0x0000, TAG, 'Heanup EntryFormAbility initializeServices called');
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!this.widgetDataManager) {
|
|
if (!this.widgetDataManager) {
|
|
|
this.widgetDataManager = new WidgetDataManager();
|
|
this.widgetDataManager = new WidgetDataManager();
|
|
|
hilog.info(0x0000, TAG, 'Heanup EntryFormAbility WidgetDataManager initialized');
|
|
hilog.info(0x0000, TAG, 'Heanup EntryFormAbility WidgetDataManager initialized');
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 设置全局状态监听器(每个进程实例设置一次)
|
|
// 设置全局状态监听器(每个进程实例设置一次)
|
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility checking global listener setup: ${this.globalListenerSetup}`);
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility checking global listener setup: ${this.globalListenerSetup}`);
|
|
|
if (!this.globalListenerSetup) {
|
|
if (!this.globalListenerSetup) {
|
|
@@ -153,17 +140,17 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
avSessionListener.addStateListener((data: WidgetData) => {
|
|
avSessionListener.addStateListener((data: WidgetData) => {
|
|
|
const now = Date.now();
|
|
const now = Date.now();
|
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] global listener received state update: isPlaying=${data.playState.isPlaying}, title=${data.currentSong.title}, age=${now - this.processStartTime}ms`);
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] global listener received state update: isPlaying=${data.playState.isPlaying}, title=${data.currentSong.title}, age=${now - this.processStartTime}ms`);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 更新健康检查时间
|
|
// 更新健康检查时间
|
|
|
this.lastHealthCheck = now;
|
|
this.lastHealthCheck = now;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 总是尝试更新,让updateAllWidgetsWithData自己检查
|
|
// 总是尝试更新,让updateAllWidgetsWithData自己检查
|
|
|
this.updateAllWidgetsWithData(data);
|
|
this.updateAllWidgetsWithData(data);
|
|
|
});
|
|
});
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 启动健康检查定时器
|
|
// 启动健康检查定时器
|
|
|
this.startHealthCheck();
|
|
this.startHealthCheck();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] global state listener setup successfully`);
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] global state listener setup successfully`);
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
hilog.error(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] failed to setup global listener: ${error}`);
|
|
hilog.error(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] failed to setup global listener: ${error}`);
|
|
@@ -177,11 +164,11 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
setInterval(() => {
|
|
setInterval(() => {
|
|
|
const now = Date.now();
|
|
const now = Date.now();
|
|
|
const timeSinceLastUpdate = now - this.lastHealthCheck;
|
|
const timeSinceLastUpdate = now - this.lastHealthCheck;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 如果超过30秒没有收到任何状态更新,可能监听器失效了
|
|
// 如果超过30秒没有收到任何状态更新,可能监听器失效了
|
|
|
if (timeSinceLastUpdate > 30000) {
|
|
if (timeSinceLastUpdate > 30000) {
|
|
|
hilog.warn(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] health check failed: ${timeSinceLastUpdate}ms since last update`);
|
|
hilog.warn(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] health check failed: ${timeSinceLastUpdate}ms since last update`);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 尝试强制重连和重新请求当前状态
|
|
// 尝试强制重连和重新请求当前状态
|
|
|
this.playerControlService.forceReconnect().then(() => {
|
|
this.playerControlService.forceReconnect().then(() => {
|
|
|
return this.playerControlService.getCurrentPlayState();
|
|
return this.playerControlService.getCurrentPlayState();
|
|
@@ -202,7 +189,7 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
*/
|
|
*/
|
|
|
private updateAllWidgetsWithData(data: WidgetData): void {
|
|
private updateAllWidgetsWithData(data: WidgetData): void {
|
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility updateAllWidgetsWithData called with isPlaying=${data.playState.isPlaying}, title=${data.currentSong.title}`);
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility updateAllWidgetsWithData called with isPlaying=${data.playState.isPlaying}, title=${data.currentSong.title}`);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 防抖机制:避免短时间内重复更新
|
|
// 防抖机制:避免短时间内重复更新
|
|
|
const now = Date.now();
|
|
const now = Date.now();
|
|
|
if (now - this.lastUpdateTime < this.updateDebounceDelay) {
|
|
if (now - this.lastUpdateTime < this.updateDebounceDelay) {
|
|
@@ -210,27 +197,27 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
this.lastUpdateTime = now;
|
|
this.lastUpdateTime = now;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const activeWidgets = this.globalWidgetManager.getActiveWidgets();
|
|
const activeWidgets = this.globalWidgetManager.getActiveWidgets();
|
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility active widgets count: ${activeWidgets.size}`);
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility active widgets count: ${activeWidgets.size}`);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 打印所有活跃的widget ID
|
|
// 打印所有活跃的widget ID
|
|
|
if (activeWidgets.size > 0) {
|
|
if (activeWidgets.size > 0) {
|
|
|
activeWidgets.forEach((size: WidgetSize, formId: string) => {
|
|
activeWidgets.forEach((size: WidgetSize, formId: string) => {
|
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility found active widget: ${formId}, size: ${size}`);
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility found active widget: ${formId}, size: ${size}`);
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (activeWidgets.size === 0) {
|
|
if (activeWidgets.size === 0) {
|
|
|
hilog.warn(0x0000, TAG, 'Heanup EntryFormAbility no widgets to update in this process, skipping');
|
|
hilog.warn(0x0000, TAG, 'Heanup EntryFormAbility no widgets to update in this process, skipping');
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
activeWidgets.forEach((size: WidgetSize, formId: string) => {
|
|
activeWidgets.forEach((size: WidgetSize, formId: string) => {
|
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility updating widget: ${formId}`);
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility updating widget: ${formId}`);
|
|
|
this.updateSingleWidget(formId, size, data);
|
|
this.updateSingleWidget(formId, size, data);
|
|
|
});
|
|
});
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility batch update completed for ${activeWidgets.size} widgets`);
|
|
hilog.info(0x0000, TAG, `Heanup EntryFormAbility batch update completed for ${activeWidgets.size} widgets`);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -241,7 +228,7 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
try {
|
|
try {
|
|
|
// 根据卡片尺寸适配数据
|
|
// 根据卡片尺寸适配数据
|
|
|
const formattedData = this.layoutManager.adaptDataForSize(data, size);
|
|
const formattedData = this.layoutManager.adaptDataForSize(data, size);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 转换为ExtendedWidgetData
|
|
// 转换为ExtendedWidgetData
|
|
|
const adaptedData: ExtendedWidgetData = {
|
|
const adaptedData: ExtendedWidgetData = {
|
|
|
isPlaying: formattedData.isPlaying,
|
|
isPlaying: formattedData.isPlaying,
|
|
@@ -263,9 +250,9 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
imgName: formattedData.imgName,
|
|
imgName: formattedData.imgName,
|
|
|
formImages: formattedData.formImages
|
|
formImages: formattedData.formImages
|
|
|
};
|
|
};
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
hilog.info(0x0000, TAG, `Heanup widget ${formId} calling formProvider.updateForm with isPlaying=${adaptedData.isPlaying}, hasNext=${adaptedData.hasNext}, hasPrevious=${adaptedData.hasPrevious}, coverImage=${adaptedData.coverImage || 'empty'}`);
|
|
hilog.info(0x0000, TAG, `Heanup widget ${formId} calling formProvider.updateForm with isPlaying=${adaptedData.isPlaying}, hasNext=${adaptedData.hasNext}, hasPrevious=${adaptedData.hasPrevious}, coverImage=${adaptedData.coverImage || 'empty'}`);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 检查是否有网络图片需要下载
|
|
// 检查是否有网络图片需要下载
|
|
|
if (adaptedData.coverImage && this.isNetworkUrl(adaptedData.coverImage)) {
|
|
if (adaptedData.coverImage && this.isNetworkUrl(adaptedData.coverImage)) {
|
|
|
this.updateWidgetWithNetworkImage(formId, adaptedData, retryCount);
|
|
this.updateWidgetWithNetworkImage(formId, adaptedData, retryCount);
|
|
@@ -275,7 +262,7 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
}
|
|
}
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
hilog.error(0x0000, TAG, `Heanup widget ${formId} process error: ${error}`);
|
|
hilog.error(0x0000, TAG, `Heanup widget ${formId} process error: ${error}`);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 如果是处理错误,也尝试重试
|
|
// 如果是处理错误,也尝试重试
|
|
|
if (retryCount < 2) {
|
|
if (retryCount < 2) {
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
@@ -294,7 +281,7 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
hilog.info(0x0000, TAG, `Heanup widget ${formId} updated successfully: isPlaying=${adaptedData.isPlaying}, title=${adaptedData.songTitle}, hasNext=${adaptedData.hasNext}, hasPrevious=${adaptedData.hasPrevious}`);
|
|
hilog.info(0x0000, TAG, `Heanup widget ${formId} updated successfully: isPlaying=${adaptedData.isPlaying}, title=${adaptedData.songTitle}, hasNext=${adaptedData.hasNext}, hasPrevious=${adaptedData.hasPrevious}`);
|
|
|
}).catch(() => {
|
|
}).catch(() => {
|
|
|
hilog.error(0x0000, TAG, `Heanup widget ${formId} update failed, retry count: ${retryCount}`);
|
|
hilog.error(0x0000, TAG, `Heanup widget ${formId} update failed, retry count: ${retryCount}`);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 重试机制:最多重试2次
|
|
// 重试机制:最多重试2次
|
|
|
if (retryCount < 2) {
|
|
if (retryCount < 2) {
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
@@ -311,28 +298,28 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
try {
|
|
try {
|
|
|
const imageUrl: string = adaptedData.coverImage;
|
|
const imageUrl: string = adaptedData.coverImage;
|
|
|
hilog.info(0x0000, TAG, `Heanup widget ${formId} downloading network image: ${imageUrl}`);
|
|
hilog.info(0x0000, TAG, `Heanup widget ${formId} downloading network image: ${imageUrl}`);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 先用无图片的数据快速更新一次
|
|
// 先用无图片的数据快速更新一次
|
|
|
const dataWithoutImage: ExtendedWidgetData = copyWidgetData(adaptedData, { coverImage: '' });
|
|
const dataWithoutImage: ExtendedWidgetData = copyWidgetData(adaptedData, { coverImage: '' });
|
|
|
this.updateWidgetDirectly(formId, dataWithoutImage, 0);
|
|
this.updateWidgetDirectly(formId, dataWithoutImage, 0);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 下载图片
|
|
// 下载图片
|
|
|
const fileName = await this.downloadNetworkImage(imageUrl);
|
|
const fileName = await this.downloadNetworkImage(imageUrl);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (fileName) {
|
|
if (fileName) {
|
|
|
// 准备包含图片的数据
|
|
// 准备包含图片的数据
|
|
|
const imageMap: Record<string, number> = {};
|
|
const imageMap: Record<string, number> = {};
|
|
|
imageMap[fileName] = await this.getImageFileDescriptor(fileName);
|
|
imageMap[fileName] = await this.getImageFileDescriptor(fileName);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const dataWithImage: ExtendedWidgetData = copyWidgetData(adaptedData, {
|
|
const dataWithImage: ExtendedWidgetData = copyWidgetData(adaptedData, {
|
|
|
coverImage: '', // 清空URL
|
|
coverImage: '', // 清空URL
|
|
|
imgName: fileName, // 设置图片名称用于memory://协议
|
|
imgName: fileName, // 设置图片名称用于memory://协议
|
|
|
formImages: imageMap
|
|
formImages: imageMap
|
|
|
});
|
|
});
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const formDataWithImage = formBindingData.createFormBindingData(dataWithImage);
|
|
const formDataWithImage = formBindingData.createFormBindingData(dataWithImage);
|
|
|
await formProvider.updateForm(formId, formDataWithImage);
|
|
await formProvider.updateForm(formId, formDataWithImage);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
hilog.info(0x0000, TAG, `Heanup widget ${formId} updated with network image: ${fileName}`);
|
|
hilog.info(0x0000, TAG, `Heanup widget ${formId} updated with network image: ${fileName}`);
|
|
|
} else {
|
|
} else {
|
|
|
hilog.warn(0x0000, TAG, `Heanup widget ${formId} failed to download image, using default`);
|
|
hilog.warn(0x0000, TAG, `Heanup widget ${formId} failed to download image, using default`);
|
|
@@ -341,7 +328,7 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
}
|
|
}
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
hilog.error(0x0000, TAG, `Heanup widget ${formId} network image update error: ${error}`);
|
|
hilog.error(0x0000, TAG, `Heanup widget ${formId} network image update error: ${error}`);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 失败后回退到无图片模式
|
|
// 失败后回退到无图片模式
|
|
|
const dataWithoutImage: ExtendedWidgetData = copyWidgetData(adaptedData, { coverImage: '' });
|
|
const dataWithoutImage: ExtendedWidgetData = copyWidgetData(adaptedData, { coverImage: '' });
|
|
|
this.updateWidgetDirectly(formId, dataWithoutImage, retryCount);
|
|
this.updateWidgetDirectly(formId, dataWithoutImage, retryCount);
|
|
@@ -366,7 +353,7 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
hilog.info(0x0000, TAG, `Using cached image: ${fileName} for ${imageUrl}`);
|
|
hilog.info(0x0000, TAG, `Using cached image: ${fileName} for ${imageUrl}`);
|
|
|
return fileName;
|
|
return fileName;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 检查是否正在下载
|
|
// 检查是否正在下载
|
|
|
if (this.downloadingImages.has(imageUrl)) {
|
|
if (this.downloadingImages.has(imageUrl)) {
|
|
|
hilog.info(0x0000, TAG, `Image already downloading, waiting: ${imageUrl}`);
|
|
hilog.info(0x0000, TAG, `Image already downloading, waiting: ${imageUrl}`);
|
|
@@ -375,20 +362,20 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
return await existingPromise;
|
|
return await existingPromise;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 开始下载
|
|
// 开始下载
|
|
|
const downloadPromise = this.performImageDownload(imageUrl);
|
|
const downloadPromise = this.performImageDownload(imageUrl);
|
|
|
this.downloadingImages.set(imageUrl, downloadPromise);
|
|
this.downloadingImages.set(imageUrl, downloadPromise);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const fileName = await downloadPromise;
|
|
const fileName = await downloadPromise;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 清理下载状态
|
|
// 清理下载状态
|
|
|
this.downloadingImages.delete(imageUrl);
|
|
this.downloadingImages.delete(imageUrl);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (fileName) {
|
|
if (fileName) {
|
|
|
this.imageCache.set(imageUrl, fileName);
|
|
this.imageCache.set(imageUrl, fileName);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return fileName;
|
|
return fileName;
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
hilog.error(0x0000, TAG, `Failed to download image ${imageUrl}: ${error}`);
|
|
hilog.error(0x0000, TAG, `Failed to download image ${imageUrl}: ${error}`);
|
|
@@ -404,7 +391,7 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
try {
|
|
try {
|
|
|
// 创建HTTP请求
|
|
// 创建HTTP请求
|
|
|
const httpRequest = http.createHttp();
|
|
const httpRequest = http.createHttp();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 设置超时时间为3秒,适合卡片的快速响应需求
|
|
// 设置超时时间为3秒,适合卡片的快速响应需求
|
|
|
const response = await httpRequest.request(imageUrl, {
|
|
const response = await httpRequest.request(imageUrl, {
|
|
|
method: http.RequestMethod.GET,
|
|
method: http.RequestMethod.GET,
|
|
@@ -412,13 +399,13 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
connectTimeout: 3000,
|
|
connectTimeout: 3000,
|
|
|
readTimeout: 3000
|
|
readTimeout: 3000
|
|
|
});
|
|
});
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (response.responseCode === http.ResponseCode.OK && response.result) {
|
|
if (response.responseCode === http.ResponseCode.OK && response.result) {
|
|
|
// 生成文件名
|
|
// 生成文件名
|
|
|
const fileName = 'cover_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5);
|
|
const fileName = 'cover_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5);
|
|
|
const tempDir = this.context.getApplicationContext().tempDir;
|
|
const tempDir = this.context.getApplicationContext().tempDir;
|
|
|
const filePath = tempDir + '/' + fileName;
|
|
const filePath = tempDir + '/' + fileName;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 保存文件
|
|
// 保存文件
|
|
|
const file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
|
|
const file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
|
|
|
await fileIo.write(file.fd, response.result as ArrayBuffer);
|
|
await fileIo.write(file.fd, response.result as ArrayBuffer);
|
|
@@ -491,8 +478,6 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
|
|
|
|
|
// 注册各种监听器
|
|
// 注册各种监听器
|
|
|
this.sizeAdapter.registerSizeChangeListener(formId, this);
|
|
this.sizeAdapter.registerSizeChangeListener(formId, this);
|
|
|
- this.themeSyncService.addThemeChangeListener(this);
|
|
|
|
|
- this.userPreferencesService.addPreferencesChangeListener(this);
|
|
|
|
|
|
|
|
|
|
// 初始化卡片数据
|
|
// 初始化卡片数据
|
|
|
this.initializeWidget(formId, widgetSize);
|
|
this.initializeWidget(formId, widgetSize);
|
|
@@ -588,15 +573,12 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
|
|
|
|
|
// 注销各种监听器
|
|
// 注销各种监听器
|
|
|
this.sizeAdapter.unregisterSizeChangeListener(formId);
|
|
this.sizeAdapter.unregisterSizeChangeListener(formId);
|
|
|
- this.themeSyncService.removeThemeChangeListener(this);
|
|
|
|
|
- this.userPreferencesService.removePreferencesChangeListener(this);
|
|
|
|
|
|
|
|
|
|
// 从全局管理器中注销卡片
|
|
// 从全局管理器中注销卡片
|
|
|
this.globalWidgetManager.unregisterWidget(formId);
|
|
this.globalWidgetManager.unregisterWidget(formId);
|
|
|
|
|
|
|
|
// 清理卡片相关数据和配置
|
|
// 清理卡片相关数据和配置
|
|
|
this.widgetDataManager?.removeWidgetData(formId);
|
|
this.widgetDataManager?.removeWidgetData(formId);
|
|
|
- this.configManager.removeWidgetConfig(formId);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -663,9 +645,6 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
onConfigurationUpdate(newConfig: Object): void {
|
|
onConfigurationUpdate(newConfig: Object): void {
|
|
|
hilog.info(0x0000, TAG, 'onConfigurationUpdate called');
|
|
hilog.info(0x0000, TAG, 'onConfigurationUpdate called');
|
|
|
|
|
|
|
|
- // 启动主题同步服务
|
|
|
|
|
- this.themeSyncService.startThemeSync();
|
|
|
|
|
-
|
|
|
|
|
// 更新所有卡片以适应新配置
|
|
// 更新所有卡片以适应新配置
|
|
|
this.widgetDataManager?.updateAllWidgets();
|
|
this.widgetDataManager?.updateAllWidgets();
|
|
|
}
|
|
}
|
|
@@ -708,27 +687,8 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
return 1; // READY状态
|
|
return 1; // READY状态
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 实现ThemeChangeListener接口
|
|
|
|
|
- * 处理主题变化事件
|
|
|
|
|
- */
|
|
|
|
|
- onThemeChanged(event: ThemeChangeEvent): void {
|
|
|
|
|
- hilog.info(0x0000, TAG, `Theme changed: ${event.themeInfo.theme}`);
|
|
|
|
|
-
|
|
|
|
|
- // 更新所有卡片的主题
|
|
|
|
|
- this.updateAllWidgetsTheme(event.themeInfo);
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 实现PreferencesChangeListener接口
|
|
|
|
|
- * 处理用户偏好设置变化事件
|
|
|
|
|
- */
|
|
|
|
|
- onPreferencesChanged(event: PreferencesChangeEvent): void {
|
|
|
|
|
- hilog.info(0x0000, TAG, `Preferences changed: ${event.changedKeys.join(', ')}`);
|
|
|
|
|
|
|
|
|
|
- // 根据变化的设置更新卡片
|
|
|
|
|
- this.handlePreferencesChange(event.changedKeys, event.newPreferences);
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 初始化卡片
|
|
* 初始化卡片
|
|
@@ -740,14 +700,6 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
// 获取当前播放状态
|
|
// 获取当前播放状态
|
|
|
const currentState = await this.playerControlService.getCurrentPlayState();
|
|
const currentState = await this.playerControlService.getCurrentPlayState();
|
|
|
|
|
|
|
|
- // 获取卡片个性化配置
|
|
|
|
|
- const personalConfig = await this.configManager.getWidgetConfig(formId, widgetSize);
|
|
|
|
|
-
|
|
|
|
|
- // 应用尺寸和个性化配置
|
|
|
|
|
- currentState.config = ObjectUtils.assign(currentState.config);
|
|
|
|
|
- currentState.config.showProgress = personalConfig.showProgress;
|
|
|
|
|
- currentState.config.showCover = personalConfig.showCover;
|
|
|
|
|
- currentState.config.theme = personalConfig.theme;
|
|
|
|
|
|
|
|
|
|
// 适配数据到指定尺寸
|
|
// 适配数据到指定尺寸
|
|
|
const adaptedData = this.layoutManager.adaptDataForSize(currentState, widgetSize);
|
|
const adaptedData = this.layoutManager.adaptDataForSize(currentState, widgetSize);
|
|
@@ -907,67 +859,6 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 更新所有卡片的主题
|
|
|
|
|
- */
|
|
|
|
|
- private async updateAllWidgetsTheme(themeInfo: ThemeInfo): Promise<void> {
|
|
|
|
|
- try {
|
|
|
|
|
- // 更新所有卡片配置中的主题信息
|
|
|
|
|
- await this.configManager.updateAllWidgetConfigs((config) => {
|
|
|
|
|
- const updatedConfig = ObjectUtils.assign(config);
|
|
|
|
|
- updatedConfig.theme = themeInfo.theme;
|
|
|
|
|
- updatedConfig.backgroundColor = themeInfo.backgroundColor;
|
|
|
|
|
- updatedConfig.textColor = themeInfo.textColor;
|
|
|
|
|
- updatedConfig.accentColor = themeInfo.accentColor;
|
|
|
|
|
- return updatedConfig;
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 刷新所有卡片显示
|
|
|
|
|
- await this.widgetDataManager?.updateAllWidgets();
|
|
|
|
|
-
|
|
|
|
|
- hilog.info(0x0000, TAG, 'All widgets theme updated');
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, TAG, `Failed to update all widgets theme: ${error}`);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理偏好设置变化
|
|
|
|
|
- */
|
|
|
|
|
- private async handlePreferencesChange(changedKeys: string[], newPreferences: UserPreferences): Promise<void> {
|
|
|
|
|
- try {
|
|
|
|
|
- // 检查是否需要重新同步主题
|
|
|
|
|
- if (changedKeys.includes('syncThemeColor') && newPreferences.syncThemeColor) {
|
|
|
|
|
- await this.themeSyncService.syncTheme();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 检查是否需要更新缓存设置
|
|
|
|
|
- if (changedKeys.includes('enableCache') || changedKeys.includes('cacheExpiry')) {
|
|
|
|
|
- // 这里可以更新缓存相关设置
|
|
|
|
|
- hilog.info(0x0000, TAG, 'Cache settings updated');
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 检查隐私设置变化
|
|
|
|
|
- const privacyKeys = ['showSongInfo', 'showArtistInfo', 'showAlbumCover'];
|
|
|
|
|
- const hasPrivacyChange = changedKeys.some(key => privacyKeys.includes(key));
|
|
|
|
|
-
|
|
|
|
|
- if (hasPrivacyChange) {
|
|
|
|
|
- // 更新所有卡片的显示配置
|
|
|
|
|
- await this.configManager.updateAllWidgetConfigs((config) => {
|
|
|
|
|
- const updatedConfig = ObjectUtils.assign(config);
|
|
|
|
|
- updatedConfig.showCover = (newPreferences.showAlbumCover as boolean) && config.showCover;
|
|
|
|
|
- return updatedConfig;
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 刷新所有卡片显示
|
|
|
|
|
- await this.widgetDataManager?.updateAllWidgets();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- hilog.info(0x0000, TAG, 'Preferences change handled successfully');
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, TAG, `Failed to handle preferences change: ${error}`);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 处理卡片设置
|
|
* 处理卡片设置
|
|
@@ -978,13 +869,11 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
|
|
|
|
|
// 获取当前卡片配置
|
|
// 获取当前卡片配置
|
|
|
const currentSize = this.globalWidgetManager.getWidgetSize(formId) || WidgetSize.MEDIUM;
|
|
const currentSize = this.globalWidgetManager.getWidgetSize(formId) || WidgetSize.MEDIUM;
|
|
|
- const currentConfig = await this.configManager.getWidgetConfig(formId, currentSize);
|
|
|
|
|
|
|
|
|
|
// 启动主应用到卡片设置页面,传递卡片ID和当前配置
|
|
// 启动主应用到卡片设置页面,传递卡片ID和当前配置
|
|
|
const settingsParams: WidgetSettingsParams = {
|
|
const settingsParams: WidgetSettingsParams = {
|
|
|
formId: formId,
|
|
formId: formId,
|
|
|
- currentSize: currentSize,
|
|
|
|
|
- currentConfig: JSON.stringify(currentConfig)
|
|
|
|
|
|
|
+ currentSize: currentSize
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
await this.playerControlService.launchMainApp('widget_settings', settingsParams);
|
|
await this.playerControlService.launchMainApp('widget_settings', settingsParams);
|
|
@@ -1005,8 +894,7 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
// 显示删除确认对话框(通过主应用)
|
|
// 显示删除确认对话框(通过主应用)
|
|
|
const deleteParams: WidgetConfigParams = {
|
|
const deleteParams: WidgetConfigParams = {
|
|
|
formId: formId,
|
|
formId: formId,
|
|
|
- configType: 'delete',
|
|
|
|
|
- configValue: 'confirm_delete'
|
|
|
|
|
|
|
+ configType: 'delete'
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
await this.playerControlService.launchMainApp('widget_delete_confirm', deleteParams);
|
|
await this.playerControlService.launchMainApp('widget_delete_confirm', deleteParams);
|
|
@@ -1026,13 +914,11 @@ implements SizeChangeListener, ThemeChangeListener, PreferencesChangeListener {
|
|
|
|
|
|
|
|
// 获取当前卡片信息
|
|
// 获取当前卡片信息
|
|
|
const currentSize = this.globalWidgetManager.getWidgetSize(formId) || WidgetSize.MEDIUM;
|
|
const currentSize = this.globalWidgetManager.getWidgetSize(formId) || WidgetSize.MEDIUM;
|
|
|
- const currentConfig = await this.configManager.getWidgetConfig(formId, currentSize);
|
|
|
|
|
|
|
|
|
|
// 启动主应用到卡片配置页面
|
|
// 启动主应用到卡片配置页面
|
|
|
const configParams: WidgetConfigParams = {
|
|
const configParams: WidgetConfigParams = {
|
|
|
formId: formId,
|
|
formId: formId,
|
|
|
- configType: 'full_config',
|
|
|
|
|
- configValue: JSON.stringify(currentConfig)
|
|
|
|
|
|
|
+ configType: 'full_config'
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
await this.playerControlService.launchMainApp('widget_config', configParams);
|
|
await this.playerControlService.launchMainApp('widget_config', configParams);
|