-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
242 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
namespace NonsPlayer.Core.Exceptions; | ||
|
||
public class SearchExceptions: Exception | ||
{ | ||
public SearchExceptions() | ||
{ | ||
} | ||
|
||
public SearchExceptions(string message) : base(message) | ||
{ | ||
} | ||
|
||
public SearchExceptions(string message, Exception inner) : base(message, inner) | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
using System.Diagnostics; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
using Newtonsoft.Json.Linq; | ||
using NonsPlayer.Core.Adapters; | ||
using NonsPlayer.Core.Api; | ||
using NonsPlayer.Core.Contracts.Models; | ||
using NonsPlayer.Core.Exceptions; | ||
using NonsPlayer.Core.Nons; | ||
|
||
namespace NonsPlayer.Core.Models; | ||
|
||
public class SearchResult : INonsModel | ||
{ | ||
public readonly string KeyWords; | ||
|
||
private SearchResult(string keyWords) | ||
{ | ||
if (keyWords.Equals(string.Empty)) | ||
{ | ||
throw new SearchExceptions("搜索KeyWords不能为空"); | ||
} | ||
|
||
KeyWords = keyWords; | ||
} | ||
|
||
public Playlist[] Playlists { get; set; } | ||
|
||
public Artist[] Artists { get; set; } | ||
|
||
public Music[] Musics { get; set; } | ||
|
||
public static async Task<SearchResult> CreateSearchAsync(string keyWords) | ||
{ | ||
var i = new SearchResult(keyWords); | ||
Debug.WriteLine(i.GetMd5(keyWords)); | ||
return i; | ||
} | ||
|
||
public async Task<Music[]> SearchMusics(int limit = 20) | ||
{ | ||
var result = await Apis.Search.Default(KeyWords, limit, 1, NonsCore.Instance); | ||
var tasks = ((JArray)result["result"]["songs"]) | ||
.Select(x => MusicAdapters.CreateById(x["id"].ToObject<long>())).ToList(); | ||
Musics = await Task.WhenAll(tasks); | ||
return Musics; | ||
} | ||
|
||
public async Task<Artist[]> SearchArtists(int limit = 2) | ||
{ | ||
var result = await Apis.Search.Default(KeyWords, limit, 100, NonsCore.Instance); | ||
Artists = ((JArray)result["result"]["artists"]) | ||
.Select(x => ArtistAdapters.CreateFromSearch((JObject)x)).ToArray(); | ||
return Artists; | ||
} | ||
|
||
public async Task<Playlist[]> SearchPlaylists(int limit = 2) | ||
{ | ||
var result = await Apis.Search.Default(KeyWords, limit, 1000, NonsCore.Instance); | ||
var tasks = ((JArray)result["result"]["playlists"]) | ||
.Select(x => PlaylistAdaptes.CreateById(x["id"].ToObject<long>())).ToList(); | ||
Playlists = await Task.WhenAll(tasks); | ||
return Playlists; | ||
} | ||
|
||
/// <returns>Md5的b64形式</returns> | ||
private string GetMd5(string keyWords) | ||
{ | ||
Md5 = MD5.HashData(Encoding.UTF8.GetBytes(keyWords)).ToBase64String(); | ||
return Md5; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,77 +1,94 @@ | ||
using CommunityToolkit.Mvvm.ComponentModel; | ||
using F23.StringSimilarity; | ||
using System.Collections.ObjectModel; | ||
using System.ComponentModel; | ||
using System.Diagnostics; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
using CommunityToolkit.Mvvm.ComponentModel; | ||
using Microsoft.UI.Xaml.Controls; | ||
using Microsoft.UI.Xaml.Input; | ||
using Newtonsoft.Json.Linq; | ||
using NonsPlayer.Components.Models; | ||
using NonsPlayer.Contracts.Services; | ||
using NonsPlayer.Contracts.ViewModels; | ||
using NonsPlayer.Core.Adapters; | ||
using NonsPlayer.Core.Api; | ||
using NonsPlayer.Core.Enums; | ||
using NonsPlayer.Core.Contracts.Models; | ||
using NonsPlayer.Core.Models; | ||
using NonsPlayer.Core.Nons; | ||
using NonsPlayer.Core.Nons.Player; | ||
using NonsPlayer.Helpers; | ||
|
||
|
||
namespace NonsPlayer.ViewModels; | ||
|
||
public class SearchViewModel : ObservableRecipient, INavigationAware | ||
public partial class SearchViewModel : ObservableRecipient, INavigationAware, INotifyPropertyChanged | ||
{ | ||
private string queryKey; | ||
public ObservableCollection<MusicItem> MusicItems = new(); | ||
[ObservableProperty] private Artist[] artists; | ||
[ObservableProperty] private Playlist[] playlists; | ||
|
||
public async void OnNavigatedTo(object parameter) | ||
public void OnNavigatedTo(object parameter) | ||
{ | ||
queryKey = (parameter as string).ToLower(); | ||
await Search(queryKey).ConfigureAwait(false); | ||
Search(queryKey).ConfigureAwait(false); | ||
} | ||
|
||
public void OnNavigatedFrom() | ||
{ | ||
} | ||
|
||
|
||
private void QuickSortAlgorithm(List<Tuple<SearchDataType, Tuple<double, JObject>>> data, int low, int high) | ||
public void DoubleClick(object sender, DoubleTappedRoutedEventArgs e) | ||
{ | ||
if (low < high) | ||
var listView = sender as ListView; | ||
if (listView.SelectedItem is MusicItem item) | ||
{ | ||
var pivotIndex = Partition(data, low, high); | ||
QuickSortAlgorithm(data, low, pivotIndex - 1); | ||
QuickSortAlgorithm(data, pivotIndex + 1, high); | ||
PlayQueue.Instance.Play(item.Music); | ||
} | ||
} | ||
|
||
private int Partition(List<Tuple<SearchDataType, Tuple<double, JObject>>> data, int low, int high) | ||
{ | ||
var pivotValue = data[high].Item2.Item1; | ||
var i = low - 1; | ||
|
||
for (var j = low; j < high; j++) | ||
if (data[j].Item2.Item1 < pivotValue) | ||
{ | ||
i++; | ||
Swap(data, i, j); | ||
} | ||
|
||
Swap(data, i + 1, high); | ||
return i + 1; | ||
} | ||
|
||
private void Swap(List<Tuple<SearchDataType, Tuple<double, JObject>>> data, int i, int j) | ||
public async Task Search(string key) | ||
{ | ||
(data[i], data[j]) = (data[j], data[i]); | ||
var searcher = await CacheHelper.GetSearchResultAsync(GetB64(key), key); | ||
await Task.WhenAll( | ||
searcher.SearchMusics(), | ||
searcher.SearchArtists(), | ||
searcher.SearchPlaylists()); | ||
SearchHelper.Instance.BestMusicResult = searcher.Musics[0]; | ||
Artists = searcher.Artists; | ||
Playlists = searcher.Playlists; | ||
for (var i = 0; i < searcher.Musics.Count(); i++) | ||
{ | ||
var index = i; | ||
if (index < App.GetService<ILocalSettingsService>().GetOptions().PlaylistTrackShowCount) | ||
ServiceHelper.DispatcherQueue.TryEnqueue(() => | ||
{ | ||
MusicItems.Add(new MusicItem | ||
{ | ||
Music = searcher.Musics[index], | ||
Index = (index + 1).ToString("D2") | ||
}); | ||
}); | ||
} | ||
} | ||
|
||
|
||
private Tuple<SearchDataType, Tuple<double, JObject>> ParseResult(SearchDataType type, string name, | ||
JObject originalJObject) | ||
public async void OnScrollViewerViewChanged(object? sender, ScrollViewerViewChangedEventArgs e) | ||
{ | ||
var l = new Levenshtein(); | ||
return new Tuple<SearchDataType, Tuple<double, JObject>> | ||
( | ||
type, | ||
new Tuple<double, JObject>(l.Distance(name, queryKey.ToLower()), originalJObject) | ||
); | ||
// | ||
// if (sender is ScrollViewer scrollViewer) | ||
// { | ||
// var offset = scrollViewer.VerticalOffset; | ||
// | ||
// var height = scrollViewer.ScrollableHeight; | ||
// if (height - offset < | ||
// App.GetService<ILocalSettingsService>().GetOptions().PlaylistTrackShowCount && | ||
// currentItemGroupIndex < playListObject.MusicsCount - 1) | ||
// await LoadMusicItemsByGroup(); | ||
// } | ||
} | ||
|
||
public async Task Search(string key) | ||
private string GetB64(string kyw) | ||
{ | ||
var result = await Apis.Search.Default(key, 1, 1, NonsCore.Instance); | ||
SearchHelper.Instance.BestMusicResult = | ||
await MusicAdapters.CreateById(result["result"]["songs"][0]["id"].ToObject<long>()); | ||
return Convert.ToBase64String(MD5.HashData(Encoding.UTF8.GetBytes(kyw))); | ||
} | ||
} |
Oops, something went wrong.