diff --git a/NonsPlayer.Core/Models/LocalMusic.cs b/NonsPlayer.Core/Models/LocalMusic.cs index b276f18..5b0dc86 100644 --- a/NonsPlayer.Core/Models/LocalMusic.cs +++ b/NonsPlayer.Core/Models/LocalMusic.cs @@ -59,10 +59,7 @@ public bool Init() { Name = Path.GetFileNameWithoutExtension(track.Title); } - - Cover = LocalUtils.CompressAndConvertToByteArray(GetCover(track), 80, 80); - - + Md5 = track.GetHashCode().ToString(); Id = $"{Name}_{Md5}"; Url = track.Path; diff --git a/NonsPlayer.Core/Utils/LocalUtils.cs b/NonsPlayer.Core/Utils/LocalUtils.cs index 2a84fb1..1a09eaf 100644 --- a/NonsPlayer.Core/Utils/LocalUtils.cs +++ b/NonsPlayer.Core/Utils/LocalUtils.cs @@ -27,7 +27,7 @@ public static bool IsMusic(string path) { if (imageData == null) return null; - using var ms = new MemoryStream(imageData); + using var ms = new MemoryStream(imageData); Image image = Image.Load(ms); image.Mutate(x => x.Resize(width, height)); using var msOutput = new MemoryStream(); diff --git a/NonsPlayer/Components/Views/MusicListItemCard.xaml b/NonsPlayer/Components/Views/MusicListItemCard.xaml index 24f9114..58eb55f 100644 --- a/NonsPlayer/Components/Views/MusicListItemCard.xaml +++ b/NonsPlayer/Components/Views/MusicListItemCard.xaml @@ -60,6 +60,7 @@ FontSize="14" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,20,0" Padding="0" + MinWidth="40" FontWeight="Medium" /> _taskQueue = new(); + private readonly Thread[] _workers; + + public GlobalThreadPool(int numberOfThreads) + { + _workers = new Thread[numberOfThreads]; + for (int i = 0; i < numberOfThreads; i++) + { + _workers[i] = new Thread(Worker); + _workers[i].Start(); + } + } + + private void Worker() + { + foreach (var task in _taskQueue.GetConsumingEnumerable()) + { + task(); + } + } + + public void Enqueue(Action task) + { + _taskQueue.Add(task); + } + + public void Shutdown() + { + _taskQueue.CompleteAdding(); + foreach (var worker in _workers) + { + worker.Join(); + } + } +} \ No newline at end of file diff --git a/NonsPlayer/Services/LocalService.cs b/NonsPlayer/Services/LocalService.cs index 21b9852..3416ade 100644 --- a/NonsPlayer/Services/LocalService.cs +++ b/NonsPlayer/Services/LocalService.cs @@ -23,9 +23,9 @@ public class LocalService private const string _dataKey = "local_dictionaries.json"; public ObservableCollection Directories = new(); - public HashSet Songs = new(); - public HashSet Artists = new(); - public HashSet Albums = new(); + public List Songs = new(); + public List Artists = new(); + public List Albums = new(); private FileService FileService = App.GetService(); @@ -40,23 +40,22 @@ public bool TryAddDirection(string path) return true; } - public bool TryAddSong(LocalMusic song) + public void AddSong(LocalMusic song) { foreach (LocalMusic songItem in Songs) { - if (songItem.FilePath.Equals(song.FilePath)) return false; + if (songItem.FilePath.Equals(song.FilePath)) return; } LocalFolderChanged?.Invoke(string.Empty); - var result = Songs.Add(song); - return result; + Songs.Add(song); } public void AddSongs(IEnumerable songs) { foreach (LocalMusic inputSongItem in songs) { - TryAddSong(inputSongItem); + AddSong(inputSongItem); } LocalFolderChanged?.Invoke(string.Empty); diff --git a/NonsPlayer/ViewModels/Local/LocalMusicLibViewModel.cs b/NonsPlayer/ViewModels/Local/LocalMusicLibViewModel.cs index 6b9151d..dcfd19d 100644 --- a/NonsPlayer/ViewModels/Local/LocalMusicLibViewModel.cs +++ b/NonsPlayer/ViewModels/Local/LocalMusicLibViewModel.cs @@ -1,13 +1,16 @@ using ABI.Windows.Devices.Midi; using CommunityToolkit.Mvvm.ComponentModel; using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; using NonsPlayer.Components.Models; using NonsPlayer.Contracts.ViewModels; using NonsPlayer.Core.Contracts.Models.Music; using NonsPlayer.Core.Models; +using NonsPlayer.Core.Utils; using NonsPlayer.Helpers; using NonsPlayer.Models; using NonsPlayer.Services; +using System.Collections.Concurrent; using System.Collections.ObjectModel; using static NonsPlayer.Core.Services.ControlFactory; @@ -19,8 +22,10 @@ public partial class LocalMusicLibViewModel : ObservableObject, INavigationAware public ObservableCollection SongModels = new(); public ObservableCollection ArtistModels = new(); public ObservableCollection AlbumModels = new(); - + private int taskCount = 8; + private int completedTasks = 0; private LocalService localService = App.GetService(); + private int currentItemGroupIndex; public LocalMusicLibViewModel() { @@ -31,14 +36,10 @@ public async void Refresh() { var index = 0; SongModels.Clear(); + await LoadMusicItemsByGroup(); foreach (LocalMusic song in localService.Songs) { index++; - SongModels.Add(new MusicModel() { Index = index.ToString("D2"), Music = song, }); - if (!song.IsInit) - { - if (!song.Init()) return; - } if (song.Artists != null) { foreach (LocalArtist artist in song.Artists) @@ -89,6 +90,49 @@ public async void Refresh() } } + public async void OnScrollViewerViewChanged(object? sender, ScrollViewerViewChangedEventArgs e) + { + if (sender is ScrollViewer scrollViewer) + { + var offset = scrollViewer.VerticalOffset; + + var height = scrollViewer.ScrollableHeight; + if (height - offset < + AppConfig.Instance.AppSettings.PlaylistTrackCount && + currentItemGroupIndex < localService.Songs.Count - 1) + await LoadMusicItemsByGroup(); + } + } + + /// + /// 用于分组加载MusicItem + /// + private async Task LoadMusicItemsByGroup() + { + for (var i = 0; i < AppConfig.Instance.AppSettings.PlaylistTrackCount; i++) + { + int currentIndex = currentItemGroupIndex + i; + if (currentIndex >= localService.Songs.Count) break; // 确保索引有效 + GlobalThreadPool.Instance.Enqueue(() => + { + var music = localService.Songs[currentIndex]; + if (!music.IsInit) + { + music.Init(); + music.Cover = LocalUtils.CompressAndConvertToByteArray(music.GetCover(), 80, 80); + } + + var model = new MusicModel { Music = music, Index = (currentIndex + 1).ToString("D2") }; + ServiceHelper.DispatcherQueue.TryEnqueue(() => + { + SongModels.Add(model); + }); + }); + } + + currentItemGroupIndex += AppConfig.Instance.AppSettings.PlaylistTrackCount; + } + public void OnNavigatedTo(object parameter) { } diff --git a/NonsPlayer/Views/Local/LocalMusicLibPage.xaml b/NonsPlayer/Views/Local/LocalMusicLibPage.xaml index c1734a0..9430369 100644 --- a/NonsPlayer/Views/Local/LocalMusicLibPage.xaml +++ b/NonsPlayer/Views/Local/LocalMusicLibPage.xaml @@ -10,62 +10,65 @@ xmlns:views="using:NonsPlayer.Components.Views" xmlns:models="using:NonsPlayer.Models" mc:Ignorable="d"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - \ No newline at end of file