using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using OwlCore.AbstractStorage; using OwlCore.WinUI.Extensions; using StrixMusic.Sdk.WinUI.Models; using Windows.ApplicationModel.Core; using Windows.Storage; using Windows.Storage.AccessCache; using Windows.Storage.Pickers; // ReSharper disable once CheckNamespace #pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. namespace StrixMusic.Services { /// public sealed class FileSystemService : IFileSystemService { private readonly List _registeredFolders; /// /// Constructs a new . /// public FileSystemService() { _registeredFolders = new List(); } /// /// Constructs a new . /// public FileSystemService(StorageFolder rootFolder) { _registeredFolders = new List(); RootFolder = new FolderData(rootFolder); } /// /// A shared singleton instance of . /// public static FileSystemService Singleton { get; } = new FileSystemService(); /// public bool IsInitialized { get; set; } /// /// Defines the root folder where new files and folders are created. /// public IFolderData RootFolder { get; } = new FolderData(ApplicationData.Current.LocalFolder); /// public Task> GetPickedFolders() { return Task.FromResult>(_registeredFolders.ToArray()); } /// public async Task PickFolder() { await CoreApplication.MainView.Dispatcher.SwitchToUI(); var picker = new FolderPicker { SuggestedStartLocation = PickerLocationId.MusicLibrary, ViewMode = PickerViewMode.List, }; picker.FileTypeFilter.Add("*"); var pickedFolder = await picker.PickSingleFolderAsync(); if (pickedFolder == null) return null; #if NETFX_CORE StorageApplicationPermissions.FutureAccessList.Add(pickedFolder, pickedFolder.Path); #endif var folderData = new FolderData(pickedFolder); _registeredFolders.Add(folderData); return folderData; } /// public Task RevokeAccess(IFolderData folder) { if (!_registeredFolders.Contains(folder) || !(folder is FolderData folderData)) return Task.CompletedTask; #if NETFX_CORE var targetFutureAccessListFile = StorageApplicationPermissions.FutureAccessList.Entries .FirstOrDefault(x => x.Metadata == folderData.StorageFolder.Path); StorageApplicationPermissions.FutureAccessList.Remove(targetFutureAccessListFile.Token); #endif _registeredFolders.Remove(folder); return Task.CompletedTask; } /// public async Task FileExistsAsync(string path) { try { var res = await StorageFile.GetFileFromPathAsync(path); return res != null; } catch (Exception) { return false; } } /// public async Task DirectoryExistsAsync(string path) { try { await StorageFile.GetFileFromPathAsync(path); return true; } catch (Exception) { return false; } } /// public Task GetFolderFromPathAsync(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(); var folderData = _registeredFolders.FirstOrDefault(x => x.Path == path); if (folderData is null) return Task.FromResult(null); else return Task.FromResult(folderData); // https://github.com/unoplatform/uno/issues/7401 // var folderData = await StorageFolder.GetFolderFromPathAsync(path); } /// public async Task GetFileFromPathAsync(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(); var file = await StorageFile.GetFileFromPathAsync(path); return new FileData(file); } /// public async Task CreateDirectoryAsync(string folderName) { var folderData = await RootFolder.CreateFolderAsync(folderName, OwlCore.AbstractStorage.CreationCollisionOption.OpenIfExists); return folderData; } /// public async Task InitAsync(CancellationToken cancellationToken = default) { #if NETFX_CORE var persistentAccessEntries = StorageApplicationPermissions.FutureAccessList.Entries.ToArray(); if (persistentAccessEntries == null || !persistentAccessEntries.Any()) return; foreach (var accessEntry in persistentAccessEntries) { StorageFolder? folder = null; try { folder = await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(accessEntry.Token); } catch { // Folder may have been removed. StorageApplicationPermissions.FutureAccessList.Remove(accessEntry.Token); } if (folder == null) continue; var folderData = new FolderData(folder); _registeredFolders.Add(folderData); } #endif IsInitialized = true; } } } #pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.