|
|
@@ -2,7 +2,7 @@ import { VideoItem } from '../viewmodel/VideoItem';
|
|
|
import { LengthMetrics, SegmentButton, SegmentButtonItemTuple, SegmentButtonOptions,
|
|
|
SymbolGlyphModifier } from '@kit.ArkUI';
|
|
|
import {
|
|
|
- PreferencesUtil, ToastUtil, StrUtil, ArrayUtil
|
|
|
+ PreferencesUtil, ToastUtil, StrUtil
|
|
|
} from '@pura/harmony-utils';
|
|
|
import {
|
|
|
ButtonFancyModifier,
|
|
|
@@ -19,10 +19,11 @@ import { Constants } from '../Constants';
|
|
|
import { EventConstants } from '../common/constants/EventConstants';
|
|
|
import { emitter } from '@kit.BasicServicesKit';
|
|
|
import { setNavidromePlaylist } from '../common/util/NavidromePlaylistStore';
|
|
|
-import { navidromeApi } from '../common/network/NavidromeApi';
|
|
|
+import { navidromeApi, NavidromeSong } from '../common/network/NavidromeApi';
|
|
|
import { ServerLogUtil } from '../common/util/ServerLogUtil';
|
|
|
import { RemoteDriveManager } from '../common/util/RemoteDriveManager';
|
|
|
const NAVIDROME_PLAYLIST_ID = 'navidrome-playlist';
|
|
|
+const NAVIDROME_SEARCH_LIMIT = 500;
|
|
|
|
|
|
interface PlaylistEventData {
|
|
|
playlistId: string;
|
|
|
@@ -75,8 +76,11 @@ export struct NavidromePage {
|
|
|
@State filterType: NavFilterType = NavFilterType.None;
|
|
|
@State filterLabel: string = '';
|
|
|
@State filterId: string = '';
|
|
|
+ @State filterSongs: VideoItem[] = [];
|
|
|
+ @State isFilterLoading: boolean = false;
|
|
|
private coverUrlCache: Map<string, string> = new Map();
|
|
|
private albumCoverLookup: Map<string, string> = new Map();
|
|
|
+ private searchTicket: number = 0;
|
|
|
|
|
|
private createTabOptions(): SegmentButtonOptions {
|
|
|
const buttons = [
|
|
|
@@ -125,6 +129,7 @@ export struct NavidromePage {
|
|
|
@State searchText: string = ''; // 用户输入内容
|
|
|
@State filteredList: Array<VideoItem> = []; // 过滤后的歌曲结果
|
|
|
@State sortType: number = 0; // 排序类型 0:名称升序 1:名称降序 2:时间升序 3:时间降序 4:大小升序 5:大小降序
|
|
|
+ @State isSearchLoading: boolean = false;
|
|
|
|
|
|
// SegmentButton选项
|
|
|
@State tabOptions: SegmentButtonOptions = this.createTabOptions();
|
|
|
@@ -143,6 +148,8 @@ export struct NavidromePage {
|
|
|
this.isSearchMode = false;
|
|
|
this.searchText = '';
|
|
|
this.filteredList = [];
|
|
|
+ this.isSearchLoading = false;
|
|
|
+ this.searchTicket++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -260,9 +267,6 @@ export struct NavidromePage {
|
|
|
return;
|
|
|
}
|
|
|
this.allVideos = [...this.allVideos, ...videos];
|
|
|
- if (this.isSearchMode && this.searchText.length > 0) {
|
|
|
- this.onSearchInput(this.searchText);
|
|
|
- }
|
|
|
this.songNextStart = response.nextStart;
|
|
|
void ServerLogUtil.info('NavidromeLoad', `歌曲列表追加: 本次 ${videos.length} 首, 总数 ${this.allVideos.length}`);
|
|
|
} finally {
|
|
|
@@ -343,6 +347,9 @@ export struct NavidromePage {
|
|
|
if (this.loading) {
|
|
|
return;
|
|
|
}
|
|
|
+ if (this.selectedTab === 0 && this.filterType !== NavFilterType.None) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
const account = this.selectedAccount;
|
|
|
if (!account) {
|
|
|
return;
|
|
|
@@ -454,6 +461,28 @@ export struct NavidromePage {
|
|
|
return map;
|
|
|
}
|
|
|
|
|
|
+ private convertApiSongsToRestSongs(songs: NavidromeSong[]): NavidromeRestSong[] {
|
|
|
+ return songs.map((song: NavidromeSong): NavidromeRestSong => ({
|
|
|
+ id: song.id,
|
|
|
+ title: song.title,
|
|
|
+ artist: song.artist,
|
|
|
+ artistId: song.artistId,
|
|
|
+ album: song.album,
|
|
|
+ albumId: song.albumId,
|
|
|
+ duration: song.duration,
|
|
|
+ bitRate: song.bitRate,
|
|
|
+ suffix: song.suffix,
|
|
|
+ size: song.size,
|
|
|
+ createdAt: song.created,
|
|
|
+ genre: song.genre,
|
|
|
+ track: song.track,
|
|
|
+ year: song.year,
|
|
|
+ contentType: song.contentType,
|
|
|
+ coverArt: song.coverArt,
|
|
|
+ coverArtId: song.coverArt
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
private async convertSongsToVideoItems(songs: NavidromeRestSong[], account: WebDavAccount): Promise<VideoItem[]> {
|
|
|
const tasks: Promise<VideoItem>[] = [];
|
|
|
let successCount = 0;
|
|
|
@@ -691,7 +720,7 @@ export struct NavidromePage {
|
|
|
.animation({ duration: 300, curve: Curve.Ease })
|
|
|
.onClick(() => {
|
|
|
this.isSearchMode = false;
|
|
|
- this.onSearchInput('');
|
|
|
+ void this.onSearchInput('');
|
|
|
})
|
|
|
.attributeModifier(new ShadowModifier())
|
|
|
.zIndex(0)
|
|
|
@@ -718,10 +747,10 @@ export struct NavidromePage {
|
|
|
.placeholderFont({ size: 14, weight: 400 })
|
|
|
.textFont({ size: 14, weight: 400 })
|
|
|
.onSubmit((value: string) => {
|
|
|
- this.onSearchInput(value);
|
|
|
+ void this.onSearchInput(value);
|
|
|
})
|
|
|
.onChange((value: string) => {
|
|
|
- this.onSearchInput(value);
|
|
|
+ void this.onSearchInput(value);
|
|
|
})
|
|
|
.visibility(this.isSearchMode?Visibility.Visible:Visibility.None)
|
|
|
.animation({ duration: 300, curve: Curve.Ease })
|
|
|
@@ -741,8 +770,8 @@ export struct NavidromePage {
|
|
|
.visibility(this.selectedTab==0?Visibility.Visible:Visibility.None)
|
|
|
.onClick(() => {
|
|
|
this.isSearchMode = true;
|
|
|
- if(ArrayUtil.isEmpty(this.filteredList)){
|
|
|
- this.filteredList = [...this.allVideos];
|
|
|
+ if (!this.isSearchLoading && this.searchText.length === 0) {
|
|
|
+ this.filteredList = [];
|
|
|
}
|
|
|
})
|
|
|
|
|
|
@@ -836,7 +865,7 @@ export struct NavidromePage {
|
|
|
|
|
|
doSortType(index: number) {
|
|
|
this.sortType = index;
|
|
|
- const songs = this.isSearchMode ? this.filteredList :this.allVideos;
|
|
|
+ const songs = this.isSearchMode && this.searchText.length > 0 ? this.filteredList : this.allVideos;
|
|
|
const sortTypeNames = ['名称升序', '名称降序', '艺术家升序', '艺术家降序', '专辑升序', '专辑降序'];
|
|
|
const sortTypeName = sortTypeNames[index] || '未知排序';
|
|
|
|
|
|
@@ -899,39 +928,73 @@ export struct NavidromePage {
|
|
|
void ServerLogUtil.debug('NavidromeSort', `排序结果示例: ${songs.slice(0, 3).map(s => `${s.name} (${s.artist})`).join(', ')}`);
|
|
|
}
|
|
|
|
|
|
- // 实时搜索逻辑
|
|
|
- private onSearchInput(value: string) {
|
|
|
- this.searchText = value.trim();
|
|
|
- let mSearchList: Array<VideoItem> = [...this.allVideos];
|
|
|
+ // 实时搜索逻辑(改为远程API搜索)
|
|
|
+ private async onSearchInput(value: string): Promise<void> {
|
|
|
+ const keyword = value.trim();
|
|
|
+ this.searchText = keyword;
|
|
|
+ const ticket = ++this.searchTicket;
|
|
|
|
|
|
- // 记录搜索操作
|
|
|
- void ServerLogUtil.debug('NavidromeSearch', `搜索输入: "${value}" -> "${this.searchText}"`);
|
|
|
- void ServerLogUtil.debug('NavidromeSearch', `搜索范围: ${mSearchList.length} 首歌曲`);
|
|
|
+ void ServerLogUtil.debug('NavidromeSearch', `搜索输入: "${value}" -> "${keyword}"`);
|
|
|
|
|
|
- // 新增条件判断:空输入时显示所有数据
|
|
|
- if (this.searchText === '') {
|
|
|
- this.filteredList = [...mSearchList]; // 创建新数组以触发状态更新
|
|
|
+ if (keyword.length === 0) {
|
|
|
+ this.filteredList = [];
|
|
|
+ this.isSearchLoading = false;
|
|
|
void ServerLogUtil.info('NavidromeSearch', '搜索已清空,显示所有歌曲');
|
|
|
- } else {
|
|
|
- const startTime = Date.now();
|
|
|
- this.filteredList = mSearchList.filter((item: VideoItem) => {
|
|
|
- // 支持模糊匹配和艺术家 专辑匹配
|
|
|
- const regex = new RegExp(this.searchText.toLowerCase().replace(/\s+/g, '.*'), 'i');
|
|
|
- return regex.test(item.name.toLowerCase()) ||
|
|
|
- regex.test(item.fileName?.toLowerCase() ?? "") ||
|
|
|
- regex.test(item.artist?.toLowerCase() ?? "") ||
|
|
|
- regex.test(item.album?.toLowerCase() ?? "")
|
|
|
- });
|
|
|
- const searchTime = Date.now() - startTime;
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- // 记录搜索结果
|
|
|
- void ServerLogUtil.info('NavidromeSearch', `搜索完成: "${this.searchText}"`);
|
|
|
- void ServerLogUtil.info('NavidromeSearch', `- 搜索耗时: ${searchTime}ms`);
|
|
|
- void ServerLogUtil.info('NavidromeSearch', `- 匹配结果: ${this.filteredList.length}/${mSearchList.length}`);
|
|
|
- void ServerLogUtil.debug('NavidromeSearch', `搜索结果示例: ${this.filteredList.slice(0, 3).map(s => `${s.name} (${s.artist})`).join(', ')}`);
|
|
|
+ if (!this.isSearchMode) {
|
|
|
+ this.isSearchMode = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ const account = this.resolveActiveAccount();
|
|
|
+ if (!account) {
|
|
|
+ this.filteredList = [];
|
|
|
+ this.isSearchLoading = false;
|
|
|
+ ToastUtil.showToast('Navidrome账号不可用');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.isSearchLoading = true;
|
|
|
+ this.filteredList = [];
|
|
|
+ const startTime = Date.now();
|
|
|
+ void ServerLogUtil.info('NavidromeSearch', `开始远程搜索: "${keyword}"`);
|
|
|
|
|
|
- if (this.filteredList.length === 0) {
|
|
|
- void ServerLogUtil.warn('NavidromeSearch', `搜索无结果: "${this.searchText}"`);
|
|
|
+ try {
|
|
|
+ const songs = await navidromeApi.searchSongs(account, keyword, NAVIDROME_SEARCH_LIMIT);
|
|
|
+ if (ticket !== this.searchTicket) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const searchTime = Date.now() - startTime;
|
|
|
+ if (!songs || songs.length === 0) {
|
|
|
+ this.filteredList = [];
|
|
|
+ void ServerLogUtil.warn('NavidromeSearch', `搜索无结果: "${keyword}"`);
|
|
|
+ void ServerLogUtil.info('NavidromeSearch', `- 搜索耗时: ${searchTime}ms`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const restSongs = this.convertApiSongsToRestSongs(songs);
|
|
|
+ const videoItems = await this.convertSongsToVideoItems(restSongs, account);
|
|
|
+ if (ticket !== this.searchTicket) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.filteredList = videoItems;
|
|
|
+ this.doSortType(this.sortType);
|
|
|
+ void ServerLogUtil.info('NavidromeSearch', `搜索完成: "${keyword}"`);
|
|
|
+ void ServerLogUtil.info('NavidromeSearch', `- 搜索耗时: ${searchTime}ms`);
|
|
|
+ void ServerLogUtil.info('NavidromeSearch', `- 匹配结果: ${videoItems.length}`);
|
|
|
+ void ServerLogUtil.debug('NavidromeSearch', `搜索结果示例: ${videoItems.slice(0, 3).map(s => `${s.name} (${s.artist})`).join(', ')}`);
|
|
|
+ } catch (error) {
|
|
|
+ if (ticket !== this.searchTicket) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.filteredList = [];
|
|
|
+ const message = (error as Error).message ?? 'Navidrome 搜索失败';
|
|
|
+ ToastUtil.showToast(message);
|
|
|
+ void ServerLogUtil.error('NavidromeSearch', `搜索失败: ${message}`);
|
|
|
+ void ServerLogUtil.info('NavidromeSearch', `- 搜索耗时: ${Date.now() - startTime}ms`);
|
|
|
+ } finally {
|
|
|
+ if (ticket === this.searchTicket) {
|
|
|
+ this.isSearchLoading = false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -954,6 +1017,12 @@ export struct NavidromePage {
|
|
|
case 2:
|
|
|
return '暂无专辑';
|
|
|
default:
|
|
|
+ if (this.isSearchMode && this.searchText.length > 0) {
|
|
|
+ return this.isSearchLoading ? '正在搜索远程歌曲' : '没有匹配的远程歌曲';
|
|
|
+ }
|
|
|
+ if (this.filterType !== NavFilterType.None && this.isFilterLoading) {
|
|
|
+ return '正在加载筛选结果';
|
|
|
+ }
|
|
|
return this.filterType === NavFilterType.None ? '暂无音乐' : '该筛选下暂无歌曲';
|
|
|
}
|
|
|
}
|
|
|
@@ -965,6 +1034,12 @@ export struct NavidromePage {
|
|
|
case 2:
|
|
|
return '当前筛选没有找到专辑';
|
|
|
default:
|
|
|
+ if (this.isSearchMode && this.searchText.length > 0) {
|
|
|
+ return this.isSearchLoading ? '请稍候,正在通过 API 搜索' : '换个关键词再试试吧';
|
|
|
+ }
|
|
|
+ if (this.filterType !== NavFilterType.None && this.isFilterLoading) {
|
|
|
+ return '请稍候...';
|
|
|
+ }
|
|
|
return this.filterType === NavFilterType.None ? '当前分类下没有找到音乐文件' : '请尝试调整筛选条件';
|
|
|
}
|
|
|
}
|
|
|
@@ -1185,27 +1260,12 @@ export struct NavidromePage {
|
|
|
}
|
|
|
|
|
|
private getVisibleSongs(): VideoItem[] {
|
|
|
- if(this.isSearchMode)
|
|
|
- return this.filteredList;
|
|
|
-
|
|
|
- if (this.filterType === NavFilterType.Artist && this.filterId.length > 0) {
|
|
|
- const filtered = this.allVideos.filter(item => item.navArtistId === this.filterId || item.artist === this.filterLabel);
|
|
|
- Logger.info('heanup', `艺术家筛选: filterId=${this.filterId}, filterLabel=${this.filterLabel}, 结果数=${filtered.length}`);
|
|
|
- return filtered;
|
|
|
+ if (this.isSearchMode) {
|
|
|
+ return this.searchText.length > 0 ? this.filteredList : this.allVideos;
|
|
|
}
|
|
|
- if (this.filterType === NavFilterType.Album && this.filterId.length > 0) {
|
|
|
- const filtered = this.allVideos.filter(item => {
|
|
|
- const match = item.navAlbumId === this.filterId || item.album === this.filterLabel;
|
|
|
- if (!match && this.allVideos.indexOf(item) < 3) {
|
|
|
- // 只打印前3首歌的调试信息
|
|
|
- Logger.info('heanup', `歌曲 ${item.name}: navAlbumId=${item.navAlbumId}, album=${item.album}, 期望albumId=${this.filterId}, 期望album=${this.filterLabel}`);
|
|
|
- }
|
|
|
- return match;
|
|
|
- });
|
|
|
- Logger.info('heanup', `专辑筛选: filterId=${this.filterId}, filterLabel=${this.filterLabel}, 结果数=${filtered.length}`);
|
|
|
- return filtered;
|
|
|
+ if (this.filterType !== NavFilterType.None) {
|
|
|
+ return this.filterSongs;
|
|
|
}
|
|
|
-
|
|
|
return this.allVideos;
|
|
|
}
|
|
|
|
|
|
@@ -1213,17 +1273,17 @@ export struct NavidromePage {
|
|
|
if (!artist || !artist.id) {
|
|
|
return;
|
|
|
}
|
|
|
- this.applyFilter(NavFilterType.Artist, artist.id, artist.name ?? Constants.UNKNOWN_ARTIST);
|
|
|
+ void this.applyFilter(NavFilterType.Artist, artist.id, artist.name ?? Constants.UNKNOWN_ARTIST);
|
|
|
}
|
|
|
|
|
|
private onAlbumSelected(album: NavidromeRestAlbum): void {
|
|
|
if (!album || !album.id) {
|
|
|
return;
|
|
|
}
|
|
|
- this.applyFilter(NavFilterType.Album, album.id, album.name ?? '未知专辑');
|
|
|
+ void this.applyFilter(NavFilterType.Album, album.id, album.name ?? '未知专辑');
|
|
|
}
|
|
|
|
|
|
- private applyFilter(type: NavFilterType, id: string, label: string): void {
|
|
|
+ private async applyFilter(type: NavFilterType, id: string, label: string): Promise<void> {
|
|
|
|
|
|
// 记录筛选操作
|
|
|
void ServerLogUtil.info('NavidromeFilter', `应用筛选:`);
|
|
|
@@ -1240,18 +1300,16 @@ export struct NavidromePage {
|
|
|
this.isSearchMode = false;
|
|
|
this.searchText = '';
|
|
|
this.filteredList = [];
|
|
|
+ this.isSearchLoading = false;
|
|
|
+ this.searchTicket++;
|
|
|
+ this.filterSongs = [];
|
|
|
+ this.isFilterLoading = true;
|
|
|
|
|
|
// 调试日志:检查筛选结果
|
|
|
- const visibleSongs = this.getVisibleSongs();
|
|
|
- if (visibleSongs.length > 0) {
|
|
|
- // 记录筛选结果详情
|
|
|
- void ServerLogUtil.info('NavidromeFilter', `筛选结果统计:`);
|
|
|
- void ServerLogUtil.info('NavidromeFilter', `- 筛选后歌曲数: ${visibleSongs.length}`);
|
|
|
- void ServerLogUtil.info('NavidromeFilter', `- 筛选成功率: ${Math.round(visibleSongs.length / this.allVideos.length * 100)}%`);
|
|
|
- void ServerLogUtil.debug('NavidromeFilter', `筛选结果示例: ${visibleSongs.slice(0, 5).map(s => `${s.name} (${s.artist})`).join(', ')}`);
|
|
|
- } else {
|
|
|
- void ServerLogUtil.warn('NavidromeFilter', `筛选结果为空: 未找到匹配的歌曲`);
|
|
|
- }
|
|
|
+ void this.loadSongsForFilter().catch((error: Error) => {
|
|
|
+ void ServerLogUtil.error('NavidromeFilter', `筛选歌曲加载失败: ${error.message}`);
|
|
|
+ ToastUtil.showToast(error.message || '筛选数据加载失败');
|
|
|
+ });
|
|
|
|
|
|
// 然后执行动画切换标签页
|
|
|
this.getUIContext().animateTo({ duration: 555 }, () => {
|
|
|
@@ -1260,10 +1318,48 @@ export struct NavidromePage {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ private async loadSongsForFilter(): Promise<void> {
|
|
|
+ if (this.filterType === NavFilterType.None || !this.filterId) {
|
|
|
+ this.filterSongs = [];
|
|
|
+ this.isFilterLoading = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const account = this.resolveActiveAccount();
|
|
|
+ if (!account) {
|
|
|
+ this.filterSongs = [];
|
|
|
+ this.isFilterLoading = false;
|
|
|
+ throw new Error('Navidrome账号不可用');
|
|
|
+ }
|
|
|
+ const expectedFilterId = this.filterId;
|
|
|
+ const expectedFilterType = this.filterType;
|
|
|
+ try {
|
|
|
+ let songs: NavidromeRestSong[] = [];
|
|
|
+ if (this.filterType === NavFilterType.Artist) {
|
|
|
+ songs = await navidromeRestApi.fetchSongsByArtist(account, this.filterId);
|
|
|
+ } else if (this.filterType === NavFilterType.Album) {
|
|
|
+ songs = await navidromeRestApi.fetchSongsByAlbum(account, this.filterId);
|
|
|
+ }
|
|
|
+ const videoItems = await this.convertSongsToVideoItems(songs, account);
|
|
|
+ if (expectedFilterId !== this.filterId || expectedFilterType !== this.filterType) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.filterSongs = videoItems;
|
|
|
+ if (videoItems.length === 0) {
|
|
|
+ void ServerLogUtil.warn('NavidromeFilter', '筛选下暂无歌曲');
|
|
|
+ } else {
|
|
|
+ void ServerLogUtil.info('NavidromeFilter', `筛选歌曲加载完成: ${videoItems.length} 首`);
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ this.isFilterLoading = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private clearFilter(): void {
|
|
|
this.filterType = NavFilterType.None;
|
|
|
this.filterId = '';
|
|
|
this.filterLabel = '';
|
|
|
+ this.filterSongs = [];
|
|
|
+ this.isFilterLoading = false;
|
|
|
}
|
|
|
|
|
|
private playSong(song: VideoItem, index: number, isJump: boolean = false): void {
|
|
|
@@ -1289,20 +1385,21 @@ export struct NavidromePage {
|
|
|
void ServerLogUtil.info('NavidromePlay', `- 封面: ${song.pixelMapPath ? '有' : '无'}`);
|
|
|
void ServerLogUtil.info('NavidromePlay', `- 播放路径: ${song.filePath}`);
|
|
|
|
|
|
- const targetIndex = this.allVideos.findIndex(item => item.id === song.id);
|
|
|
- const startIndex = targetIndex >= 0 ? targetIndex : index;
|
|
|
+ const playlistSource = this.getVisibleSongs().length > 0 ? this.getVisibleSongs() : this.allVideos;
|
|
|
+ const targetIndex = playlistSource.findIndex(item => item.id === song.id);
|
|
|
+ const startIndex = targetIndex >= 0 ? targetIndex : Math.min(index, Math.max(playlistSource.length - 1, 0));
|
|
|
|
|
|
- void ServerLogUtil.info('NavidromePlay', `播放列表设置: 起始索引 ${startIndex}, 总数 ${this.allVideos.length}`);
|
|
|
+ void ServerLogUtil.info('NavidromePlay', `播放列表设置: 起始索引 ${startIndex}, 总数 ${playlistSource.length}`);
|
|
|
|
|
|
- setNavidromePlaylist(this.allVideos, startIndex);
|
|
|
+ setNavidromePlaylist(playlistSource, startIndex);
|
|
|
|
|
|
const playlistData: PlaylistEventData = {
|
|
|
playlistId: NAVIDROME_PLAYLIST_ID,
|
|
|
playlistName: `Navidrome - ${account.name ?? '未知账户'}`,
|
|
|
- songCount: this.allVideos.length,
|
|
|
+ songCount: playlistSource.length,
|
|
|
startIndex,
|
|
|
isJump: isJump,//设置true会弹出播放页
|
|
|
- songFilePaths: this.allVideos.map(item => item.filePath)
|
|
|
+ songFilePaths: playlistSource.map(item => item.filePath)
|
|
|
};
|
|
|
|
|
|
const eventPlaylistPlay: emitter.InnerEvent = { eventId: EventConstants.EVENT_PLAYLIST_PLAY };
|
|
|
@@ -1362,41 +1459,69 @@ export struct NavidromePage {
|
|
|
.padding({ left: 16, right: 16, top: 12, bottom: 2 })
|
|
|
}
|
|
|
|
|
|
- List({ space: 8 }) {
|
|
|
- if (this.selectedTab === 0) {
|
|
|
- ForEach(this.getVisibleSongs(), (item: VideoItem, index: number) => {
|
|
|
- ListItem() {
|
|
|
- this.buildSongItem(item, index)
|
|
|
- }
|
|
|
- }, (item: VideoItem) => item.id)
|
|
|
- } else if (this.selectedTab === 1) {
|
|
|
- ForEach(this.artists, (artist: NavidromeRestArtist) => {
|
|
|
- ListItem() {
|
|
|
- this.buildArtistItem(artist)
|
|
|
- }
|
|
|
- }, (artist: NavidromeRestArtist) => artist.id)
|
|
|
- } else {
|
|
|
- ForEach(this.albums, (album: NavidromeRestAlbum) => {
|
|
|
- ListItem() {
|
|
|
- this.buildAlbumItem(album)
|
|
|
- }
|
|
|
- }, (album: NavidromeRestAlbum) => album.id)
|
|
|
+ if (this.isSearchMode && this.selectedTab === 0 && this.searchText.length > 0 && this.isSearchLoading) {
|
|
|
+ Column() {
|
|
|
+ LoadingProgress()
|
|
|
+ .width(40)
|
|
|
+ .height(40)
|
|
|
+ .color(this.themeColor)
|
|
|
+ Text('正在通过 API 搜索歌曲...')
|
|
|
+ .margin({ top: 12 })
|
|
|
+ .fontSize(14)
|
|
|
+ .fontColor($r('app.color.index_tab_unselected_font_color'))
|
|
|
}
|
|
|
- }
|
|
|
- .width('100%')
|
|
|
- .layoutWeight(1)
|
|
|
- .cachedCount(3)
|
|
|
- .padding({ top: 5, bottom: 5 })
|
|
|
- .listDirection(Axis.Vertical)
|
|
|
+ .width('100%')
|
|
|
+ .layoutWeight(1)
|
|
|
+ } else if (this.selectedTab === 0 && this.filterType !== NavFilterType.None && this.isFilterLoading) {
|
|
|
+ Column() {
|
|
|
+ LoadingProgress()
|
|
|
+ .width(40)
|
|
|
+ .height(40)
|
|
|
+ .color(this.themeColor)
|
|
|
+ Text('正在加载筛选歌曲...')
|
|
|
+ .margin({ top: 12 })
|
|
|
+ .fontSize(14)
|
|
|
+ .fontColor($r('app.color.index_tab_unselected_font_color'))
|
|
|
+ }
|
|
|
+ .width('100%')
|
|
|
+ .layoutWeight(1)
|
|
|
+ } else {
|
|
|
+ List({ space: 8 }) {
|
|
|
+ if (this.selectedTab === 0) {
|
|
|
+ ForEach(this.getVisibleSongs(), (item: VideoItem, index: number) => {
|
|
|
+ ListItem() {
|
|
|
+ this.buildSongItem(item, index)
|
|
|
+ }
|
|
|
+ }, (item: VideoItem) => item.id)
|
|
|
+ } else if (this.selectedTab === 1) {
|
|
|
+ ForEach(this.artists, (artist: NavidromeRestArtist) => {
|
|
|
+ ListItem() {
|
|
|
+ this.buildArtistItem(artist)
|
|
|
+ }
|
|
|
+ }, (artist: NavidromeRestArtist) => artist.id)
|
|
|
+ } else {
|
|
|
+ ForEach(this.albums, (album: NavidromeRestAlbum) => {
|
|
|
+ ListItem() {
|
|
|
+ this.buildAlbumItem(album)
|
|
|
+ }
|
|
|
+ }, (album: NavidromeRestAlbum) => album.id)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .width('100%')
|
|
|
+ .layoutWeight(1)
|
|
|
+ .cachedCount(3)
|
|
|
+ .padding({ top: 5, bottom: 5 })
|
|
|
+ .listDirection(Axis.Vertical)
|
|
|
.contentEndOffset(this.bottomSafeHeight+70)
|
|
|
- .scrollBar(BarState.Auto)
|
|
|
- .edgeEffect(EdgeEffect.Spring)
|
|
|
- .onReachEnd(() => {
|
|
|
- void this.handleReachEnd();
|
|
|
- })
|
|
|
+ .scrollBar(BarState.Auto)
|
|
|
+ .edgeEffect(EdgeEffect.Spring)
|
|
|
+ .onReachEnd(() => {
|
|
|
+ void this.handleReachEnd();
|
|
|
+ })
|
|
|
+ }
|
|
|
|
|
|
// 空状态
|
|
|
- if (this.getCurrentCount() === 0) {
|
|
|
+ if (this.getCurrentCount() === 0 && !(this.selectedTab === 0 && this.filterType !== NavFilterType.None && this.isFilterLoading) && !(this.isSearchMode && this.searchText.length > 0 && this.isSearchLoading)) {
|
|
|
Column() {
|
|
|
Image($r('app.media.music_red'))
|
|
|
.width(80)
|