mirror of
https://github.com/knah/VRCMelonAssistant.git
synced 2024-05-21 12:53:18 +12:00
commit
4e185333ad
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using static ModAssistant.Http;
|
||||
|
@ -13,49 +15,124 @@ namespace ModAssistant.API
|
|||
private static readonly string CustomSongsFolder = Path.Combine("Beat Saber_Data", "CustomLevels");
|
||||
private const bool BypassDownloadCounter = false;
|
||||
|
||||
public static async Task GetFromKey(string Key)
|
||||
public static async Task<BeatSaverMap> GetFromKey(string Key, bool showNotification = true)
|
||||
{
|
||||
BeatSaverApiResponse Map = await GetResponse(BeatSaverURLPrefix + "/api/maps/detail/" + Key);
|
||||
await InstallMap(Map);
|
||||
return await GetMap(Key, "key", showNotification);
|
||||
}
|
||||
|
||||
public static async Task GetFromHash(string Hash)
|
||||
public static async Task<BeatSaverMap> GetFromHash(string Hash, bool showNotification = true)
|
||||
{
|
||||
BeatSaverApiResponse Map = await GetResponse(BeatSaverURLPrefix + "/api/maps/by-hash/" + Hash);
|
||||
await InstallMap(Map);
|
||||
return await GetMap(Hash, "hash", showNotification);
|
||||
}
|
||||
|
||||
private static async Task<BeatSaverApiResponse> GetResponse(string url)
|
||||
private static async Task<BeatSaverMap> GetMap(string id, string type, bool showNotification)
|
||||
{
|
||||
string urlSegment;
|
||||
switch (type)
|
||||
{
|
||||
case "hash":
|
||||
urlSegment = "/api/maps/by-hash/";
|
||||
break;
|
||||
case "key":
|
||||
urlSegment = "/api/maps/detail/";
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
BeatSaverMap map = new BeatSaverMap();
|
||||
map.Success = false;
|
||||
try
|
||||
{
|
||||
var resp = await HttpClient.GetAsync(url);
|
||||
var body = await resp.Content.ReadAsStringAsync();
|
||||
|
||||
return JsonSerializer.Deserialize<BeatSaverApiResponse>(body);
|
||||
BeatSaverApiResponse beatsaver = await GetResponse(BeatSaverURLPrefix + urlSegment + id);
|
||||
map.Name = await InstallMap(beatsaver.map, showNotification);
|
||||
map.Success = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show($"{Application.Current.FindResource("OneClick:MapDownloadFailed")}\n\n" + e);
|
||||
ModAssistant.Utils.Log($"Failed downloading BeatSaver map: {id} | Error: {e}", "ERROR");
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static async Task<BeatSaverApiResponse> GetResponse(string url, bool showNotification = true)
|
||||
{
|
||||
BeatSaverApiResponse response = new BeatSaverApiResponse();
|
||||
try
|
||||
{
|
||||
var resp = await HttpClient.GetAsync(url);
|
||||
response.statusCode = resp.StatusCode;
|
||||
response.ratelimit = GetRatelimit(resp.Headers);
|
||||
if (response.statusCode == HttpStatusCode.OK)
|
||||
{
|
||||
if (response.ratelimit.IsSafe)
|
||||
{
|
||||
string body = await resp.Content.ReadAsStringAsync();
|
||||
response.map = JsonSerializer.Deserialize<BeatSaverApiResponseMap>(body);
|
||||
return response;
|
||||
}
|
||||
else
|
||||
{
|
||||
return response;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return response;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (showNotification)
|
||||
{
|
||||
MessageBox.Show($"{Application.Current.FindResource("OneClick:MapDownloadFailed")}\n\n" + e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task InstallMap(BeatSaverApiResponse Map)
|
||||
private static BeatSaverRatelimit GetRatelimit(HttpResponseHeaders headers)
|
||||
{
|
||||
BeatSaverRatelimit ratelimit = new BeatSaverRatelimit();
|
||||
|
||||
var _rateLimitRemaining = headers.GetValues("Rate-Limit-Remaining").GetEnumerator();
|
||||
var _rateLimitReset = headers.GetValues("Rate-Limit-Reset").GetEnumerator();
|
||||
var _rateLimitTotal = headers.GetValues("Rate-Limit-Total").GetEnumerator();
|
||||
_rateLimitRemaining.MoveNext();
|
||||
_rateLimitReset.MoveNext();
|
||||
_rateLimitTotal.MoveNext();
|
||||
ratelimit.Remaining = Int32.Parse(_rateLimitRemaining.Current);
|
||||
ratelimit.Reset = Int32.Parse(_rateLimitReset.Current);
|
||||
ratelimit.Total = Int32.Parse(_rateLimitTotal.Current);
|
||||
ratelimit.ResetTime = UnixTimestampToDateTime((long)ratelimit.Reset);
|
||||
|
||||
return ratelimit;
|
||||
}
|
||||
|
||||
public static DateTime UnixTimestampToDateTime(double unixTime)
|
||||
{
|
||||
DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
|
||||
long unixTimeStampInTicks = (long)(unixTime * TimeSpan.TicksPerSecond);
|
||||
return new DateTime(unixStart.Ticks + unixTimeStampInTicks, System.DateTimeKind.Utc);
|
||||
}
|
||||
|
||||
public static async Task<string> InstallMap(BeatSaverApiResponseMap Map, bool showNotification = true)
|
||||
{
|
||||
string zip = Path.Combine(Utils.BeatSaberPath, CustomSongsFolder, Map.hash) + ".zip";
|
||||
string mapName = string.Concat(($"{Map.key} ({Map.metadata.songName} - {Map.metadata.levelAuthorName})")
|
||||
.Split(ModAssistant.Utils.Constants.IllegalCharacters));
|
||||
string directory = Path.Combine(Utils.BeatSaberPath, CustomSongsFolder, mapName);
|
||||
|
||||
#pragma warning disable CS0162 // Unreachable code detected
|
||||
if (BypassDownloadCounter)
|
||||
{
|
||||
await Utils.DownloadAsset(BeatSaverURLPrefix + Map.directDownload, CustomSongsFolder, Map.hash + ".zip", mapName);
|
||||
await Utils.DownloadAsset(BeatSaverURLPrefix + Map.directDownload, CustomSongsFolder, Map.hash + ".zip", mapName, showNotification);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Utils.DownloadAsset(BeatSaverURLPrefix + Map.downloadURL, CustomSongsFolder, Map.hash + ".zip", mapName);
|
||||
await Utils.DownloadAsset(BeatSaverURLPrefix + Map.downloadURL, CustomSongsFolder, Map.hash + ".zip", mapName, showNotification);
|
||||
}
|
||||
#pragma warning restore CS0162 // Unreachable code detected
|
||||
|
||||
if (File.Exists(zip))
|
||||
{
|
||||
|
@ -81,14 +158,54 @@ namespace ModAssistant.API
|
|||
}
|
||||
else
|
||||
{
|
||||
string line1 = (string)Application.Current.FindResource("OneClick:SongDownload:Failed");
|
||||
string line2 = (string)Application.Current.FindResource("OneClick:SongDownload:NetworkIssues");
|
||||
string title = (string)Application.Current.FindResource("OneClick:SongDownload:FailedTitle");
|
||||
MessageBox.Show($"{line1}\n{line2}", title);
|
||||
if (showNotification)
|
||||
{
|
||||
string line1 = (string)Application.Current.FindResource("OneClick:SongDownload:Failed");
|
||||
string line2 = (string)Application.Current.FindResource("OneClick:SongDownload:NetworkIssues");
|
||||
string title = (string)Application.Current.FindResource("OneClick:SongDownload:FailedTitle");
|
||||
MessageBox.Show($"{line1}\n{line2}", title);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return mapName;
|
||||
}
|
||||
|
||||
public class BeatSaverMap
|
||||
{
|
||||
public BeatSaverApiResponse response { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
public class BeatSaverApiResponse
|
||||
{
|
||||
public HttpStatusCode statusCode { get; set; }
|
||||
public BeatSaverRatelimit ratelimit { get; set;}
|
||||
public BeatSaverApiResponseMap map { get; set; }
|
||||
}
|
||||
|
||||
public class BeatSaverRatelimit
|
||||
{
|
||||
public int Remaining { get; set; }
|
||||
public int Total { get; set; }
|
||||
public int Reset { get; set; }
|
||||
public DateTime ResetTime { get; set; }
|
||||
public bool IsSafe
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Remaining > 3) return true;
|
||||
else return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Wait()
|
||||
{
|
||||
await Task.Delay(new TimeSpan(ResetTime.Ticks - DateTime.Now.Ticks));
|
||||
}
|
||||
}
|
||||
|
||||
public class BeatSaverApiResponseMap
|
||||
{
|
||||
public Metadata metadata { get; set; }
|
||||
public Stats stats { get; set; }
|
||||
|
|
120
ModAssistant/Classes/External Interfaces/Playlists.cs
Normal file
120
ModAssistant/Classes/External Interfaces/Playlists.cs
Normal file
|
@ -0,0 +1,120 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static ModAssistant.Http;
|
||||
using System.Windows;
|
||||
|
||||
namespace ModAssistant.API
|
||||
{
|
||||
public class Playlists
|
||||
{
|
||||
private const string BSaberURLPrefix = "https://bsaber.com/PlaylistAPI/";
|
||||
private const string PlaylistsFolder = "Playlists";
|
||||
private static readonly string BeatSaberPath = Utils.BeatSaberPath;
|
||||
|
||||
public static async Task DownloadAll(Uri uri)
|
||||
{
|
||||
switch (uri.Host)
|
||||
{
|
||||
case "playlist":
|
||||
Uri url = new Uri($"{uri.LocalPath.Trim('/')}");
|
||||
string filename = await Get(url);
|
||||
await DownloadFrom(filename);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> Get(Uri url)
|
||||
{
|
||||
string filename = url.Segments.Last();
|
||||
string absolutePath = Path.Combine(BeatSaberPath, PlaylistsFolder, filename);
|
||||
try
|
||||
{
|
||||
await Utils.DownloadAsset(url.ToString(), PlaylistsFolder, filename);
|
||||
return absolutePath;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task DownloadFrom(string file, bool gui = false, System.Windows.Controls.ProgressBar progress = null)
|
||||
{
|
||||
int Errors = 0;
|
||||
int Minimum = 0;
|
||||
int Value = 0;
|
||||
if (progress != null)
|
||||
{
|
||||
progress.Minimum = 0;
|
||||
progress.Maximum = 1;
|
||||
progress.Value = 0;
|
||||
}
|
||||
Playlist playlist = JsonSerializer.Deserialize<Playlist>(File.ReadAllText(file));
|
||||
int Maximum = playlist.songs.Length;
|
||||
if (progress != null) progress.Maximum = playlist.songs.Length;
|
||||
|
||||
foreach (Playlist.Song song in playlist.songs)
|
||||
{
|
||||
API.BeatSaver.BeatSaverMap response = new BeatSaver.BeatSaverMap();
|
||||
if (!string.IsNullOrEmpty(song.hash))
|
||||
{
|
||||
response = await BeatSaver.GetFromHash(song.hash, false);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(song.key))
|
||||
{
|
||||
response = await BeatSaver.GetFromKey(song.key, false);
|
||||
}
|
||||
Value++;
|
||||
if (progress != null) progress.Value++;
|
||||
|
||||
if (gui)
|
||||
{
|
||||
if (response.Success)
|
||||
{
|
||||
MainWindow.Instance.MainText = $"{string.Format((string)Application.Current.FindResource("Options:InstallingPlaylist"), TextProgress(Minimum, Maximum, Value))}";
|
||||
}
|
||||
else
|
||||
{
|
||||
MainWindow.Instance.MainText = $"{string.Format((string)Application.Current.FindResource("Options:FailedPlaylistSong"), song.songName)}";
|
||||
ModAssistant.Utils.Log($"Failed installing BeatSaver map: {song.songName} | {song.key} | {song.hash}");
|
||||
await Task.Delay(3 * 1000);
|
||||
Errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gui)
|
||||
{
|
||||
MainWindow.Instance.MainText = $"{string.Format((string)Application.Current.FindResource("Options:FinishedPlaylist"), Errors, playlist.playlistTitle)}";
|
||||
}
|
||||
}
|
||||
|
||||
private static string TextProgress(int min, int max, int value)
|
||||
{
|
||||
if (max == value)
|
||||
{
|
||||
return $" {string.Concat(Enumerable.Repeat("▒", 10))} [{value}/{max}]";
|
||||
}
|
||||
int interval = (int)Math.Floor((double)value / ( ((double)max - (double)min ) / (double)10));
|
||||
return $" {string.Concat(Enumerable.Repeat("▒", interval))}{string.Concat(Enumerable.Repeat("░", 10 - interval))} [{value}/{max}]";
|
||||
}
|
||||
|
||||
class Playlist
|
||||
{
|
||||
public string playlistTitle { get; set; }
|
||||
public string playlistAuthor { get; set; }
|
||||
public string image { get; set; }
|
||||
public Song[] songs { get; set; }
|
||||
|
||||
public class Song
|
||||
{
|
||||
public string key { get; set; }
|
||||
public string hash { get; set; }
|
||||
public string songName { get; set; }
|
||||
public string uploader { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,12 +11,18 @@ namespace ModAssistant.API
|
|||
{
|
||||
public static readonly string BeatSaberPath = App.BeatSaberInstallDirectory;
|
||||
|
||||
public static async Task DownloadAsset(string link, string folder, bool showNotifcation, string fileName = null)
|
||||
{
|
||||
await DownloadAsset(link, folder, fileName, null, showNotifcation);
|
||||
}
|
||||
|
||||
public static async Task DownloadAsset(string link, string folder, string fileName = null, string displayName = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(displayName))
|
||||
{
|
||||
displayName = Path.GetFileNameWithoutExtension(fileName);
|
||||
}
|
||||
await DownloadAsset(link, folder, fileName, displayName, true);
|
||||
}
|
||||
|
||||
public static async Task DownloadAsset(string link, string folder, string fileName, string displayName, bool showNotification)
|
||||
{
|
||||
if (string.IsNullOrEmpty(BeatSaberPath))
|
||||
{
|
||||
ModAssistant.Utils.SendNotify((string)Application.Current.FindResource("OneClick:InstallDirNotFound"));
|
||||
|
@ -32,9 +38,16 @@ namespace ModAssistant.API
|
|||
{
|
||||
fileName = WebUtility.UrlDecode(Path.Combine(BeatSaberPath, folder, fileName));
|
||||
}
|
||||
if (string.IsNullOrEmpty(displayName))
|
||||
{
|
||||
displayName = Path.GetFileNameWithoutExtension(fileName);
|
||||
}
|
||||
|
||||
await ModAssistant.Utils.Download(link, fileName);
|
||||
ModAssistant.Utils.SendNotify(string.Format((string)Application.Current.FindResource("OneClick:InstalledAsset"), displayName));
|
||||
if (showNotification)
|
||||
{
|
||||
ModAssistant.Utils.SendNotify(string.Format((string)Application.Current.FindResource("OneClick:InstalledAsset"), displayName));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace ModAssistant
|
|||
{
|
||||
class OneClickInstaller
|
||||
{
|
||||
private static readonly string[] Protocols = new[] { "modelsaber", "beatsaver" };
|
||||
private static readonly string[] Protocols = new[] { "modelsaber", "beatsaver", "bsplaylist" };
|
||||
|
||||
public static async Task InstallAsset(string link)
|
||||
{
|
||||
|
@ -23,6 +23,9 @@ namespace ModAssistant
|
|||
case "beatsaver":
|
||||
await BeatSaver(uri);
|
||||
break;
|
||||
case "bsplaylist":
|
||||
await Playlist(uri);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +40,11 @@ namespace ModAssistant
|
|||
await API.ModelSaber.GetModel(uri);
|
||||
}
|
||||
|
||||
private static async Task Playlist(Uri uri)
|
||||
{
|
||||
await API.Playlists.DownloadAll(uri);
|
||||
}
|
||||
|
||||
public static void Register(string Protocol, bool Background = false)
|
||||
{
|
||||
if (IsRegistered(Protocol) == true)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
@ -309,7 +310,7 @@ namespace ModAssistant
|
|||
|
||||
public static string GetManualDir()
|
||||
{
|
||||
var dialog = new Microsoft.Win32.SaveFileDialog()
|
||||
var dialog = new SaveFileDialog()
|
||||
{
|
||||
Title = (string)Application.Current.FindResource("Utils:InstallDir:DialogTitle"),
|
||||
Filter = "Directory|*.this.directory",
|
||||
|
@ -339,6 +340,22 @@ namespace ModAssistant
|
|||
return null;
|
||||
}
|
||||
|
||||
public static string GetManualFile(string filter = "", string title = "Open File")
|
||||
{
|
||||
var dialog = new OpenFileDialog()
|
||||
{
|
||||
Title = title,
|
||||
Filter = filter,
|
||||
Multiselect = false,
|
||||
};
|
||||
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
return dialog.FileName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool IsVoid()
|
||||
{
|
||||
string directory = App.BeatSaberInstallDirectory;
|
||||
|
@ -387,6 +404,13 @@ namespace ModAssistant
|
|||
MessageBox.Show($"{string.Format((string)Application.Current.FindResource("Utils:CannotOpenFolder"), location)}.");
|
||||
}
|
||||
|
||||
public static void Log(string message, string severity = "LOG")
|
||||
{
|
||||
string path = Path.GetDirectoryName(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath);
|
||||
string logFile = $"{path}{Path.DirectorySeparatorChar}log.log";
|
||||
File.AppendAllText(logFile, $"[{DateTime.UtcNow.ToString("yyyy-mm-dd HH:mm:ss.ffffff")}][{severity.ToUpper()}] {message}\n");
|
||||
}
|
||||
|
||||
public static async Task Download(string link, string output)
|
||||
{
|
||||
var resp = await HttpClient.GetAsync(link);
|
||||
|
|
|
@ -102,6 +102,11 @@
|
|||
<sys:String x:Key="Options:GameType">Options:GameType</sys:String>
|
||||
<sys:String x:Key="Options:GameType:Steam">Options:GameType:Steam</sys:String>
|
||||
<sys:String x:Key="Options:GameType:Oculus">Options:GameType:Oculus</sys:String>
|
||||
<sys:String x:Key="Options:Tools">Options:Tools</sys:String>
|
||||
<sys:String x:Key="Options:InstallPlaylist">Options:InstallPlaylist</sys:String>
|
||||
<sys:String x:Key="Options:InstallingPlaylist">{0} Options:InstallingPlaylist</sys:String>
|
||||
<sys:String x:Key="Options:FailedPlaylistSong">{0} Options:FailedPlaylistSong</sys:String>
|
||||
<sys:String x:Key="Options:FinishedPlaylist">{0} {1} Options:FinishedPlaylist</sys:String>
|
||||
<sys:String x:Key="Options:Diagnostics">Options:Diagnostics</sys:String>
|
||||
<sys:String x:Key="Options:OpenLogsButton">Options:OpenLogsButton</sys:String>
|
||||
<sys:String x:Key="Options:OpenAppDataButton">Options:OpenAppDataButton</sys:String>
|
||||
|
|
|
@ -142,6 +142,11 @@
|
|||
<sys:String x:Key="Options:GameType">Game Type</sys:String>
|
||||
<sys:String x:Key="Options:GameType:Steam">Steam</sys:String>
|
||||
<sys:String x:Key="Options:GameType:Oculus">Oculus</sys:String>
|
||||
<sys:String x:Key="Options:Tools">Tools</sys:String>
|
||||
<sys:String x:Key="Options:InstallPlaylist">Install Playlist</sys:String>
|
||||
<sys:String x:Key="Options:InstallingPlaylist">Installing Playlist: {0}</sys:String>
|
||||
<sys:String x:Key="Options:FailedPlaylistSong">Failed song: {0}</sys:String>
|
||||
<sys:String x:Key="Options:FinishedPlaylist">[{0} fails] Finished Installing Playlist: {1}</sys:String>
|
||||
<sys:String x:Key="Options:Diagnostics">Diagnostics</sys:String>
|
||||
<sys:String x:Key="Options:OpenLogsButton">Open Logs</sys:String>
|
||||
<sys:String x:Key="Options:OpenAppDataButton">Open AppData</sys:String>
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
|
@ -67,6 +68,7 @@
|
|||
</ApplicationDefinition>
|
||||
<Compile Include="Classes\External Interfaces\BeatSaver.cs" />
|
||||
<Compile Include="Classes\External Interfaces\ModelSaber.cs" />
|
||||
<Compile Include="Classes\External Interfaces\Playlists.cs" />
|
||||
<Compile Include="Classes\External Interfaces\Utils.cs" />
|
||||
<Compile Include="Classes\Http.cs" />
|
||||
<Compile Include="Classes\HyperlinkExtensions.cs" />
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto" />
|
||||
|
@ -265,13 +267,34 @@
|
|||
HorizontalAlignment="Left"
|
||||
FontSize="24"
|
||||
FontWeight="Bold"
|
||||
Text="{DynamicResource Options:Diagnostics}" />
|
||||
Text="{DynamicResource Options:Tools}" />
|
||||
<StackPanel
|
||||
Grid.Row="15"
|
||||
Grid.ColumnSpan="4"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Left"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Height="30"
|
||||
Margin="5"
|
||||
Padding="5"
|
||||
Click="InstallPlaylistButton_Click"
|
||||
Content="{DynamicResource Options:InstallPlaylist}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="16"
|
||||
Margin="15,5,5,5"
|
||||
HorizontalAlignment="Left"
|
||||
FontSize="24"
|
||||
FontWeight="Bold"
|
||||
Text="{DynamicResource Options:Diagnostics}" />
|
||||
<StackPanel
|
||||
Grid.Row="17"
|
||||
Grid.ColumnSpan="4"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Left"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Height="30"
|
||||
Margin="5"
|
||||
|
|
|
@ -308,5 +308,14 @@ namespace ModAssistant.Pages
|
|||
MessageBox.Show((string)Application.Current.FindResource("Options:ThemeFolderNotFound"));
|
||||
}
|
||||
}
|
||||
|
||||
private void InstallPlaylistButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
string playlistFile = Utils.GetManualFile();
|
||||
if (File.Exists(playlistFile))
|
||||
{
|
||||
Task.Run(() => { API.Playlists.DownloadFrom(playlistFile, true).Wait(); });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue