787a6e9f48
UI navigation framework Related Work Items: #408, #414, #416
149 lines
4.8 KiB
C#
149 lines
4.8 KiB
C#
using Newtonsoft.Json;
|
|
using System;
|
|
using System.IO;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
using Windows.Storage;
|
|
using Windows.Storage.AccessCache;
|
|
using YoutubeExplode.Videos;
|
|
using YoutubeExplode.Videos.Streams;
|
|
using FoxTube.Utils;
|
|
using FoxTube.Models;
|
|
using Windows.Storage.Pickers;
|
|
|
|
namespace FoxTube.Services
|
|
{
|
|
public static class DownloadsService
|
|
{
|
|
public static List<SavedVideo> History { get; } = new List<SavedVideo>();
|
|
public static List<DownloadItem> Queue { get; } = new List<DownloadItem>();
|
|
|
|
public static async Task Initialize()
|
|
{
|
|
StorageFile file = await StorageService.Folder.CreateFileAsync("DownloadHistory.json", CreationCollisionOption.OpenIfExists);
|
|
try
|
|
{
|
|
List<SavedVideo> savedVideos = JsonConvert.DeserializeObject<List<SavedVideo>>(File.ReadAllText(file.Path) ?? "") ?? new List<SavedVideo>();
|
|
History.AddRange(savedVideos);
|
|
|
|
foreach (SavedVideo i in History)
|
|
try { i.IsPathValid = await StorageApplicationPermissions.MostRecentlyUsedList.GetFileAsync(i.AccessToken) != null; }
|
|
catch { i.IsPathValid = false; }
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
await file.DeleteAsync(StorageDeleteOption.PermanentDelete);
|
|
StorageApplicationPermissions.MostRecentlyUsedList.Clear();
|
|
Metrics.SendReport(new Exception("Failed to load downloads history", e));
|
|
}
|
|
}
|
|
|
|
public static Task DownloadVideo(Video meta, IStreamInfo streamInfo) =>
|
|
DownloadVideo(meta, streamInfo, null);
|
|
|
|
public static async Task DownloadVideo(Video meta, IStreamInfo streamInfo, IStorageFile destination)
|
|
{
|
|
DownloadItem item = new DownloadItem
|
|
{
|
|
Title = $"[{(streamInfo as IVideoStreamInfo)?.VideoQualityLabel ?? "Audio"}] {meta.Title}",
|
|
Author = meta.Author,
|
|
Thumbnail = meta.Thumbnails.LowResUrl,
|
|
Duration = meta.Duration,
|
|
Id = meta.Id
|
|
};
|
|
Queue.Add(item);
|
|
|
|
if (destination == null)
|
|
destination = await (await GetDefaultDownloadsFolder()).CreateFileAsync($"{meta.Title.ReplaceInvalidChars('_')}.{streamInfo.Container.Name}", CreationCollisionOption.GenerateUniqueName);
|
|
|
|
item.Path = destination.Path;
|
|
|
|
try
|
|
{
|
|
await item.CommenceDownload(streamInfo, destination);
|
|
|
|
SavedVideo savedItem = item;
|
|
savedItem.AccessToken = StorageApplicationPermissions.MostRecentlyUsedList.Add(destination);
|
|
|
|
History.Add(savedItem);
|
|
|
|
StorageFile file = await StorageService.Folder.CreateFileAsync("DownloadHistory.json", CreationCollisionOption.OpenIfExists);
|
|
File.WriteAllText(file.Path, JsonConvert.SerializeObject(History));
|
|
}
|
|
catch (OperationCanceledException) { }
|
|
catch (Exception e)
|
|
{
|
|
await destination.DeleteAsync(StorageDeleteOption.PermanentDelete);
|
|
Metrics.SendReport(new Exception("Failed to download video", e), null,
|
|
("Video ID", meta.Id),
|
|
("Stream tag", streamInfo.Tag.ToString()));
|
|
}
|
|
finally
|
|
{
|
|
Queue.Remove(item);
|
|
}
|
|
}
|
|
|
|
public static async Task RemoveItems(bool removeFiles, params SavedVideo[] items)
|
|
{
|
|
foreach(SavedVideo i in items)
|
|
{
|
|
History.Remove(i);
|
|
try
|
|
{
|
|
if (removeFiles)
|
|
{
|
|
StorageFile file = await StorageApplicationPermissions.MostRecentlyUsedList.GetFileAsync(i.AccessToken);
|
|
await file?.DeleteAsync();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
StorageApplicationPermissions.MostRecentlyUsedList.Remove(i.AccessToken);
|
|
}
|
|
}
|
|
|
|
StorageFile historyFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("DownloadHistory.json", CreationCollisionOption.OpenIfExists);
|
|
File.WriteAllText(historyFile.Path, JsonConvert.SerializeObject(History));
|
|
}
|
|
|
|
public static async Task<StorageFolder> GetDefaultDownloadsFolder()
|
|
{
|
|
if (SettingsService.DefaultDownloadsFolder is string token && !string.IsNullOrWhiteSpace(token))
|
|
return await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(token) ??
|
|
await KnownFolders.VideosLibrary.CreateFolderAsync("FoxTube", CreationCollisionOption.OpenIfExists);
|
|
else
|
|
return await KnownFolders.VideosLibrary.CreateFolderAsync("FoxTube", CreationCollisionOption.OpenIfExists);
|
|
}
|
|
|
|
public static async Task CancelAll()
|
|
{
|
|
Queue.ForEach(i => i.Cancel());
|
|
while (Queue.Count > 0)
|
|
await Task.Delay(500);
|
|
}
|
|
|
|
public static async Task<StorageFolder> ChangeDefaultFolder()
|
|
{
|
|
FolderPicker picker = new FolderPicker
|
|
{
|
|
SuggestedStartLocation = PickerLocationId.Downloads
|
|
};
|
|
|
|
StorageFolder folder = await picker.PickSingleFolderAsync();
|
|
|
|
if (folder != null)
|
|
{
|
|
if (SettingsService.DefaultDownloadsFolder is string token && !string.IsNullOrWhiteSpace(token))
|
|
StorageApplicationPermissions.FutureAccessList.AddOrReplace(token, folder);
|
|
else
|
|
{
|
|
token = StorageApplicationPermissions.FutureAccessList.Add(folder);
|
|
SettingsService.DefaultDownloadsFolder = token;
|
|
}
|
|
}
|
|
|
|
return folder;
|
|
}
|
|
}
|
|
} |