|
@@ -154,6 +154,7 @@ export struct LocalMusic {
|
|
|
@State isShowTitleBar: boolean = true //是否显示分类导航条
|
|
@State isShowTitleBar: boolean = true //是否显示分类导航条
|
|
|
@State isShowAllBar: boolean = true //是否显示播放全部条
|
|
@State isShowAllBar: boolean = true //是否显示播放全部条
|
|
|
@State isShowSingleLineLyric: boolean = false //是否显示单行歌词
|
|
@State isShowSingleLineLyric: boolean = false //是否显示单行歌词
|
|
|
|
|
+ @State backgroundOpacity: number = 1.0 //背景透明度,用于过渡动画
|
|
|
@State isShowHistory: boolean = true //是否显示最近播放
|
|
@State isShowHistory: boolean = true //是否显示最近播放
|
|
|
@State isCustomizeBg: boolean = false //自定义背景界面
|
|
@State isCustomizeBg: boolean = false //自定义背景界面
|
|
|
@State isGridMusic: boolean = false //是否网格布局
|
|
@State isGridMusic: boolean = false //是否网格布局
|
|
@@ -457,7 +458,11 @@ export struct LocalMusic {
|
|
|
this.cover = this.currentSong.pixelMapPath;
|
|
this.cover = this.currentSong.pixelMapPath;
|
|
|
|
|
|
|
|
// 更新背景
|
|
// 更新背景
|
|
|
- this.updateMusicBackground();
|
|
|
|
|
|
|
+ if (this.isMusicBGCover && this.cover && StrUtil.isNotEmpty(this.cover)) {
|
|
|
|
|
+ this.setImageColor2(this.cover);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.getFixedDefaultBackground();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
LogUtils.getInstance().LOGI(`Heanup LocalMusic: Restored playlist from UnifiedPlayerService - ${this.songList.length} songs, index ${this.curIndex}, current song: ${this.currentSong?.name || 'null'}`);
|
|
LogUtils.getInstance().LOGI(`Heanup LocalMusic: Restored playlist from UnifiedPlayerService - ${this.songList.length} songs, index ${this.curIndex}, current song: ${this.currentSong?.name || 'null'}`);
|
|
@@ -1135,7 +1140,11 @@ export struct LocalMusic {
|
|
|
AppStorage.setOrCreate('currentSong',this.currentSong);
|
|
AppStorage.setOrCreate('currentSong',this.currentSong);
|
|
|
|
|
|
|
|
// 更新背景
|
|
// 更新背景
|
|
|
- this.updateMusicBackground();
|
|
|
|
|
|
|
+ if (this.isMusicBGCover && this.cover && StrUtil.isNotEmpty(this.cover)) {
|
|
|
|
|
+ this.setImageColor2(this.cover);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.getFixedDefaultBackground();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
LogUtils.getInstance().LOGI(`Heanup LocalMusic: mkDownLoadDir - UI updated with existing playlist: ${this.songList.length} songs, current index: ${this.curIndex}, current song: ${this.currentSong?.name || 'none'}`);
|
|
LogUtils.getInstance().LOGI(`Heanup LocalMusic: mkDownLoadDir - UI updated with existing playlist: ${this.songList.length} songs, current index: ${this.curIndex}, current song: ${this.currentSong?.name || 'none'}`);
|
|
@@ -7227,6 +7236,7 @@ export struct LocalMusic {
|
|
|
// .transition(TransitionEffect.asymmetric(TransitionEffect.scale({ x: 1.2, y: 1.2 }).animation({ duration: 500 }),
|
|
// .transition(TransitionEffect.asymmetric(TransitionEffect.scale({ x: 1.2, y: 1.2 }).animation({ duration: 500 }),
|
|
|
// TransitionEffect.scale({ x: 0, y: 0 }) ))
|
|
// TransitionEffect.scale({ x: 0, y: 0 }) ))
|
|
|
.backgroundBrightness({ rate: this.isPuraWP() ? 0.1 : 0, lightUpDegree: -0.1 })
|
|
.backgroundBrightness({ rate: this.isPuraWP() ? 0.1 : 0, lightUpDegree: -0.1 })
|
|
|
|
|
+ .opacity(this.backgroundOpacity)
|
|
|
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
|
|
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
|
|
|
.onClick(() => {
|
|
.onClick(() => {
|
|
|
// this.startAutoHide()
|
|
// this.startAutoHide()
|
|
@@ -12521,28 +12531,125 @@ export struct LocalMusic {
|
|
|
// 注意:不再手动调用 startPlayOrResumePlay(),因为 UnifiedPlayerService 已经处理了播放逻辑
|
|
// 注意:不再手动调用 startPlayOrResumePlay(),因为 UnifiedPlayerService 已经处理了播放逻辑
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- // 更新背景
|
|
|
|
|
- this.updateMusicBackground();
|
|
|
|
|
|
|
+ // 平滑更新背景
|
|
|
|
|
+ this.updateMusicBackgroundWithAnimation();
|
|
|
}, 500);
|
|
}, 500);
|
|
|
}else{
|
|
}else{
|
|
|
this.cover = this.songList[this.curIndex].pixelMapPath
|
|
this.cover = this.songList[this.curIndex].pixelMapPath
|
|
|
// 注意:不再手动调用 startPlayOrResumePlay(),因为 UnifiedPlayerService 已经处理了播放逻辑
|
|
// 注意:不再手动调用 startPlayOrResumePlay(),因为 UnifiedPlayerService 已经处理了播放逻辑
|
|
|
|
|
|
|
|
- // 更新背景
|
|
|
|
|
- this.updateMusicBackground();
|
|
|
|
|
|
|
+ // 平滑更新背景
|
|
|
|
|
+ this.updateMusicBackgroundWithAnimation();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 更新音乐播放背景
|
|
|
|
|
|
|
+ * 平滑更新音乐播放背景 - 带淡入淡出动画
|
|
|
*/
|
|
*/
|
|
|
- private updateMusicBackground() {
|
|
|
|
|
- if (this.isMusicBGCover && this.cover !== undefined && StrUtil.isNotEmpty(this.cover)) {
|
|
|
|
|
- this.setImageColor2(this.cover);
|
|
|
|
|
- } else {
|
|
|
|
|
- this.getImageColor();
|
|
|
|
|
|
|
+ private updateMusicBackgroundWithAnimation() {
|
|
|
|
|
+ if (!this.isMusicBGCover || !this.cover || StrUtil.isEmpty(this.cover)) {
|
|
|
|
|
+ this.getFixedDefaultBackgroundWithAnimation();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 第一步:淡出当前背景
|
|
|
|
|
+ this.getUIContext()?.animateTo({
|
|
|
|
|
+ duration: 300,
|
|
|
|
|
+ curve: Curve.EaseOut
|
|
|
|
|
+ }, () => {
|
|
|
|
|
+ this.backgroundOpacity = 0.3;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 第二步:延迟后更新背景并淡入
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.setImageColor2(this.cover!);
|
|
|
|
|
+
|
|
|
|
|
+ // 第三步:淡入新背景
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.getUIContext()?.animateTo({
|
|
|
|
|
+ duration: 400,
|
|
|
|
|
+ curve: Curve.EaseIn
|
|
|
|
|
+ }, () => {
|
|
|
|
|
+ this.backgroundOpacity = 1.0;
|
|
|
|
|
+ });
|
|
|
|
|
+ }, 100);
|
|
|
|
|
+ }, 350);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取固定的默认背景 - 根据当前歌曲索引生成固定背景,避免闪烁
|
|
|
|
|
+ */
|
|
|
|
|
+ private getFixedDefaultBackground() {
|
|
|
|
|
+ if (!this.context) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 使用当前歌曲索引生成固定的背景,而不是随机
|
|
|
|
|
+ let bg = Utility.getMusisBg2(this.curIndex);
|
|
|
|
|
+ this.imageLabel = bg;
|
|
|
|
|
+
|
|
|
|
|
+ ColorConversion.setSysBarLightBackground(true);
|
|
|
|
|
+ this.context.resourceManager.getMediaContent(bg)
|
|
|
|
|
+ .then((value: Uint8Array) => {
|
|
|
|
|
+ let buffer = value.buffer as ArrayBuffer;
|
|
|
|
|
+ image.createImageSource(buffer).createPixelMap().then((pixelMap) => {
|
|
|
|
|
+ effectKit.createColorPicker(pixelMap, (error, colorPicker) => {
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ Logger.error('Failed to create color picker.');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ let color = colorPicker.getLargestProportionColor();
|
|
|
|
|
+ let colorArr = ColorConversion.dealColor(color.red, color.green, color.blue);
|
|
|
|
|
+ this.imageColor = `rgba(${colorArr[0]}, ${colorArr[1]}, ${colorArr[2]}, 1)`;
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ let headFilter = effectKit.createEffect(pixelMap);
|
|
|
|
|
+ if (headFilter !== null) {
|
|
|
|
|
+ headFilter.blur(15);
|
|
|
|
|
+ headFilter.getEffectPixelMap().then((value) => {
|
|
|
|
|
+ this.imageLabelBg = value;
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch((error: BusinessError) => {
|
|
|
|
|
+ Logger.error(`${error.code} + ${error.message}`)
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch((error: BusinessError) => {
|
|
|
|
|
+ Logger.error(`Failed to load background: ${error.code} + ${error.message}`)
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 带动画的固定默认背景更新
|
|
|
|
|
+ */
|
|
|
|
|
+ private getFixedDefaultBackgroundWithAnimation() {
|
|
|
|
|
+ if (!this.context) {
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 第一步:淡出当前背景
|
|
|
|
|
+ this.getUIContext()?.animateTo({
|
|
|
|
|
+ duration: 300,
|
|
|
|
|
+ curve: Curve.EaseOut
|
|
|
|
|
+ }, () => {
|
|
|
|
|
+ this.backgroundOpacity = 0.3;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 第二步:延迟后更新背景并淡入
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.getFixedDefaultBackground();
|
|
|
|
|
+
|
|
|
|
|
+ // 第三步:淡入新背景
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.getUIContext()?.animateTo({
|
|
|
|
|
+ duration: 400,
|
|
|
|
|
+ curve: Curve.EaseIn
|
|
|
|
|
+ }, () => {
|
|
|
|
|
+ this.backgroundOpacity = 1.0;
|
|
|
|
|
+ });
|
|
|
|
|
+ }, 100);
|
|
|
|
|
+ }, 350);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 存储已播放的歌曲索引
|
|
// 存储已播放的歌曲索引
|