RunOrOpenCommand
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
namespace FileTime.App.Core.UserCommand;
|
||||||
|
|
||||||
|
public class RunOrOpenCommand : IIdentifiableUserCommand
|
||||||
|
{
|
||||||
|
public const string CommandName = "run_or_open";
|
||||||
|
public static RunOrOpenCommand Instance { get; } = new();
|
||||||
|
|
||||||
|
private RunOrOpenCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public string UserCommandID => CommandName;
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Diagnostics;
|
||||||
using DeclarativeProperty;
|
using DeclarativeProperty;
|
||||||
using FileTime.App.CommandPalette.Services;
|
using FileTime.App.CommandPalette.Services;
|
||||||
using FileTime.App.Core.Extensions;
|
using FileTime.App.Core.Extensions;
|
||||||
@@ -78,11 +79,31 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase
|
|||||||
new TypeUserCommandHandler<OpenCommandPaletteCommand>(OpenCommandPalette),
|
new TypeUserCommandHandler<OpenCommandPaletteCommand>(OpenCommandPalette),
|
||||||
new TypeUserCommandHandler<OpenContainerCommand>(OpenContainer),
|
new TypeUserCommandHandler<OpenContainerCommand>(OpenContainer),
|
||||||
new TypeUserCommandHandler<OpenSelectedCommand>(OpenSelected),
|
new TypeUserCommandHandler<OpenSelectedCommand>(OpenSelected),
|
||||||
|
new TypeUserCommandHandler<RunOrOpenCommand>(RunOrOpen),
|
||||||
new TypeUserCommandHandler<RefreshCommand>(Refresh),
|
new TypeUserCommandHandler<RefreshCommand>(Refresh),
|
||||||
new TypeUserCommandHandler<SwitchToTabCommand>(SwitchToTab),
|
new TypeUserCommandHandler<SwitchToTabCommand>(SwitchToTab),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task RunOrOpen()
|
||||||
|
{
|
||||||
|
if (_currentSelectedItem?.Value is IContainerViewModel)
|
||||||
|
{
|
||||||
|
await OpenSelected();
|
||||||
|
}
|
||||||
|
else if (_currentSelectedItem?.Value is IElementViewModel
|
||||||
|
{Element: {NativePath: not null, Provider: ILocalContentProvider} localFile}
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo(localFile.NativePath!.Path) {UseShellExecute = true});
|
||||||
|
|
||||||
|
if (_viewMode == ViewMode.RapidTravel)
|
||||||
|
{
|
||||||
|
await ExitRapidTravel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Task OpenCommandPalette()
|
private Task OpenCommandPalette()
|
||||||
{
|
{
|
||||||
_commandPaletteService.OpenCommandPalette();
|
_commandPaletteService.OpenCommandPalette();
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler
|
|||||||
AddUserCommand(PauseCommandSchedulerCommand.Instance);
|
AddUserCommand(PauseCommandSchedulerCommand.Instance);
|
||||||
AddUserCommand(RefreshCommand.Instance);
|
AddUserCommand(RefreshCommand.Instance);
|
||||||
AddUserCommand(RenameCommand.Instance);
|
AddUserCommand(RenameCommand.Instance);
|
||||||
|
AddUserCommand(RunOrOpenCommand.Instance);
|
||||||
AddUserCommand(StartCommandSchedulerCommand.Instance);
|
AddUserCommand(StartCommandSchedulerCommand.Instance);
|
||||||
AddUserCommand(IdentifiableSearchCommand.SearchByNameContains);
|
AddUserCommand(IdentifiableSearchCommand.SearchByNameContains);
|
||||||
AddUserCommand(SwitchToTabCommand.SwitchToLastTab);
|
AddUserCommand(SwitchToTabCommand.SwitchToLastTab);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using DeclarativeProperty;
|
using DeclarativeProperty;
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
@@ -87,22 +86,6 @@ public partial class TabViewModel : ITabViewModel
|
|||||||
() => CurrentItems.Subscribe(c => UpdateConsumer(c, ref _currentItemsConsumer))
|
() => CurrentItems.Subscribe(c => UpdateConsumer(c, ref _currentItemsConsumer))
|
||||||
);
|
);
|
||||||
|
|
||||||
/*CurrentSelectedItem =
|
|
||||||
Observable.CombineLatest(
|
|
||||||
CurrentItems,
|
|
||||||
tab.CurrentSelectedItem,
|
|
||||||
(currentItems, currentSelectedItemPath) =>
|
|
||||||
currentItems == null
|
|
||||||
? Observable.Return((IItemViewModel?)null)
|
|
||||||
: currentItems
|
|
||||||
.ToCollection()
|
|
||||||
.Select(items =>
|
|
||||||
items.FirstOrDefault(i => i.BaseItem?.FullName?.Path == currentSelectedItemPath?.Path.Path))
|
|
||||||
)
|
|
||||||
.Switch()
|
|
||||||
.Publish(null)
|
|
||||||
.RefCount();*/
|
|
||||||
|
|
||||||
CurrentSelectedItem = DeclarativePropertyHelpers.CombineLatest(
|
CurrentSelectedItem = DeclarativePropertyHelpers.CombineLatest(
|
||||||
tab.CurrentSelectedItem,
|
tab.CurrentSelectedItem,
|
||||||
CurrentItems.Watch<ObservableCollection<IItemViewModel>, IItemViewModel>(),
|
CurrentItems.Watch<ObservableCollection<IItemViewModel>, IItemViewModel>(),
|
||||||
@@ -118,17 +101,6 @@ public partial class TabViewModel : ITabViewModel
|
|||||||
);
|
);
|
||||||
|
|
||||||
CurrentSelectedItemAsContainer = CurrentSelectedItem.Map(i => i as IContainerViewModel);
|
CurrentSelectedItemAsContainer = CurrentSelectedItem.Map(i => i as IContainerViewModel);
|
||||||
//CurrentSelectedItem = tab.CurrentSelectedItem.Map((item, _) => Task.FromResult(CurrentItems.Value?.FirstOrDefault(i => i.BaseItem?.FullName?.Path == item?.Path.Path)));
|
|
||||||
|
|
||||||
/*CurrentSelectedItem =
|
|
||||||
Observable.CombineLatest(
|
|
||||||
CurrentItems,
|
|
||||||
tab.CurrentSelectedItem,
|
|
||||||
(currentItems, currentSelectedItemPath) =>
|
|
||||||
CurrentItemsCollection?.Collection?.FirstOrDefault(i => i.BaseItem?.FullName?.Path == currentSelectedItemPath?.Path.Path)
|
|
||||||
)
|
|
||||||
.Publish(null)
|
|
||||||
.RefCount();*/
|
|
||||||
|
|
||||||
SelectedsChildren = CurrentSelectedItem
|
SelectedsChildren = CurrentSelectedItem
|
||||||
.Debounce(TimeSpan.FromMilliseconds(200), resetTimer: true)
|
.Debounce(TimeSpan.FromMilliseconds(200), resetTimer: true)
|
||||||
@@ -167,62 +139,6 @@ public partial class TabViewModel : ITabViewModel
|
|||||||
);
|
);
|
||||||
|
|
||||||
tab.CurrentLocation.Subscribe(_ => _markedItems.Clear()).AddToDisposables(_disposables);
|
tab.CurrentLocation.Subscribe(_ => _markedItems.Clear()).AddToDisposables(_disposables);
|
||||||
|
|
||||||
/*IObservable<IObservable<IChangeSet<IItemViewModel, string>>?> InitSelectedsChildren()
|
|
||||||
{
|
|
||||||
var currentSelectedItemThrottled =
|
|
||||||
CurrentSelectedItem.Throttle(TimeSpan.FromMilliseconds(250)).Publish(null).RefCount();
|
|
||||||
return Observable.Merge(
|
|
||||||
currentSelectedItemThrottled
|
|
||||||
.WhereNotNull()
|
|
||||||
.OfType<IContainerViewModel>()
|
|
||||||
.Where(c => c?.Container is not null)
|
|
||||||
.Select(c => c.Container!.Items)
|
|
||||||
.Select(i =>
|
|
||||||
i
|
|
||||||
?.TransformAsync(MapItemAsync)
|
|
||||||
.Transform(i => MapItemToViewModel(i, ItemViewModelType.SelectedChild))
|
|
||||||
.Sort(SortItems())
|
|
||||||
),
|
|
||||||
currentSelectedItemThrottled
|
|
||||||
.Where(c => c is null or not IContainerViewModel)
|
|
||||||
.Select(_ => (IObservable<IChangeSet<IItemViewModel, string>>?) null)
|
|
||||||
)
|
|
||||||
/*.ObserveOn(_rxSchedulerService.GetWorkerScheduler())
|
|
||||||
.SubscribeOn(_rxSchedulerService.GetUIScheduler())#1#
|
|
||||||
.Publish(null)
|
|
||||||
.RefCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
IObservable<IObservable<IChangeSet<IItemViewModel, string>>?> InitParentsChildren()
|
|
||||||
{
|
|
||||||
var parentThrottled = CurrentLocation
|
|
||||||
.Select(l => l?.Parent)
|
|
||||||
.DistinctUntilChanged()
|
|
||||||
.Publish(null)
|
|
||||||
.RefCount();
|
|
||||||
|
|
||||||
return Observable.Merge(
|
|
||||||
parentThrottled
|
|
||||||
.Where(p => p is not null)
|
|
||||||
.Select(p => Observable.FromAsync(async () => (IContainer) await p!.ResolveAsync()))
|
|
||||||
.Switch()
|
|
||||||
.Select(p => p.Items)
|
|
||||||
.Select(items =>
|
|
||||||
items
|
|
||||||
?.TransformAsync(MapItemAsync)
|
|
||||||
.Transform(i => MapItemToViewModel(i, ItemViewModelType.Parent))
|
|
||||||
.Sort(SortItems())
|
|
||||||
),
|
|
||||||
parentThrottled
|
|
||||||
.Where(p => p is null)
|
|
||||||
.Select(_ => (IObservable<IChangeSet<IItemViewModel, string>>?) null)
|
|
||||||
)
|
|
||||||
/*.ObserveOn(_rxSchedulerService.GetWorkerScheduler())
|
|
||||||
.SubscribeOn(_rxSchedulerService.GetUIScheduler())#1#
|
|
||||||
.Publish(null)
|
|
||||||
.RefCount();
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -310,9 +226,7 @@ public partial class TabViewModel : ITabViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void ClearMarkedItems()
|
public void ClearMarkedItems()
|
||||||
{
|
=> _markedItems.Clear();
|
||||||
_markedItems.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
~TabViewModel() => Dispose(false);
|
~TabViewModel() => Dispose(false);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.Reactive.Disposables;
|
|
||||||
using System.Reactive.Subjects;
|
using System.Reactive.Subjects;
|
||||||
using DeclarativeProperty;
|
using DeclarativeProperty;
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
@@ -10,7 +8,6 @@ using FileTime.Core.Helper;
|
|||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
using FileTime.Core.Timeline;
|
using FileTime.Core.Timeline;
|
||||||
using ObservableComputations;
|
using ObservableComputations;
|
||||||
using static System.DeferTools;
|
|
||||||
|
|
||||||
namespace FileTime.Core.Services;
|
namespace FileTime.Core.Services;
|
||||||
|
|
||||||
@@ -57,19 +54,6 @@ public class Tab : ITab
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
});
|
});
|
||||||
|
|
||||||
/*CurrentLocation = _currentLocation
|
|
||||||
.DistinctUntilChanged()
|
|
||||||
.Merge(_currentLocationForced)
|
|
||||||
.Do(_ =>
|
|
||||||
{
|
|
||||||
if (_currentSelectedItemCached is not null)
|
|
||||||
{
|
|
||||||
LastDeepestSelectedPath = FullName.CreateSafe(PathHelper.GetLongerPath(LastDeepestSelectedPath?.Path, _currentSelectedItemCached.Path.Path));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Publish(null)
|
|
||||||
.RefCount();*/
|
|
||||||
|
|
||||||
CurrentItems = CurrentLocation.Map((container, _) =>
|
CurrentItems = CurrentLocation.Map((container, _) =>
|
||||||
{
|
{
|
||||||
var items = container is null
|
var items = container is null
|
||||||
@@ -77,49 +61,9 @@ public class Tab : ITab
|
|||||||
: container.Items.Selecting<AbsolutePath, IItem>(i => MapItem(i));
|
: container.Items.Selecting<AbsolutePath, IItem>(i => MapItem(i));
|
||||||
return Task.FromResult(items);
|
return Task.FromResult(items);
|
||||||
}
|
}
|
||||||
) /*.Watch<ObservableCollection<IItem>, IItem>()*/;
|
);
|
||||||
/*using var _ = Defer(() =>
|
|
||||||
CurrentItems.Subscribe(c => UpdateConsumer(c, ref _currentItemsConsumer))
|
|
||||||
);*/
|
|
||||||
|
|
||||||
/*CurrentItems.RegisterTrigger(
|
|
||||||
(sender, items) =>
|
|
||||||
{
|
|
||||||
if (items is null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
items.CollectionChanged += Handler;
|
|
||||||
|
|
||||||
return Disposable.Create(() => items.CollectionChanged -= Handler);
|
|
||||||
|
|
||||||
void Handler(object? o, NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
var t = Task.Run(async () => await sender.ReFireAsync());
|
|
||||||
t.Wait();
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
|
|
||||||
/*CurrentItems =
|
|
||||||
Observable.Merge(
|
|
||||||
Observable.CombineLatest(
|
|
||||||
CurrentLocation
|
|
||||||
.Where(c => c is not null)
|
|
||||||
.Select(c => c!.ItemsCollection)
|
|
||||||
.Select(items => items.TransformAsync(MapItem)),
|
|
||||||
_itemFilters.Connect().StartWithEmpty().ToCollection(),
|
|
||||||
(items, filters) =>
|
|
||||||
//Note: Dont user Sort before where, as DynamicData cant handle
|
|
||||||
//sort in (so that's if they are before) filters
|
|
||||||
items
|
|
||||||
.Where(i => filters.All(f => f.Filter(i)))
|
|
||||||
.Sort(SortItems())
|
|
||||||
),
|
|
||||||
CurrentLocation
|
|
||||||
.Where(c => c is null)
|
|
||||||
.Select(_ => (IObservable<IChangeSet<IItem, string>>?) null)
|
|
||||||
)
|
|
||||||
.Publish(null)
|
|
||||||
.RefCount();*/
|
|
||||||
CurrentSelectedItem = DeclarativePropertyHelpers.CombineLatest(
|
CurrentSelectedItem = DeclarativePropertyHelpers.CombineLatest(
|
||||||
CurrentItems.Watch<ObservableCollection<IItem>, IItem>(),
|
CurrentItems.Watch<ObservableCollection<IItem>, IItem>(),
|
||||||
_currentRequestItem.DistinctUntilChanged(),
|
_currentRequestItem.DistinctUntilChanged(),
|
||||||
@@ -137,29 +81,6 @@ public class Tab : ITab
|
|||||||
_refreshSmoothnessCalculator.RecalculateSmoothness();
|
_refreshSmoothnessCalculator.RecalculateSmoothness();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/*CurrentSelectedItem =
|
|
||||||
Observable.CombineLatest(
|
|
||||||
CurrentItems
|
|
||||||
.Select(c =>
|
|
||||||
c == null
|
|
||||||
? Observable.Return<IReadOnlyCollection<IItem>?>(null)
|
|
||||||
: c.ToCollection()
|
|
||||||
)
|
|
||||||
.Switch(),
|
|
||||||
_currentSelectedItem,
|
|
||||||
(items, selected) =>
|
|
||||||
{
|
|
||||||
if (selected != null && (items?.Any(i => i.FullName == selected.Path) ?? true)) return selected;
|
|
||||||
if (items == null || items.Count == 0) return null;
|
|
||||||
|
|
||||||
return GetSelectedItemByItems(items);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.DistinctUntilChanged()
|
|
||||||
.Publish(null)
|
|
||||||
.RefCount();*/
|
|
||||||
|
|
||||||
CurrentSelectedItem.Subscribe(async (s, _) =>
|
CurrentSelectedItem.Subscribe(async (s, _) =>
|
||||||
{
|
{
|
||||||
_currentSelectedItemCached = s;
|
_currentSelectedItemCached = s;
|
||||||
|
|||||||
@@ -66,12 +66,18 @@ public static class MainConfiguration
|
|||||||
new(GoToPathCommand.CommandName, new[] {Key.G, Key.P}),
|
new(GoToPathCommand.CommandName, new[] {Key.G, Key.P}),
|
||||||
new(GoToProviderCommand.CommandName, new[] {Key.G, Key.T}),
|
new(GoToProviderCommand.CommandName, new[] {Key.G, Key.T}),
|
||||||
new(GoToRootCommand.CommandName, new[] {Key.G, Key.R}),
|
new(GoToRootCommand.CommandName, new[] {Key.G, Key.R}),
|
||||||
|
new(GoUpCommand.CommandName, Key.Left),
|
||||||
new(DeleteCommand.HardDeleteCommandName, new[] {new KeyConfig(Key.D, shift: true), new KeyConfig(Key.D, shift: true)}),
|
new(DeleteCommand.HardDeleteCommandName, new[] {new KeyConfig(Key.D, shift: true), new KeyConfig(Key.D, shift: true)}),
|
||||||
new(MarkCommand.CommandName, Key.Space),
|
new(MarkCommand.CommandName, Key.Space),
|
||||||
new(MoveCursorToLastCommand.CommandName, new KeyConfig(Key.G, shift: true)),
|
new(MoveCursorToLastCommand.CommandName, new KeyConfig(Key.G, shift: true)),
|
||||||
new(MoveCursorToFirstCommand.CommandName, new[] {Key.G, Key.G}),
|
new(MoveCursorToFirstCommand.CommandName, new[] {Key.G, Key.G}),
|
||||||
|
new(MoveCursorUpCommand.CommandName, Key.Up),
|
||||||
|
new(MoveCursorDownCommand.CommandName, Key.Down),
|
||||||
|
new(MoveCursorUpPageCommand.CommandName, Key.PageUp),
|
||||||
|
new(MoveCursorDownPageCommand.CommandName, Key.PageDown),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.NextTimelineBlock, Key.L ),
|
//new CommandBindingConfiguration(ConfigCommand.NextTimelineBlock, Key.L ),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.NextTimelineCommand, Key.J ),
|
//new CommandBindingConfiguration(ConfigCommand.NextTimelineCommand, Key.J ),
|
||||||
|
new(OpenSelectedCommand.CommandName, Key.Right),
|
||||||
new(OpenCommandPaletteCommand.CommandName, new[] {Key.F1}),
|
new(OpenCommandPaletteCommand.CommandName, new[] {Key.F1}),
|
||||||
new(OpenCommandPaletteCommand.CommandName, new[] {new KeyConfig(Key.P, ctrl: true, shift: true)}),
|
new(OpenCommandPaletteCommand.CommandName, new[] {new KeyConfig(Key.P, ctrl: true, shift: true)}),
|
||||||
new(OpenInDefaultFileExplorerCommand.CommandName, new[] {Key.O, Key.E}),
|
new(OpenInDefaultFileExplorerCommand.CommandName, new[] {Key.O, Key.E}),
|
||||||
@@ -85,7 +91,8 @@ public static class MainConfiguration
|
|||||||
//new CommandBindingConfiguration(ConfigCommand.PreviousTimelineCommand, Key.K ),
|
//new CommandBindingConfiguration(ConfigCommand.PreviousTimelineCommand, Key.K ),
|
||||||
new(RefreshCommand.CommandName, Key.R),
|
new(RefreshCommand.CommandName, Key.R),
|
||||||
new(RenameCommand.CommandName, Key.F2),
|
new(RenameCommand.CommandName, Key.F2),
|
||||||
new(RenameCommand.CommandName, new[] { Key.C, Key.W }),
|
new(RenameCommand.CommandName, new[] {Key.C, Key.W}),
|
||||||
|
new(RunOrOpenCommand.CommandName, Key.Enter),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.RunCommand, new KeyConfig(Key.D4, shift: true)),
|
//new CommandBindingConfiguration(ConfigCommand.RunCommand, new KeyConfig(Key.D4, shift: true)),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.ScanContainerSize, new[] { Key.C, Key.S }),
|
//new CommandBindingConfiguration(ConfigCommand.ScanContainerSize, new[] { Key.C, Key.S }),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.ShowAllShortcut, Key.F1),
|
//new CommandBindingConfiguration(ConfigCommand.ShowAllShortcut, Key.F1),
|
||||||
@@ -104,13 +111,6 @@ public static class MainConfiguration
|
|||||||
//new CommandBindingConfiguration(ConfigCommand.TimelineRefresh, new[] { Key.T, Key.R }),
|
//new CommandBindingConfiguration(ConfigCommand.TimelineRefresh, new[] { Key.T, Key.R }),
|
||||||
new(StartCommandSchedulerCommand.CommandName, new[] {Key.T, Key.S}),
|
new(StartCommandSchedulerCommand.CommandName, new[] {Key.T, Key.S}),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.ToggleAdvancedIcons, new[] { Key.Z, Key.I }),
|
//new CommandBindingConfiguration(ConfigCommand.ToggleAdvancedIcons, new[] { Key.Z, Key.I }),
|
||||||
new(GoUpCommand.CommandName, Key.Left),
|
|
||||||
new(OpenSelectedCommand.CommandName, Key.Right),
|
|
||||||
//new CommandBindingConfiguration(ConfigCommand.OpenOrRun, Key.Enter),
|
|
||||||
new(MoveCursorUpCommand.CommandName, Key.Up),
|
|
||||||
new(MoveCursorDownCommand.CommandName, Key.Down),
|
|
||||||
new(MoveCursorUpPageCommand.CommandName, Key.PageUp),
|
|
||||||
new(MoveCursorDownPageCommand.CommandName, Key.PageDown),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static void PopulateDefaultEditorPrograms(Dictionary<string, string> configuration)
|
private static void PopulateDefaultEditorPrograms(Dictionary<string, string> configuration)
|
||||||
|
|||||||
Reference in New Issue
Block a user