|
@@ -284,6 +284,9 @@ export struct LocalMusic {
|
|
|
@StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number =
|
|
@StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number =
|
|
|
ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET;
|
|
ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET;
|
|
|
|
|
|
|
|
|
|
+ // WebDAV认证信息缓存(作为实例变量,比全局上下文更可靠)
|
|
|
|
|
+ private currentWebDavAuthInfo: WebDavAuthInfo | null = null;
|
|
|
|
|
+
|
|
|
//瀑布流的列数横竖屏动态切换
|
|
//瀑布流的列数横竖屏动态切换
|
|
|
onIsLandscapeChange() {
|
|
onIsLandscapeChange() {
|
|
|
if(this.isLandscape){
|
|
if(this.isLandscape){
|
|
@@ -610,7 +613,6 @@ export struct LocalMusic {
|
|
|
this.getSortedFiles(this.currentPath)
|
|
this.getSortedFiles(this.currentPath)
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
// 组件生命周期
|
|
// 组件生命周期
|
|
|
aboutToAppear() {
|
|
aboutToAppear() {
|
|
|
// 初始化 PlaylistTable
|
|
// 初始化 PlaylistTable
|
|
@@ -800,7 +802,6 @@ export struct LocalMusic {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
//载入媒体库,艺术家,专辑等缓存
|
|
//载入媒体库,艺术家,专辑等缓存
|
|
|
initLoadCache(){
|
|
initLoadCache(){
|
|
|
this.mediaKuCount = PreferencesUtil.getNumberSync('mediaKuCount', 0)
|
|
this.mediaKuCount = PreferencesUtil.getNumberSync('mediaKuCount', 0)
|
|
@@ -1141,7 +1142,7 @@ export struct LocalMusic {
|
|
|
this.isFirstStartPlay = false
|
|
this.isFirstStartPlay = false
|
|
|
this.currentSong = this.songList[0]
|
|
this.currentSong = this.songList[0]
|
|
|
}
|
|
}
|
|
|
- this.videoUrl = this.currentSong.filePath
|
|
|
|
|
|
|
+ this.videoUrl = this.currentSong.filePath.replace(/ /g, '%20');
|
|
|
this.name = this.currentSong.name
|
|
this.name = this.currentSong.name
|
|
|
this.cover = this.currentSong.pixelMapPath
|
|
this.cover = this.currentSong.pixelMapPath
|
|
|
AppStorage.setOrCreate('currentSong',this.currentSong) ;
|
|
AppStorage.setOrCreate('currentSong',this.currentSong) ;
|
|
@@ -1397,7 +1398,6 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
return mediaItems;
|
|
return mediaItems;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
updateListData(mList: Array<VideoItem>, noSort?: boolean) {
|
|
updateListData(mList: Array<VideoItem>, noSort?: boolean) {
|
|
|
|
|
|
|
|
animateTo({ duration: 666 }, () => {
|
|
animateTo({ duration: 666 }, () => {
|
|
@@ -1524,7 +1524,6 @@ export struct LocalMusic {
|
|
|
this.isHasDir = false
|
|
this.isHasDir = false
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
showRankDialog() {
|
|
showRankDialog() {
|
|
|
if ((this.modeType === 2&&!this.isCanBack) || (this.modeType === 3&&!this.isCanBack)) {
|
|
if ((this.modeType === 2&&!this.isCanBack) || (this.modeType === 3&&!this.isCanBack)) {
|
|
|
//动作面板
|
|
//动作面板
|
|
@@ -2135,7 +2134,6 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
//复制 到另个文件夹的对话框
|
|
//复制 到另个文件夹的对话框
|
|
|
|
|
|
|
|
showCopyDialog(isCurrent: boolean, item: VideoItem, index: number, id: string) {
|
|
showCopyDialog(isCurrent: boolean, item: VideoItem, index: number, id: string) {
|
|
@@ -2880,7 +2878,6 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
@Builder
|
|
@Builder
|
|
|
private DirItem(item: VideoItem, index?: number) {
|
|
private DirItem(item: VideoItem, index?: number) {
|
|
|
Button({ type: ButtonType.Normal, stateEffect: true }) {
|
|
Button({ type: ButtonType.Normal, stateEffect: true }) {
|
|
@@ -4877,7 +4874,6 @@ export struct LocalMusic {
|
|
|
this.pinchValue = 1;
|
|
this.pinchValue = 1;
|
|
|
this.scaleValue = 1;
|
|
this.scaleValue = 1;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
@Builder
|
|
@Builder
|
|
|
getList(){
|
|
getList(){
|
|
|
Refresh({ refreshing: $$this.isRefreshing, refreshingContent: this.contentNode }) {
|
|
Refresh({ refreshing: $$this.isRefreshing, refreshingContent: this.contentNode }) {
|
|
@@ -5529,7 +5525,7 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
AppStorage.setOrCreate('currentSong',this.currentSong) ;
|
|
AppStorage.setOrCreate('currentSong',this.currentSong) ;
|
|
|
- this.videoUrl = this.currentSong.filePath
|
|
|
|
|
|
|
+ this.videoUrl = this.currentSong.filePath.replace(/ /g, '%20');
|
|
|
this.name = this.currentSong.name
|
|
this.name = this.currentSong.name
|
|
|
this.cover = this.currentSong.pixelMapPath
|
|
this.cover = this.currentSong.pixelMapPath
|
|
|
this.artist = this.currentSong.artist
|
|
this.artist = this.currentSong.artist
|
|
@@ -5538,7 +5534,7 @@ export struct LocalMusic {
|
|
|
this.startPlayOrResumePlay()
|
|
this.startPlayOrResumePlay()
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
- case CommonConstants.TYPE_INTERNET:
|
|
|
|
|
|
|
+ case CommonConstants.TYPE_WEBDAV:
|
|
|
// 处理网络音频播放(WebDAV)
|
|
// 处理网络音频播放(WebDAV)
|
|
|
Logger.info(`heanup 处理网络音频播放: ${item.name}, URL: ${item.filePath}`)
|
|
Logger.info(`heanup 处理网络音频播放: ${item.name}, URL: ${item.filePath}`)
|
|
|
|
|
|
|
@@ -5564,7 +5560,7 @@ export struct LocalMusic {
|
|
|
Logger.info(`heanup 网络音频 isFromSonPlayList分支 - 当前播放列表长度: ${this.songList.length}, 当前索引: ${this.curIndex}`)
|
|
Logger.info(`heanup 网络音频 isFromSonPlayList分支 - 当前播放列表长度: ${this.songList.length}, 当前索引: ${this.curIndex}`)
|
|
|
} else {
|
|
} else {
|
|
|
// 从全局网络音频列表中查找
|
|
// 从全局网络音频列表中查找
|
|
|
- let globalVideoList = this.videoLocalList.filter(video => video.type === CommonConstants.TYPE_INTERNET) as VideoItem[];
|
|
|
|
|
|
|
+ let globalVideoList = this.videoLocalList.filter(video => video.type === CommonConstants.TYPE_WEBDAV) as VideoItem[];
|
|
|
this.curIndex = globalVideoList.findIndex(video => video.filePath === item.filePath);
|
|
this.curIndex = globalVideoList.findIndex(video => video.filePath === item.filePath);
|
|
|
if (this.curIndex === -1 && index !== undefined) {
|
|
if (this.curIndex === -1 && index !== undefined) {
|
|
|
this.curIndex = index;
|
|
this.curIndex = index;
|
|
@@ -5576,12 +5572,13 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
AppStorage.setOrCreate('currentSong', this.currentSong);
|
|
AppStorage.setOrCreate('currentSong', this.currentSong);
|
|
|
- this.videoUrl = this.currentSong.filePath // 网络URL
|
|
|
|
|
|
|
+ // 对WebDAV URL进行编码处理,确保空格等特殊字符被正确编码
|
|
|
|
|
+ this.videoUrl = this.currentSong.filePath.replace(/ /g, '%20');
|
|
|
this.name = this.currentSong.name
|
|
this.name = this.currentSong.name
|
|
|
this.cover = this.currentSong.pixelMapPath
|
|
this.cover = this.currentSong.pixelMapPath
|
|
|
this.artist = this.currentSong.artist
|
|
this.artist = this.currentSong.artist
|
|
|
|
|
|
|
|
- Logger.info(`heanup 准备播放网络音频 - 歌名: ${this.name}, 艺术家: ${this.artist}, URL: ${this.videoUrl}`)
|
|
|
|
|
|
|
+ Logger.info(`heanup 准备播放网络音频 - 歌名: ${this.name}, 艺术家: ${this.artist}, 编码后URL: ${this.videoUrl}`)
|
|
|
|
|
|
|
|
this.startPlayOrResumePlay()
|
|
this.startPlayOrResumePlay()
|
|
|
break;
|
|
break;
|
|
@@ -5639,7 +5636,7 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
this.songList = globalVideoList
|
|
this.songList = globalVideoList
|
|
|
this.sonDataSource.pushArrayData(this.songList)
|
|
this.sonDataSource.pushArrayData(this.songList)
|
|
|
- this.videoUrl = this.currentSong.filePath
|
|
|
|
|
|
|
+ this.videoUrl = this.currentSong.filePath.replace(/ /g, '%20');
|
|
|
this.name = item.title||this.currentSong.name
|
|
this.name = item.title||this.currentSong.name
|
|
|
this.cover = this.currentSong.pixelMapPath
|
|
this.cover = this.currentSong.pixelMapPath
|
|
|
this.artist = item.performer||this.currentSong.artist
|
|
this.artist = item.performer||this.currentSong.artist
|
|
@@ -5653,8 +5650,6 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
@Builder
|
|
@Builder
|
|
|
PlayController() {
|
|
PlayController() {
|
|
|
Column() {
|
|
Column() {
|
|
@@ -6046,9 +6041,6 @@ export struct LocalMusic {
|
|
|
.width('100%')
|
|
.width('100%')
|
|
|
.height('100%')
|
|
.height('100%')
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
@Builder
|
|
@Builder
|
|
|
editDetail(item: VideoItem) {
|
|
editDetail(item: VideoItem) {
|
|
|
Column() {
|
|
Column() {
|
|
@@ -11565,7 +11557,7 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
updateLastPlayTimeStr(filePath: string) {
|
|
updateLastPlayTimeStr(filePath: string) {
|
|
|
// 检查是否为网络音频(WebDAV),如果是则不更新本地数据库
|
|
// 检查是否为网络音频(WebDAV),如果是则不更新本地数据库
|
|
|
- if (this.currentSong && this.currentSong.type === CommonConstants.TYPE_INTERNET) {
|
|
|
|
|
|
|
+ if (this.currentSong && this.currentSong.type === CommonConstants.TYPE_WEBDAV) {
|
|
|
Logger.info(`heanup 检测到网络音频播放,跳过数据库更新: ${filePath}`)
|
|
Logger.info(`heanup 检测到网络音频播放,跳过数据库更新: ${filePath}`)
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -11770,7 +11762,6 @@ export struct LocalMusic {
|
|
|
Logger.error(`heanup 添加WebDAV认证头失败: ${error}`);
|
|
Logger.error(`heanup 添加WebDAV认证头失败: ${error}`);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
private async play(url: string,startOffset?:number) {
|
|
private async play(url: string,startOffset?:number) {
|
|
|
let that = this;
|
|
let that = this;
|
|
|
that.showLoadIng();
|
|
that.showLoadIng();
|
|
@@ -11802,72 +11793,55 @@ export struct LocalMusic {
|
|
|
this.mIjkMediaPlayer.setDataSource(url);
|
|
this.mIjkMediaPlayer.setDataSource(url);
|
|
|
//设置视频源http请求头
|
|
//设置视频源http请求头
|
|
|
let headers = new Map([
|
|
let headers = new Map([
|
|
|
- ["user_agent", "Mozilla/5.0 BiliDroid/7.30.0 (bbcallen@gmail.com)"],
|
|
|
|
|
|
|
+ ["user_agent", "Mozilla/5.0 BiliDroid/7.30.0 (ttmusic)"],
|
|
|
["referer", "https://www.bilibili.com"]
|
|
["referer", "https://www.bilibili.com"]
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
// 如果是WebDAV网络音频,添加安全的HTTP头认证
|
|
// 如果是WebDAV网络音频,添加安全的HTTP头认证
|
|
|
Logger.info(`heanup 开始检查WebDAV认证需求 - currentSong存在: ${!!this.currentSong}`);
|
|
Logger.info(`heanup 开始检查WebDAV认证需求 - currentSong存在: ${!!this.currentSong}`);
|
|
|
|
|
+ let isWebDavSong = false;
|
|
|
|
|
+ let webDavAuthInfo: WebDavAuthInfo | null = null;
|
|
|
if (this.currentSong) {
|
|
if (this.currentSong) {
|
|
|
const currentSong = this.currentSong;
|
|
const currentSong = this.currentSong;
|
|
|
Logger.info(`heanup 当前歌曲信息 - name: ${currentSong.name}, type: ${currentSong.type}, filePath: ${currentSong.filePath}`);
|
|
Logger.info(`heanup 当前歌曲信息 - name: ${currentSong.name}, type: ${currentSong.type}, filePath: ${currentSong.filePath}`);
|
|
|
- let isWebDavSong = false;
|
|
|
|
|
-
|
|
|
|
|
// 检查是否为WebDAV歌曲(优先通过URL特征判断,因为全局上下文可能失效)
|
|
// 检查是否为WebDAV歌曲(优先通过URL特征判断,因为全局上下文可能失效)
|
|
|
- if (currentSong.type === CommonConstants.TYPE_INTERNET) {
|
|
|
|
|
- Logger.info(`heanup 检测到网络音频,开始WebDAV识别流程`);
|
|
|
|
|
-
|
|
|
|
|
- // 直接通过URL特征判断WebDAV
|
|
|
|
|
- const filePath = currentSong.filePath || '';
|
|
|
|
|
- Logger.info(`heanup 开始URL特征检测 - filePath: ${filePath}`);
|
|
|
|
|
-
|
|
|
|
|
- const hasWebDavPath = filePath.includes('/webdav');
|
|
|
|
|
- const hasPort8080 = filePath.includes(':8080');
|
|
|
|
|
- const hasPort5005 = filePath.includes(':5005'); // 匹配实际的WebDAV服务器端口
|
|
|
|
|
- const hasPort5000 = filePath.includes(':5000'); // 通用WebDAV端口
|
|
|
|
|
- const hasRemotePhp = filePath.includes('/remote.php');
|
|
|
|
|
- const hasDavPath = filePath.includes('/dav/');
|
|
|
|
|
- const hasSharePath = filePath.includes('/share/'); // 特定于这个服务器
|
|
|
|
|
-
|
|
|
|
|
- Logger.info(`heanup URL特征检测结果 - webdav: ${hasWebDavPath}, 8080: ${hasPort8080}, 5005: ${hasPort5005}, 5000: ${hasPort5000}, remote.php: ${hasRemotePhp}, dav/: ${hasDavPath}, share/: ${hasSharePath}`);
|
|
|
|
|
-
|
|
|
|
|
- if (hasWebDavPath || hasPort8080 || hasPort5005 || hasPort5000 || hasRemotePhp || hasDavPath || hasSharePath) {
|
|
|
|
|
- isWebDavSong = true;
|
|
|
|
|
- Logger.info(`heanup 通过URL特征检测到WebDAV播放`);
|
|
|
|
|
|
|
+ if (currentSong.type === CommonConstants.TYPE_WEBDAV) {
|
|
|
|
|
+ isWebDavSong=true;
|
|
|
|
|
+
|
|
|
|
|
+ // 优先从实例变量获取认证信息(更可靠)
|
|
|
|
|
+ if (this.currentWebDavAuthInfo) {
|
|
|
|
|
+ webDavAuthInfo = this.currentWebDavAuthInfo;
|
|
|
|
|
+ Logger.info(`heanup 从实例变量获取到WebDAV认证信息,账户ID: ${webDavAuthInfo.accountId}`);
|
|
|
} else {
|
|
} else {
|
|
|
- Logger.warn(`heanup URL特征检测未发现WebDAV标识`);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 尝试从全局上下文获取认证信息(作为备用)
|
|
|
|
|
- let webDavAuthInfo: WebDavAuthInfo | null = null;
|
|
|
|
|
- try {
|
|
|
|
|
- const globalContext = GlobalContext.getContext();
|
|
|
|
|
- webDavAuthInfo = globalContext.getObject('webDavAuthInfo') as WebDavAuthInfo;
|
|
|
|
|
- if (webDavAuthInfo) {
|
|
|
|
|
- Logger.info(`heanup 从全局上下文获取到WebDAV认证信息,账户ID: ${webDavAuthInfo.accountId}`);
|
|
|
|
|
- } else {
|
|
|
|
|
- Logger.warn(`heanup 全局上下文中没有WebDAV认证信息`);
|
|
|
|
|
|
|
+ // 回退到全局上下文
|
|
|
|
|
+ try {
|
|
|
|
|
+ const globalContext = GlobalContext.getContext();
|
|
|
|
|
+ webDavAuthInfo = globalContext.getObject('webDavAuthInfo') as WebDavAuthInfo;
|
|
|
|
|
+ if (webDavAuthInfo) {
|
|
|
|
|
+ Logger.info(`heanup 从全局上下文获取到WebDAV认证信息,账户ID: ${webDavAuthInfo.accountId}`);
|
|
|
|
|
+ // 保存到实例变量中作为备份
|
|
|
|
|
+ this.currentWebDavAuthInfo = webDavAuthInfo;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Logger.warn(`heanup 全局上下文中没有WebDAV认证信息`);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ Logger.error(`heanup 获取全局上下文失败:`, error.toString());
|
|
|
}
|
|
}
|
|
|
- } catch (error) {
|
|
|
|
|
- Logger.error(`heanup 获取全局上下文失败:`, error.toString());
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 如果识别为WebDAV但没有认证信息,尝试使用默认配置或提示用户
|
|
// 如果识别为WebDAV但没有认证信息,尝试使用默认配置或提示用户
|
|
|
- if (isWebDavSong && !webDavAuthInfo) {
|
|
|
|
|
|
|
+ if (!webDavAuthInfo) {
|
|
|
Logger.warn(`heanup 识别为WebDAV播放但缺少认证信息,可能需要手动配置WebDAV账户`);
|
|
Logger.warn(`heanup 识别为WebDAV播放但缺少认证信息,可能需要手动配置WebDAV账户`);
|
|
|
// TODO: 可以在这里添加默认认证逻辑或用户提示
|
|
// TODO: 可以在这里添加默认认证逻辑或用户提示
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (isWebDavSong) {
|
|
|
|
|
|
|
+ if (isWebDavSong&&webDavAuthInfo) {
|
|
|
|
|
+ // URL已在doPlay中编码过,这里无需再编码
|
|
|
|
|
+ // 但确保当前使用的this.videoUrl是已编码的版本
|
|
|
Logger.info(`heanup 检测到WebDAV播放,添加安全认证头`);
|
|
Logger.info(`heanup 检测到WebDAV播放,添加安全认证头`);
|
|
|
- Logger.info(`heanup 歌曲URL: ${currentSong.filePath}`);
|
|
|
|
|
-
|
|
|
|
|
- // 重新获取WebDAV认证信息(因为可能在上面作用域中获取过)
|
|
|
|
|
|
|
+ Logger.info(`heanup 歌曲URL: ${this.videoUrl}`);
|
|
|
try {
|
|
try {
|
|
|
- const globalContext = GlobalContext.getContext();
|
|
|
|
|
- const webDavAuthInfo = globalContext.getObject('webDavAuthInfo') as WebDavAuthInfo;
|
|
|
|
|
-
|
|
|
|
|
if (webDavAuthInfo && webDavAuthInfo.accountId) {
|
|
if (webDavAuthInfo && webDavAuthInfo.accountId) {
|
|
|
Logger.info(`heanup 找到WebDAV认证信息,账户ID: ${webDavAuthInfo.accountId}`);
|
|
Logger.info(`heanup 找到WebDAV认证信息,账户ID: ${webDavAuthInfo.accountId}`);
|
|
|
// 使用WebdavManager获取认证头
|
|
// 使用WebdavManager获取认证头
|
|
@@ -11877,16 +11851,11 @@ export struct LocalMusic {
|
|
|
if (authHeaders) {
|
|
if (authHeaders) {
|
|
|
// 添加Basic认证头
|
|
// 添加Basic认证头
|
|
|
headers.set("authorization", authHeaders.headers.Authorization);
|
|
headers.set("authorization", authHeaders.headers.Authorization);
|
|
|
- Logger.info(`heanup 已添加WebDAV Basic认证头`);
|
|
|
|
|
- Logger.info(`heanup 认证URL基础地址: ${authHeaders.url}`);
|
|
|
|
|
} else {
|
|
} else {
|
|
|
Logger.error(`heanup 无法获取WebDAV认证头`);
|
|
Logger.error(`heanup 无法获取WebDAV认证头`);
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
Logger.error(`heanup WebDAV认证信息无效或缺少accountId`);
|
|
Logger.error(`heanup WebDAV认证信息无效或缺少accountId`);
|
|
|
- // 尝试使用简单的用户名密码认证(基于常见的WebDAV配置)
|
|
|
|
|
- Logger.warn(`heanup 尝试使用常见的WebDAV认证模式`);
|
|
|
|
|
- // 这里可以根据实际服务器配置添加认证逻辑
|
|
|
|
|
}
|
|
}
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
Logger.error(`heanup 获取WebDAV认证信息失败:`, error.toString());
|
|
Logger.error(`heanup 获取WebDAV认证信息失败:`, error.toString());
|
|
@@ -11902,88 +11871,26 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 输出所有设置的头部信息用于调试
|
|
// 输出所有设置的头部信息用于调试
|
|
|
- Logger.info(`heanup 设置的HTTP头部信息:`);
|
|
|
|
|
|
|
+ console.log(`heanup 设置的HTTP头部信息:`);
|
|
|
const headerIterator = headers.entries();
|
|
const headerIterator = headers.entries();
|
|
|
let headerEntry = headerIterator.next();
|
|
let headerEntry = headerIterator.next();
|
|
|
while (!headerEntry.done) {
|
|
while (!headerEntry.done) {
|
|
|
const key = headerEntry.value[0];
|
|
const key = headerEntry.value[0];
|
|
|
const value = headerEntry.value[1];
|
|
const value = headerEntry.value[1];
|
|
|
- if (key.toLowerCase().includes('auth')) {
|
|
|
|
|
- Logger.info(`heanup ${key}: [认证信息已隐藏]`);
|
|
|
|
|
- } else {
|
|
|
|
|
- Logger.info(`heanup ${key}: ${value}`);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ console.log(`heanup ${key}: ${value}`);
|
|
|
|
|
+ // if (key.toLowerCase().includes('auth')) {
|
|
|
|
|
+ // Logger.info(`heanup ${key}: [认证信息已隐藏]`);
|
|
|
|
|
+ // } else {
|
|
|
|
|
+ // Logger.info(`heanup ${key}: ${value}`);
|
|
|
|
|
+ // }
|
|
|
headerEntry = headerIterator.next();
|
|
headerEntry = headerIterator.next();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 对于WebDAV播放,进行额外的连接验证
|
|
|
|
|
- let isWebDavSong = false;
|
|
|
|
|
- if (this.currentSong && this.currentSong.type === CommonConstants.TYPE_INTERNET && this.currentSong.filePath) {
|
|
|
|
|
- try {
|
|
|
|
|
- const globalContext = GlobalContext.getContext();
|
|
|
|
|
- const webDavAuthInfo = globalContext.getObject('webDavAuthInfo') as WebDavAuthInfo;
|
|
|
|
|
- if (webDavAuthInfo) {
|
|
|
|
|
- isWebDavSong = true;
|
|
|
|
|
- } else {
|
|
|
|
|
- // 通过URL特征判断
|
|
|
|
|
- const filePath = this.currentSong.filePath;
|
|
|
|
|
- if (filePath.includes('/webdav') || filePath.includes(':8080') || filePath.includes(':5000') ||
|
|
|
|
|
- filePath.includes('/remote.php') || filePath.includes('/dav/')) {
|
|
|
|
|
- isWebDavSong = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- // 通过URL特征判断
|
|
|
|
|
- const filePath = this.currentSong.filePath;
|
|
|
|
|
- if (filePath.includes('/webdav') || filePath.includes(':8080') || filePath.includes(':5000') ||
|
|
|
|
|
- filePath.includes('/remote.php') || filePath.includes('/dav/')) {
|
|
|
|
|
- isWebDavSong = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (isWebDavSong) {
|
|
|
|
|
- Logger.info(`heanup 开始WebDAV播放,URL: ${this.videoUrl}`);
|
|
|
|
|
-
|
|
|
|
|
- // 验证认证信息是否已设置
|
|
|
|
|
- const authHeader = headers.get("authorization");
|
|
|
|
|
- if (!authHeader) {
|
|
|
|
|
- Logger.warn(`heanup 警告:WebDAV播放未设置认证头,可能导致播放失败`);
|
|
|
|
|
- } else {
|
|
|
|
|
- Logger.info(`heanup WebDAV认证头已设置完成`);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
this.mIjkMediaPlayer.setDataSourceHeader(headers);
|
|
this.mIjkMediaPlayer.setDataSourceHeader(headers);
|
|
|
|
|
|
|
|
- // 为WebDAV播放设置IjkPlayer选项
|
|
|
|
|
- let shouldApplyWebDavSettings = false;
|
|
|
|
|
- if (this.currentSong && this.currentSong.type === CommonConstants.TYPE_INTERNET && this.currentSong.filePath) {
|
|
|
|
|
- try {
|
|
|
|
|
- const globalContext = GlobalContext.getContext();
|
|
|
|
|
- const webDavAuthInfo = globalContext.getObject('webDavAuthInfo') as WebDavAuthInfo;
|
|
|
|
|
- if (webDavAuthInfo) {
|
|
|
|
|
- shouldApplyWebDavSettings = true;
|
|
|
|
|
- } else {
|
|
|
|
|
- // 通过URL特征判断
|
|
|
|
|
- const filePath = this.currentSong.filePath;
|
|
|
|
|
- if (filePath.includes('/webdav') || filePath.includes(':8080') || filePath.includes(':5000') ||
|
|
|
|
|
- filePath.includes('/remote.php') || filePath.includes('/dav/')) {
|
|
|
|
|
- shouldApplyWebDavSettings = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- // 通过URL特征判断
|
|
|
|
|
- const filePath = this.currentSong.filePath;
|
|
|
|
|
- if (filePath.includes('/webdav') || filePath.includes(':8080') || filePath.includes(':5000') ||
|
|
|
|
|
- filePath.includes('/remote.php') || filePath.includes('/dav/')) {
|
|
|
|
|
- shouldApplyWebDavSettings = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- if (shouldApplyWebDavSettings) {
|
|
|
|
|
- Logger.info(`heanup 为WebDAV播放设置IjkPlayer选项`);
|
|
|
|
|
|
|
+ if (isWebDavSong) {
|
|
|
|
|
+ console.log(`heanup 为WebDAV播放设置IjkPlayer选项`);
|
|
|
|
|
|
|
|
// 网络超时设置(单位:微秒,文档显示应该是字符串格式)
|
|
// 网络超时设置(单位:微秒,文档显示应该是字符串格式)
|
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", "30000000"); // 30秒
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", "30000000"); // 30秒
|
|
@@ -11996,7 +11903,7 @@ export struct LocalMusic {
|
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", "50"); // 减少最小帧数
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", "50"); // 减少最小帧数
|
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", "1"); // 预加载启动
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", "1"); // 预加载启动
|
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", "0"); // 无缓冲播放
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", "0"); // 无缓冲播放
|
|
|
- this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", "10000"); // 最大缓存10秒
|
|
|
|
|
|
|
+ this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", "30000"); // 最大缓存30秒
|
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", "1"); // 无限制收流
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", "1"); // 无限制收流
|
|
|
|
|
|
|
|
// 网络相关设置
|
|
// 网络相关设置
|
|
@@ -12006,7 +11913,7 @@ export struct LocalMusic {
|
|
|
// 重连设置
|
|
// 重连设置
|
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "reconnect", "3"); // 重连3次
|
|
this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "reconnect", "3"); // 重连3次
|
|
|
|
|
|
|
|
- Logger.info(`heanup WebDAV IjkPlayer选项设置完成`);
|
|
|
|
|
|
|
+ console.log(`heanup WebDAV IjkPlayer选项设置完成`);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// if(PreferencesUtil.getBooleanSync(SettingPage.IS_MIDIACODEC_OPEN,false)){
|
|
// if(PreferencesUtil.getBooleanSync(SettingPage.IS_MIDIACODEC_OPEN,false)){
|
|
@@ -12310,7 +12217,7 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
// 检查是否为WebDAV播放错误
|
|
// 检查是否为WebDAV播放错误
|
|
|
let isWebDavError = false;
|
|
let isWebDavError = false;
|
|
|
- if (this.currentSong && this.currentSong.type === CommonConstants.TYPE_INTERNET && this.currentSong.filePath) {
|
|
|
|
|
|
|
+ if (this.currentSong && this.currentSong.type === CommonConstants.TYPE_WEBDAV && this.currentSong.filePath) {
|
|
|
try {
|
|
try {
|
|
|
const globalContext = GlobalContext.getContext();
|
|
const globalContext = GlobalContext.getContext();
|
|
|
const webDavAuthInfo = globalContext.getObject('webDavAuthInfo') as WebDavAuthInfo;
|
|
const webDavAuthInfo = globalContext.getObject('webDavAuthInfo') as WebDavAuthInfo;
|
|
@@ -12336,6 +12243,10 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
if (isWebDavError) {
|
|
if (isWebDavError) {
|
|
|
Logger.error(`heanup WebDAV播放错误 - what: ${what}, extra: ${extra}, URL: ${this.videoUrl}`);
|
|
Logger.error(`heanup WebDAV播放错误 - what: ${what}, extra: ${extra}, URL: ${this.videoUrl}`);
|
|
|
|
|
+
|
|
|
|
|
+ // 播放失败时清空实例变量中的WebDAV认证信息,防止错误账户持续使用
|
|
|
|
|
+ // this.currentWebDavAuthInfo = null;
|
|
|
|
|
+ Logger.info('heanup WebDAV播放失败,保留认证信息用于后续歌曲切换');
|
|
|
|
|
|
|
|
// 根据错误代码提供更具体的错误信息
|
|
// 根据错误代码提供更具体的错误信息
|
|
|
let errorMessage = "WebDAV播放失败";
|
|
let errorMessage = "WebDAV播放失败";
|
|
@@ -12640,7 +12551,6 @@ export struct LocalMusic {
|
|
|
this.durationTime = Math.floor(this.duration / 1000);
|
|
this.durationTime = Math.floor(this.duration / 1000);
|
|
|
this.durationStringTime = secondToTime((this.durationTime));
|
|
this.durationStringTime = secondToTime((this.durationTime));
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
private playbackStateChangeListener = (playbackState: avSession.AVPlaybackState) => {
|
|
private playbackStateChangeListener = (playbackState: avSession.AVPlaybackState) => {
|
|
|
const duration = playbackState?.extras?.duration;
|
|
const duration = playbackState?.extras?.duration;
|
|
|
if (typeof duration === 'number') {
|
|
if (typeof duration === 'number') {
|
|
@@ -13006,7 +12916,7 @@ export struct LocalMusic {
|
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
|
this.stop();
|
|
this.stop();
|
|
|
this.currentSong = this.songList[this.curIndex]
|
|
this.currentSong = this.songList[this.curIndex]
|
|
|
- this.videoUrl = this.songList[this.curIndex].filePath;
|
|
|
|
|
|
|
+ this.videoUrl = this.songList[this.curIndex].filePath.replace(/ /g, '%20');
|
|
|
this.artist = this.songList[this.curIndex].artist
|
|
this.artist = this.songList[this.curIndex].artist
|
|
|
this.name = this.songList[this.curIndex].name
|
|
this.name = this.songList[this.curIndex].name
|
|
|
//this.cover = this.songList[this.curIndex].pixelMapPath
|
|
//this.cover = this.songList[this.curIndex].pixelMapPath
|
|
@@ -13094,7 +13004,7 @@ export struct LocalMusic {
|
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
|
this.stop();
|
|
this.stop();
|
|
|
this.currentSong = this.songList[this.curIndex];
|
|
this.currentSong = this.songList[this.curIndex];
|
|
|
- this.videoUrl = this.songList[this.curIndex].filePath;
|
|
|
|
|
|
|
+ this.videoUrl = this.songList[this.curIndex].filePath.replace(/ /g, '%20');
|
|
|
this.name = this.songList[this.curIndex].name;
|
|
this.name = this.songList[this.curIndex].name;
|
|
|
this.artist = this.songList[this.curIndex].artist
|
|
this.artist = this.songList[this.curIndex].artist
|
|
|
// this.cover = this.songList[this.curIndex].pixelMapPath
|
|
// this.cover = this.songList[this.curIndex].pixelMapPath
|
|
@@ -13111,7 +13021,7 @@ export struct LocalMusic {
|
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
|
this.stop();
|
|
this.stop();
|
|
|
this.currentSong = this.songList[this.curIndex]
|
|
this.currentSong = this.songList[this.curIndex]
|
|
|
- this.videoUrl = this.songList[index].filePath;
|
|
|
|
|
|
|
+ this.videoUrl = this.songList[index].filePath.replace(/ /g, '%20');
|
|
|
this.name = this.songList[index].name
|
|
this.name = this.songList[index].name
|
|
|
this.artist = this.songList[this.curIndex].artist
|
|
this.artist = this.songList[this.curIndex].artist
|
|
|
this.curIndex = index;
|
|
this.curIndex = index;
|
|
@@ -13139,7 +13049,7 @@ export struct LocalMusic {
|
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
|
this.stop();
|
|
this.stop();
|
|
|
this.currentSong = this.songList[this.curIndex]
|
|
this.currentSong = this.songList[this.curIndex]
|
|
|
- this.videoUrl = this.songList[this.curIndex].filePath;
|
|
|
|
|
|
|
+ this.videoUrl = this.songList[this.curIndex].filePath.replace(/ /g, '%20');
|
|
|
this.name = this.songList[this.curIndex].name
|
|
this.name = this.songList[this.curIndex].name
|
|
|
this.artist = this.songList[this.curIndex].artist
|
|
this.artist = this.songList[this.curIndex].artist
|
|
|
this.changeImageAnimation()
|
|
this.changeImageAnimation()
|
|
@@ -13154,7 +13064,7 @@ export struct LocalMusic {
|
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
|
this.stop();
|
|
this.stop();
|
|
|
this.currentSong = prevSong;
|
|
this.currentSong = prevSong;
|
|
|
- this.videoUrl = prevSong.filePath;
|
|
|
|
|
|
|
+ this.videoUrl = prevSong.filePath.replace(/ /g, '%20');
|
|
|
this.cover = prevSong.pixelMapPath
|
|
this.cover = prevSong.pixelMapPath
|
|
|
this.artist = prevSong.artist
|
|
this.artist = prevSong.artist
|
|
|
this.name = prevSong.name;
|
|
this.name = prevSong.name;
|
|
@@ -13170,7 +13080,7 @@ export struct LocalMusic {
|
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
this.CONTROL_PlayStatus = PlayStatus.INIT;
|
|
|
this.stop();
|
|
this.stop();
|
|
|
this.currentSong = this.songList[this.curIndex];
|
|
this.currentSong = this.songList[this.curIndex];
|
|
|
- this.videoUrl = this.songList[this.curIndex].filePath;
|
|
|
|
|
|
|
+ this.videoUrl = this.songList[this.curIndex].filePath.replace(/ /g, '%20');
|
|
|
this.artist = this.songList[this.curIndex].artist
|
|
this.artist = this.songList[this.curIndex].artist
|
|
|
this.name = this.songList[this.curIndex].name;
|
|
this.name = this.songList[this.curIndex].name;
|
|
|
this.changeImageAnimation()
|
|
this.changeImageAnimation()
|
|
@@ -13592,11 +13502,17 @@ export struct LocalMusic {
|
|
|
if (playlistId === 'webdav-playlist') {
|
|
if (playlistId === 'webdav-playlist') {
|
|
|
Logger.info(`heanup 检测到WebDAV播放请求,使用事件传递的认证信息`)
|
|
Logger.info(`heanup 检测到WebDAV播放请求,使用事件传递的认证信息`)
|
|
|
|
|
|
|
|
- // 如果有WebDAV认证信息,保存到全局上下文中供后续使用
|
|
|
|
|
|
|
+ // 如果有WebDAV认证信息,保存到实例变量和全局上下文中
|
|
|
if (webDavAuthInfo) {
|
|
if (webDavAuthInfo) {
|
|
|
- const globalContext = GlobalContext.getContext();
|
|
|
|
|
- globalContext.setObject('webDavAuthInfo', webDavAuthInfo);
|
|
|
|
|
- Logger.info(`heanup 已将WebDAV认证信息保存到全局上下文,账户ID: ${webDavAuthInfo.accountId}`);
|
|
|
|
|
|
|
+ this.currentWebDavAuthInfo = webDavAuthInfo;
|
|
|
|
|
+ // 同时保存到全局上下文作为持久化备份(防止实例变量被清空)
|
|
|
|
|
+ try {
|
|
|
|
|
+ const globalContext = GlobalContext.getContext();
|
|
|
|
|
+ globalContext.setObject('webDavAuthInfo', webDavAuthInfo as Object);
|
|
|
|
|
+ Logger.info(`heanup 已将WebDAV认证信息保存到实例变量和全局上下文,账户ID: ${webDavAuthInfo.accountId}`);
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ Logger.error(`heanup 保存到全局上下文失败:`, error.toString());
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
Logger.warn(`heanup WebDAV播放请求中没有认证信息`);
|
|
Logger.warn(`heanup WebDAV播放请求中没有认证信息`);
|
|
|
}
|
|
}
|
|
@@ -13625,15 +13541,15 @@ export struct LocalMusic {
|
|
|
const fileName = songFilePaths[i].split('/').pop() || `WebDAV歌曲${i+1}`;
|
|
const fileName = songFilePaths[i].split('/').pop() || `WebDAV歌曲${i+1}`;
|
|
|
const videoItem = new VideoItem(
|
|
const videoItem = new VideoItem(
|
|
|
fileName.replace(/\.(flac|mp3|wav|m4a)$/i, ''), // name (去掉扩展名)
|
|
fileName.replace(/\.(flac|mp3|wav|m4a)$/i, ''), // name (去掉扩展名)
|
|
|
- i.toString(), // id
|
|
|
|
|
|
|
+ '', // id
|
|
|
songFilePaths[i], // filePath (URL)
|
|
songFilePaths[i], // filePath (URL)
|
|
|
- CommonConstants.TYPE_INTERNET, // type
|
|
|
|
|
- 0, // fileSize
|
|
|
|
|
- "0", // time
|
|
|
|
|
|
|
+ CommonConstants.TYPE_WEBDAV, // type
|
|
|
|
|
+ 0, // videoSize
|
|
|
|
|
+ "0", // cTime
|
|
|
undefined, // pixelMap
|
|
undefined, // pixelMap
|
|
|
undefined, // size
|
|
undefined, // size
|
|
|
undefined, // pixelMapPath
|
|
undefined, // pixelMapPath
|
|
|
- "WebDAV艺术家", // artist
|
|
|
|
|
|
|
+ "WebDAV", // artist
|
|
|
undefined, // album
|
|
undefined, // album
|
|
|
fileName // fileName
|
|
fileName // fileName
|
|
|
);
|
|
);
|
|
@@ -13940,6 +13856,4 @@ async function scanCurrentDirectoryTask(context: Context, dirPath: string, lockP
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
console.error(' 扫描当前目录失败:', error);
|
|
console.error(' 扫描当前目录失败:', error);
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+}
|