RapidTravel impr, GoBack/Forward, header navigation
This commit is contained in:
@@ -63,9 +63,9 @@ public static class MainConfiguration
|
||||
//new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Key.F4)),
|
||||
new(EnterRapidTravelCommand.CommandName, new KeyConfig(Key.OemComma, shift: true)),
|
||||
new(EnterRapidTravelCommand.CommandName, new KeyConfig(Key.OemQuestion, shift: true)),
|
||||
//new CommandBindingConfiguration(ConfigCommand.FindByName, new[] { Key.F, Key.N }),
|
||||
//new CommandBindingConfiguration(ConfigCommand.FindByNameRegex, new[] { Key.F, Key.R }),
|
||||
new(GoBackCommand.CommandName, new KeyConfig(Key.Left, alt: true)),
|
||||
new(GoByFrequencyCommand.CommandName, Key.Z),
|
||||
new(GoForwardCommand.CommandName, new KeyConfig(Key.Right, alt: true)),
|
||||
new(GoToHomeCommand.CommandName, new[] {Key.G, Key.H}),
|
||||
new(GoToPathCommand.CommandName, new KeyConfig(Key.L, ctrl: true)),
|
||||
new(GoToPathCommand.CommandName, new[] {Key.G, Key.P}),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Globalization;
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Threading;
|
||||
using FileTime.Core.Models;
|
||||
using FileTime.GuiApp.App.ViewModels;
|
||||
|
||||
@@ -9,6 +10,7 @@ namespace FileTime.GuiApp.App.Converters;
|
||||
public class NamePartShrinkerConverter : IMultiValueConverter
|
||||
{
|
||||
private const int PixelPerChar = 8;
|
||||
|
||||
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Count > 0 && values[0] is IList<ItemNamePart> nameParts)
|
||||
@@ -20,8 +22,13 @@ public class NamePartShrinkerConverter : IMultiValueConverter
|
||||
newNameParts = GetNamePartsForWidth(nameParts, width - attributeWidth);
|
||||
}
|
||||
|
||||
return newNameParts.Select(p => new ItemNamePartViewModel(p.Text, p.IsSpecial ? TextDecorations.Underline : null)).ToList();
|
||||
var result = /* Dispatcher.UIThread.Invoke(() => */
|
||||
newNameParts.Select(p => new ItemNamePartViewModel(p.Text, p.IsSpecial ? TextDecorations.Underline : null)).ToList();
|
||||
/* ); */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -75,6 +82,7 @@ public class NamePartShrinkerConverter : IMultiValueConverter
|
||||
proposedText = proposedText[0..^1];
|
||||
trimmed = true;
|
||||
}
|
||||
|
||||
newNameParts[trimmedIndex] = new ItemNamePart(proposedText + (trimmed ? "..." : ""));
|
||||
if (trimmed) break;
|
||||
}
|
||||
@@ -100,6 +108,7 @@ public class NamePartShrinkerConverter : IMultiValueConverter
|
||||
if (!string.IsNullOrWhiteSpace(proposedText)) newNameParts.Add(new ItemNamePart(proposedText, namePart.IsSpecial));
|
||||
if (trimmed) break;
|
||||
}
|
||||
|
||||
if (newNameParts.Last().IsSpecial)
|
||||
{
|
||||
newNameParts.Add(new ItemNamePart("..."));
|
||||
@@ -109,6 +118,7 @@ public class NamePartShrinkerConverter : IMultiValueConverter
|
||||
var last = newNameParts.Last();
|
||||
newNameParts[^1] = new ItemNamePart(last.Text + "...");
|
||||
}
|
||||
|
||||
return newNameParts;
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,11 @@
|
||||
<Setter Property="Background" Value="{DynamicResource AppBackgroundColor}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBlock.PathPresenterItem:pointerover">
|
||||
<Setter Property="TextDecorations" Value="Underline" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Border.SelectedTimelineCommand">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ForegroundBrush}" />
|
||||
</Style>
|
||||
|
||||
@@ -43,12 +43,22 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
|
||||
_appState.SelectedTab.Subscribe(t => _selectedTab = t);
|
||||
|
||||
_openModals = modalService.OpenModals.ToBindedCollection();
|
||||
|
||||
_appState.RapidTravelTextDebounced.Subscribe((v, _) =>
|
||||
{
|
||||
if (_selectedTab?.Tab is not { } tab) return Task.CompletedTask;
|
||||
tab.RemoveItemFilter(RapidTravelFilterName);
|
||||
|
||||
if (v is null) return Task.CompletedTask;
|
||||
|
||||
tab.AddItemFilter(new ItemFilter(RapidTravelFilterName, i => i.Name.ToLower().Contains(v)));
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action<bool> setHandled)
|
||||
{
|
||||
var keyString = key.ToString();
|
||||
var updateRapidTravelFilter = false;
|
||||
|
||||
if (key == Key.Escape)
|
||||
{
|
||||
@@ -70,7 +80,6 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
|
||||
await _appState.RapidTravelText.SetValue(
|
||||
_appState.RapidTravelText.Value![..^1]
|
||||
);
|
||||
updateRapidTravelFilter = true;
|
||||
}
|
||||
}
|
||||
else if (keyString.Length == 1)
|
||||
@@ -79,11 +88,10 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
|
||||
await _appState.RapidTravelText.SetValue(
|
||||
_appState.RapidTravelText.Value + keyString.ToLower()
|
||||
);
|
||||
updateRapidTravelFilter = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var currentKeyAsList = new List<KeyConfig>() { new KeyConfig(key) };
|
||||
var currentKeyAsList = new List<KeyConfig>() {new KeyConfig(key)};
|
||||
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(currentKeyAsList));
|
||||
if (selectedCommandBinding != null)
|
||||
{
|
||||
@@ -91,42 +99,6 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
|
||||
await CallCommandAsync(_identifiableUserCommandService.GetCommand(selectedCommandBinding.Command));
|
||||
}
|
||||
}
|
||||
|
||||
if (updateRapidTravelFilter)
|
||||
{
|
||||
if (_selectedTab?.Tab is not ITab tab) return;
|
||||
|
||||
tab.RemoveItemFilter(RapidTravelFilterName);
|
||||
tab.AddItemFilter(new ItemFilter(RapidTravelFilterName, i => i.Name.ToLower().Contains(_appState.RapidTravelText.Value!)));
|
||||
/*var currentLocation = await _appState.SelectedTab.CurrentLocation.Container.WithoutVirtualContainer(MainPageViewModel.RAPIDTRAVEL);
|
||||
var newLocation = new VirtualContainer(
|
||||
currentLocation,
|
||||
new List<Func<IEnumerable<IContainer>, IEnumerable<IContainer>>>()
|
||||
{
|
||||
container => container.Where(c => c.Name.ToLower().Contains(_appState.RapidTravelText))
|
||||
},
|
||||
new List<Func<IEnumerable<IElement>, IEnumerable<IElement>>>()
|
||||
{
|
||||
element => element.Where(e => e.Name.ToLower().Contains(_appState.RapidTravelText))
|
||||
},
|
||||
virtualContainerName: MainPageViewModel.RAPIDTRAVEL
|
||||
);
|
||||
|
||||
await newLocation.Init();
|
||||
|
||||
await _appState.SelectedTab.OpenContainer(newLocation);
|
||||
|
||||
var selectedItemName = _appState.SelectedTab.SelectedItem?.Item.Name;
|
||||
var currentLocationItems = await _appState.SelectedTab.CurrentLocation.GetItems();
|
||||
if (currentLocationItems.FirstOrDefault(i => string.Equals(i.Item.Name, _appState.RapidTravelText, StringComparison.OrdinalIgnoreCase)) is IItemViewModel matchItem)
|
||||
{
|
||||
await _appState.SelectedTab.SetCurrentSelectedItem(matchItem.Item);
|
||||
}
|
||||
else if (!currentLocationItems.Select(i => i.Item.Name).Any(n => n == selectedItemName))
|
||||
{
|
||||
await _appState.SelectedTab.MoveCursorToFirst();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CallCommandAsync(IUserCommand command)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using FileTime.App.CommandPalette.Services;
|
||||
using DeclarativeProperty;
|
||||
using FileTime.App.CommandPalette.Services;
|
||||
using FileTime.App.Core.Services;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.App.FrequencyNavigation.Services;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<UserControl
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d"
|
||||
x:Class="FileTime.GuiApp.App.Views.PathPresenter"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:coremodels="using:FileTime.Core.Models"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ItemsControl ItemsSource="{Binding Converter={StaticResource SplitStringConverter}, ConverterParameter={x:Static coremodels:Constants.SeparatorChar}}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
@@ -17,10 +17,13 @@
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding}" />
|
||||
<TextBlock
|
||||
Margin="5,0,5,0"
|
||||
Classes="PathPresenterItem"
|
||||
PointerPressed="InputElement_OnPointerPressed"
|
||||
Text="{Binding}" />
|
||||
<TextBlock
|
||||
Foreground="{DynamicResource LightForegroundBrush}"
|
||||
Margin="5,0,5,0"
|
||||
Text="/" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
@@ -1,11 +1,53 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using FileTime.App.Core.Services;
|
||||
using FileTime.App.Core.UserCommand;
|
||||
using FileTime.Core.Enums;
|
||||
using FileTime.Core.Models;
|
||||
using FileTime.Core.Timeline;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace FileTime.GuiApp.App.Views;
|
||||
|
||||
public partial class PathPresenter : UserControl
|
||||
{
|
||||
private readonly Lazy<ILogger<PathPresenter>> _logger;
|
||||
|
||||
public PathPresenter()
|
||||
{
|
||||
InitializeComponent();
|
||||
_logger = new Lazy<ILogger<PathPresenter>>(
|
||||
() => DI.ServiceProvider.GetRequiredService<ILogger<PathPresenter>>()
|
||||
);
|
||||
}
|
||||
|
||||
private async void InputElement_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed
|
||||
&& DataContext is string fullPath
|
||||
&& sender is TextBlock textBlock)
|
||||
{
|
||||
var pathPart = textBlock.Text;
|
||||
var path = fullPath[..(fullPath.IndexOf(pathPart) + pathPart.Length)];
|
||||
var timelessContentProvider = DI.ServiceProvider.GetRequiredService<ITimelessContentProvider>();
|
||||
var userCommandHandlerService = DI.ServiceProvider.GetRequiredService<IUserCommandHandlerService>();
|
||||
await userCommandHandlerService.HandleCommandAsync(
|
||||
new OpenContainerCommand(
|
||||
new AbsolutePath(
|
||||
timelessContentProvider,
|
||||
PointInTime.Present,
|
||||
new FullName(path),
|
||||
AbsolutePathType.Container)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Value.LogError(exception, "Failed to open container");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user