Ver Fonte

网盘的RemoteMusicPage加载数据改成懒加载LazyForEach

onecold há 6 meses atrás
pai
commit
5699a84110
1 ficheiros alterados com 69 adições e 13 exclusões
  1. 69 13
      entry/src/main/ets/view/RemoteMusicPage.ets

+ 69 - 13
entry/src/main/ets/view/RemoteMusicPage.ets

@@ -31,6 +31,7 @@ import { plexApi, PlexAlbum, PlexArtist, PlexPlaylist, PlexSong } from '../commo
 import { daoLiYuApi, DaoLiYuAlbum, DaoLiYuArtist, DaoLiYuTrack, DaoLiYuPlaylist } from '../common/network/DaoLiYuApi';
 import { getRemoteDriveDisplayLabel } from '../common/util/RemoteDriveLabel';
 import NavidromeListCache, { AllCacheData } from '../common/util/NavidromeListCache';
+import { LazyDataSource } from '../common/util/LazyDataSource';
 import { taskpool } from '@kit.ArkTS';
 
 const NAVIDROME_PLAYLIST_ID = 'navidrome-playlist';
@@ -142,6 +143,13 @@ export struct RemoteMusicPage {
   @State artists: NavidromeRestArtist[] = [];
   @State albums: NavidromeRestAlbum[] = [];
   @State playlists: NavidromeRestPlaylist[] = [];
+
+  // LazyForEach 数据源实例
+  private songDataSource: LazyDataSource<VideoItem> = new LazyDataSource<VideoItem>([]);
+  private artistDataSource: LazyDataSource<NavidromeRestArtist> = new LazyDataSource<NavidromeRestArtist>([]);
+  private albumDataSource: LazyDataSource<NavidromeRestAlbum> = new LazyDataSource<NavidromeRestAlbum>([]);
+  private playlistDataSource: LazyDataSource<NavidromeRestPlaylist> = new LazyDataSource<NavidromeRestPlaylist>([]);
+
   @State loading: boolean = false;
   @State songNextStart: number | null = 0;
   @State artistNextStart: number | null = 0;
@@ -422,6 +430,11 @@ export struct RemoteMusicPage {
     this.artists = [];
     this.albums = [];
     this.playlists = [];
+    // 更新 LazyForEach 数据源
+    this.songDataSource.pushArrayData([]);
+    this.artistDataSource.pushArrayData([]);
+    this.albumDataSource.pushArrayData([]);
+    this.playlistDataSource.pushArrayData([]);
     this.jellyfinSongIdSeen.clear();
     this.embySongIdSeen.clear();
     this.jellyfinSongKeySeen.clear();
@@ -440,6 +453,14 @@ export struct RemoteMusicPage {
     this.serverTotalSongCount = 0;
   }
 
+  // 更新所有 LazyForEach 数据源
+  private updateAllDataSources(): void {
+    this.songDataSource.pushArrayData(this.allVideos);
+    this.artistDataSource.pushArrayData(this.artists);
+    this.albumDataSource.pushArrayData(this.albums);
+    this.playlistDataSource.pushArrayData(this.playlists);
+  }
+
   private async loadMediaLibrary(account: WebDavAccount): Promise<void> {
     if (this.isNavidromeAccount(account)) {
       await this.loadNavidromeLibrary(account);
@@ -484,19 +505,23 @@ export struct RemoteMusicPage {
       let loadedFromCache = false;
       if (cachedData.songs && cachedData.songs.length > 0) {
         this.allVideos = cachedData.songs;
+        this.songDataSource.pushArrayData(cachedData.songs);
         loadedFromCache = true;
         void ServerLogUtil.info('NavidromeLoad', `从缓存加载歌曲: ${cachedData.songs.length} 首`);
       }
       if (cachedData.artists && cachedData.artists.length > 0) {
         this.artists = cachedData.artists;
+        this.artistDataSource.pushArrayData(cachedData.artists);
         void ServerLogUtil.info('NavidromeLoad', `从缓存加载艺术家: ${cachedData.artists.length} 位`);
       }
       if (cachedData.albums && cachedData.albums.length > 0) {
         this.albums = cachedData.albums;
+        this.albumDataSource.pushArrayData(cachedData.albums);
         void ServerLogUtil.info('NavidromeLoad', `从缓存加载专辑: ${cachedData.albums.length} 张`);
       }
       if (cachedData.playlists && cachedData.playlists.length > 0) {
         this.playlists = cachedData.playlists;
+        this.playlistDataSource.pushArrayData(cachedData.playlists);
         void ServerLogUtil.info('NavidromeLoad', `从缓存加载歌单: ${cachedData.playlists.length} 个`);
       }
 
@@ -535,15 +560,19 @@ export struct RemoteMusicPage {
           // 直接更新数据(封面已在后台处理)
           if (taskResult.songs && taskResult.songs.length > 0) {
             this.allVideos = taskResult.songs;
+            this.songDataSource.pushArrayData(taskResult.songs);
           }
           if (taskResult.artists && taskResult.artists.length > 0) {
             this.artists = taskResult.artists;
+            this.artistDataSource.pushArrayData(taskResult.artists);
           }
           if (taskResult.albums && taskResult.albums.length > 0) {
             this.albums = taskResult.albums;
+            this.albumDataSource.pushArrayData(taskResult.albums);
           }
           if (taskResult.playlists && taskResult.playlists.length > 0) {
             this.playlists = taskResult.playlists;
+            this.playlistDataSource.pushArrayData(taskResult.playlists);
           }
 
           // 保存新的缓存(前50条)
@@ -773,6 +802,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.allVideos = [...this.allVideos, ...videos];
+      this.updateAllDataSources();
       // 打印前20条数据
       // const previewCount = Math.min(20, this.allVideos.length);
       // console.info(`onecold allVideos: ${this.allVideos.length}, 打印前${previewCount}条:`);
@@ -867,6 +897,7 @@ export struct RemoteMusicPage {
         return album;
       });
       this.albums = [...this.albums, ...processed];
+      this.updateAllDataSources();
       this.albumNextStart = response.nextStart;
       void ServerLogUtil.info('AlbumCover', `专辑列表追加: 本次 ${processed.length} 张, 总数 ${this.albums.length}`);
     } finally {
@@ -911,6 +942,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.allVideos = this.dedupRemoteSongsByKey([...this.allVideos, ...videoItems]);
+      this.updateAllDataSources();
       this.songNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `Jellyfin 歌曲追加: 本次 ${videoItems.length} 首, 已加载 ${this.allVideos.length}, 服务端总数 ${this.serverTotalSongCount}`);
     } finally {
@@ -934,6 +966,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.artists = [...this.artists, ...processed];
+      this.updateAllDataSources();
       this.artistNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `Jellyfin 艺术家追加: 本次 ${processed.length} 位, 总数 ${this.artists.length}`);
     } finally {
@@ -957,6 +990,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.albums = [...this.albums, ...processed];
+      this.updateAllDataSources();
       this.albumNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `Jellyfin 专辑追加: 本次 ${processed.length} 张, 总数 ${this.albums.length}`);
     } finally {
@@ -1001,6 +1035,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.allVideos = this.dedupRemoteSongsByKey([...this.allVideos, ...videoItems]);
+      this.updateAllDataSources();
       this.songNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `Emby 歌曲追加: 本次 ${videoItems.length} 首, 已加载 ${this.allVideos.length}, 服务端总数 ${this.serverTotalSongCount}`);
     } finally {
@@ -1024,6 +1059,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.artists = [...this.artists, ...processed];
+      this.updateAllDataSources();
       this.artistNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `Emby 艺术家追加: 本次 ${processed.length} 位, 总数 ${this.artists.length}`);
     } finally {
@@ -1047,6 +1083,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.albums = [...this.albums, ...processed];
+      this.updateAllDataSources();
       this.albumNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `Emby 专辑追加: 本次 ${processed.length} 张, 总数 ${this.albums.length}`);
     } finally {
@@ -1077,6 +1114,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.allVideos = this.dedupRemoteSongsByKey([...this.allVideos, ...videoItems]);
+      this.updateAllDataSources();
       this.songNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `AudioStation 歌曲追加: 本次 ${videoItems.length} 首, 已加载 ${this.allVideos.length}, 服务端总数 ${this.serverTotalSongCount}`);
     } finally {
@@ -1100,6 +1138,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.artists = [...this.artists, ...processed];
+      this.updateAllDataSources();
       this.artistNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `AudioStation 艺术家追加: 本次 ${processed.length} 位, 总数 ${this.artists.length}`);
     } finally {
@@ -1123,6 +1162,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.albums = [...this.albums, ...processed];
+      this.updateAllDataSources();
       this.albumNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `AudioStation 专辑追加: 本次 ${processed.length} 张, 总数 ${this.albums.length}`);
     } finally {
@@ -1146,6 +1186,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.playlists = [...this.playlists, ...processed];
+      this.updateAllDataSources();
       this.playlistNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `AudioStation 歌单追加: 本次 ${processed.length} 个, 总数 ${this.playlists.length}`);
     } finally {
@@ -1176,6 +1217,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.allVideos = this.dedupRemoteSongsByKey([...this.allVideos, ...videoItems]);
+      this.updateAllDataSources();
       this.songNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `Plex 歌曲追加: 本次 ${videoItems.length} 首, 已加载 ${this.allVideos.length}, 服务端总数 ${this.serverTotalSongCount}`);
     } finally {
@@ -1199,6 +1241,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.artists = [...this.artists, ...processed];
+      this.updateAllDataSources();
       this.artistNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `Plex 艺术家追加: 本次 ${processed.length} 位, 总数 ${this.artists.length}`);
     } finally {
@@ -1222,6 +1265,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.albums = [...this.albums, ...processed];
+      this.updateAllDataSources();
       this.albumNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `Plex 专辑追加: 本次 ${processed.length} 张, 总数 ${this.albums.length}`);
     } finally {
@@ -1245,6 +1289,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.playlists = [...this.playlists, ...processed];
+      this.updateAllDataSources();
       this.playlistNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `Plex 歌单追加: 本次 ${processed.length} 个, 总数 ${this.playlists.length}`);
     } finally {
@@ -1275,6 +1320,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.allVideos = [...this.allVideos, ...videoItems];
+      this.updateAllDataSources();
       this.songNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `道理鱼 歌曲追加: 本次 ${videoItems.length} 首, 已加载 ${this.allVideos.length}, 服务端总数 ${this.serverTotalSongCount}`);
     } finally {
@@ -1298,6 +1344,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.artists = [...this.artists, ...processed];
+      this.updateAllDataSources();
       this.artistNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `道理鱼 艺术家追加: 本次 ${processed.length} 位, 总数 ${this.artists.length}`);
     } finally {
@@ -1321,6 +1368,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.albums = [...this.albums, ...processed];
+      this.updateAllDataSources();
       this.albumNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `道理鱼 专辑追加: 本次 ${processed.length} 张, 总数 ${this.albums.length}`);
     } finally {
@@ -1344,6 +1392,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.playlists = [...this.playlists, ...processed];
+      this.updateAllDataSources();
       this.playlistNextStart = response.nextStart;
       void ServerLogUtil.info('NavidromeLoad', `道理鱼 歌单追加: 本次 ${processed.length} 个, 总数 ${this.playlists.length}`);
     } finally {
@@ -3130,7 +3179,8 @@ export struct RemoteMusicPage {
     if (this.isSearchMode) {
       return this.searchText.length > 0 ? this.filteredList : this.allVideos;
     }
-    if (this.filterType !== NavFilterType.None) {
+    // 详情视图模式或有筛选时,返回筛选后的歌曲
+    if (this.isDetailView || this.filterType !== NavFilterType.None) {
       return this.filterSongs;
     }
     return this.allVideos;
@@ -3193,6 +3243,7 @@ export struct RemoteMusicPage {
     this.isSearchLoading = false;
     this.searchTicket++;
     this.filterSongs = [];
+    this.songDataSource.pushArrayData([]); // 立即清空数据源,避免闪现旧数据
     this.isFilterLoading = true;
 
     // 调试日志:检查筛选结果
@@ -3274,6 +3325,7 @@ export struct RemoteMusicPage {
       }
       const videoItems = await this.convertSongsToVideoItems(restSongs, account);
       this.filterSongs = videoItems;
+      this.songDataSource.pushArrayData(this.filterSongs);
       this.isFilterLoading = false;
       return;
     }
@@ -3293,6 +3345,7 @@ export struct RemoteMusicPage {
         return;
       }
       this.filterSongs = videoItems;
+      this.songDataSource.pushArrayData(this.filterSongs);
       if (videoItems.length === 0) {
         void ServerLogUtil.warn('NavidromeFilter', '筛选下暂无歌曲');
       } else {
@@ -3309,6 +3362,8 @@ export struct RemoteMusicPage {
     this.filterLabel = '';
     this.filterSongs = [];
     this.isFilterLoading = false;
+    // 恢复完整列表的数据源
+    this.songDataSource.pushArrayData(this.allVideos);
     // 退出详情视图
     this.isDetailView = false;
   }
@@ -3414,19 +3469,20 @@ export struct RemoteMusicPage {
         }
         .width('100%')
         .layoutWeight(1)
-      } else if (this.selectedTab === 0 && this.filterType !== NavFilterType.None && this.isFilterLoading) {
+      } else if (this.isDetailView && this.filterType !== NavFilterType.None && this.isFilterLoading) {
         Column() {
           LoadingProgress()
             .width(40)
             .height(40)
             .color(this.themeColor)
-          Text('正在加载筛选歌曲...')
+          Text('正在加载')
             .margin({ top: 12 })
             .fontSize(14)
             .fontColor($r('app.color.index_tab_unselected_font_color'))
         }
         .width('100%')
         .layoutWeight(1)
+        .justifyContent(FlexAlign.Center)
       } else {
         if(this.isGridMusic){
           this.getGridView()
@@ -3436,7 +3492,7 @@ export struct RemoteMusicPage {
       }
 
       // 空状态
-      if (this.getCurrentCount() === 0 && !(this.selectedTab === 0 && this.filterType !== NavFilterType.None && this.isFilterLoading) && !(this.isSearchMode && this.searchText.length > 0 && this.isSearchLoading)) {
+      if (this.getCurrentCount() === 0 && !(this.isDetailView && this.filterType !== NavFilterType.None && this.isFilterLoading) && !(this.isSearchMode && this.searchText.length > 0 && this.isSearchLoading)) {
         Column() {
           SymbolGlyph($r('sys.symbol.music_fill'))
             .fontSize(50)
@@ -3479,25 +3535,25 @@ export struct RemoteMusicPage {
 
 
       if (this.selectedTab === 0||this.isDetailView) {
-        ForEach(this.getVisibleSongs(), (item: VideoItem, index: number) => {
+        LazyForEach(this.songDataSource, (item: VideoItem, index: number) => {
           GridItem() {
             this.buildSongItemGrid(item, index)
           }
         }, (item: VideoItem) => item.id)
       } else if (this.selectedTab === 1) {
-        ForEach(this.artists, (artist: NavidromeRestArtist) => {
+        LazyForEach(this.artistDataSource, (artist: NavidromeRestArtist) => {
           GridItem() {
             this.buildArtistItemGrid(artist)
           }
         }, (artist: NavidromeRestArtist) => artist.id)
       } else if (this.selectedTab === 2) {
-        ForEach(this.albums, (album: NavidromeRestAlbum) => {
+        LazyForEach(this.albumDataSource, (album: NavidromeRestAlbum) => {
           GridItem() {
             this.buildAlbumItemGrid(album)
           }
         }, (album: NavidromeRestAlbum) => album.id)
       } else if (this.selectedTab === 3) {
-        ForEach(this.playlists, (playlist: NavidromeRestPlaylist) => {
+        LazyForEach(this.playlistDataSource, (playlist: NavidromeRestPlaylist) => {
           GridItem() {
             this.buildPlaylistItemGrid(playlist)
           }
@@ -3512,7 +3568,7 @@ export struct RemoteMusicPage {
     .editMode(true)
     .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
       .animation({ duration: 500, curve: Curve.Ease }))
-    .padding({bottom:this.bottomSafeHeight+this.bottomSafeHeight+10})
+    .padding({bottom:this.bottomSafeHeight+this.bottomSafeHeight+26})
     .reuseId('grid_item')
     .layoutWeight(1)
     .cachedCount(this.twoFingerType==1?5:this.twoFingerType==2?4:3)
@@ -4004,25 +4060,25 @@ export struct RemoteMusicPage {
     List({scroller:this.scroller, space: 8 }) {
       // 详情视图模式下显示筛选后的歌曲,否则根据标签页显示对应内容
       if (this.selectedTab === 0||this.isDetailView) {
-        ForEach(this.getVisibleSongs(), (item: VideoItem, index: number) => {
+        LazyForEach(this.songDataSource, (item: VideoItem, index: number) => {
           ListItem() {
             this.buildSongItem(item, index)
           }
         }, (item: VideoItem) => item.id)
       } else if (this.selectedTab === 1) {
-        ForEach(this.artists, (artist: NavidromeRestArtist) => {
+        LazyForEach(this.artistDataSource, (artist: NavidromeRestArtist) => {
           ListItem() {
             this.buildArtistItem(artist)
           }
         }, (artist: NavidromeRestArtist) => artist.id)
       } else if (this.selectedTab === 2) {
-        ForEach(this.albums, (album: NavidromeRestAlbum) => {
+        LazyForEach(this.albumDataSource, (album: NavidromeRestAlbum) => {
           ListItem() {
             this.buildAlbumItem(album)
           }
         }, (album: NavidromeRestAlbum) => album.id)
       } else if (this.selectedTab === 3) {
-        ForEach(this.playlists, (playlist: NavidromeRestPlaylist) => {
+        LazyForEach(this.playlistDataSource, (playlist: NavidromeRestPlaylist) => {
           ListItem() {
             this.buildPlaylistItem(playlist)
           }