using Avalonia; using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Platform.Storage; using Dinah.Core; using LibationFileManager; using ReactiveUI; using System.Collections.Generic; using System.IO; using System.Linq; namespace LibationAvalonia.Controls; public partial class DirectoryOrCustomSelectControl : UserControl { public static readonly StyledProperty?> KnownDirectoriesProperty = AvaloniaProperty.Register?>(nameof(KnownDirectories), DefaultKnownDirectories); public static readonly StyledProperty SubDirectoryProperty = AvaloniaProperty.Register(nameof(SubDirectory)); public static readonly StyledProperty DirectoryProperty = AvaloniaProperty.Register(nameof(Directory)); public IList? KnownDirectories { get => GetValue(KnownDirectoriesProperty); set => SetValue(KnownDirectoriesProperty, value); } public string? Directory { get => GetValue(DirectoryProperty); set => SetValue(DirectoryProperty, value); } public string? SubDirectory { get => GetValue(SubDirectoryProperty); set => SetValue(SubDirectoryProperty, value); } public static IList DefaultKnownDirectories => [ Configuration.KnownDirectories.WinTemp, Configuration.KnownDirectories.UserProfile, Configuration.KnownDirectories.ApplicationData, Configuration.KnownDirectories.AppDir, Configuration.KnownDirectories.MyMusic, Configuration.KnownDirectories.MyDocs, Configuration.KnownDirectories.LibationFiles]; private readonly AvaloniaList _knownDirNames; public DirectoryOrCustomSelectControl() { InitializeComponent(); _knownDirNames = new(GetKnownDirectories(DefaultKnownDirectories)); cmbKnownDirs.ItemsSource = _knownDirNames; cmbKnownDirs.SelectionChanged += CmbKnownDirs_SelectionChanged; btnBrowse.Click += Browse_Click; } private void CmbKnownDirs_SelectionChanged(object? sender, SelectionChangedEventArgs e) { if (cmbKnownDirs.SelectedItem is KnownDirectoryItem item && item.Directory is not null) { Directory = item.Directory; } } private IEnumerable GetKnownDirectories(IEnumerable knownDirs) => knownDirs.Select(k => new KnownDirectoryItem(k, SubDirectory)).Where(k => k.Directory is not null); protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { if (change.Property == SubDirectoryProperty) { foreach (var item in _knownDirNames) { item.SubDirectory = SubDirectory; } VerifyAndApplyDirectory(Directory); } else if (change.Property == KnownDirectoriesProperty) { var knownDirs = KnownDirectories?.Count > 0 ? KnownDirectories : DefaultKnownDirectories; if (!_knownDirNames.Select(k => k.KnownDirectory).SequenceEqual(knownDirs)) { _knownDirNames.Clear(); _knownDirNames.AddRange(GetKnownDirectories(knownDirs)); } VerifyAndApplyDirectory(Directory); } else if (change.Property == DirectoryProperty) { VerifyAndApplyDirectory(Directory); } base.OnPropertyChanged(change); } private void VerifyAndApplyDirectory(string? directory) { if (string.IsNullOrWhiteSpace(Directory)) return; bool dirIsKnown = false; foreach (var item in _knownDirNames) { if (item.IsSamePathAs(directory)) { rbKnown.IsChecked = true; Directory = item.Directory; cmbKnownDirs.SelectedItem = item; dirIsKnown = true; break; } } if (!dirIsKnown) { tboxCustomDirPath.Text = directory; rbCustom.IsChecked = true; } } public async void Browse_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) { if (VisualRoot is not Window window) return; var options = new FolderPickerOpenOptions { AllowMultiple = false }; var selectedFolders = await window.StorageProvider.OpenFolderPickerAsync(options); Directory = selectedFolders.SingleOrDefault()?.TryGetLocalPath() ?? Directory; } private class KnownDirectoryItem : ReactiveObject { public Configuration.KnownDirectories KnownDirectory { get; set; } public string? Directory { get => field; set => this.RaiseAndSetIfChanged(ref field, value); } public string? Name { get; } public string? SubDirectory { get => field; set { field = value; if (Configuration.GetKnownDirectoryPath(KnownDirectory) is string dir) { Directory = Path.Combine(dir, field ?? ""); } } } public KnownDirectoryItem(Configuration.KnownDirectories known, string? subDir) { Name = known.GetDescription(); KnownDirectory = known; SubDirectory = subDir; } public bool IsSamePathAs(string? otherPath) { if (string.IsNullOrWhiteSpace(otherPath) || string.IsNullOrWhiteSpace(Directory)) return false; try { var p1 = Path.GetFullPath(Directory); var p2 = Path.GetFullPath(otherPath); return p1.Equals(p2, System.StringComparison.OrdinalIgnoreCase); } catch { return false; } } public override string? ToString() => Name?.ToString(); } }