|
@@ -78,6 +78,7 @@ import { hilog } from '@kit.PerformanceAnalysisKit';
|
|
|
import { LazyDataSource } from '../common/util/LazyDataSource';
|
|
import { LazyDataSource } from '../common/util/LazyDataSource';
|
|
|
import MediaTable from '../common/util/MediaTable';
|
|
import MediaTable from '../common/util/MediaTable';
|
|
|
import FileDeletionWatcher from '../common/util/FileDeletionWatcher';
|
|
import FileDeletionWatcher from '../common/util/FileDeletionWatcher';
|
|
|
|
|
+import LyricUtil from '../common/util/LyricUtil';
|
|
|
import NetAxiosUtil from '../common/util/NetAxiosUtil';
|
|
import NetAxiosUtil from '../common/util/NetAxiosUtil';
|
|
|
import ImageUtils from '../common/util/ImageUtils';
|
|
import ImageUtils from '../common/util/ImageUtils';
|
|
|
import { ringtone } from '@kit.RingtoneKit';
|
|
import { ringtone } from '@kit.RingtoneKit';
|
|
@@ -89,12 +90,14 @@ import '../common/network/RemoteCacheRegistry';
|
|
|
import { RemoteCacheType, resolveCacheFilePath } from '../common/network/RemoteSongCache';
|
|
import { RemoteCacheType, resolveCacheFilePath } from '../common/network/RemoteSongCache';
|
|
|
import { findWebDavCacheIfExists, triggerWebDavCacheDownload } from '../common/network/WebDavFileCache';
|
|
import { findWebDavCacheIfExists, triggerWebDavCacheDownload } from '../common/network/WebDavFileCache';
|
|
|
import { navidromeApi } from '../common/network/NavidromeApi';
|
|
import { navidromeApi } from '../common/network/NavidromeApi';
|
|
|
|
|
+import { navidromeRestApi } from '../common/network/NavidromeRestApi';
|
|
|
import { jellyfinApi } from '../common/network/JellyfinApi';
|
|
import { jellyfinApi } from '../common/network/JellyfinApi';
|
|
|
import { embyApi } from '../common/network/EmbyApi';
|
|
import { embyApi } from '../common/network/EmbyApi';
|
|
|
import { ServerLogUtil } from '../common/util/ServerLogUtil';
|
|
import { ServerLogUtil } from '../common/util/ServerLogUtil';
|
|
|
import { ensureSmbFileStreaming, SmbStreamingMeta } from '../common/network/SmbFileCache';
|
|
import { ensureSmbFileStreaming, SmbStreamingMeta } from '../common/network/SmbFileCache';
|
|
|
import { ensureBaiduFileCached } from '../common/network/BaiduFileCache';
|
|
import { ensureBaiduFileCached } from '../common/network/BaiduFileCache';
|
|
|
import FileManager from '../common/util/FileManager';
|
|
import FileManager from '../common/util/FileManager';
|
|
|
|
|
+import { lyricService, SongData } from '../common/service/LyricService';
|
|
|
|
|
|
|
|
import { HSBColorPicker, HSBColorPickerLayout } from '@keke/color-picker'
|
|
import { HSBColorPicker, HSBColorPickerLayout } from '@keke/color-picker'
|
|
|
import app from '@system.app';
|
|
import app from '@system.app';
|
|
@@ -192,8 +195,8 @@ function isSmbType(type: number): boolean {
|
|
|
return type === CommonConstants.TYPE_SMB;
|
|
return type === CommonConstants.TYPE_SMB;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function isNavidromeType(type: number): boolean {
|
|
|
|
|
- return type === CommonConstants.TYPE_NAVIDROME;
|
|
|
|
|
|
|
+function isNavidromeType(type: number | undefined): boolean {
|
|
|
|
|
+ return type !== undefined && type === CommonConstants.TYPE_NAVIDROME;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function isFtpType(type: number): boolean {
|
|
function isFtpType(type: number): boolean {
|
|
@@ -204,12 +207,12 @@ function isBaiduType(type: number): boolean {
|
|
|
return type === CommonConstants.TYPE_BAIDU;
|
|
return type === CommonConstants.TYPE_BAIDU;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function isJellyfinType(type: number): boolean {
|
|
|
|
|
- return type === CommonConstants.TYPE_JELLYFIN;
|
|
|
|
|
|
|
+function isJellyfinType(type: number | undefined): boolean {
|
|
|
|
|
+ return type !== undefined && type === CommonConstants.TYPE_JELLYFIN;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function isEmbyType(type: number): boolean {
|
|
|
|
|
- return type === CommonConstants.TYPE_EMBY;
|
|
|
|
|
|
|
+function isEmbyType(type: number | undefined): boolean {
|
|
|
|
|
+ return type !== undefined && type === CommonConstants.TYPE_EMBY;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function isRemoteCloudType(type: number): boolean {
|
|
function isRemoteCloudType(type: number): boolean {
|
|
@@ -814,6 +817,8 @@ const ITEM_HEIGHT_BIG: number = 78; // 列表项大高度
|
|
|
@Preview
|
|
@Preview
|
|
|
@Component
|
|
@Component
|
|
|
export struct LocalMusic {
|
|
export struct LocalMusic {
|
|
|
|
|
+ @State isPaging: boolean = true;//是否分页加载机制
|
|
|
|
|
+ @State isCoverRectangle: boolean = true;
|
|
|
@State showZMIndex: boolean = false //是否右侧显示字母索引
|
|
@State showZMIndex: boolean = false //是否右侧显示字母索引
|
|
|
private prevOffsetY: number = 0; // 记录上一次的Y轴偏移量
|
|
private prevOffsetY: number = 0; // 记录上一次的Y轴偏移量
|
|
|
@State autoHideTitle: boolean = true //滚动自动隐藏标题栏
|
|
@State autoHideTitle: boolean = true //滚动自动隐藏标题栏
|
|
@@ -1286,7 +1291,7 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
//侧滑广播接收时间
|
|
//侧滑广播接收时间
|
|
|
let eventUpdateSwipeBack: emitter.InnerEvent = { eventId: EventConstants.EVENT_SWIPE_BACK_UPDATE }
|
|
let eventUpdateSwipeBack: emitter.InnerEvent = { eventId: EventConstants.EVENT_SWIPE_BACK_UPDATE }
|
|
|
- // 监听广播事件(打开其他应用处理)
|
|
|
|
|
|
|
+ // 监听广播事件(手势返回处理)
|
|
|
emitter.on(eventUpdateSwipeBack, (eventData: emitter.EventData) => {
|
|
emitter.on(eventUpdateSwipeBack, (eventData: emitter.EventData) => {
|
|
|
|
|
|
|
|
animateTo({ duration: 555 }, () => {
|
|
animateTo({ duration: 555 }, () => {
|
|
@@ -1880,22 +1885,11 @@ export struct LocalMusic {
|
|
|
this.refreshLazyListViews(mainListUpdated, playlistUpdated);
|
|
this.refreshLazyListViews(mainListUpdated, playlistUpdated);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private closeLoadingDialog(): void {
|
|
|
|
|
- if (!this.loadingDialogId) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- DialogHelper.closeDialog(this.loadingDialogId);
|
|
|
|
|
- this.loadingDialogId = '';
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- private closeLoadingProgressDialog(): void {
|
|
|
|
|
- DialogHelper.closeLoading();
|
|
|
|
|
- this.loadingProgressDialogId = '';
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
private handleEditMusicResult(result: WorkerEditMusicResult): void {
|
|
private handleEditMusicResult(result: WorkerEditMusicResult): void {
|
|
|
// 关闭进度条
|
|
// 关闭进度条
|
|
|
- this.closeLoadingDialog();
|
|
|
|
|
|
|
+ DialogHelper.closeDialog(this.loadingDialogId)
|
|
|
|
|
|
|
|
if (result.success) {
|
|
if (result.success) {
|
|
|
console.log("heanup 编辑信息成功,数据库已同步");
|
|
console.log("heanup 编辑信息成功,数据库已同步");
|
|
@@ -2961,14 +2955,13 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
// 初始化进度条
|
|
// 初始化进度条
|
|
|
this.progress = 0;
|
|
this.progress = 0;
|
|
|
- DialogHelper.showLoadingProgress({
|
|
|
|
|
|
|
+ this.loadingProgressDialogId = DialogHelper.showLoadingProgress({
|
|
|
progress: this.progress,
|
|
progress: this.progress,
|
|
|
backCancel: false,
|
|
backCancel: false,
|
|
|
autoCancel: false,
|
|
autoCancel: false,
|
|
|
loadColor: $r('app.color.title_bar_bg'),
|
|
loadColor: $r('app.color.title_bar_bg'),
|
|
|
fontColor: $r('app.color.title_bar_bg')
|
|
fontColor: $r('app.color.title_bar_bg')
|
|
|
});
|
|
});
|
|
|
- this.loadingProgressDialogId = '';
|
|
|
|
|
|
|
|
|
|
// 计算处理总数用于进度计算
|
|
// 计算处理总数用于进度计算
|
|
|
const totalItems = uris.length;
|
|
const totalItems = uris.length;
|
|
@@ -2996,18 +2989,18 @@ export struct LocalMusic {
|
|
|
// 更新进度
|
|
// 更新进度
|
|
|
processedItems++;
|
|
processedItems++;
|
|
|
this.progress = Math.floor((processedItems / totalItems) * 100);
|
|
this.progress = Math.floor((processedItems / totalItems) * 100);
|
|
|
- DialogHelper.updateLoading(` 正在处理 ${this.progress}%`, this.progress);
|
|
|
|
|
|
|
+ DialogHelper.updateLoading(this.loadingProgressDialogId,` 正在处理 ${this.progress}%`, this.progress);
|
|
|
|
|
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
Logger.error(TAG, 'saveVideoDatas failed with err: ' + JSON.stringify(error));
|
|
Logger.error(TAG, 'saveVideoDatas failed with err: ' + JSON.stringify(error));
|
|
|
// 即使出错也更新进度
|
|
// 即使出错也更新进度
|
|
|
processedItems++;
|
|
processedItems++;
|
|
|
this.progress = Math.floor((processedItems / totalItems) * 100);
|
|
this.progress = Math.floor((processedItems / totalItems) * 100);
|
|
|
- DialogHelper.updateLoading(` 正在处理 ${this.progress}%`, this.progress);
|
|
|
|
|
|
|
+ DialogHelper.updateLoading(this.loadingProgressDialogId,` 正在处理 ${this.progress}%`, this.progress);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
// 关闭进度条
|
|
// 关闭进度条
|
|
|
- this.closeLoadingProgressDialog();
|
|
|
|
|
|
|
+ DialogHelper.closeDialog(this.loadingProgressDialogId)
|
|
|
this.isZero = false
|
|
this.isZero = false
|
|
|
// 删除目标路径缓存
|
|
// 删除目标路径缓存
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
@@ -3024,14 +3017,13 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
let newUris: string[] = [];
|
|
let newUris: string[] = [];
|
|
|
this.progress = 0
|
|
this.progress = 0
|
|
|
- DialogHelper.showLoadingProgress({
|
|
|
|
|
|
|
+ this.loadingProgressDialogId = DialogHelper.showLoadingProgress({
|
|
|
progress: this.progress,
|
|
progress: this.progress,
|
|
|
backCancel: false,
|
|
backCancel: false,
|
|
|
autoCancel: false,
|
|
autoCancel: false,
|
|
|
loadColor: this.themeColor,
|
|
loadColor: this.themeColor,
|
|
|
fontColor: this.themeColor
|
|
fontColor: this.themeColor
|
|
|
});
|
|
});
|
|
|
- this.loadingProgressDialogId = '';
|
|
|
|
|
// 计算所有文件的总大小
|
|
// 计算所有文件的总大小
|
|
|
let totalSize = 0;
|
|
let totalSize = 0;
|
|
|
for (let uri of uris) {
|
|
for (let uri of uris) {
|
|
@@ -3063,7 +3055,7 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
// 计算总进度
|
|
// 计算总进度
|
|
|
this.progress = Math.floor((totalRead / totalSize) * 100);
|
|
this.progress = Math.floor((totalRead / totalSize) * 100);
|
|
|
- DialogHelper.updateLoading(`正在导入 ${this.progress}%`, this.progress);
|
|
|
|
|
|
|
+ DialogHelper.updateLoading( this.loadingProgressDialogId,`正在导入 ${this.progress}%`, this.progress);
|
|
|
|
|
|
|
|
len = await fileIo.read(sourceFile.fd, buffer);
|
|
len = await fileIo.read(sourceFile.fd, buffer);
|
|
|
}
|
|
}
|
|
@@ -3093,16 +3085,10 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- this.closeLoadingProgressDialog()
|
|
|
|
|
|
|
+ DialogHelper.closeDialog(this.loadingProgressDialogId);
|
|
|
this.isZero = false
|
|
this.isZero = false
|
|
|
- this.loadingProgressDialogId = ''
|
|
|
|
|
|
|
|
|
|
- // setTimeout(() => {
|
|
|
|
|
- // // 删除目标路径缓存
|
|
|
|
|
- // this.cache.delete(this.currentPath);
|
|
|
|
|
- // this.getSortedFiles(this.currentPath,true,destPath,isOpen)
|
|
|
|
|
- // }, 500);
|
|
|
|
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
|
|
Logger.info(TAG, 'scan select video result:' + newUris)
|
|
Logger.info(TAG, 'scan select video result:' + newUris)
|
|
@@ -3456,8 +3442,7 @@ export struct LocalMusic {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
.bindContentCover($$this.isShowPlay, this.MusicPlayBuilder(), {
|
|
.bindContentCover($$this.isShowPlay, this.MusicPlayBuilder(), {
|
|
|
- modalTransition: this.isCoverRectangle?ModalTransition.DEFAULT:ModalTransition.NONE,
|
|
|
|
|
- transition: this.isCoverRectangle?null:AnimationHelper.transitionInDown(500),
|
|
|
|
|
|
|
+ modalTransition:ModalTransition.DEFAULT,
|
|
|
onWillDisappear: () => {
|
|
onWillDisappear: () => {
|
|
|
this.setShowPlayFalse()
|
|
this.setShowPlayFalse()
|
|
|
},
|
|
},
|
|
@@ -6738,7 +6723,7 @@ export struct LocalMusic {
|
|
|
) //拖动List关键代码结束
|
|
) //拖动List关键代码结束
|
|
|
|
|
|
|
|
}, (item: VideoItem) => item.filePath + '_' + this.listRefreshKey)
|
|
}, (item: VideoItem) => item.filePath + '_' + this.listRefreshKey)
|
|
|
- // }
|
|
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
.onScrollStart(() => {
|
|
.onScrollStart(() => {
|
|
|
this.isScrolling = true
|
|
this.isScrolling = true
|
|
@@ -7424,8 +7409,7 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
//内嵌音乐标签不能开启监听
|
|
//内嵌音乐标签不能开启监听
|
|
|
// this.deletionWatcher?.stop();
|
|
// this.deletionWatcher?.stop();
|
|
|
- DialogHelper.showLoadingDialog()
|
|
|
|
|
- this.loadingDialogId = 'loading_dialog'
|
|
|
|
|
|
|
+ this.loadingDialogId = DialogHelper.showLoadingDialog()
|
|
|
await PermissionUtil.activatePermission(item.filePath)
|
|
await PermissionUtil.activatePermission(item.filePath)
|
|
|
let tempOutPath = ''
|
|
let tempOutPath = ''
|
|
|
// 如果不是 packName 包下的文件,则直接路径用this.currentPath
|
|
// 如果不是 packName 包下的文件,则直接路径用this.currentPath
|
|
@@ -7536,13 +7520,12 @@ export struct LocalMusic {
|
|
|
console.error(" onecold 编辑信息数据库失败 ");
|
|
console.error(" onecold 编辑信息数据库失败 ");
|
|
|
}
|
|
}
|
|
|
// 关闭进度条
|
|
// 关闭进度条
|
|
|
- this.closeLoadingDialog();
|
|
|
|
|
-
|
|
|
|
|
|
|
+ DialogHelper.closeDialog(this.loadingDialogId)
|
|
|
|
|
|
|
|
|
|
|
|
|
}).catch((error: Error) => {
|
|
}).catch((error: Error) => {
|
|
|
// 关闭进度条
|
|
// 关闭进度条
|
|
|
- this.closeLoadingDialog();
|
|
|
|
|
|
|
+ DialogHelper.closeDialog(this.loadingDialogId)
|
|
|
console.error('onecold Subtitle sync failed:', error);
|
|
console.error('onecold Subtitle sync failed:', error);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -7551,7 +7534,7 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
// 关闭进度条
|
|
// 关闭进度条
|
|
|
- this.closeLoadingDialog();
|
|
|
|
|
|
|
+ DialogHelper.closeDialog(this.loadingDialogId)
|
|
|
ToastUtil.showToast('内嵌音乐标签失败')
|
|
ToastUtil.showToast('内嵌音乐标签失败')
|
|
|
console.log('onecold 内嵌音乐标签失败');
|
|
console.log('onecold 内嵌音乐标签失败');
|
|
|
}
|
|
}
|
|
@@ -7586,7 +7569,7 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
- this.closeLoadingDialog();
|
|
|
|
|
|
|
+ DialogHelper.closeDialog(this.loadingDialogId)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Builder
|
|
@Builder
|
|
@@ -9812,7 +9795,7 @@ export struct LocalMusic {
|
|
|
.setTextSize(15)
|
|
.setTextSize(15)
|
|
|
.setCacheSize(4)
|
|
.setCacheSize(4)
|
|
|
.setTextColor("#FFFFFF")
|
|
.setTextColor("#FFFFFF")
|
|
|
- .setHighlightColor("#FFFFFF")
|
|
|
|
|
|
|
+ .setHighlightColor(this.currentHighLightLyricColor)
|
|
|
.setHighlightScale(1.2)
|
|
.setHighlightScale(1.2)
|
|
|
.setEmptyHint("")
|
|
.setEmptyHint("")
|
|
|
.setAlignMode('center')
|
|
.setAlignMode('center')
|
|
@@ -9846,183 +9829,137 @@ export struct LocalMusic {
|
|
|
this.lyricControllerSingle.setLyric(null)
|
|
this.lyricControllerSingle.setLyric(null)
|
|
|
let jiaMilyricPath = lyricPath.substring(0, lyricPath.lastIndexOf('.')) + '.lrcc'
|
|
let jiaMilyricPath = lyricPath.substring(0, lyricPath.lastIndexOf('.')) + '.lrcc'
|
|
|
console.log("onecold lyricPath =" + lyricPath)
|
|
console.log("onecold lyricPath =" + lyricPath)
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 检查内嵌歌词
|
|
|
let neiqianLrc = ''
|
|
let neiqianLrc = ''
|
|
|
let lyContent = this.currentSong?.lyricContent
|
|
let lyContent = this.currentSong?.lyricContent
|
|
|
- if(lyContent&&StrUtil.isNotEmpty(lyContent)){//取数据库里面的歌词lyContent
|
|
|
|
|
|
|
+ if(lyContent && StrUtil.isNotEmpty(lyContent)){
|
|
|
neiqianLrc = lyContent
|
|
neiqianLrc = lyContent
|
|
|
}
|
|
}
|
|
|
- if (StrUtil.isNotEmpty(neiqianLrc) && !isOnLineAndToast&&!isLocal&&!isLocal) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (StrUtil.isNotEmpty(neiqianLrc) && !isOnLineAndToast && !isLocal) {
|
|
|
console.log("onecold 找到内嵌歌词 neiqianLrc =" + neiqianLrc)
|
|
console.log("onecold 找到内嵌歌词 neiqianLrc =" + neiqianLrc)
|
|
|
- //赋值给this.lyricContent,播控中心才可以显示歌词
|
|
|
|
|
- this.lyricContent = neiqianLrc
|
|
|
|
|
- // 将文件内容按行分割成字符串数组
|
|
|
|
|
- let lines = neiqianLrc.split('\n').map(line => line.trim());
|
|
|
|
|
- // 3.解析歌词
|
|
|
|
|
- let lyric = this.parser.parse(lines);
|
|
|
|
|
- // 4.设置歌词
|
|
|
|
|
- this.lyricController.setLyric(lyric);
|
|
|
|
|
- this.lyricControllerXF.setLyric(lyric)
|
|
|
|
|
- this.lyricControllerSingle.setLyric(lyric)
|
|
|
|
|
|
|
+ // Navidrome JSON歌词转换
|
|
|
|
|
+ if (this.currentSong && isNavidromeType(this.currentSong.type)) {
|
|
|
|
|
+ const convertedLyric = LyricUtil.convertNavidromeJsonLyricToLrc(neiqianLrc);
|
|
|
|
|
+ if (convertedLyric) {
|
|
|
|
|
+ neiqianLrc = convertedLyric;
|
|
|
|
|
+ console.log("onecold Navidrome歌词转换成功");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ this.setLyricToControllers(neiqianLrc);
|
|
|
return
|
|
return
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 2. 尝试从服务器获取歌词 (Navidrome/Jellyfin/Emby)
|
|
|
|
|
+ if (this.currentSong && (isJellyfinType(this.currentSong.type)|| isEmbyType(this.currentSong.type))) {
|
|
|
|
|
+ const manager = RemoteDriveManager.getInstance();
|
|
|
|
|
+ const getAccount = (accountId: string) => manager.getWebDavAccountById(accountId);
|
|
|
|
|
+
|
|
|
|
|
+ // 将currentSong转换为SongData接口
|
|
|
|
|
+ const songData: SongData = {
|
|
|
|
|
+ webdav_account_id: this.currentSong.webdav_account_id,
|
|
|
|
|
+ artist: this.currentSong.artist,
|
|
|
|
|
+ name: this.currentSong.name,
|
|
|
|
|
+ webdav_id: this.currentSong.webdav_id,
|
|
|
|
|
+ lyricIndex: this.currentSong.lyricIndex,
|
|
|
|
|
+ type: this.currentSong.type
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- if (isOnLineAndToast || ((!FileUtil.accessSync(lyricPath) && !FileUtil.accessSync(jiaMilyricPath))
|
|
|
|
|
- && !Utility.isVideoByExtension(this.videoUrl))) {
|
|
|
|
|
- if (this.currentSong !== undefined) {
|
|
|
|
|
- // ToastUtil.showShort('正在为你搜索在线歌词!')
|
|
|
|
|
- //判断是不是赞助会员,是会员的话才开启歌词功能
|
|
|
|
|
- // if (!this.isDebug) {
|
|
|
|
|
- // if (!Utility.isNoble()) {
|
|
|
|
|
- // LogUtil.debug("onecold 不是赞助会员")
|
|
|
|
|
- // return
|
|
|
|
|
- // }
|
|
|
|
|
- // if(!Utility.isPassInstallTime(33)){
|
|
|
|
|
- // LogUtil.debug("onecold not pass time")
|
|
|
|
|
- // // LogUtil.debug("onecold 用户安装app没超过12天" )
|
|
|
|
|
- // return
|
|
|
|
|
- // }
|
|
|
|
|
- // }
|
|
|
|
|
-
|
|
|
|
|
- let artist = this.currentSong?.artist
|
|
|
|
|
- if (artist === undefined) {
|
|
|
|
|
- artist = ''
|
|
|
|
|
- }
|
|
|
|
|
- if (isApi2 === undefined) {
|
|
|
|
|
- isApi2 = false
|
|
|
|
|
- }
|
|
|
|
|
- NetAxiosUtil.getLyric(this.name, artist, isApi2).then((res) => {
|
|
|
|
|
-
|
|
|
|
|
- // LogUtil.debug("onecold res =" + res)
|
|
|
|
|
- if (StrUtil.isNotEmpty(res) && res !== 'unknown' && res !== 'Timeout was reached') {
|
|
|
|
|
-
|
|
|
|
|
- if (StrUtil.isNotEmpty(res)) {
|
|
|
|
|
- this.lyricContent = res
|
|
|
|
|
- let lines = res.split('\n').map(line => line.trim());
|
|
|
|
|
-
|
|
|
|
|
- // 3.解析歌词
|
|
|
|
|
- let lyric = this.parser.parse(lines);
|
|
|
|
|
- // 4.设置歌词
|
|
|
|
|
- this.lyricController.setLyric(lyric);
|
|
|
|
|
- this.lyricControllerXF.setLyric(lyric)
|
|
|
|
|
- this.lyricControllerSingle.setLyric(lyric)
|
|
|
|
|
- this.showSingleLyric = true
|
|
|
|
|
- // 4.保存歌词文件lyric到本地
|
|
|
|
|
- //2025年8月28日歌词不再加密下载
|
|
|
|
|
- this.saveDataToFile(res, lyricPath, false)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- this.lyricController.setLyric(null)
|
|
|
|
|
- this.lyricControllerXF.setLyric(null)
|
|
|
|
|
- this.lyricControllerSingle.setLyric(null)
|
|
|
|
|
- if (isOnLineAndToast) {
|
|
|
|
|
- ToastUtil.showShort('未获取到歌词!')
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- this.lyricController.setLyric(null)
|
|
|
|
|
- this.lyricControllerXF.setLyric(null)
|
|
|
|
|
- this.lyricControllerSingle.setLyric(null)
|
|
|
|
|
- if (isOnLineAndToast) {
|
|
|
|
|
- ToastUtil.showShort('未获取到歌词!')
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ let serverLyric = '';
|
|
|
|
|
+ if (!serverLyric && isJellyfinType(songData.type)) {
|
|
|
|
|
+ serverLyric = await lyricService.fetchJellyfinLyric(songData, getAccount);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!serverLyric && isEmbyType(songData.type)) {
|
|
|
|
|
+ serverLyric = await lyricService.fetchEmbyLyric(songData, getAccount);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- })
|
|
|
|
|
- } else {
|
|
|
|
|
- this.lyricController.setLyric(null)
|
|
|
|
|
- this.lyricControllerXF.setLyric(null)
|
|
|
|
|
- this.lyricControllerSingle.setLyric(null)
|
|
|
|
|
- if (isOnLineAndToast) {
|
|
|
|
|
- ToastUtil.showShort('未获取到歌词!')
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (serverLyric) {
|
|
|
|
|
+ this.setLyricToControllers(serverLyric, lyricPath);
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ // 3. 尝试在线歌词API
|
|
|
|
|
+ if (isOnLineAndToast || ((!FileUtil.accessSync(lyricPath) && !FileUtil.accessSync(jiaMilyricPath))
|
|
|
|
|
+ && !Utility.isVideoByExtension(this.videoUrl))) {
|
|
|
|
|
+ this.fetchOnlineLyric(lyricPath, isOnLineAndToast || false, isApi2);
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 4. 从本地文件读取歌词
|
|
|
|
|
+ await this.loadLyricFromFile(lyricPath, jiaMilyricPath, isLocal || false);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 从本地文件加载歌词
|
|
|
|
|
+ */
|
|
|
|
|
+ private async loadLyricFromFile(lyricPath: string, jiaMilyricPath: string, isLocal: boolean): Promise<void> {
|
|
|
try {
|
|
try {
|
|
|
let isJiaMi = false;
|
|
let isJiaMi = false;
|
|
|
- let realLyricPath = lyricPath
|
|
|
|
|
|
|
+ let realLyricPath = lyricPath;
|
|
|
|
|
+
|
|
|
if (FileUtil.accessSync(jiaMilyricPath)) {
|
|
if (FileUtil.accessSync(jiaMilyricPath)) {
|
|
|
- isJiaMi = true
|
|
|
|
|
- realLyricPath = jiaMilyricPath
|
|
|
|
|
|
|
+ isJiaMi = true;
|
|
|
|
|
+ realLyricPath = jiaMilyricPath;
|
|
|
console.info("onecold 找到加密本地歌词 ");
|
|
console.info("onecold 找到加密本地歌词 ");
|
|
|
} else {
|
|
} else {
|
|
|
- isJiaMi = false
|
|
|
|
|
- realLyricPath = lyricPath
|
|
|
|
|
-
|
|
|
|
|
|
|
+ isJiaMi = false;
|
|
|
|
|
+ realLyricPath = lyricPath;
|
|
|
console.info("onecold 找到本地歌词 ");
|
|
console.info("onecold 找到本地歌词 ");
|
|
|
}
|
|
}
|
|
|
- // 3.读取文件内容并指定编码为 UTF-8
|
|
|
|
|
- let file = fs.openSync(realLyricPath, fs.OpenMode.READ_ONLY);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 读取文件内容
|
|
|
|
|
+ let file = fs.openSync(realLyricPath, fs.OpenMode.READ_ONLY);
|
|
|
const stat = await fileIo.stat(file.fd);
|
|
const stat = await fileIo.stat(file.fd);
|
|
|
const arrayBuffer = new ArrayBuffer(stat.size);
|
|
const arrayBuffer = new ArrayBuffer(stat.size);
|
|
|
|
|
+
|
|
|
fs.read(file.fd, arrayBuffer)
|
|
fs.read(file.fd, arrayBuffer)
|
|
|
.then((readLen: number) => {
|
|
.then((readLen: number) => {
|
|
|
console.info("read file data succeed");
|
|
console.info("read file data succeed");
|
|
|
- // let buf = buffer.from(arrayBuffer, 0, readLen);
|
|
|
|
|
-
|
|
|
|
|
let buf = new Uint8Array(arrayBuffer, 0, readLen);
|
|
let buf = new Uint8Array(arrayBuffer, 0, readLen);
|
|
|
- // 检查 buf 是否为空
|
|
|
|
|
|
|
+
|
|
|
if (buf.length === 0) {
|
|
if (buf.length === 0) {
|
|
|
throw new Error("Buffer is empty after reading the file");
|
|
throw new Error("Buffer is empty after reading the file");
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
// 检测文件编码
|
|
// 检测文件编码
|
|
|
- // let detectedEncoding = chardet.detect(buf);
|
|
|
|
|
- // console.info("onecoldT Detected encoding: " + detectedEncoding);
|
|
|
|
|
- let detectedEncoding = this.detect(arrayBuffer)
|
|
|
|
|
|
|
+ let detectedEncoding = this.detect(arrayBuffer);
|
|
|
console.info("onecoldT Detected encoding: " + detectedEncoding);
|
|
console.info("onecoldT Detected encoding: " + detectedEncoding);
|
|
|
|
|
+
|
|
|
// 使用检测到的编码解码,解决中文乱码问题
|
|
// 使用检测到的编码解码,解决中文乱码问题
|
|
|
let textDecoder = new util.TextDecoder(detectedEncoding || 'utf-8');
|
|
let textDecoder = new util.TextDecoder(detectedEncoding || 'utf-8');
|
|
|
console.info("onecoldT Detected textDecoder: " + textDecoder);
|
|
console.info("onecoldT Detected textDecoder: " + textDecoder);
|
|
|
let fileContent = textDecoder.decode(buf);
|
|
let fileContent = textDecoder.decode(buf);
|
|
|
console.info(`onecoldT The content of file1: ${fileContent}`);
|
|
console.info(`onecoldT The content of file1: ${fileContent}`);
|
|
|
- //解密
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 解密
|
|
|
if (isJiaMi) {
|
|
if (isJiaMi) {
|
|
|
- fileContent = StrUtil.unit8ArrayToStr(Base64Util.decodeSync(fileContent))
|
|
|
|
|
|
|
+ fileContent = StrUtil.unit8ArrayToStr(Base64Util.decodeSync(fileContent));
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
console.info(`onecold The content of file2: ${fileContent}`);
|
|
console.info(`onecold The content of file2: ${fileContent}`);
|
|
|
- this.lyricContent = fileContent
|
|
|
|
|
- if(isLocal){//编辑标签选择本地歌词需要赋值给this.lyricConStr
|
|
|
|
|
- this.lyricConStr = fileContent
|
|
|
|
|
|
|
+ this.lyricContent = fileContent;
|
|
|
|
|
+
|
|
|
|
|
+ if(isLocal){
|
|
|
|
|
+ // 编辑标签选择本地歌词需要赋值给this.lyricConStr
|
|
|
|
|
+ this.lyricConStr = fileContent;
|
|
|
}
|
|
}
|
|
|
- // 将文件内容按行分割成字符串数组
|
|
|
|
|
- let lines = fileContent.split('\n').map(line => line.trim());
|
|
|
|
|
- console.info(`onecold The content of file: ${fileContent}`);
|
|
|
|
|
- // 3.解析歌词
|
|
|
|
|
- let lyric = this.parser.parse(lines);
|
|
|
|
|
-
|
|
|
|
|
- // 4.设置歌词
|
|
|
|
|
- this.lyricController.setLyric(lyric);
|
|
|
|
|
- this.lyricControllerXF.setLyric(lyric)
|
|
|
|
|
- this.lyricControllerSingle.setLyric(lyric)
|
|
|
|
|
-
|
|
|
|
|
- this.showSingleLyric = true
|
|
|
|
|
|
|
+
|
|
|
|
|
+ this.setLyricToControllers(fileContent);
|
|
|
console.info(`The content of file: ${fileContent}`);
|
|
console.info(`The content of file: ${fileContent}`);
|
|
|
} catch (chardetError) {
|
|
} catch (chardetError) {
|
|
|
console.error("chardet.detect failed with error: " + chardetError.message);
|
|
console.error("chardet.detect failed with error: " + chardetError.message);
|
|
|
- this.lyricController.setLyric(null);
|
|
|
|
|
- this.lyricControllerXF.setLyric(null)
|
|
|
|
|
- this.lyricControllerSingle.setLyric(null)
|
|
|
|
|
|
|
+ this.clearLyricControllers();
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
.catch((err: BusinessError) => {
|
|
.catch((err: BusinessError) => {
|
|
|
- this.lyricController.setLyric(null)
|
|
|
|
|
- this.lyricControllerXF.setLyric(null)
|
|
|
|
|
- this.lyricControllerSingle.setLyric(null)
|
|
|
|
|
|
|
+ this.clearLyricControllers();
|
|
|
console.error("read file data failed with error message: " + err.message + ", error code: " + err.code);
|
|
console.error("read file data failed with error message: " + err.message + ", error code: " + err.code);
|
|
|
})
|
|
})
|
|
|
.catch((err: Error) => {
|
|
.catch((err: Error) => {
|
|
|
- this.lyricController.setLyric(null)
|
|
|
|
|
- this.lyricControllerXF.setLyric(null)
|
|
|
|
|
- this.lyricControllerSingle.setLyric(null)
|
|
|
|
|
|
|
+ this.clearLyricControllers();
|
|
|
console.error("read file 2 data failed with error message: " + err.message);
|
|
console.error("read file 2 data failed with error message: " + err.message);
|
|
|
})
|
|
})
|
|
|
.finally(() => {
|
|
.finally(() => {
|
|
@@ -10030,12 +9967,9 @@ export struct LocalMusic {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
- this.lyricController.setLyric(null)
|
|
|
|
|
- this.lyricControllerSingle.setLyric(null)
|
|
|
|
|
- this.lyricControllerXF.setLyric(null)
|
|
|
|
|
|
|
+ this.clearLyricControllers();
|
|
|
Logger.error(TAG, 'init Lyric failed with err: ' + JSON.stringify(error));
|
|
Logger.error(TAG, 'init Lyric failed with err: ' + JSON.stringify(error));
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
detect(data: ArrayBuffer): string {
|
|
detect(data: ArrayBuffer): string {
|
|
@@ -10053,6 +9987,70 @@ export struct LocalMusic {
|
|
|
return detected;
|
|
return detected;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 设置歌词到所有控制器
|
|
|
|
|
+ * @param lyricText 歌词文本
|
|
|
|
|
+ * @param savePath 可选,如果提供则保存到本地文件
|
|
|
|
|
+ */
|
|
|
|
|
+ private setLyricToControllers(lyricText: string, savePath?: string): void {
|
|
|
|
|
+ if (StrUtil.isEmpty(lyricText)) {
|
|
|
|
|
+ this.clearLyricControllers();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.lyricContent = lyricText;
|
|
|
|
|
+ let lines = lyricText.split('\n').map(line => line.trim());
|
|
|
|
|
+ let lyric = this.parser.parse(lines);
|
|
|
|
|
+
|
|
|
|
|
+ this.lyricController.setLyric(lyric);
|
|
|
|
|
+ this.lyricControllerXF.setLyric(lyric);
|
|
|
|
|
+ this.lyricControllerSingle.setLyric(lyric);
|
|
|
|
|
+ this.showSingleLyric = true;
|
|
|
|
|
+
|
|
|
|
|
+ // 如果提供了保存路径,保存歌词到本地
|
|
|
|
|
+ if (savePath) {
|
|
|
|
|
+ this.saveDataToFile(lyricText, savePath, false);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 清空所有歌词控制器
|
|
|
|
|
+ */
|
|
|
|
|
+ private clearLyricControllers(): void {
|
|
|
|
|
+ this.lyricController.setLyric(null);
|
|
|
|
|
+ this.lyricControllerXF.setLyric(null);
|
|
|
|
|
+ this.lyricControllerSingle.setLyric(null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 从在线API获取歌词
|
|
|
|
|
+ */
|
|
|
|
|
+ private fetchOnlineLyric(lyricPath: string, isOnLineAndToast: boolean, isApi2?: boolean): void {
|
|
|
|
|
+ if (!this.currentSong) {
|
|
|
|
|
+ this.clearLyricControllers();
|
|
|
|
|
+ if (isOnLineAndToast) {
|
|
|
|
|
+ ToastUtil.showShort('未获取到歌词!');
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let artist = this.currentSong.artist || '';
|
|
|
|
|
+ if (isApi2 === undefined) {
|
|
|
|
|
+ isApi2 = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ NetAxiosUtil.getLyric(this.name, artist, isApi2).then((res) => {
|
|
|
|
|
+ if (StrUtil.isNotEmpty(res) && res !== 'unknown' && res !== 'Timeout was reached') {
|
|
|
|
|
+ this.setLyricToControllers(res, lyricPath);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.clearLyricControllers();
|
|
|
|
|
+ if (isOnLineAndToast) {
|
|
|
|
|
+ ToastUtil.showShort('未获取到歌词!');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
//初始化悬浮歌词的自定义设置
|
|
//初始化悬浮歌词的自定义设置
|
|
|
initPipLyricSetting() {
|
|
initPipLyricSetting() {
|
|
|
this.lyricControllerXF
|
|
this.lyricControllerXF
|
|
@@ -10187,24 +10185,38 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义开始旋转的方法
|
|
// 定义开始旋转的方法
|
|
|
- // 定时器用于一百毫秒执行一次旋转角度
|
|
|
|
|
|
|
+ // 使用动画系统优化旋转性能,避免 setInterval 频繁更新导致卡顿
|
|
|
@State timer: number = 0
|
|
@State timer: number = 0
|
|
|
@State rotateAngle: number = 0
|
|
@State rotateAngle: number = 0
|
|
|
|
|
+ @State isRotationRunning: boolean = false // 旋转动画是否正在运行
|
|
|
|
|
|
|
|
//封面旋转动画
|
|
//封面旋转动画
|
|
|
animationRoFun() {
|
|
animationRoFun() {
|
|
|
-
|
|
|
|
|
if (this.isPlaying && !this.isCoverRectangle) {
|
|
if (this.isPlaying && !this.isCoverRectangle) {
|
|
|
- this.timer = setInterval(() => {
|
|
|
|
|
- this.rotateAngle += 1
|
|
|
|
|
- }, 100)
|
|
|
|
|
|
|
+ // 启动旋转动画
|
|
|
|
|
+ if (!this.isRotationRunning) {
|
|
|
|
|
+ this.isRotationRunning = true
|
|
|
|
|
+ this.startContinuousRotation()
|
|
|
|
|
+ }
|
|
|
this.startRotation()
|
|
this.startRotation()
|
|
|
} else {
|
|
} else {
|
|
|
|
|
+ // 停止旋转动画
|
|
|
|
|
+ this.isRotationRunning = false
|
|
|
clearInterval(this.timer)
|
|
clearInterval(this.timer)
|
|
|
this.stopRotation()
|
|
this.stopRotation()
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
+ // 使用持续的动画进行旋转,避免频繁状态更新
|
|
|
|
|
+ private startContinuousRotation() {
|
|
|
|
|
+ clearInterval(this.timer)
|
|
|
|
|
+ // 改为每 1000ms 更新 36 度(10秒一圈),减少更新频率
|
|
|
|
|
+ // 不使用 % 360 取模,让角度持续累加,避免反转
|
|
|
|
|
+ this.timer = setInterval(() => {
|
|
|
|
|
+ if (this.isRotationRunning) {
|
|
|
|
|
+ this.rotateAngle = this.rotateAngle + 36
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 1000)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 定义开始旋转的方法
|
|
// 定义开始旋转的方法
|
|
@@ -10941,7 +10953,7 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@State is_auto_hide_progress: boolean = false //手机横屏自动隐藏播放进退条,点击屏幕可以显示,倒计时4秒后又自动隐藏
|
|
@State is_auto_hide_progress: boolean = false //手机横屏自动隐藏播放进退条,点击屏幕可以显示,倒计时4秒后又自动隐藏
|
|
|
- @State isCoverRectangle: boolean = false
|
|
|
|
|
|
|
+
|
|
|
// 添加控制缩放的状态变量
|
|
// 添加控制缩放的状态变量
|
|
|
@State scaleValueImage: number = 1
|
|
@State scaleValueImage: number = 1
|
|
|
@State scaleValueText: number = 1
|
|
@State scaleValueText: number = 1
|
|
@@ -11050,6 +11062,11 @@ export struct LocalMusic {
|
|
|
z: 1,
|
|
z: 1,
|
|
|
angle: this.rotateAngle
|
|
angle: this.rotateAngle
|
|
|
})
|
|
})
|
|
|
|
|
+ .animation({
|
|
|
|
|
+ duration: 1000, // 与 setInterval 同步
|
|
|
|
|
+ curve: Curve.Linear,
|
|
|
|
|
+ iterations: 1
|
|
|
|
|
+ })
|
|
|
.shadow({
|
|
.shadow({
|
|
|
radius: 22,
|
|
radius: 22,
|
|
|
type: ShadowType.BLUR,
|
|
type: ShadowType.BLUR,
|
|
@@ -11084,8 +11101,9 @@ export struct LocalMusic {
|
|
|
centerY: "50%",
|
|
centerY: "50%",
|
|
|
})
|
|
})
|
|
|
.animation({
|
|
.animation({
|
|
|
- duration: 100,
|
|
|
|
|
- curve: Curve.Linear
|
|
|
|
|
|
|
+ duration: 1000, // 改为 1000ms 与 setInterval 同步
|
|
|
|
|
+ curve: Curve.Linear,
|
|
|
|
|
+ iterations: 1 // 只执行一次,下一次更新会触发新的动画
|
|
|
})
|
|
})
|
|
|
.shadow({
|
|
.shadow({
|
|
|
radius: 22,
|
|
radius: 22,
|
|
@@ -11118,6 +11136,11 @@ export struct LocalMusic {
|
|
|
z: 1,
|
|
z: 1,
|
|
|
angle: this.rotateAngle
|
|
angle: this.rotateAngle
|
|
|
})
|
|
})
|
|
|
|
|
+ .animation({
|
|
|
|
|
+ duration: 1000, // 与 setInterval 同步
|
|
|
|
|
+ curve: Curve.Linear,
|
|
|
|
|
+ iterations: 1
|
|
|
|
|
+ })
|
|
|
.onClick(() => {
|
|
.onClick(() => {
|
|
|
this.isMusicBGCover = !this.isMusicBGCover
|
|
this.isMusicBGCover = !this.isMusicBGCover
|
|
|
})
|
|
})
|
|
@@ -11864,38 +11887,6 @@ export struct LocalMusic {
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
- if (!isPip) {
|
|
|
|
|
- Row() {
|
|
|
|
|
- Text(`歌词模糊:`)
|
|
|
|
|
- .fontSize(14)
|
|
|
|
|
- .fontColor(Color.White)
|
|
|
|
|
- Slider({
|
|
|
|
|
- value: isPip ? this.blurDegreePip : this.blurDegree,
|
|
|
|
|
- min: 0,
|
|
|
|
|
- max: 5,
|
|
|
|
|
- step: 0.1,
|
|
|
|
|
- style: SliderStyle.OutSet
|
|
|
|
|
- })
|
|
|
|
|
- .blockColor(this.themeColor)
|
|
|
|
|
- .trackColor($r('app.color.speed_text_color'))
|
|
|
|
|
- .selectedColor(Color.White)
|
|
|
|
|
- .trackThickness(6)
|
|
|
|
|
- .onChange((value: number) => {
|
|
|
|
|
- this.setBlurDegree(value, isPip)
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
- .width('76%')
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- .margin({
|
|
|
|
|
- left: 20,
|
|
|
|
|
- right: 15,
|
|
|
|
|
- top: 5,
|
|
|
|
|
- bottom: 15
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
Row() {
|
|
Row() {
|
|
|
this.pushLyricButton($r('app.media.cut_current'), 0, '本地歌词')
|
|
this.pushLyricButton($r('app.media.cut_current'), 0, '本地歌词')
|
|
|
this.pushLyricButton($r('app.media.white_search'), 1, '获取歌词')
|
|
this.pushLyricButton($r('app.media.white_search'), 1, '获取歌词')
|
|
@@ -13948,8 +13939,8 @@ export struct LocalMusic {
|
|
|
let mOnErrorListener: OnErrorListener = {
|
|
let mOnErrorListener: OnErrorListener = {
|
|
|
onError: (what: number, extra: number) => {
|
|
onError: (what: number, extra: number) => {
|
|
|
this.stopProgressTask();
|
|
this.stopProgressTask();
|
|
|
- LogUtils.getInstance().LOGI("heanup OnErrorListener-->go:" + what + "===" + extra + " this.videoUrl=" + this.videoUrl)
|
|
|
|
|
- LogUtils.getInstance().LOGI('heanup 播放错误,歌曲详情:' + JSON.stringify(this.currentSong))
|
|
|
|
|
|
|
+ console.info("heanup OnErrorListener-->go:" + what + "===" + extra + " this.videoUrl=" + this.videoUrl)
|
|
|
|
|
+ console.info('heanup 播放错误,歌曲详情:' + JSON.stringify(this.currentSong))
|
|
|
// 检查是否为WebDAV播放错误
|
|
// 检查是否为WebDAV播放错误
|
|
|
let isWebDavError = false;
|
|
let isWebDavError = false;
|
|
|
if (this.currentSong && isRemoteCloudType(this.currentSong.type) && this.currentSong.filePath) {
|
|
if (this.currentSong && isRemoteCloudType(this.currentSong.type) && this.currentSong.filePath) {
|
|
@@ -13965,11 +13956,11 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (isWebDavError) {
|
|
if (isWebDavError) {
|
|
|
- Logger.error(`heanup WebDAV播放错误 - what: ${what}, extra: ${extra}, URL: ${this.videoUrl}`);
|
|
|
|
|
|
|
+ console.info(`heanup WebDAV播放错误 - what: ${what}, extra: ${extra}, URL: ${this.videoUrl}`);
|
|
|
|
|
|
|
|
// 播放失败时清空实例变量中的WebDAV认证信息,防止错误账户持续使用
|
|
// 播放失败时清空实例变量中的WebDAV认证信息,防止错误账户持续使用
|
|
|
// this.currentWebDavAuthInfo = null;
|
|
// this.currentWebDavAuthInfo = null;
|
|
|
- Logger.info('heanup WebDAV播放失败,保留认证信息用于后续歌曲切换');
|
|
|
|
|
|
|
+ console.info('heanup WebDAV播放失败,保留认证信息用于后续歌曲切换');
|
|
|
|
|
|
|
|
// 根据错误代码提供更具体的错误信息
|
|
// 根据错误代码提供更具体的错误信息
|
|
|
let errorMessage = "WebDAV播放失败";
|
|
let errorMessage = "WebDAV播放失败";
|
|
@@ -13986,14 +13977,14 @@ export struct LocalMusic {
|
|
|
ToastUtil.showToast(errorMessage);
|
|
ToastUtil.showToast(errorMessage);
|
|
|
} else {
|
|
} else {
|
|
|
if (StrUtil.isNotEmpty(this.videoUrl) &&
|
|
if (StrUtil.isNotEmpty(this.videoUrl) &&
|
|
|
- !this.videoUrl.startsWith('http://') &&
|
|
|
|
|
- !this.videoUrl.startsWith('https://') &&
|
|
|
|
|
|
|
+ !this.videoUrl.startsWith('http') &&
|
|
|
|
|
+ this.currentSong &&this.currentSong.type==CommonConstants.TYPE_LOCAL&&
|
|
|
!FileUtil.accessSync(this.videoUrl)) {
|
|
!FileUtil.accessSync(this.videoUrl)) {
|
|
|
- ToastUtil.showToast(Utility.resourceToString(getContext(), $r('app.string.file_not_exist')))
|
|
|
|
|
|
|
+ console.info('heanup 播放.文件不存在');
|
|
|
|
|
+ ToastUtil.showToast(Utility.resourceToString(this.context, $r('app.string.file_not_exist')))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
that.hideLoadIng();
|
|
that.hideLoadIng();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|