using System.IO; namespace EmbyToolbox.Services; /// /// Сценарии для запоминания последних каталогов в диалогах открытия/сохранения. /// public enum RecentPathScenario { SeriesRenamer, ConversionAddFiles, ConversionAddFolder, Merge, VideoInfoOpenFile, SettingsTempFolder, SettingsOutputFolder, TrackExtractDestination } /// /// Запоминает последние каталоги по сценариям и общий каталог; сохраняет вместе с . /// public sealed class RecentPathService { private readonly AppSettingsService _settingsService; private string? _lastSeriesRenamerFolder; private string? _lastConversionFilesFolder; private string? _lastConversionFolder; private string? _lastMergeFolder; private string? _lastVideoInfoFolder; private string? _lastTempFolder; private string? _lastOutputFolder; private string? _lastTrackExtractDestinationFolder; private string? _lastCommonFolder; public RecentPathService(AppSettingsService settingsService) { _settingsService = settingsService; } public void HydrateFrom(AppSettings settings) { _lastSeriesRenamerFolder = settings.LastSeriesRenamerFolder; _lastConversionFilesFolder = settings.LastConversionFilesFolder; _lastConversionFolder = settings.LastConversionFolder; _lastMergeFolder = settings.LastMergeFolder; _lastVideoInfoFolder = settings.LastVideoInfoFolder; _lastTempFolder = settings.LastTempFolder; _lastOutputFolder = settings.LastOutputFolder; _lastTrackExtractDestinationFolder = settings.LastTrackExtractDestinationFolder; _lastCommonFolder = settings.LastCommonFolder; } public void ApplyTo(AppSettings target) { target.LastSeriesRenamerFolder = _lastSeriesRenamerFolder; target.LastConversionFilesFolder = _lastConversionFilesFolder; target.LastConversionFolder = _lastConversionFolder; target.LastMergeFolder = _lastMergeFolder; target.LastVideoInfoFolder = _lastVideoInfoFolder; target.LastTempFolder = _lastTempFolder; target.LastOutputFolder = _lastOutputFolder; target.LastTrackExtractDestinationFolder = _lastTrackExtractDestinationFolder; target.LastCommonFolder = _lastCommonFolder; } /// /// Дополнительный существующий каталог перед стандартным «Видео» (для TEMP: текущий выбранный каталог из настроек). /// public string GetInitialDirectory(RecentPathScenario scenario, string? extraFolderFallbackBeforeDefault = null) { foreach (var candidate in GetCandidateChain(scenario, extraFolderFallbackBeforeDefault)) { if (IsUsableExistingDirectory(candidate)) { return candidate!; } } return Environment.GetFolderPath(Environment.SpecialFolder.MyVideos); } public void RememberChosenFiles(RecentPathScenario scenario, IReadOnlyList chosenFilePaths) { if (chosenFilePaths.Count == 0) { return; } var dir = NormalizeExistingDirectory(Path.GetDirectoryName(chosenFilePaths[0])); if (dir is null) { return; } SetScenarioFolder(scenario, dir); _lastCommonFolder = dir; Persist(); } public string? GetNormalizedRememberedFolderPath(RecentPathScenario scenario) { var folder = GetScenarioStored(scenario); if (string.IsNullOrWhiteSpace(folder)) { return null; } try { return Path.GetFullPath(folder.Trim()); } catch { return null; } } public void RememberChosenFolder(RecentPathScenario scenario, string folderPathOrFile) { var dir = NormalizeExistingDirectory(folderPathOrFile); if (dir is null) { return; } SetScenarioFolder(scenario, dir); _lastCommonFolder = dir; Persist(); } private IEnumerable GetCandidateChain(RecentPathScenario scenario, string? extraFolderFallbackBeforeDefault) { yield return GetScenarioStored(scenario); yield return _lastCommonFolder; if (!string.IsNullOrWhiteSpace(extraFolderFallbackBeforeDefault)) { yield return NormalizePathOnly(extraFolderFallbackBeforeDefault); } } private string? GetScenarioStored(RecentPathScenario scenario) => scenario switch { RecentPathScenario.SeriesRenamer => _lastSeriesRenamerFolder, RecentPathScenario.ConversionAddFiles => _lastConversionFilesFolder, RecentPathScenario.ConversionAddFolder => _lastConversionFolder, RecentPathScenario.Merge => _lastMergeFolder, RecentPathScenario.VideoInfoOpenFile => _lastVideoInfoFolder, RecentPathScenario.SettingsTempFolder => _lastTempFolder, RecentPathScenario.SettingsOutputFolder => _lastOutputFolder, RecentPathScenario.TrackExtractDestination => _lastTrackExtractDestinationFolder, _ => null }; private void SetScenarioFolder(RecentPathScenario scenario, string normalizedDirectory) { switch (scenario) { case RecentPathScenario.SeriesRenamer: _lastSeriesRenamerFolder = normalizedDirectory; break; case RecentPathScenario.ConversionAddFiles: _lastConversionFilesFolder = normalizedDirectory; break; case RecentPathScenario.ConversionAddFolder: _lastConversionFolder = normalizedDirectory; break; case RecentPathScenario.Merge: _lastMergeFolder = normalizedDirectory; break; case RecentPathScenario.VideoInfoOpenFile: _lastVideoInfoFolder = normalizedDirectory; break; case RecentPathScenario.SettingsTempFolder: _lastTempFolder = normalizedDirectory; break; case RecentPathScenario.SettingsOutputFolder: _lastOutputFolder = normalizedDirectory; break; case RecentPathScenario.TrackExtractDestination: _lastTrackExtractDestinationFolder = normalizedDirectory; break; default: throw new ArgumentOutOfRangeException(nameof(scenario), scenario, null); } } private void Persist() { var disk = _settingsService.Load(); ApplyTo(disk); _settingsService.Save(disk); } private static string? NormalizeExistingDirectory(string? path) { if (string.IsNullOrWhiteSpace(path)) { return null; } try { var full = Path.GetFullPath(path.Trim()); return Directory.Exists(full) ? full : null; } catch { return null; } } private static string? NormalizePathOnly(string? path) { if (string.IsNullOrWhiteSpace(path)) { return null; } try { return Path.GetFullPath(path.Trim()); } catch { return null; } } private static bool IsUsableExistingDirectory(string? path) { if (string.IsNullOrWhiteSpace(path)) { return false; } try { return Directory.Exists(Path.GetFullPath(path.Trim())); } catch { return false; } } }