using FileTime.Core.Components; using FileTime.Core.Interactions; using FileTime.Core.Models; using FileTime.Providers.Local; using FileTime.Avalonia.Application; using FileTime.Avalonia.Misc; using FileTime.Avalonia.Models; using FileTime.Avalonia.Services; using MvvmGen; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using FileTime.Core.Timeline; using FileTime.Core.Providers; using Syroot.Windows.IO; using FileTime.Avalonia.IconProviders; using Microsoft.Extensions.Logging; using System.Threading; using Avalonia.Input; using System.Reflection; namespace FileTime.Avalonia.ViewModels { [ViewModel] [Inject(typeof(LocalContentProvider))] [Inject(typeof(AppState), PropertyAccessModifier = AccessModifier.Public)] [Inject(typeof(StatePersistenceService), PropertyName = "StatePersistence", PropertyAccessModifier = AccessModifier.Public)] [Inject(typeof(ItemNameConverterService))] [Inject(typeof(ILogger), PropertyName = "_logger")] [Inject(typeof(KeyboardConfigurationService))] [Inject(typeof(CommandHandlerService), PropertyAccessModifier = AccessModifier.Public)] [Inject(typeof(IDialogService), PropertyName = "_dialogService")] [Inject(typeof(KeyInputHandlerService))] public partial class MainPageViewModel : IMainPageViewModelBase { public const string RAPIDTRAVEL = "rapidTravel"; private TimeRunner _timeRunner; [Property] private string _text; [Property] private List _rootDriveInfos; [Property] private List _places; [Property] private bool _loading = true; public string Title { get; private set; } async partial void OnInitialize() { _logger?.LogInformation($"Starting {nameof(MainPageViewModel)} initialization..."); var version = Assembly.GetExecutingAssembly().GetName().Version; var versionString = "Unknwon version"; if (version != null) { versionString = $"{version.Major}.{version.Minor}.{version.Build}"; if (version.Revision != 0) { versionString += $" ({version.Revision})"; } } Title = "FileTime " + versionString; _timeRunner = App.ServiceProvider.GetService()!; var inputInterface = (BasicInputHandler)App.ServiceProvider.GetService()!; inputInterface.InputHandler = _dialogService.ReadInputs; App.ServiceProvider.GetService(); await StatePersistence.LoadStatesAsync(); _timeRunner.CommandsChangedAsync.Add(UpdateParallelCommands); if (AppState.Tabs.Count == 0) { var tab = new Tab(); await tab.Init(LocalContentProvider); var tabContainer = new TabContainer(_timeRunner, tab, LocalContentProvider, ItemNameConverterService); await tabContainer.Init(1); tabContainer.IsSelected = true; AppState.Tabs.Add(tabContainer); } var driveInfos = new List(); var drives = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? DriveInfo.GetDrives().Where(d => d.DriveType == DriveType.Fixed) : DriveInfo.GetDrives().Where(d => d.DriveType == DriveType.Fixed && d.DriveFormat != "pstorefs" && d.DriveFormat != "bpf_fs" && d.DriveFormat != "tracefs" && !d.RootDirectory.FullName.StartsWith("/snap/")); foreach (var drive in drives) { var container = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? await GetContainerForWindowsDrive(drive) : await GetContainerForLinuxDrive(drive); if (container != null) { var driveInfo = new RootDriveInfo(drive, container); driveInfos.Add(driveInfo); } } RootDriveInfos = driveInfos.OrderBy(d => d.Name).ToList(); var places = new List(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var placesFolders = new List() { KnownFolders.Profile, KnownFolders.Desktop, KnownFolders.DocumentsLocalized, KnownFolders.DownloadsLocalized, KnownFolders.Music, KnownFolders.Pictures, KnownFolders.Videos, }; foreach (var placesFolder in placesFolders) { var possibleContainer = await LocalContentProvider.GetByPath(placesFolder.Path); if (possibleContainer is IContainer container) { var name = container.Name; if (await container.GetByPath("desktop.ini") is LocalFile element) { var lines = File.ReadAllLines(element.File.FullName); if (Array.Find(lines, l => l.StartsWith("localizedresourcename", StringComparison.OrdinalIgnoreCase)) is string nameLine) { var nameLineValue = string.Join('=', nameLine.Split('=')[1..]); var environemntVariables = Environment.GetEnvironmentVariables(); foreach (var keyo in environemntVariables.Keys) { if (keyo is string key && environemntVariables[key] is string value) { nameLineValue = nameLineValue.Replace($"%{key}%", value); } } if (nameLineValue.StartsWith("@")) { var parts = nameLineValue[1..].Split(','); if (parts.Length >= 2 && long.TryParse(parts[^1], out var parsedResourceId)) { if (parsedResourceId < 0) parsedResourceId *= -1; name = NativeMethodHelpers.GetStringResource(string.Join(',', parts[..^1]), (uint)parsedResourceId); } } else { name = nameLineValue; } } } places.Add(new PlaceInfo(name, container)); } } LocalContentProvider.Unload(); } else { throw new Exception("TODO linux places"); } Places = places; await Task.Delay(100); Loading = false; _logger?.LogInformation($"{nameof(MainPageViewModel)} initialized."); } private Task UpdateParallelCommands(object? sender, IReadOnlyList parallelCommands, CancellationToken token) { foreach (var parallelCommand in parallelCommands) { if (!AppState.TimelineCommands.Any(c => c.Id == parallelCommand.Id)) { AppState.TimelineCommands.Add(new ParallelCommandsViewModel(parallelCommand)); } } var itemsToRemove = new List(); foreach (var parallelCommandVm in AppState.TimelineCommands) { if (!parallelCommands.Any(c => c.Id == parallelCommandVm.Id)) { itemsToRemove.Add(parallelCommandVm); } } for (var i = 0; i < itemsToRemove.Count; i++) { itemsToRemove[i].Destroy(); AppState.TimelineCommands.Remove(itemsToRemove[i]); } foreach (var parallelCommand in parallelCommands) { var parallelCommandsVM = AppState.TimelineCommands.First(t => t.Id == parallelCommand.Id); foreach (var command in parallelCommand.Commands) { if (!parallelCommandsVM.ParallelCommands.Any(c => c.CommandTimeState.Command == command.Command)) { parallelCommandsVM.ParallelCommands.Add(new ParallelCommandViewModel(command)); } } var commandVMsToRemove = new List(); foreach (var commandVM in parallelCommandsVM.ParallelCommands) { if (!parallelCommand.Commands.Any(c => c.Command == commandVM.CommandTimeState.Command)) { commandVMsToRemove.Add(commandVM); } } for (var i = 0; i < commandVMsToRemove.Count; i++) { commandVMsToRemove[i].Destroy(); parallelCommandsVM.ParallelCommands.Remove(commandVMsToRemove[i]); } } return Task.CompletedTask; } private async Task GetContainerForWindowsDrive(DriveInfo drive) { return (await LocalContentProvider.GetContainers())!.FirstOrDefault(d => d.Name == drive.Name.TrimEnd(Path.DirectorySeparatorChar)); } private async Task GetContainerForLinuxDrive(DriveInfo drive) { return await LocalContentProvider.GetByPath(drive.Name) as IContainer; } [Command] public async void ProcessInputs() { await _dialogService.ProcessInputs(); } [Command] public void CancelInputs() { _dialogService.CancelInputs(); } [Command] public void ProcessMessageBox() { _dialogService.ProcessMessageBox(); } [Command] public void CancelMessageBox() { _dialogService.CancelMessageBox(); } public void ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action setHandled) { KeyInputHandlerService.ProcessKeyDown(key, keyModifiers, setHandled); } } }