Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01815db1fe | ||
|
|
80cf43d3bf | ||
|
|
050f162c08 | ||
|
|
f5e03c9856 | ||
|
|
f763798683 | ||
|
|
46120e3431 | ||
|
|
829077883b | ||
|
|
8c928faa09 | ||
|
|
1654e9f1f5 | ||
|
|
f542331192 | ||
|
|
6830adb788 | ||
|
|
02e015371c | ||
|
|
80bdfa012c | ||
|
|
70326e9585 | ||
|
|
c0e1415b6e | ||
|
|
13a3402b58 | ||
|
|
73703412f8 | ||
|
|
ab226d95d4 | ||
|
|
de7a76bb3b | ||
|
|
379f58b4b8 | ||
|
|
3a04cd3db2 | ||
|
|
df0d3f080b | ||
|
|
04131d271a | ||
|
|
d66fe26634 | ||
|
|
8870f0621c | ||
|
|
e5250a7ae8 | ||
|
|
b2b6cedf2c | ||
|
|
e777c2c5ac | ||
|
|
7dcd8e1fbb | ||
|
|
37518cf88b | ||
|
|
ca0e22b8d0 | ||
|
|
074f5f9c7e | ||
|
|
0b40963c82 | ||
|
|
0b6b8a9968 | ||
|
|
47613454c7 | ||
|
|
96d063b4fd | ||
|
|
fec44fb0b5 | ||
|
|
58e7de5271 | ||
|
|
466b7a7503 | ||
|
|
50f9c84420 | ||
|
|
f07dae98ee | ||
|
|
1cc74f79b4 | ||
|
|
60c4f0518d | ||
|
|
f9fb05b194 | ||
|
|
d933f60b8b | ||
|
|
45bba6e2eb | ||
|
|
210aeedc25 | ||
|
|
acfb8e8883 |
No files matched your search
@@ -1,5 +1,7 @@
|
||||
# Project specific
|
||||
FluentTerminal.App/Win32
|
||||
FluentTerminal.App/Client/
|
||||
FluentTerminal.Client/dist
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
reg add "HKCU\Software\Classes\Directory\shell\Open Fluent Terminal here\command" /d "\"%LOCALAPPDATA%\Microsoft\WindowsApps\flute.exe\" \"new %%1\"" /f
|
||||
reg add "HKCU\Software\Classes\Directory\Background\shell\Open Fluent Terminal here\command" /d "\"%LOCALAPPDATA%\Microsoft\WindowsApps\flute.exe\" \"new %%V\"" /f
|
||||
reg add "HKCU\Software\Classes\LibraryFolder\Background\shell\Open Fluent Terminal here\command" /d "\"%LOCALAPPDATA%\Microsoft\WindowsApps\flute.exe\" \"new %%V\"" /f
|
||||
@@ -0,0 +1,3 @@
|
||||
reg delete "HKCU\Software\Classes\Directory\shell\Open Fluent Terminal here" /f
|
||||
reg delete "HKCU\Software\Classes\Directory\Background\shell\Open Fluent Terminal here" /f
|
||||
reg delete "HKCU\Software\Classes\LibraryFolder\Background\shell\Open Fluent Terminal here" /f
|
||||
@@ -1,12 +1,32 @@
|
||||
<Application
|
||||
x:Class="FluentTerminal.App.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="using:FluentTerminal.App.Converters">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Styles\Custom.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<converters:IntToVisibilityConverter
|
||||
x:Key="OneToVisibleConverter"
|
||||
Else="Collapsed"
|
||||
If="1"
|
||||
Then="Visible" />
|
||||
<converters:IntToVisibilityConverter
|
||||
x:Key="OneToCollapsedConverter"
|
||||
Else="Visible"
|
||||
If="1"
|
||||
Then="Collapsed" />
|
||||
<converters:NegateConverter x:Key="NegateConverter" />
|
||||
<converters:FalseToVisibleConverter x:Key="FalseToVisibleConverter" />
|
||||
<converters:TrueToVisibleConverter x:Key="TrueToVisibleConverter" />
|
||||
<converters:IntToVisibilityConverter
|
||||
x:Key="ZeroToCollapsedConverter"
|
||||
Else="Visible"
|
||||
If="0"
|
||||
Then="Collapsed" />
|
||||
<converters:IntToExtendedVirtualKeyConverter x:Key="IntToExtendedVirtualKeyConverter" />
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -3,7 +3,12 @@ using FluentTerminal.App.Services;
|
||||
using FluentTerminal.App.Services.Implementation;
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using FluentTerminal.App.Views;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
@@ -14,6 +19,7 @@ using Windows.UI.Core;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using IContainer = Autofac.IContainer;
|
||||
|
||||
namespace FluentTerminal.App
|
||||
{
|
||||
@@ -24,27 +30,44 @@ namespace FluentTerminal.App
|
||||
public static App Instance;
|
||||
private bool _alreadyLaunched;
|
||||
private IContainer _container;
|
||||
private int _openTerminalWindows;
|
||||
private int? _settingsWindowId;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private ApplicationSettings _applicationSettings;
|
||||
|
||||
private List<MainViewModel> _mainViewModels;
|
||||
|
||||
public App()
|
||||
{
|
||||
_mainViewModels = new List<MainViewModel>();
|
||||
|
||||
InitializeComponent();
|
||||
Instance = this;
|
||||
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterType<SettingsService>().As<ISettingsService>().InstancePerDependency();
|
||||
builder.RegisterType<SettingsService>().As<ISettingsService>().SingleInstance();
|
||||
builder.RegisterType<DefaultValueProvider>().As<IDefaultValueProvider>().SingleInstance();
|
||||
builder.RegisterType<TerminalService>().As<ITerminalService>().SingleInstance();
|
||||
builder.RegisterType<TrayProcessCommunicationService>().As<ITrayProcessCommunicationService>().SingleInstance();
|
||||
builder.RegisterType<DialogService>().As<IDialogService>().SingleInstance();
|
||||
builder.RegisterType<KeyboardCommandService>().As<IKeyboardCommandService>().InstancePerDependency();
|
||||
builder.RegisterType<MainViewModel>().InstancePerDependency();
|
||||
builder.RegisterType<SettingsViewModel>().InstancePerDependency();
|
||||
|
||||
_container = builder.Build();
|
||||
|
||||
_settingsService = _container.Resolve<ISettingsService>();
|
||||
_settingsService.ApplicationSettingsChanged += OnApplicationSettingsChanged;
|
||||
|
||||
_applicationSettings = _settingsService.GetApplicationSettings();
|
||||
}
|
||||
|
||||
public async Task CreateNewTerminalWindow()
|
||||
private void OnApplicationSettingsChanged(object sender, EventArgs e)
|
||||
{
|
||||
var id = await CreateSecondaryView(typeof(MainPage), true);
|
||||
_applicationSettings = _settingsService.GetApplicationSettings();
|
||||
}
|
||||
|
||||
public async Task CreateNewTerminalWindow(string startupDirectory)
|
||||
{
|
||||
var id = await CreateSecondaryView<MainViewModel>(typeof(MainPage), true, startupDirectory);
|
||||
await ApplicationViewSwitcher.TryShowAsStandaloneAsync(id);
|
||||
}
|
||||
|
||||
@@ -57,41 +80,67 @@ namespace FluentTerminal.App
|
||||
{
|
||||
if (_settingsWindowId == null)
|
||||
{
|
||||
_settingsWindowId = await CreateSecondaryView(typeof(SettingsPage), true);
|
||||
_settingsWindowId = await CreateSecondaryView<SettingsViewModel>(typeof(SettingsPage), true, null);
|
||||
}
|
||||
await ApplicationViewSwitcher.TryShowAsStandaloneAsync(_settingsWindowId.Value);
|
||||
}
|
||||
|
||||
public void TerminalWindowClosed()
|
||||
public void TerminalWindowClosed(MainViewModel viewModel)
|
||||
{
|
||||
_openTerminalWindows--;
|
||||
_mainViewModels.Remove(viewModel);
|
||||
}
|
||||
|
||||
protected override async void OnActivated(IActivatedEventArgs args)
|
||||
{
|
||||
if (args is CommandLineActivatedEventArgs commandLineActivated)
|
||||
{
|
||||
var argument = commandLineActivated.Operation.Arguments.Trim();
|
||||
if (string.IsNullOrWhiteSpace(commandLineActivated.Operation.Arguments))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var arguments = commandLineActivated.Operation.Arguments.Split(' ', 2);
|
||||
var command = arguments[0];
|
||||
var parameter = arguments.Length > 1 ? arguments[1] : string.Empty;
|
||||
|
||||
if (_alreadyLaunched)
|
||||
{
|
||||
if (argument == "settings")
|
||||
if (command == "settings")
|
||||
{
|
||||
await ShowSettings();
|
||||
}
|
||||
else if (argument == "new")
|
||||
else if (command == "new")
|
||||
{
|
||||
await CreateNewTerminalWindow();
|
||||
if (_applicationSettings.NewTerminalLocation == NewTerminalLocation.Tab && _mainViewModels.Any())
|
||||
{
|
||||
await _mainViewModels.Last().AddTerminal(parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
await CreateNewTerminalWindow(parameter);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (argument == "settings")
|
||||
if (command == "settings")
|
||||
{
|
||||
CreateMainView(typeof(SettingsPage), true);
|
||||
var viewModel = _container.Resolve<SettingsViewModel>();
|
||||
await CreateMainView(typeof(SettingsPage), viewModel, true);
|
||||
}
|
||||
else if (argument == "new")
|
||||
else if (command == "new")
|
||||
{
|
||||
CreateMainView(typeof(MainPage), true);
|
||||
if (_applicationSettings.NewTerminalLocation == NewTerminalLocation.Tab && _mainViewModels.Any())
|
||||
{
|
||||
await _mainViewModels.Last().AddTerminal(parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var viewModel = _container.Resolve<MainViewModel>();
|
||||
await viewModel.AddTerminal(parameter);
|
||||
await CreateMainView(typeof(MainPage), viewModel, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,24 +159,26 @@ namespace FluentTerminal.App
|
||||
}
|
||||
|
||||
protected override async void OnLaunched(LaunchActivatedEventArgs e)
|
||||
{
|
||||
if (!_alreadyLaunched)
|
||||
{
|
||||
var viewModel = _container.Resolve<MainViewModel>();
|
||||
await viewModel.AddTerminal(null);
|
||||
await CreateMainView(typeof(MainPage), viewModel, true);
|
||||
Window.Current.Activate();
|
||||
}
|
||||
else if (_mainViewModels.Any() == false)
|
||||
{
|
||||
await CreateSecondaryView<MainViewModel>(typeof(MainPage), true, string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CreateMainView(Type pageType, INotifyPropertyChanged viewModel, bool extendViewIntoTitleBar)
|
||||
{
|
||||
var launch = FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync().AsTask();
|
||||
var clearCache = WebView.ClearTemporaryWebDataAsync().AsTask();
|
||||
await Task.WhenAll(launch, clearCache);
|
||||
|
||||
if (!_alreadyLaunched)
|
||||
{
|
||||
CreateMainView(typeof(MainPage), true);
|
||||
Window.Current.Activate();
|
||||
}
|
||||
else if (_openTerminalWindows == 0)
|
||||
{
|
||||
await CreateSecondaryView(typeof(MainPage), true);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateMainView(Type pageType, bool extendViewIntoTitleBar)
|
||||
{
|
||||
Frame rootFrame = Window.Current.Content as Frame;
|
||||
if (rootFrame == null)
|
||||
{
|
||||
@@ -138,52 +189,44 @@ namespace FluentTerminal.App
|
||||
if (rootFrame.Content == null)
|
||||
{
|
||||
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = extendViewIntoTitleBar;
|
||||
rootFrame.Navigate(pageType, GetViewModelForPageType(pageType));
|
||||
|
||||
if (pageType == typeof(MainPage))
|
||||
if (viewModel is MainViewModel mainViewModel)
|
||||
{
|
||||
_openTerminalWindows++;
|
||||
_mainViewModels.Add(mainViewModel);
|
||||
}
|
||||
|
||||
rootFrame.Navigate(pageType, viewModel);
|
||||
}
|
||||
_alreadyLaunched = true;
|
||||
Window.Current.Activate();
|
||||
}
|
||||
|
||||
private async Task<int> CreateSecondaryView(Type pageType, bool ExtendViewIntoTitleBar)
|
||||
private async Task<int> CreateSecondaryView<TViewModel>(Type pageType, bool ExtendViewIntoTitleBar, object parameter)
|
||||
{
|
||||
int windowId = 0;
|
||||
TViewModel viewModel = default;
|
||||
await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
viewModel = _container.Resolve<TViewModel>();
|
||||
|
||||
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = ExtendViewIntoTitleBar;
|
||||
var frame = new Frame();
|
||||
frame.Navigate(pageType, GetViewModelForPageType(pageType));
|
||||
frame.Navigate(pageType, viewModel);
|
||||
Window.Current.Content = frame;
|
||||
Window.Current.Activate();
|
||||
|
||||
windowId = ApplicationView.GetForCurrentView().Id;
|
||||
});
|
||||
|
||||
if (pageType == typeof(MainPage))
|
||||
if (viewModel is MainViewModel mainViewModel && parameter is string directory)
|
||||
{
|
||||
_openTerminalWindows++;
|
||||
_mainViewModels.Add(mainViewModel);
|
||||
await mainViewModel.AddTerminal(directory);
|
||||
}
|
||||
|
||||
return windowId;
|
||||
}
|
||||
|
||||
private object GetViewModelForPageType(Type pageType)
|
||||
{
|
||||
if (pageType == typeof(MainPage))
|
||||
{
|
||||
return _container.Resolve<MainViewModel>();
|
||||
}
|
||||
else if (pageType == typeof(SettingsPage))
|
||||
{
|
||||
return _container.Resolve<SettingsViewModel>();
|
||||
}
|
||||
throw new Exception("No ViewModel defined for Page: " + pageType.Name);
|
||||
}
|
||||
|
||||
private void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
|
||||
{
|
||||
if (args.Request.Message.ContainsKey("exit"))
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,40 @@
|
||||
using Microsoft.Xaml.Interactivity;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Input;
|
||||
|
||||
namespace FluentTerminal.App.Behaviors
|
||||
{
|
||||
public class MiddleClickBehavior : Trigger<UIElement>
|
||||
{
|
||||
private bool _middleButtonPressed;
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
AssociatedObject.PointerPressed += OnPointerPressed;
|
||||
AssociatedObject.PointerReleased += OnPointerReleased;
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
AssociatedObject.PointerPressed -= OnPointerPressed;
|
||||
AssociatedObject.PointerReleased -= OnPointerReleased;
|
||||
}
|
||||
|
||||
private void OnPointerPressed(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
var point = e.GetCurrentPoint(AssociatedObject);
|
||||
_middleButtonPressed = point.Properties.IsMiddleButtonPressed;
|
||||
}
|
||||
|
||||
private void OnPointerReleased(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
var point = e.GetCurrentPoint(AssociatedObject);
|
||||
var middleButtonStillPressed = point.Properties.IsMiddleButtonPressed;
|
||||
|
||||
if (_middleButtonPressed && !middleButtonStillPressed)
|
||||
{
|
||||
Interaction.ExecuteActions(AssociatedObject, Actions, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using FluentTerminal.Models.Enums;
|
||||
using System;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace FluentTerminal.App.Converters
|
||||
{
|
||||
public class IntToExtendedVirtualKeyConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is int intValue)
|
||||
{
|
||||
return ((ExtendedVirtualKey)intValue).ToString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace FluentTerminal.App.Converters
|
||||
{
|
||||
public class IntToVisibilityConverter : DependencyObject, IValueConverter
|
||||
{
|
||||
public static readonly DependencyProperty ElseProperty =
|
||||
DependencyProperty.Register(nameof(Else), typeof(Visibility), typeof(IntToVisibilityConverter), new PropertyMetadata(Visibility.Collapsed));
|
||||
|
||||
public static readonly DependencyProperty IfProperty =
|
||||
DependencyProperty.Register(nameof(If), typeof(int), typeof(IntToVisibilityConverter), new PropertyMetadata(0));
|
||||
|
||||
public static readonly DependencyProperty ThenProperty =
|
||||
DependencyProperty.Register(nameof(Then), typeof(Visibility), typeof(IntToVisibilityConverter), new PropertyMetadata(Visibility.Visible));
|
||||
|
||||
public Visibility Else
|
||||
{
|
||||
get { return (Visibility)GetValue(ElseProperty); }
|
||||
set { SetValue(ElseProperty, value); }
|
||||
}
|
||||
|
||||
public int If
|
||||
{
|
||||
get { return (int)GetValue(IfProperty); }
|
||||
set { SetValue(IfProperty, value); }
|
||||
}
|
||||
|
||||
public Visibility Then
|
||||
{
|
||||
get { return (Visibility)GetValue(ThenProperty); }
|
||||
set { SetValue(ThenProperty, value); }
|
||||
}
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is int count)
|
||||
{
|
||||
return count == If ? Then : Else;
|
||||
}
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace FluentTerminal.App.Converters
|
||||
{
|
||||
public class NegateConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is bool boolean)
|
||||
{
|
||||
return !boolean;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
<LangVersion>7.1</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -79,6 +80,7 @@
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<LangVersion>7.1</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
@@ -91,6 +93,7 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
<LangVersion>7.1</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||
@@ -99,34 +102,58 @@
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Behaviors\MiddleClickBehavior.cs" />
|
||||
<Compile Include="Converters\FalseToVisibleConverter.cs" />
|
||||
<Compile Include="Converters\IntToExtendedVirtualKeyConverter.cs" />
|
||||
<Compile Include="Converters\IntToVisibilityConverter.cs" />
|
||||
<Compile Include="Converters\NegateConverter.cs" />
|
||||
<Compile Include="Converters\TerminalViewModelToViewConverter.cs" />
|
||||
<Compile Include="Converters\TrueToVisibleConverter.cs" />
|
||||
<Compile Include="Services\IDialogService.cs" />
|
||||
<Compile Include="Services\Implementation\DialogService.cs" />
|
||||
<Compile Include="Services\Implementation\KeyboardCommandService.cs" />
|
||||
<Compile Include="Services\IKeyboardCommandService.cs" />
|
||||
<Compile Include="Utilities\ApplicationDataContainerExtensions.cs" />
|
||||
<Compile Include="Services\IDefaultValueProvider.cs" />
|
||||
<Compile Include="Services\Implementation\DefaultValueProvider.cs" />
|
||||
<Compile Include="Services\Implementation\SettingsService.cs" />
|
||||
<Compile Include="Services\Implementation\TerminalService.cs" />
|
||||
<Compile Include="Services\Implementation\TrayProcessCommunicationService.cs" />
|
||||
<Compile Include="Services\ISettingsService.cs" />
|
||||
<Compile Include="Services\ITerminalService.cs" />
|
||||
<Compile Include="Services\ITrayProcessCommunicationService.cs" />
|
||||
<Compile Include="Utilities\ColorExtensions.cs" />
|
||||
<Compile Include="Utilities\HttpJsonContent.cs" />
|
||||
<Compile Include="Utilities\IHttpContentExtensions.cs" />
|
||||
<Compile Include="ViewModels\MainViewModel.cs" />
|
||||
<Compile Include="ViewModels\SettingsViewModel.cs" />
|
||||
<Compile Include="ViewModels\Settings\GeneralPageViewModel.cs" />
|
||||
<Compile Include="ViewModels\Settings\KeyBindingsPageViewModel.cs" />
|
||||
<Compile Include="ViewModels\Settings\KeyBindingsViewModel.cs" />
|
||||
<Compile Include="ViewModels\Settings\KeyBindingViewModel.cs" />
|
||||
<Compile Include="ViewModels\Settings\ShellPageViewModel.cs" />
|
||||
<Compile Include="ViewModels\Settings\TerminalPageViewModel.cs" />
|
||||
<Compile Include="ViewModels\Settings\ThemesPageViewModel.cs" />
|
||||
<Compile Include="ViewModels\ThemeViewModel.cs" />
|
||||
<Compile Include="ViewModels\TerminalViewModel.cs" />
|
||||
<Compile Include="Views\BindableColorsTitleBar.cs" />
|
||||
<Compile Include="Views\ITerminalView.cs" />
|
||||
<Compile Include="Views\KeyBindingsView.xaml.cs">
|
||||
<DependentUpon>KeyBindingsView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\MainPage.xaml.cs">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Views\CreateKeyBindingDialog.xaml.cs">
|
||||
<DependentUpon>CreateKeyBindingDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPage.xaml.cs">
|
||||
<DependentUpon>SettingsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPages\ColorSettings.xaml.cs">
|
||||
<DependentUpon>ColorSettings.xaml</DependentUpon>
|
||||
<Compile Include="Views\SettingsPages\ThemeSettings.xaml.cs">
|
||||
<DependentUpon>ThemeSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPages\FontSettings.xaml.cs">
|
||||
<DependentUpon>FontSettings.xaml</DependentUpon>
|
||||
<Compile Include="Views\SettingsPages\TerminalSettings.xaml.cs">
|
||||
<DependentUpon>TerminalSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPages\GeneralSettings.xaml.cs">
|
||||
<DependentUpon>GeneralSettings.xaml</DependentUpon>
|
||||
@@ -137,6 +164,9 @@
|
||||
<Compile Include="Views\SettingsPages\ShellSettings.xaml.cs">
|
||||
<DependentUpon>ShellSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\TerminalColorPicker.xaml.cs">
|
||||
<DependentUpon>TerminalColorPicker.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\TerminalView.xaml.cs">
|
||||
<DependentUpon>TerminalView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -145,74 +175,18 @@
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
<None Include="FluentTerminal.App_StoreKey.pfx" />
|
||||
<None Include="FluentTerminal.App_TemporaryKey.pfx" />
|
||||
<Content Include="Win32\FluentTerminal.Models.dll" />
|
||||
<Content Include="Win32\FluentTerminal.Models.pdb" />
|
||||
<Content Include="Win32\FluentTerminal.SystemTray.exe.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Assets\AppIcons\LargeTile.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\LargeTile.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\LargeTile.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\LargeTile.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\LargeTile.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\SmallTile.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\SmallTile.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\SmallTile.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\SmallTile.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\SmallTile.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\SplashScreen.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\SplashScreen.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\SplashScreen.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\SplashScreen.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\SplashScreen.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\Square150x150Logo.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\Square150x150Logo.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\Square150x150Logo.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\Square150x150Logo.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\Square150x150Logo.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-16.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-24.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-256.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-32.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-48.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-16.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-24.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-256.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-32.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-48.png" />
|
||||
<Content Include="Assets\AppIcons\StoreLogo.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\StoreLogo.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\StoreLogo.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\StoreLogo.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\StoreLogo.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-400.png" />
|
||||
<None Include="Package.StoreAssociation.xml" />
|
||||
<Content Include="Properties\Default.rd.xml" />
|
||||
<Content Include="Win32\Client\bundle.js" />
|
||||
<Content Include="Win32\Client\index.html" />
|
||||
<Content Include="Win32\Client\style.css" />
|
||||
<Content Include="Win32\Client\xterm.css" />
|
||||
<Content Include="Assets\settingsicons.ttf" />
|
||||
<Content Include="Win32\CommonServiceLocator.dll" />
|
||||
<Content Include="Win32\CommonServiceLocator.pdb" />
|
||||
<Content Include="Win32\Fleck.dll" />
|
||||
<Content Include="Win32\FluentTerminal.Models.dll" />
|
||||
<Content Include="Win32\FluentTerminal.Models.pdb" />
|
||||
<Content Include="Win32\FluentTerminal.SystemTray.exe" />
|
||||
<Content Include="Win32\FluentTerminal.SystemTray.pdb" />
|
||||
<Content Include="Win32\GlobalHotKey.dll" />
|
||||
<Content Include="Win32\Microsoft.Owin.dll" />
|
||||
<Content Include="Win32\Microsoft.Owin.FileSystems.dll" />
|
||||
<Content Include="Win32\Microsoft.Owin.Host.HttpListener.dll" />
|
||||
<Content Include="Win32\Microsoft.Owin.Hosting.dll" />
|
||||
<Content Include="Win32\Microsoft.Owin.StaticFiles.dll" />
|
||||
<Content Include="Win32\Microsoft.Win32.Primitives.dll" />
|
||||
<Content Include="Win32\netstandard.dll" />
|
||||
<Content Include="Win32\Newtonsoft.Json.dll" />
|
||||
@@ -333,12 +307,72 @@
|
||||
<Content Include="Win32\winpty-debugserver.exe" />
|
||||
<Content Include="Win32\winpty.dll" />
|
||||
<Content Include="Win32\winpty.NET.dll" />
|
||||
<None Include="FluentTerminal.App_StoreKey.pfx" />
|
||||
<None Include="FluentTerminal.App_TemporaryKey.pfx" />
|
||||
<Content Include="Client\bundle.js" />
|
||||
<Content Include="Client\index.html" />
|
||||
<Content Include="Client\style.css" />
|
||||
<Content Include="Client\xterm.css" />
|
||||
<Content Include="Win32\FluentTerminal.SystemTray.exe.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Assets\AppIcons\LargeTile.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\LargeTile.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\LargeTile.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\LargeTile.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\LargeTile.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\SmallTile.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\SmallTile.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\SmallTile.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\SmallTile.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\SmallTile.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\SplashScreen.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\SplashScreen.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\SplashScreen.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\SplashScreen.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\SplashScreen.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\Square150x150Logo.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\Square150x150Logo.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\Square150x150Logo.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\Square150x150Logo.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\Square150x150Logo.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-16.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-24.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-256.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-32.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-48.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-16.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-24.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-256.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-32.png" />
|
||||
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-48.png" />
|
||||
<Content Include="Assets\AppIcons\StoreLogo.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\StoreLogo.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\StoreLogo.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\StoreLogo.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\StoreLogo.scale-400.png" />
|
||||
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-100.png" />
|
||||
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-125.png" />
|
||||
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-150.png" />
|
||||
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-200.png" />
|
||||
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-400.png" />
|
||||
<None Include="Package.StoreAssociation.xml" />
|
||||
<Content Include="Properties\Default.rd.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="Views\KeyBindingsView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\MainPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@@ -348,15 +382,19 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Page>
|
||||
<Page Include="Views\CreateKeyBindingDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPages\ColorSettings.xaml">
|
||||
<Page Include="Views\SettingsPages\ThemeSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPages\FontSettings.xaml">
|
||||
<Page Include="Views\SettingsPages\TerminalSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
@@ -372,6 +410,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\TerminalColorPicker.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\TerminalView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -384,12 +426,24 @@
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.0.6</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.UI">
|
||||
<Version>2.1.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls">
|
||||
<Version>2.1.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Uwp.Managed">
|
||||
<Version>2.0.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MvvmLightLibs">
|
||||
<Version>5.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>10.0.3</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Win2D.uwp">
|
||||
<Version>1.21.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<SDKReference Include="WindowsDesktop, Version=10.0.16299.0">
|
||||
@@ -406,6 +460,7 @@
|
||||
<Name>FluentTerminal.RuntimeComponent</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
@@ -414,6 +469,9 @@
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>xcopy /y "$(SolutionDir)FluentTerminal.Client\dist" "$(ProjectDir)Client"</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10" IgnorableNamespaces="uap mp desktop rescap">
|
||||
<Identity Name="53621FSApps.FluentTerminal" Publisher="CN=BDC72197-B634-438A-B863-16DCB7D90C85" Version="0.1.4.0" />
|
||||
<Identity Name="53621FSApps.FluentTerminal" Publisher="CN=BDC72197-B634-438A-B863-16DCB7D90C85" Version="0.1.7.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="f7225014-f405-4342-ad2e-ebf6ac60ea2c" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>Fluent Terminal</DisplayName>
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
using FluentTerminal.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface IDefaultValueProvider
|
||||
{
|
||||
ShellConfiguration GetDefaultShellConfiguration();
|
||||
TerminalOptions GetDefaultTerminalOptions();
|
||||
KeyBindings GetDefaultKeyBindings();
|
||||
ApplicationSettings GetDefaultApplicationSettings();
|
||||
Guid GetDefaultThemeId();
|
||||
IEnumerable<TerminalTheme> GetPreInstalledThemes();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public enum DialogButton
|
||||
{
|
||||
OK,
|
||||
Cancel
|
||||
}
|
||||
|
||||
public interface IDialogService
|
||||
{
|
||||
Task<DialogButton> ShowDialogAsnyc(string title, string content, params DialogButton[] buttons);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using FluentTerminal.Models.Enums;
|
||||
using System;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface IKeyboardCommandService
|
||||
{
|
||||
void RegisterCommandHandler(Command command, Action handler);
|
||||
void SendCommand(Command command);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,35 @@
|
||||
using FluentTerminal.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface ISettingsService
|
||||
{
|
||||
event EventHandler CurrentThemeChanged;
|
||||
event EventHandler TerminalOptionsChanged;
|
||||
event EventHandler ApplicationSettingsChanged;
|
||||
event EventHandler KeyBindingsChanged;
|
||||
|
||||
ShellConfiguration GetShellConfiguration();
|
||||
void SaveShellConfiguration(ShellConfiguration spawnConfiguration);
|
||||
void SaveShellConfiguration(ShellConfiguration shellConfiguration);
|
||||
|
||||
TerminalOptions GetTerminalOptions();
|
||||
void SaveTerminalOptions(TerminalOptions terminalOptions);
|
||||
|
||||
ApplicationSettings GetApplicationSettings();
|
||||
void SaveApplicationSettings(ApplicationSettings applicationSettings);
|
||||
|
||||
KeyBindings GetKeyBindings();
|
||||
void SaveKeyBindings(KeyBindings keyBindings);
|
||||
|
||||
TerminalTheme GetCurrentTheme();
|
||||
Guid GetCurrentThemeId();
|
||||
TerminalTheme GetTheme(Guid id);
|
||||
void SaveCurrentThemeId(Guid id);
|
||||
|
||||
IEnumerable<TerminalTheme> GetThemes();
|
||||
void SaveTheme(TerminalTheme theme);
|
||||
void DeleteTheme(Guid id);
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -3,9 +3,10 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface ITerminalService
|
||||
public interface ITrayProcessCommunicationService
|
||||
{
|
||||
Task<CreateTerminalResponse> CreateTerminal(TerminalSize size, ShellConfiguration shellConfiguration);
|
||||
Task ResizeTerminal(int id, TerminalSize size);
|
||||
Task UpdateToggleWindowKeyBindings();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,121 @@
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Windows.System;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
internal class DefaultValueProvider : IDefaultValueProvider
|
||||
{
|
||||
public ApplicationSettings GetDefaultApplicationSettings()
|
||||
{
|
||||
return new ApplicationSettings
|
||||
{
|
||||
ConfirmClosingTabs = false,
|
||||
ConfirmClosingWindows = false,
|
||||
NewTerminalLocation = NewTerminalLocation.Tab
|
||||
};
|
||||
}
|
||||
|
||||
public KeyBindings GetDefaultKeyBindings()
|
||||
{
|
||||
return new KeyBindings
|
||||
{
|
||||
NewTab = new[]
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
Command = Command.NewTab,
|
||||
Ctrl = true,
|
||||
Alt = false,
|
||||
Shift = false,
|
||||
Key = (int)VirtualKey.T
|
||||
}
|
||||
},
|
||||
CloseTab = new[] {
|
||||
new KeyBinding
|
||||
{
|
||||
Command = Command.CloseTab,
|
||||
Ctrl = true,
|
||||
Alt = false,
|
||||
Shift = false,
|
||||
Key = (int)VirtualKey.W
|
||||
}
|
||||
},
|
||||
NextTab = new[] {
|
||||
new KeyBinding
|
||||
{
|
||||
Command = Command.NextTab,
|
||||
Ctrl = true,
|
||||
Alt = false,
|
||||
Shift = false,
|
||||
Key = (int)VirtualKey.Tab
|
||||
}
|
||||
},
|
||||
PreviousTab = new[] {
|
||||
new KeyBinding
|
||||
{
|
||||
Command = Command.PreviousTab,
|
||||
Ctrl = true,
|
||||
Alt = false,
|
||||
Shift = true,
|
||||
Key = (int)VirtualKey.Tab
|
||||
}
|
||||
},
|
||||
NewWindow = new[] {
|
||||
new KeyBinding
|
||||
{
|
||||
Command = Command.NewWindow,
|
||||
Ctrl = true,
|
||||
Alt = false,
|
||||
Shift = false,
|
||||
Key = (int)VirtualKey.N
|
||||
}
|
||||
},
|
||||
ShowSettings = new[] {
|
||||
new KeyBinding
|
||||
{
|
||||
Command = Command.ShowSettings,
|
||||
Ctrl = true,
|
||||
Alt = false,
|
||||
Shift = false,
|
||||
Key = 188 // comma
|
||||
}
|
||||
},
|
||||
Copy = new[] {
|
||||
new KeyBinding
|
||||
{
|
||||
Command = Command.Copy,
|
||||
Ctrl = true,
|
||||
Alt = false,
|
||||
Shift = true,
|
||||
Key = (int)VirtualKey.C
|
||||
}
|
||||
},
|
||||
Paste = new[] {
|
||||
new KeyBinding
|
||||
{
|
||||
Command = Command.Paste,
|
||||
Ctrl = true,
|
||||
Alt = false,
|
||||
Shift = false,
|
||||
Key = (int)VirtualKey.V
|
||||
}
|
||||
},
|
||||
ToggleWindow = new[] {
|
||||
new KeyBinding
|
||||
{
|
||||
Command = Command.ToggleWindow,
|
||||
Ctrl = false,
|
||||
Alt = false,
|
||||
Shift = false,
|
||||
Key = (int)VirtualKey.Scroll
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ShellConfiguration GetDefaultShellConfiguration()
|
||||
{
|
||||
return new ShellConfiguration
|
||||
@@ -15,5 +126,93 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
Arguments = string.Empty
|
||||
};
|
||||
}
|
||||
|
||||
public TerminalOptions GetDefaultTerminalOptions()
|
||||
{
|
||||
return new TerminalOptions
|
||||
{
|
||||
BellStyle = BellStyle.None,
|
||||
CursorBlink = true,
|
||||
CursorStyle = CursorStyle.Block,
|
||||
FontFamily = "Consolas",
|
||||
FontSize = 13
|
||||
};
|
||||
}
|
||||
|
||||
public Guid GetDefaultThemeId()
|
||||
{
|
||||
return Guid.Parse("281e4352-bb50-47b7-a691-2b13830df95e");
|
||||
}
|
||||
|
||||
public IEnumerable<TerminalTheme> GetPreInstalledThemes()
|
||||
{
|
||||
var defaultXterm = new TerminalTheme
|
||||
{
|
||||
Id = GetDefaultThemeId(),
|
||||
Author = "xterm.js",
|
||||
Name = "Xterm.js Default",
|
||||
PreInstalled = true,
|
||||
BackgroundOpacity = 0.8,
|
||||
Colors = new TerminalColors
|
||||
{
|
||||
Black = "#2e3436",
|
||||
Red = "#cc0000",
|
||||
Green = "#4e9a06",
|
||||
Yellow = "#c4a000",
|
||||
Blue = "#3465a4",
|
||||
Magenta = "#75507b",
|
||||
Cyan = "#06989a",
|
||||
White = "#d3d7cf",
|
||||
BrightBlack = "#555753",
|
||||
BrightRed = "#ef2929",
|
||||
BrightGreen = "#8ae234",
|
||||
BrightYellow = "#fce94f",
|
||||
BrightBlue = "#729fcf",
|
||||
BrightMagenta = "#ad7fa8",
|
||||
BrightCyan = "#34e2e2",
|
||||
BrightWhite = "#eeeeec",
|
||||
Foreground = "#ffffff",
|
||||
Background = "#000000",
|
||||
Cursor = "#ffffff",
|
||||
CursorAccent = "#000000",
|
||||
Selection = "rgba(255, 255, 255, 0.3)"
|
||||
}
|
||||
};
|
||||
|
||||
var powerShell = new TerminalTheme
|
||||
{
|
||||
Id = Guid.Parse("3571ce1b-31ce-4cf7-ae15-e0bff70c3eea"),
|
||||
Author = "Microsoft",
|
||||
Name = "PowerShell",
|
||||
PreInstalled = true,
|
||||
BackgroundOpacity = 0.8,
|
||||
Colors = new TerminalColors
|
||||
{
|
||||
Black = "#000000",
|
||||
Red = "#800000",
|
||||
Green = "#008000",
|
||||
Yellow = "#EEEDF0",
|
||||
Blue = "#000080",
|
||||
Magenta = "#012456",
|
||||
Cyan = "#008080",
|
||||
White = "#c0c0c0",
|
||||
BrightBlack = "#808080",
|
||||
BrightRed = "#ff0000",
|
||||
BrightGreen = "#00ff00",
|
||||
BrightYellow = "#ffff00",
|
||||
BrightBlue = "#0000ff",
|
||||
BrightMagenta = "#ff00ff",
|
||||
BrightCyan = "#00ffff",
|
||||
BrightWhite = "#ffffff",
|
||||
Foreground = "#ffffff",
|
||||
Background = "#012456",
|
||||
Cursor = "#fedba9",
|
||||
CursorAccent = "#000000",
|
||||
Selection = "#fedba9"
|
||||
}
|
||||
};
|
||||
|
||||
return new[] { defaultXterm, powerShell };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Popups;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
internal class DialogService : IDialogService
|
||||
{
|
||||
public async Task<DialogButton> ShowDialogAsnyc(string title, string content, params DialogButton[] buttons)
|
||||
{
|
||||
var dialog = new MessageDialog(content, title);
|
||||
|
||||
foreach (var button in buttons)
|
||||
{
|
||||
dialog.Commands.Add(new UICommand(button.ToString()));
|
||||
}
|
||||
|
||||
var result = await dialog.ShowAsync();
|
||||
|
||||
return Enum.Parse<DialogButton>(result.Label);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FluentTerminal.Models.Enums;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
public class KeyboardCommandService : IKeyboardCommandService
|
||||
{
|
||||
private Dictionary<Command, Action> _commandHandlers = new Dictionary<Command, Action>();
|
||||
|
||||
public void RegisterCommandHandler(Command command, Action handler)
|
||||
{
|
||||
_commandHandlers[command] = handler;
|
||||
}
|
||||
|
||||
public void SendCommand(Command command)
|
||||
{
|
||||
if (_commandHandlers.TryGetValue(command, out Action handler))
|
||||
{
|
||||
handler.Invoke();
|
||||
return;
|
||||
}
|
||||
throw new Exception($"No handler registered for command: {command}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
using FluentTerminal.App.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentTerminal.App.Utilities;
|
||||
using FluentTerminal.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
@@ -8,13 +12,27 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private ApplicationDataContainer _localSettings;
|
||||
private ApplicationDataContainer _themes;
|
||||
private ApplicationDataContainer _roamingSettings;
|
||||
|
||||
public event EventHandler CurrentThemeChanged;
|
||||
public event EventHandler TerminalOptionsChanged;
|
||||
public event EventHandler ApplicationSettingsChanged;
|
||||
public event EventHandler KeyBindingsChanged;
|
||||
|
||||
public SettingsService(IDefaultValueProvider defaultValueProvider)
|
||||
{
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
_localSettings = ApplicationData.Current.LocalSettings;
|
||||
_roamingSettings = ApplicationData.Current.RoamingSettings;
|
||||
|
||||
_themes = _roamingSettings.CreateContainer("Themes", ApplicationDataCreateDisposition.Always);
|
||||
|
||||
foreach (var theme in _defaultValueProvider.GetPreInstalledThemes())
|
||||
{
|
||||
_themes.WriteValueAsJson(theme.Id.ToString(), theme);
|
||||
}
|
||||
|
||||
ApplicationData.Current.DataChanged += OnDataChanged;
|
||||
}
|
||||
|
||||
@@ -28,11 +46,89 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
return _localSettings.ReadValueFromJson(nameof(ShellConfiguration), _defaultValueProvider.GetDefaultShellConfiguration());
|
||||
}
|
||||
|
||||
public void SaveShellConfiguration(ShellConfiguration spawnConfiguration)
|
||||
public void SaveShellConfiguration(ShellConfiguration shellConfiguration)
|
||||
{
|
||||
_localSettings.WriteValueAsJson(nameof(ShellConfiguration), spawnConfiguration);
|
||||
_localSettings.WriteValueAsJson(nameof(ShellConfiguration), shellConfiguration);
|
||||
}
|
||||
|
||||
|
||||
public TerminalTheme GetCurrentTheme()
|
||||
{
|
||||
var id = GetCurrentThemeId();
|
||||
return GetTheme(id);
|
||||
}
|
||||
|
||||
public Guid GetCurrentThemeId()
|
||||
{
|
||||
if (_roamingSettings.Values.TryGetValue("CurrentTheme", out object value))
|
||||
{
|
||||
return (Guid)value;
|
||||
}
|
||||
return _defaultValueProvider.GetDefaultThemeId();
|
||||
}
|
||||
|
||||
public void SaveCurrentThemeId(Guid id)
|
||||
{
|
||||
_roamingSettings.Values["CurrentTheme"] = id;
|
||||
|
||||
CurrentThemeChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void SaveTheme(TerminalTheme theme)
|
||||
{
|
||||
_themes.WriteValueAsJson(theme.Id.ToString(), theme);
|
||||
|
||||
if (theme.Id == GetCurrentThemeId())
|
||||
{
|
||||
CurrentThemeChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteTheme(Guid id)
|
||||
{
|
||||
_themes.Values.Remove(id.ToString());
|
||||
}
|
||||
|
||||
public IEnumerable<TerminalTheme> GetThemes()
|
||||
{
|
||||
return _themes.Values.Select(x => JsonConvert.DeserializeObject<TerminalTheme>((string)x.Value)).ToList();
|
||||
}
|
||||
|
||||
public TerminalTheme GetTheme(Guid id)
|
||||
{
|
||||
return _themes.ReadValueFromJson(id.ToString(), default(TerminalTheme));
|
||||
}
|
||||
|
||||
public TerminalOptions GetTerminalOptions()
|
||||
{
|
||||
return _roamingSettings.ReadValueFromJson(nameof(TerminalOptions), _defaultValueProvider.GetDefaultTerminalOptions());
|
||||
}
|
||||
|
||||
public void SaveTerminalOptions(TerminalOptions terminalOptions)
|
||||
{
|
||||
_roamingSettings.WriteValueAsJson(nameof(TerminalOptions), terminalOptions);
|
||||
TerminalOptionsChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public ApplicationSettings GetApplicationSettings()
|
||||
{
|
||||
return _roamingSettings.ReadValueFromJson(nameof(ApplicationSettings), _defaultValueProvider.GetDefaultApplicationSettings());
|
||||
}
|
||||
|
||||
public void SaveApplicationSettings(ApplicationSettings applicationSettings)
|
||||
{
|
||||
_roamingSettings.WriteValueAsJson(nameof(ApplicationSettings), applicationSettings);
|
||||
ApplicationSettingsChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public KeyBindings GetKeyBindings()
|
||||
{
|
||||
return _roamingSettings.ReadValueFromJson(nameof(KeyBindings), _defaultValueProvider.GetDefaultKeyBindings());
|
||||
}
|
||||
|
||||
public void SaveKeyBindings(KeyBindings keyBindings)
|
||||
{
|
||||
_roamingSettings.WriteValueAsJson(nameof(KeyBindings), keyBindings);
|
||||
KeyBindingsChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-2
@@ -6,13 +6,23 @@ using Windows.Web.Http;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
internal class TerminalService : ITerminalService
|
||||
internal class TrayProcessCommunicationService : ITrayProcessCommunicationService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
public TerminalService()
|
||||
public TrayProcessCommunicationService(ISettingsService settingsService)
|
||||
{
|
||||
_httpClient = new HttpClient();
|
||||
_settingsService = settingsService;
|
||||
|
||||
UpdateToggleWindowKeyBindings();
|
||||
}
|
||||
|
||||
public Task UpdateToggleWindowKeyBindings()
|
||||
{
|
||||
var keyBindings = _settingsService.GetKeyBindings().ToggleWindow;
|
||||
return _httpClient.PostAsync(new Uri($"http://localhost:9000/keybindings/togglewindow"), HttpJsonContent.From(keyBindings)).AsTask();
|
||||
}
|
||||
|
||||
public async Task<CreateTerminalResponse> CreateTerminal(TerminalSize size, ShellConfiguration shellConfiguration)
|
||||
@@ -11,6 +11,7 @@
|
||||
<SolidColorBrush x:Key="TitleBarHoverBackgroundColor" Color="#18FFFFFF" />
|
||||
|
||||
<SolidColorBrush x:Key="TitleBarPressedBackgroundColor" Color="#30FFFFFF" />
|
||||
<SolidColorBrush x:Key="DisabledForegroundColor" Color="#80FFFFFF" />
|
||||
|
||||
<Style x:Key="TitleBarButtonStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
@@ -68,4 +69,279 @@
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ColorPreviewButtonStyle" TargetType="Button">
|
||||
<Setter Property="Width" Value="24" />
|
||||
<Setter Property="Height" Value="24" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="True" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
|
||||
<ContentPresenter
|
||||
x:Name="ContentPresenter"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTransitions="{TemplateBinding ContentTransitions}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ThemeAppBarButtonStyle" TargetType="AppBarButton">
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource AppBarButtonBorderBrush}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Top" />
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="Width" Value="68" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="True" />
|
||||
<Setter Property="AllowFocusOnInteraction" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="AppBarButton">
|
||||
<Grid
|
||||
x:Name="Root"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
MaxWidth="{TemplateBinding MaxWidth}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<Grid x:Name="ContentRoot" MinHeight="{ThemeResource AppBarThemeMinHeight}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Viewbox
|
||||
x:Name="ContentViewbox"
|
||||
Height="20"
|
||||
Margin="0,14,0,4"
|
||||
HorizontalAlignment="Stretch"
|
||||
AutomationProperties.AccessibilityView="Raw">
|
||||
<ContentPresenter
|
||||
x:Name="Content"
|
||||
Height="20"
|
||||
Content="{TemplateBinding Icon}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
</Viewbox>
|
||||
<TextBlock
|
||||
x:Name="TextLabel"
|
||||
Grid.Row="1"
|
||||
Margin="2,0,2,6"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
FontSize="12"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Text="{TemplateBinding Label}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
x:Name="OverflowTextLabel"
|
||||
Margin="12,0,12,0"
|
||||
Padding="0,5,0,7"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
FontSize="15"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Text="{TemplateBinding Label}"
|
||||
TextAlignment="Left"
|
||||
TextTrimming="Clip"
|
||||
TextWrapping="NoWrap"
|
||||
Visibility="Collapsed" />
|
||||
</Grid>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="ApplicationViewStates">
|
||||
<VisualState x:Name="FullSize" />
|
||||
<VisualState x:Name="Compact">
|
||||
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="LabelOnRight">
|
||||
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentViewbox" Storyboard.TargetProperty="Margin">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="12,14,0,14" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="MinHeight">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource AppBarThemeCompactHeight}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="(Grid.Row)">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="0" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="(Grid.Column)">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="1" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="TextAlignment">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Left" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Margin">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="8,15,12,17" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="LabelCollapsed">
|
||||
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="MinHeight">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource AppBarThemeCompactHeight}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Overflow">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentRoot.MinHeight" Value="0" />
|
||||
<Setter Target="ContentViewbox.Visibility" Value="Collapsed" />
|
||||
<Setter Target="TextLabel.Visibility" Value="Collapsed" />
|
||||
<Setter Target="OverflowTextLabel.Visibility" Value="Visible" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowWithToggleButtons">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentRoot.MinHeight" Value="0" />
|
||||
<Setter Target="ContentViewbox.Visibility" Value="Collapsed" />
|
||||
<Setter Target="TextLabel.Visibility" Value="Collapsed" />
|
||||
<Setter Target="OverflowTextLabel.Visibility" Value="Visible" />
|
||||
<Setter Target="OverflowTextLabel.Margin" Value="38,0,12,0" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowWithMenuIcons">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentRoot.MinHeight" Value="0" />
|
||||
<Setter Target="ContentViewbox.HorizontalAlignment" Value="Left" />
|
||||
<Setter Target="ContentViewbox.VerticalAlignment" Value="Center" />
|
||||
<Setter Target="ContentViewbox.Width" Value="16" />
|
||||
<Setter Target="ContentViewbox.Height" Value="16" />
|
||||
<Setter Target="ContentViewbox.Margin" Value="12,0,12,0" />
|
||||
<Setter Target="TextLabel.Visibility" Value="Collapsed" />
|
||||
<Setter Target="OverflowTextLabel.Visibility" Value="Visible" />
|
||||
<Setter Target="OverflowTextLabel.Margin" Value="38,0,12,0" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowWithToggleButtonsAndMenuIcons">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentRoot.MinHeight" Value="0" />
|
||||
<Setter Target="ContentViewbox.HorizontalAlignment" Value="Left" />
|
||||
<Setter Target="ContentViewbox.VerticalAlignment" Value="Center" />
|
||||
<Setter Target="ContentViewbox.Width" Value="16" />
|
||||
<Setter Target="ContentViewbox.Height" Value="16" />
|
||||
<Setter Target="ContentViewbox.Margin" Value="38,0,12,0" />
|
||||
<Setter Target="TextLabel.Visibility" Value="Collapsed" />
|
||||
<Setter Target="OverflowTextLabel.Visibility" Value="Visible" />
|
||||
<Setter Target="OverflowTextLabel.Margin" Value="76,0,12,0" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal">
|
||||
<Storyboard>
|
||||
<PointerUpThemeAnimation Storyboard.TargetName="OverflowTextLabel" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Root.Background" Value="{StaticResource TitleBarHoverBackgroundColor}" />
|
||||
<Setter Target="Root.BorderBrush" Value="{ThemeResource AppBarButtonBorderBrushPointerOver}" />
|
||||
</VisualState.Setters>
|
||||
|
||||
<Storyboard>
|
||||
<PointerUpThemeAnimation Storyboard.TargetName="OverflowTextLabel" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Pressed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Root.Background" Value="{StaticResource TitleBarPressedBackgroundColor}" />
|
||||
<Setter Target="Root.BorderBrush" Value="{ThemeResource AppBarButtonBorderBrushPressed}" />
|
||||
</VisualState.Setters>
|
||||
|
||||
<Storyboard>
|
||||
<PointerDownThemeAnimation Storyboard.TargetName="OverflowTextLabel" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Root.Background" Value="Transparent" />
|
||||
<Setter Target="Root.BorderBrush" Value="{ThemeResource AppBarButtonBorderBrushDisabled}" />
|
||||
<Setter Target="Content.Foreground" Value="{StaticResource DisabledForegroundColor}" />
|
||||
<Setter Target="TextLabel.Foreground" Value="{StaticResource DisabledForegroundColor}" />
|
||||
<Setter Target="OverflowTextLabel.Foreground" Value="{StaticResource DisabledForegroundColor}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowNormal">
|
||||
|
||||
<Storyboard>
|
||||
<PointerUpThemeAnimation Storyboard.TargetName="ContentRoot" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowPointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Root.Background" Value="{StaticResource TitleBarHoverBackgroundColor}" />
|
||||
<Setter Target="Root.BorderBrush" Value="{ThemeResource AppBarButtonBorderBrushPointerOver}" />
|
||||
</VisualState.Setters>
|
||||
|
||||
<Storyboard>
|
||||
<PointerUpThemeAnimation Storyboard.TargetName="ContentRoot" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowPressed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Root.Background" Value="{StaticResource TitleBarPressedBackgroundColor}" />
|
||||
<Setter Target="Root.BorderBrush" Value="{ThemeResource AppBarButtonBorderBrushPressed}" />
|
||||
</VisualState.Setters>
|
||||
|
||||
<Storyboard>
|
||||
<PointerDownThemeAnimation Storyboard.TargetName="ContentRoot" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="InputModeStates">
|
||||
<VisualState x:Name="InputModeDefault" />
|
||||
<VisualState x:Name="TouchInputMode">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="OverflowTextLabel.Padding" Value="0,11,0,13" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="GameControllerInputMode">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="OverflowTextLabel.Padding" Value="0,11,0,13" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -1,4 +1,5 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace FluentTerminal.App.Utilities
|
||||
@@ -9,6 +10,11 @@ namespace FluentTerminal.App.Utilities
|
||||
{
|
||||
if (container.Values.TryGetValue(name, out object value))
|
||||
{
|
||||
if (fallbackValue == null)
|
||||
{
|
||||
fallbackValue = Activator.CreateInstance<T>();
|
||||
}
|
||||
|
||||
JsonConvert.PopulateObject((string)value, fallbackValue);
|
||||
}
|
||||
return fallbackValue;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using Microsoft.Toolkit.Uwp.Helpers;
|
||||
using System.Globalization;
|
||||
using Windows.UI;
|
||||
|
||||
namespace FluentTerminal.App.Utilities
|
||||
{
|
||||
public static class ColorExtensions
|
||||
{
|
||||
public static string ToColorString(this Color color, bool allowTransparency)
|
||||
{
|
||||
if (allowTransparency)
|
||||
{
|
||||
return $"rgba({color.R:G}, {color.G:G}, {color.B:G}, {ToDoubleString(color.A)})";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"#{color.R:X2}{color.G:X2}{color.B:X2}";
|
||||
}
|
||||
}
|
||||
|
||||
private static string ToDoubleString(byte alpha)
|
||||
{
|
||||
return (alpha / 256.0).ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public static Color FromString(this string colorString)
|
||||
{
|
||||
if (colorString.Contains("rgba("))
|
||||
{
|
||||
colorString = colorString.Replace("rgba(", string.Empty);
|
||||
colorString = colorString.Replace(")", string.Empty);
|
||||
|
||||
var parts = colorString.Split(", ");
|
||||
|
||||
return new Color
|
||||
{
|
||||
A = (byte)(int)(double.Parse(parts[3]) * 256.0),
|
||||
R = byte.Parse(parts[0]),
|
||||
G = byte.Parse(parts[1]),
|
||||
B = byte.Parse(parts[2])
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return colorString.ToColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,90 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.Core.Preview;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
public class MainViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IKeyboardCommandService _keyboardCommandService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ITerminalService _terminalService;
|
||||
private readonly ITrayProcessCommunicationService _trayProcessCommunicationService;
|
||||
private ApplicationSettings _applicationSettings;
|
||||
private string _background;
|
||||
private double _backgroundOpacity;
|
||||
private CoreDispatcher _dispatcher;
|
||||
private int _nextTerminalId;
|
||||
private TerminalViewModel _selectedTerminal;
|
||||
private string _title;
|
||||
|
||||
public MainViewModel(ISettingsService settingsService, ITerminalService terminalService)
|
||||
public MainViewModel(ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService, IKeyboardCommandService keyboardCommandService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_terminalService = terminalService;
|
||||
Title = "Fluent Terminal";
|
||||
_settingsService.CurrentThemeChanged += OnCurrentThemeChanged;
|
||||
_settingsService.ApplicationSettingsChanged += OnApplicationSettingsChanged;
|
||||
_trayProcessCommunicationService = trayProcessCommunicationService;
|
||||
_dialogService = dialogService;
|
||||
_keyboardCommandService = keyboardCommandService;
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.NewTab, () => AddTerminal(null));
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.CloseTab, CloseCurrentTab);
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.NextTab, SelectNextTab);
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.PreviousTab, SelectPreviousTab);
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.NewWindow, async () => await NewWindow());
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.ShowSettings, async () => await ShowSettings());
|
||||
var currentTheme = _settingsService.GetCurrentTheme();
|
||||
Background = currentTheme.Colors.Background;
|
||||
BackgroundOpacity = currentTheme.BackgroundOpacity;
|
||||
_applicationSettings = _settingsService.GetApplicationSettings();
|
||||
|
||||
AddTerminalCommand = new RelayCommand(AddTerminal);
|
||||
AddTerminalCommand = new RelayCommand(() => AddTerminal(null));
|
||||
ShowSettingsCommand = new RelayCommand(async () => await ShowSettings());
|
||||
|
||||
AddTerminal();
|
||||
Terminals.CollectionChanged += OnTerminalsCollectionChanged;
|
||||
|
||||
Title = "Fluent Terminal";
|
||||
|
||||
_dispatcher = CoreApplication.GetCurrentView().Dispatcher;
|
||||
SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += OnCloseRequest;
|
||||
}
|
||||
|
||||
public RelayCommand AddTerminalCommand { get; }
|
||||
public RelayCommand ShowSettingsCommand { get; }
|
||||
|
||||
public string Background
|
||||
{
|
||||
get => _background;
|
||||
set => Set(ref _background, value);
|
||||
}
|
||||
|
||||
public double BackgroundOpacity
|
||||
{
|
||||
get => _backgroundOpacity;
|
||||
set => Set(ref _backgroundOpacity, value);
|
||||
}
|
||||
|
||||
public TerminalViewModel SelectedTerminal
|
||||
{
|
||||
get => _selectedTerminal;
|
||||
set => Set(ref _selectedTerminal, value);
|
||||
set
|
||||
{
|
||||
if (Set(ref _selectedTerminal, value))
|
||||
{
|
||||
SelectedTerminal?.FocusTerminal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RelayCommand ShowSettingsCommand { get; }
|
||||
|
||||
public ObservableCollection<TerminalViewModel> Terminals { get; } = new ObservableCollection<TerminalViewModel>();
|
||||
|
||||
public string Title
|
||||
@@ -42,19 +93,132 @@ namespace FluentTerminal.App.ViewModels
|
||||
set => Set(ref _title, value);
|
||||
}
|
||||
|
||||
private void AddTerminal()
|
||||
public Task AddTerminal(string startupDirectory)
|
||||
{
|
||||
var terminal = new TerminalViewModel(_settingsService, _terminalService);
|
||||
terminal.PropertyChanged += (s, e) =>
|
||||
return _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
if (e.PropertyName == nameof(TerminalViewModel.Title) && Terminals.Count == 1)
|
||||
{
|
||||
Title = terminal.Title;
|
||||
}
|
||||
};
|
||||
Terminals.Add(terminal);
|
||||
var terminal = new TerminalViewModel(GetNextTerminalId(), _settingsService, _trayProcessCommunicationService, _dialogService, _keyboardCommandService, _applicationSettings, startupDirectory);
|
||||
terminal.CloseRequested += OnTerminalCloseRequested;
|
||||
terminal.TitleChanged += OnTitleChanged;
|
||||
Terminals.Add(terminal);
|
||||
|
||||
SelectedTerminal = terminal;
|
||||
SelectedTerminal = terminal;
|
||||
}).AsTask();
|
||||
}
|
||||
|
||||
public void CloseAllTerminals()
|
||||
{
|
||||
foreach (var terminal in Terminals)
|
||||
{
|
||||
terminal.CloseView();
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseCurrentTab()
|
||||
{
|
||||
SelectedTerminal?.CloseCommand.Execute(null);
|
||||
}
|
||||
|
||||
private int GetNextTerminalId()
|
||||
{
|
||||
return _nextTerminalId++;
|
||||
}
|
||||
|
||||
private Task NewWindow()
|
||||
{
|
||||
return App.Instance.CreateNewTerminalWindow(string.Empty);
|
||||
}
|
||||
|
||||
private async void OnApplicationSettingsChanged(object sender, EventArgs e)
|
||||
{
|
||||
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
|
||||
{
|
||||
_applicationSettings = _settingsService.GetApplicationSettings();
|
||||
});
|
||||
}
|
||||
|
||||
private async void OnCloseRequest(object sender, SystemNavigationCloseRequestedPreviewEventArgs e)
|
||||
{
|
||||
var deferral = e.GetDeferral();
|
||||
|
||||
if (_applicationSettings.ConfirmClosingWindows)
|
||||
{
|
||||
var result = await _dialogService.ShowDialogAsnyc("Please confirm", "Are you sure you want to close this window?", DialogButton.OK, DialogButton.Cancel);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
CloseAllTerminals();
|
||||
App.Instance.TerminalWindowClosed(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseAllTerminals();
|
||||
App.Instance.TerminalWindowClosed(this);
|
||||
}
|
||||
deferral.Complete();
|
||||
}
|
||||
|
||||
private async void OnCurrentThemeChanged(object sender, System.EventArgs e)
|
||||
{
|
||||
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
var currentTheme = _settingsService.GetCurrentTheme();
|
||||
Background = currentTheme.Colors.Background;
|
||||
BackgroundOpacity = currentTheme.BackgroundOpacity;
|
||||
});
|
||||
}
|
||||
|
||||
private void OnTerminalCloseRequested(object sender, EventArgs e)
|
||||
{
|
||||
if (Terminals.Count == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (sender is TerminalViewModel terminal)
|
||||
{
|
||||
terminal.CloseView();
|
||||
if (SelectedTerminal == terminal)
|
||||
{
|
||||
SelectedTerminal = Terminals.LastOrDefault(t => t != terminal);
|
||||
}
|
||||
Terminals.Remove(terminal);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTerminalsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (Terminals.Any())
|
||||
{
|
||||
Title = Terminals.First().Title;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTitleChanged(object sender, string e)
|
||||
{
|
||||
if (sender is TerminalViewModel terminal && Terminals.First() == terminal)
|
||||
{
|
||||
Title = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectNextTab()
|
||||
{
|
||||
var currentIndex = Terminals.IndexOf(SelectedTerminal);
|
||||
var nextIndex = (currentIndex + 1) % Terminals.Count;
|
||||
SelectedTerminal = Terminals[nextIndex];
|
||||
}
|
||||
|
||||
private void SelectPreviousTab()
|
||||
{
|
||||
var currentIndex = Terminals.IndexOf(SelectedTerminal);
|
||||
var previousIndex = (currentIndex - 1 + Terminals.Count) % Terminals.Count;
|
||||
SelectedTerminal = Terminals[previousIndex];
|
||||
}
|
||||
|
||||
private Task ShowSettings()
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Settings
|
||||
{
|
||||
public class GeneralPageViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private ApplicationSettings _applicationSettings;
|
||||
private bool _editingNewTerminalLocation;
|
||||
|
||||
public GeneralPageViewModel(ISettingsService settingsService, IDialogService dialogService, IDefaultValueProvider defaultValueProvider)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_dialogService = dialogService;
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
_applicationSettings = _settingsService.GetApplicationSettings();
|
||||
|
||||
RestoreDefaultsCommand = new RelayCommand(async () => await RestoreDefaults());
|
||||
}
|
||||
|
||||
public bool ConfirmClosingTabs
|
||||
{
|
||||
get => _applicationSettings.ConfirmClosingTabs;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.ConfirmClosingTabs != value)
|
||||
{
|
||||
_applicationSettings.ConfirmClosingTabs = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ConfirmClosingWindows
|
||||
{
|
||||
get => _applicationSettings.ConfirmClosingWindows;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.ConfirmClosingWindows != value)
|
||||
{
|
||||
_applicationSettings.ConfirmClosingWindows = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public NewTerminalLocation NewTerminalLocation
|
||||
{
|
||||
get => _applicationSettings.NewTerminalLocation;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.NewTerminalLocation != value && !_editingNewTerminalLocation)
|
||||
{
|
||||
_editingNewTerminalLocation = true;
|
||||
_applicationSettings.NewTerminalLocation = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
RaisePropertyChanged(nameof(WindowIsSelected));
|
||||
RaisePropertyChanged(nameof(TabIsSelected));
|
||||
_editingNewTerminalLocation = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RelayCommand RestoreDefaultsCommand { get; }
|
||||
|
||||
public bool TabIsSelected
|
||||
{
|
||||
get => NewTerminalLocation == NewTerminalLocation.Tab;
|
||||
set => NewTerminalLocation = NewTerminalLocation.Tab;
|
||||
}
|
||||
|
||||
public bool WindowIsSelected
|
||||
{
|
||||
get => NewTerminalLocation == NewTerminalLocation.Window;
|
||||
set => NewTerminalLocation = NewTerminalLocation.Window;
|
||||
}
|
||||
|
||||
private async Task RestoreDefaults()
|
||||
{
|
||||
var result = await _dialogService.ShowDialogAsnyc("Please confirm", "Are you sure you want to restore the general settings?", DialogButton.OK, DialogButton.Cancel);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
var defaults = _defaultValueProvider.GetDefaultApplicationSettings();
|
||||
ConfirmClosingWindows = defaults.ConfirmClosingWindows;
|
||||
ConfirmClosingTabs = defaults.ConfirmClosingTabs;
|
||||
NewTerminalLocation = defaults.NewTerminalLocation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.App.Views;
|
||||
using FluentTerminal.Models;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Settings
|
||||
{
|
||||
public class KeyBindingViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IDialogService _dialogService;
|
||||
|
||||
public KeyBindingViewModel(KeyBinding keyBinding, IDialogService dialogService)
|
||||
{
|
||||
Model = keyBinding;
|
||||
_dialogService = dialogService;
|
||||
EditCommand = new RelayCommand(async () => await Edit());
|
||||
DeleteCommand = new RelayCommand(async () => await Delete());
|
||||
}
|
||||
|
||||
public event EventHandler Deleted;
|
||||
|
||||
public event EventHandler Edited;
|
||||
|
||||
public bool Alt
|
||||
{
|
||||
get => Model.Alt;
|
||||
set
|
||||
{
|
||||
if (Model.Alt != value)
|
||||
{
|
||||
Model.Alt = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Ctrl
|
||||
{
|
||||
get => Model.Ctrl;
|
||||
set
|
||||
{
|
||||
if (Model.Ctrl != value)
|
||||
{
|
||||
Model.Ctrl = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RelayCommand DeleteCommand { get; }
|
||||
public RelayCommand EditCommand { get; }
|
||||
|
||||
public int Key
|
||||
{
|
||||
get => Model.Key;
|
||||
set
|
||||
{
|
||||
if (Model.Key != value)
|
||||
{
|
||||
Model.Key = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public KeyBinding Model { get; }
|
||||
|
||||
public bool Shift
|
||||
{
|
||||
get => Model.Shift;
|
||||
set
|
||||
{
|
||||
if (Model.Shift != value)
|
||||
{
|
||||
Model.Shift = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> Edit()
|
||||
{
|
||||
var dialog = new CreateKeyBindingDialog(_dialogService);
|
||||
var result = await dialog.ShowAsync();
|
||||
|
||||
if (result == ContentDialogResult.Primary)
|
||||
{
|
||||
Alt = dialog.KeyBinding.Alt;
|
||||
Ctrl = dialog.KeyBinding.Ctrl;
|
||||
Shift = dialog.KeyBinding.Shift;
|
||||
Key = dialog.KeyBinding.Key;
|
||||
|
||||
Edited?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task Delete()
|
||||
{
|
||||
var result = await _dialogService.ShowDialogAsnyc("Please confirm", "Are you sure you want to delete this keybinding?", DialogButton.OK, DialogButton.Cancel);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
Deleted?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Settings
|
||||
{
|
||||
public class KeyBindingsPageViewModel : ViewModelBase
|
||||
{
|
||||
private KeyBindings _keyBindings;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private readonly ITrayProcessCommunicationService _trayProcessCommunicationService;
|
||||
|
||||
public KeyBindingsPageViewModel(ISettingsService settingsService, IDialogService dialogService, IDefaultValueProvider defaultValueProvider, ITrayProcessCommunicationService trayProcessCommunicationService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_dialogService = dialogService;
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
_trayProcessCommunicationService = trayProcessCommunicationService;
|
||||
RestoreDefaultsCommand = new RelayCommand(async () => await RestoreDefaults());
|
||||
AddCommand = new RelayCommand<Command>(async command => await Add(command));
|
||||
|
||||
Initialize(_settingsService.GetKeyBindings());
|
||||
}
|
||||
|
||||
private void Initialize(KeyBindings keyBindings)
|
||||
{
|
||||
_keyBindings = keyBindings;
|
||||
|
||||
_keyBindings.NewTab = new List<KeyBinding>(_keyBindings.NewTab);
|
||||
|
||||
NewTab = CreateViewModel(Command.NewTab, _keyBindings.NewTab);
|
||||
ToggleWindow = CreateViewModel(Command.ToggleWindow, _keyBindings.ToggleWindow);
|
||||
NextTab = CreateViewModel(Command.NextTab, _keyBindings.NextTab);
|
||||
PreviousTab = CreateViewModel(Command.PreviousTab, _keyBindings.PreviousTab);
|
||||
CloseTab = CreateViewModel(Command.CloseTab, _keyBindings.CloseTab);
|
||||
NewWindow = CreateViewModel(Command.NewWindow, _keyBindings.NewWindow);
|
||||
ShowSettings = CreateViewModel(Command.ShowSettings, _keyBindings.ShowSettings);
|
||||
Copy = CreateViewModel(Command.Copy, _keyBindings.Copy);
|
||||
Paste = CreateViewModel(Command.Paste, _keyBindings.Paste);
|
||||
|
||||
RaisePropertyChanged(nameof(NewTab));
|
||||
RaisePropertyChanged(nameof(ToggleWindow));
|
||||
RaisePropertyChanged(nameof(NextTab));
|
||||
RaisePropertyChanged(nameof(PreviousTab));
|
||||
RaisePropertyChanged(nameof(CloseTab));
|
||||
RaisePropertyChanged(nameof(NewWindow));
|
||||
RaisePropertyChanged(nameof(ShowSettings));
|
||||
RaisePropertyChanged(nameof(Copy));
|
||||
RaisePropertyChanged(nameof(Paste));
|
||||
}
|
||||
|
||||
public KeyBindingsViewModel NewTab { get; private set; }
|
||||
public KeyBindingsViewModel ToggleWindow { get; private set; }
|
||||
public KeyBindingsViewModel NextTab { get; private set; }
|
||||
public KeyBindingsViewModel PreviousTab { get; private set; }
|
||||
public KeyBindingsViewModel CloseTab { get; private set; }
|
||||
public KeyBindingsViewModel NewWindow { get; private set; }
|
||||
public KeyBindingsViewModel ShowSettings { get; private set; }
|
||||
public KeyBindingsViewModel Copy { get; private set; }
|
||||
public KeyBindingsViewModel Paste { get; private set; }
|
||||
|
||||
public RelayCommand RestoreDefaultsCommand { get; }
|
||||
public RelayCommand<Command> AddCommand { get; }
|
||||
|
||||
private Task Add(Command command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case Command.ToggleWindow:
|
||||
return ToggleWindow.Add();
|
||||
case Command.NextTab:
|
||||
return NextTab.Add();
|
||||
case Command.PreviousTab:
|
||||
return PreviousTab.Add();
|
||||
case Command.NewTab:
|
||||
return NewTab.Add();
|
||||
case Command.CloseTab:
|
||||
return CloseTab.Add();
|
||||
case Command.NewWindow:
|
||||
return NewWindow.Add();
|
||||
case Command.ShowSettings:
|
||||
return ShowSettings.Add();
|
||||
case Command.Copy:
|
||||
return Copy.Add();
|
||||
case Command.Paste:
|
||||
return Paste.Add();
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task RestoreDefaults()
|
||||
{
|
||||
var result = await _dialogService.ShowDialogAsnyc("Please confirm", "Are you sure you want to restore the default keybindings?", DialogButton.OK, DialogButton.Cancel);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
Initialize(_defaultValueProvider.GetDefaultKeyBindings());
|
||||
_settingsService.SaveKeyBindings(_keyBindings);
|
||||
}
|
||||
}
|
||||
|
||||
private KeyBindingsViewModel CreateViewModel(Command command, ICollection<KeyBinding> keyBindings)
|
||||
{
|
||||
var viewModel = new KeyBindingsViewModel(command, keyBindings, _dialogService);
|
||||
viewModel.Edited += OnEdited;
|
||||
|
||||
return viewModel;
|
||||
}
|
||||
|
||||
private void OnEdited(object sender, System.EventArgs e)
|
||||
{
|
||||
_settingsService.SaveKeyBindings(_keyBindings);
|
||||
_trayProcessCommunicationService.UpdateToggleWindowKeyBindings();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Settings
|
||||
{
|
||||
public class KeyBindingsViewModel : ViewModelBase
|
||||
{
|
||||
private readonly Command _command;
|
||||
private readonly IDialogService _dialogService;
|
||||
private ICollection<KeyBinding> _keyBindings;
|
||||
|
||||
public KeyBindingsViewModel(Command command, ICollection<KeyBinding> keyBindings, IDialogService dialogService)
|
||||
{
|
||||
_command = command;
|
||||
_keyBindings = keyBindings;
|
||||
_dialogService = dialogService;
|
||||
|
||||
foreach (var binding in keyBindings)
|
||||
{
|
||||
var viewModel = new KeyBindingViewModel(binding, _dialogService);
|
||||
viewModel.Deleted += ViewModel_Deleted;
|
||||
viewModel.Edited += ViewModel_Edited;
|
||||
KeyBindings.Add(viewModel);
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler Edited;
|
||||
|
||||
public ObservableCollection<KeyBindingViewModel> KeyBindings { get; } = new ObservableCollection<KeyBindingViewModel>();
|
||||
|
||||
public async Task Add()
|
||||
{
|
||||
var newKeyBinding = new KeyBindingViewModel(new KeyBinding { Command = _command }, _dialogService);
|
||||
|
||||
if (await newKeyBinding.Edit())
|
||||
{
|
||||
newKeyBinding.Deleted += ViewModel_Deleted;
|
||||
newKeyBinding.Edited += ViewModel_Edited;
|
||||
KeyBindings.Add(newKeyBinding);
|
||||
_keyBindings.Add(newKeyBinding.Model);
|
||||
Edited?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private void ViewModel_Deleted(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is KeyBindingViewModel keyBinding)
|
||||
{
|
||||
_keyBindings.Remove(keyBinding.Model);
|
||||
KeyBindings.Remove(keyBinding);
|
||||
Edited?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private void ViewModel_Edited(object sender, EventArgs e)
|
||||
{
|
||||
Edited?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage.Pickers;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Settings
|
||||
{
|
||||
public class ShellPageViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private ShellConfiguration _shellConfiguration;
|
||||
private bool _editingShellType;
|
||||
|
||||
public ShellPageViewModel(ISettingsService settingsService, IDialogService dialogService, IDefaultValueProvider defaultValueProvider)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_dialogService = dialogService;
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
|
||||
RestoreDefaultsCommand = new RelayCommand(async () => await RestoreDefaults());
|
||||
BrowseForCustomShellCommand = new RelayCommand(async () => await BrowseForCustomShell());
|
||||
BrowseForWorkingDirectoryCommand = new RelayCommand(async () => await BrowseForWorkingDirectory());
|
||||
|
||||
_shellConfiguration = _settingsService.GetShellConfiguration();
|
||||
}
|
||||
|
||||
public string Arguments
|
||||
{
|
||||
get => _shellConfiguration.Arguments;
|
||||
set
|
||||
{
|
||||
if (_shellConfiguration.Arguments != value)
|
||||
{
|
||||
_shellConfiguration.Arguments = value;
|
||||
_settingsService.SaveShellConfiguration(_shellConfiguration);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RelayCommand BrowseForCustomShellCommand { get; }
|
||||
|
||||
public RelayCommand BrowseForWorkingDirectoryCommand { get; }
|
||||
|
||||
public bool CMDIsSelected
|
||||
{
|
||||
get => ShellType == ShellType.CMD;
|
||||
set => ShellType = ShellType.CMD;
|
||||
}
|
||||
|
||||
public bool CustomShellIsSelected
|
||||
{
|
||||
get => ShellType == ShellType.Custom;
|
||||
set => ShellType = ShellType.Custom;
|
||||
}
|
||||
|
||||
public string CustomShellLocation
|
||||
{
|
||||
get => _shellConfiguration.CustomShellLocation;
|
||||
set
|
||||
{
|
||||
if (_shellConfiguration.CustomShellLocation != value)
|
||||
{
|
||||
_shellConfiguration.CustomShellLocation = value;
|
||||
_settingsService.SaveShellConfiguration(_shellConfiguration);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool PoweShellIsSelected
|
||||
{
|
||||
get => ShellType == ShellType.PowerShell;
|
||||
set => ShellType = ShellType.PowerShell;
|
||||
}
|
||||
|
||||
public RelayCommand RestoreDefaultsCommand { get; }
|
||||
|
||||
public ShellType ShellType
|
||||
{
|
||||
get => _shellConfiguration.Shell;
|
||||
set
|
||||
{
|
||||
if (_shellConfiguration.Shell != value && !_editingShellType)
|
||||
{
|
||||
_editingShellType = true;
|
||||
_shellConfiguration.Shell = value;
|
||||
_settingsService.SaveShellConfiguration(_shellConfiguration);
|
||||
RaisePropertyChanged();
|
||||
RaisePropertyChanged(nameof(CustomShellIsSelected));
|
||||
RaisePropertyChanged(nameof(PoweShellIsSelected));
|
||||
RaisePropertyChanged(nameof(CMDIsSelected));
|
||||
_editingShellType = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string WorkingDirectory
|
||||
{
|
||||
get => _shellConfiguration.WorkingDirectory;
|
||||
set
|
||||
{
|
||||
if (_shellConfiguration.WorkingDirectory != value)
|
||||
{
|
||||
_shellConfiguration.WorkingDirectory = value;
|
||||
_settingsService.SaveShellConfiguration(_shellConfiguration);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task BrowseForCustomShell()
|
||||
{
|
||||
var picker = new FileOpenPicker();
|
||||
picker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
|
||||
picker.FileTypeFilter.Add(".exe");
|
||||
|
||||
var file = await picker.PickSingleFileAsync().AsTask();
|
||||
if (file != null)
|
||||
{
|
||||
CustomShellLocation = file.Path;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task BrowseForWorkingDirectory()
|
||||
{
|
||||
var picker = new FolderPicker();
|
||||
picker.FileTypeFilter.Add(".whatever"); // else a ComException is thrown
|
||||
picker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
|
||||
|
||||
var folder = await picker.PickSingleFolderAsync();
|
||||
if (folder != null)
|
||||
{
|
||||
WorkingDirectory = folder.Path;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RestoreDefaults()
|
||||
{
|
||||
var result = await _dialogService.ShowDialogAsnyc("Please confirm", "Are you sure you want to restore the default shell configuration?", DialogButton.OK, DialogButton.Cancel);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
var defaults = _defaultValueProvider.GetDefaultShellConfiguration();
|
||||
ShellType = defaults.Shell;
|
||||
CustomShellLocation = defaults.CustomShellLocation;
|
||||
WorkingDirectory = defaults.WorkingDirectory;
|
||||
Arguments = defaults.Arguments;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Settings
|
||||
{
|
||||
public class TerminalPageViewModel : ViewModelBase
|
||||
{
|
||||
private TerminalOptions _terminalOptions;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private bool _isEditingCursorStyle;
|
||||
|
||||
public bool BarIsSelected
|
||||
{
|
||||
get => CursorStyle == CursorStyle.Bar;
|
||||
set => CursorStyle = CursorStyle.Bar;
|
||||
}
|
||||
|
||||
public bool BlockIsSelected
|
||||
{
|
||||
get => CursorStyle == CursorStyle.Block;
|
||||
set => CursorStyle = CursorStyle.Block;
|
||||
}
|
||||
|
||||
public bool CursorBlink
|
||||
{
|
||||
get => _terminalOptions.CursorBlink;
|
||||
set
|
||||
{
|
||||
if (_terminalOptions.CursorBlink != value)
|
||||
{
|
||||
_terminalOptions.CursorBlink = value;
|
||||
_settingsService.SaveTerminalOptions(_terminalOptions);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string FontFamily
|
||||
{
|
||||
get => _terminalOptions.FontFamily;
|
||||
set
|
||||
{
|
||||
if (_terminalOptions.FontFamily != value)
|
||||
{
|
||||
_terminalOptions.FontFamily = value;
|
||||
_settingsService.SaveTerminalOptions(_terminalOptions);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> Fonts { get; }
|
||||
|
||||
public int FontSize
|
||||
{
|
||||
get => _terminalOptions.FontSize;
|
||||
set
|
||||
{
|
||||
if (_terminalOptions.FontSize != value)
|
||||
{
|
||||
_terminalOptions.FontSize = value;
|
||||
_settingsService.SaveTerminalOptions(_terminalOptions);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<int> Sizes { get; }
|
||||
|
||||
public bool UnderlineIsSelected
|
||||
{
|
||||
get => CursorStyle == CursorStyle.Underline;
|
||||
set => CursorStyle = CursorStyle.Underline;
|
||||
}
|
||||
|
||||
public RelayCommand RestoreDefaultsCommand { get; }
|
||||
|
||||
private CursorStyle CursorStyle
|
||||
{
|
||||
get => _terminalOptions.CursorStyle;
|
||||
set
|
||||
{
|
||||
if (_terminalOptions.CursorStyle != value && !_isEditingCursorStyle)
|
||||
{
|
||||
_isEditingCursorStyle = true;
|
||||
_terminalOptions.CursorStyle = value;
|
||||
_settingsService.SaveTerminalOptions(_terminalOptions);
|
||||
RaisePropertyChanged();
|
||||
RaisePropertyChanged(nameof(BlockIsSelected));
|
||||
RaisePropertyChanged(nameof(BarIsSelected));
|
||||
RaisePropertyChanged(nameof(UnderlineIsSelected));
|
||||
_isEditingCursorStyle = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RestoreDefaults()
|
||||
{
|
||||
var result = await _dialogService.ShowDialogAsnyc("Please confirm", "Are you sure you want to restore the default terminal options?", DialogButton.OK, DialogButton.Cancel);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
var defaults = _defaultValueProvider.GetDefaultTerminalOptions();
|
||||
CursorBlink = defaults.CursorBlink;
|
||||
CursorStyle = defaults.CursorStyle;
|
||||
FontFamily = defaults.FontFamily;
|
||||
FontSize = defaults.FontSize;
|
||||
}
|
||||
}
|
||||
|
||||
public TerminalPageViewModel(ISettingsService settingsService, IDialogService dialogService, IDefaultValueProvider defaultValueProvider)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_dialogService = dialogService;
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
|
||||
RestoreDefaultsCommand = new RelayCommand(async () => await RestoreDefaults());
|
||||
|
||||
Fonts = CanvasTextFormat.GetSystemFontFamilies().OrderBy(s => s);
|
||||
Sizes = Enumerable.Range(1, 72);
|
||||
|
||||
_terminalOptions = _settingsService.GetTerminalOptions();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.Models;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Settings
|
||||
{
|
||||
public class ThemesPageViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private ThemeViewModel _selectedTheme;
|
||||
|
||||
public ThemesPageViewModel(ISettingsService settingsService, IDialogService dialogService, IDefaultValueProvider defaultValueProvider)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_dialogService = dialogService;
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
|
||||
CreateThemeCommand = new RelayCommand(CreateTheme);
|
||||
|
||||
var activeThemeId = _settingsService.GetCurrentThemeId();
|
||||
foreach (var theme in _settingsService.GetThemes())
|
||||
{
|
||||
var viewModel = new ThemeViewModel(theme, _settingsService, _dialogService);
|
||||
viewModel.Activated += OnThemeActivated;
|
||||
viewModel.Deleted += OnThemeDeleted;
|
||||
|
||||
if (theme.Id == activeThemeId)
|
||||
{
|
||||
viewModel.IsActive = true;
|
||||
}
|
||||
Themes.Add(viewModel);
|
||||
}
|
||||
|
||||
SelectedTheme = Themes.First(t => t.IsActive);
|
||||
}
|
||||
|
||||
public RelayCommand CreateThemeCommand { get; set; }
|
||||
|
||||
public ThemeViewModel SelectedTheme
|
||||
{
|
||||
get => _selectedTheme;
|
||||
set => Set(ref _selectedTheme, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<ThemeViewModel> Themes { get; } = new ObservableCollection<ThemeViewModel>();
|
||||
|
||||
private void CreateTheme()
|
||||
{
|
||||
var defaultTheme = _settingsService.GetTheme(_defaultValueProvider.GetDefaultThemeId());
|
||||
var theme = new TerminalTheme
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
PreInstalled = false,
|
||||
Name = "New Theme",
|
||||
BackgroundOpacity = defaultTheme.BackgroundOpacity,
|
||||
Colors = new TerminalColors(defaultTheme.Colors)
|
||||
};
|
||||
|
||||
_settingsService.SaveTheme(theme);
|
||||
|
||||
var viewModel = new ThemeViewModel(theme, _settingsService, _dialogService);
|
||||
viewModel.Activated += OnThemeActivated;
|
||||
viewModel.Deleted += OnThemeDeleted;
|
||||
Themes.Add(viewModel);
|
||||
SelectedTheme = viewModel;
|
||||
}
|
||||
|
||||
private void OnThemeActivated(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is ThemeViewModel activatedTheme)
|
||||
{
|
||||
_settingsService.SaveCurrentThemeId(activatedTheme.Id);
|
||||
|
||||
foreach (var theme in Themes)
|
||||
{
|
||||
theme.IsActive = theme.Id == activatedTheme.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnThemeDeleted(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is ThemeViewModel theme)
|
||||
{
|
||||
if (SelectedTheme == theme)
|
||||
{
|
||||
SelectedTheme = Themes.First();
|
||||
}
|
||||
Themes.Remove(theme);
|
||||
|
||||
if (theme.IsActive)
|
||||
{
|
||||
Themes.First().IsActive = true;
|
||||
_settingsService.SaveCurrentThemeId(Themes.First().Id);
|
||||
}
|
||||
_settingsService.DeleteTheme(theme.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,157 +1,24 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using FluentTerminal.App.ViewModels.Settings;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage.Pickers;
|
||||
using Windows.UI.Popups;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
public class SettingsViewModel : ViewModelBase
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private ShellConfiguration _shellConfiguration;
|
||||
|
||||
public SettingsViewModel(ISettingsService settingsService, IDefaultValueProvider defaultValueProvider)
|
||||
public SettingsViewModel(ISettingsService settingsService, IDefaultValueProvider defaultValueProvider, IDialogService dialogService, ITrayProcessCommunicationService trayProcessCommunicationService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
|
||||
BrowseForCustomShellCommand = new RelayCommand(async () => await BrowseForCustomShell());
|
||||
BrowseForWorkingDirectoryCommand = new RelayCommand(async () => await BrowseForWorkingDirectory());
|
||||
RestoreDefaultsCommand = new RelayCommand<string>(async (area) => await RestoreDefaults(area));
|
||||
|
||||
_shellConfiguration = _settingsService.GetShellConfiguration();
|
||||
ShellType = _shellConfiguration.Shell;
|
||||
KeyBindings = new KeyBindingsPageViewModel(settingsService, dialogService, defaultValueProvider, trayProcessCommunicationService);
|
||||
General = new GeneralPageViewModel(settingsService, dialogService, defaultValueProvider);
|
||||
Shell = new ShellPageViewModel(settingsService, dialogService, defaultValueProvider);
|
||||
Terminal = new TerminalPageViewModel(settingsService, dialogService, defaultValueProvider);
|
||||
Themes = new ThemesPageViewModel(settingsService, dialogService, defaultValueProvider);
|
||||
}
|
||||
|
||||
public RelayCommand BrowseForCustomShellCommand { get; }
|
||||
public RelayCommand BrowseForWorkingDirectoryCommand { get; }
|
||||
public RelayCommand<string> RestoreDefaultsCommand { get; }
|
||||
|
||||
public bool CMDIsSelected
|
||||
{
|
||||
get => ShellType == ShellType.CMD;
|
||||
set => ShellType = ShellType.CMD;
|
||||
}
|
||||
|
||||
public bool CustomShellIsSelected
|
||||
{
|
||||
get => ShellType == ShellType.Custom;
|
||||
set => ShellType = ShellType.Custom;
|
||||
}
|
||||
|
||||
public string CustomShellLocation
|
||||
{
|
||||
get => _shellConfiguration.CustomShellLocation;
|
||||
set
|
||||
{
|
||||
if (_shellConfiguration.CustomShellLocation != value)
|
||||
{
|
||||
_shellConfiguration.CustomShellLocation = value;
|
||||
_settingsService.SaveShellConfiguration(_shellConfiguration);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string WorkingDirectory
|
||||
{
|
||||
get => _shellConfiguration.WorkingDirectory;
|
||||
set
|
||||
{
|
||||
if (_shellConfiguration.WorkingDirectory != value)
|
||||
{
|
||||
_shellConfiguration.WorkingDirectory = value;
|
||||
_settingsService.SaveShellConfiguration(_shellConfiguration);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Arguments
|
||||
{
|
||||
get => _shellConfiguration.Arguments;
|
||||
set
|
||||
{
|
||||
if (_shellConfiguration.Arguments != value)
|
||||
{
|
||||
_shellConfiguration.Arguments = value;
|
||||
_settingsService.SaveShellConfiguration(_shellConfiguration);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool PoweShellIsSelected
|
||||
{
|
||||
get => ShellType == ShellType.PowerShell;
|
||||
set => ShellType = ShellType.PowerShell;
|
||||
}
|
||||
|
||||
public ShellType ShellType
|
||||
{
|
||||
get => _shellConfiguration.Shell;
|
||||
set
|
||||
{
|
||||
if (_shellConfiguration.Shell != value)
|
||||
{
|
||||
_shellConfiguration.Shell = value;
|
||||
_settingsService.SaveShellConfiguration(_shellConfiguration);
|
||||
RaisePropertyChanged();
|
||||
RaisePropertyChanged(nameof(CustomShellIsSelected));
|
||||
RaisePropertyChanged(nameof(PoweShellIsSelected));
|
||||
RaisePropertyChanged(nameof(CMDIsSelected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task BrowseForCustomShell()
|
||||
{
|
||||
var picker = new FileOpenPicker();
|
||||
picker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
|
||||
picker.FileTypeFilter.Add(".exe");
|
||||
|
||||
var file = await picker.PickSingleFileAsync().AsTask();
|
||||
if (file != null)
|
||||
{
|
||||
CustomShellLocation = file.Path;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task BrowseForWorkingDirectory()
|
||||
{
|
||||
var picker = new FolderPicker();
|
||||
picker.FileTypeFilter.Add(".whatever"); // else a ComException is thrown
|
||||
picker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
|
||||
|
||||
var folder = await picker.PickSingleFolderAsync();
|
||||
if (folder != null)
|
||||
{
|
||||
WorkingDirectory = folder.Path;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RestoreDefaults(string area)
|
||||
{
|
||||
var dialog = new MessageDialog("Are you sure you want to restore default values for this page?", "Please confirm");
|
||||
dialog.Commands.Add(new UICommand("OK"));
|
||||
dialog.Commands.Add(new UICommand("Cancel"));
|
||||
|
||||
var result = await dialog.ShowAsync();
|
||||
|
||||
if (result.Label == "OK" && area == "shell")
|
||||
{
|
||||
var defaults = _defaultValueProvider.GetDefaultShellConfiguration();
|
||||
ShellType = defaults.Shell;
|
||||
CustomShellLocation = defaults.CustomShellLocation;
|
||||
WorkingDirectory = defaults.WorkingDirectory;
|
||||
Arguments = defaults.Arguments;
|
||||
}
|
||||
}
|
||||
public GeneralPageViewModel General { get; }
|
||||
public KeyBindingsPageViewModel KeyBindings { get; }
|
||||
public TerminalPageViewModel Terminal { get; }
|
||||
public ShellPageViewModel Shell { get; }
|
||||
public ThemesPageViewModel Themes { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,84 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.App.Views;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Popups;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
public class TerminalViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IKeyboardCommandService _keyboardCommandService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ITrayProcessCommunicationService _trayProcessCommunicationService;
|
||||
private ApplicationSettings _applicationSettings;
|
||||
private CoreDispatcher _dispatcher;
|
||||
private string _resizeOverlayContent;
|
||||
private DispatcherTimer _resizeOverlayTimer;
|
||||
private bool _showResizeOverlay;
|
||||
private string _startupDirectory;
|
||||
private int _terminalId;
|
||||
private ITerminalView _terminalView;
|
||||
private string _title;
|
||||
private string _resizeOverlayContent;
|
||||
private bool _showResizeOverlay;
|
||||
private DispatcherTimer _resizeOverlayTimer;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ITerminalService _terminalService;
|
||||
private int _terminalId;
|
||||
|
||||
public TerminalViewModel(int id, ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService, IKeyboardCommandService keyboardCommandService, ApplicationSettings applicationSettings, string startupDirectory)
|
||||
{
|
||||
Id = id;
|
||||
Title = DefaultTitle;
|
||||
|
||||
_settingsService = settingsService;
|
||||
_settingsService.CurrentThemeChanged += OnCurrentThemeChanged;
|
||||
_settingsService.TerminalOptionsChanged += OnTerminalOptionsChanged;
|
||||
_settingsService.ApplicationSettingsChanged += OnApplicationSettingsChanged;
|
||||
_settingsService.KeyBindingsChanged += OnKeyBindingsChanged;
|
||||
_trayProcessCommunicationService = trayProcessCommunicationService;
|
||||
_dialogService = dialogService;
|
||||
_keyboardCommandService = keyboardCommandService;
|
||||
_applicationSettings = applicationSettings;
|
||||
_startupDirectory = startupDirectory;
|
||||
_resizeOverlayTimer = new DispatcherTimer();
|
||||
_resizeOverlayTimer.Interval = new TimeSpan(0, 0, 2);
|
||||
_resizeOverlayTimer.Tick += OnResizeOverlayTimerFinished;
|
||||
|
||||
CloseCommand = new RelayCommand(async () => await InvokeCloseRequested());
|
||||
|
||||
_dispatcher = CoreApplication.GetCurrentView().Dispatcher;
|
||||
}
|
||||
|
||||
private async void OnKeyBindingsChanged(object sender, EventArgs e)
|
||||
{
|
||||
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
|
||||
{
|
||||
var keyBindings = _settingsService.GetKeyBindings();
|
||||
await _terminalView.ChangeKeyBindings(GetKeyBindingsCollection(keyBindings));
|
||||
});
|
||||
}
|
||||
|
||||
public event EventHandler CloseRequested;
|
||||
|
||||
public event EventHandler<string> TitleChanged;
|
||||
|
||||
public RelayCommand CloseCommand { get; }
|
||||
|
||||
public int Id { get; private set; }
|
||||
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
public string Title
|
||||
public string DefaultTitle { get; private set; } = "Fluent Terminal";
|
||||
|
||||
public string ResizeOverlayContent
|
||||
{
|
||||
get => _title;
|
||||
set => Set(ref _title, value);
|
||||
get => _resizeOverlayContent;
|
||||
set => Set(ref _resizeOverlayContent, value);
|
||||
}
|
||||
|
||||
public bool ShowResizeOverlay
|
||||
@@ -47,19 +98,123 @@ namespace FluentTerminal.App.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public string ResizeOverlayContent
|
||||
public string Title
|
||||
{
|
||||
get => _resizeOverlayContent;
|
||||
set => Set(ref _resizeOverlayContent, value);
|
||||
get => _title;
|
||||
set
|
||||
{
|
||||
value = string.IsNullOrWhiteSpace(value) ? DefaultTitle: value;
|
||||
|
||||
if (Set(ref _title, value))
|
||||
{
|
||||
TitleChanged?.Invoke(this, Title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TerminalViewModel(ISettingsService settingsService, ITerminalService terminalService)
|
||||
public void CloseView()
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_terminalService = terminalService;
|
||||
_resizeOverlayTimer = new DispatcherTimer();
|
||||
_resizeOverlayTimer.Interval = new TimeSpan(0, 0, 2);
|
||||
_resizeOverlayTimer.Tick += OnResizeOverlayTimerFinished;
|
||||
_terminalView.Close();
|
||||
}
|
||||
|
||||
public Task FocusTerminal()
|
||||
{
|
||||
return _terminalView?.FocusTerminal();
|
||||
}
|
||||
|
||||
public async Task OnViewIsReady(ITerminalView terminalView)
|
||||
{
|
||||
_terminalView = terminalView;
|
||||
|
||||
var options = _settingsService.GetTerminalOptions();
|
||||
var theme = _settingsService.GetCurrentTheme();
|
||||
var keyBindings = _settingsService.GetKeyBindings();
|
||||
|
||||
var size = await _terminalView.CreateTerminal(options, theme.Colors, GetKeyBindingsCollection(keyBindings));
|
||||
var configuration = _settingsService.GetShellConfiguration();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_startupDirectory))
|
||||
{
|
||||
configuration.WorkingDirectory = _startupDirectory;
|
||||
}
|
||||
|
||||
var response = await _trayProcessCommunicationService.CreateTerminal(size, configuration);
|
||||
|
||||
if (response.Success)
|
||||
{
|
||||
_terminalId = response.Id;
|
||||
_terminalView.TerminalSizeChanged += OnTerminalSizeChanged;
|
||||
_terminalView.TerminalTitleChanged += OnTerminalTitleChanged;
|
||||
_terminalView.KeyboardCommandReceived += OnKeyboardCommandReceived;
|
||||
|
||||
DefaultTitle = response.ShellExecutableName;
|
||||
Title = DefaultTitle;
|
||||
|
||||
await _terminalView.ConnectToSocket(response.WebSocketUrl);
|
||||
Initialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
await _dialogService.ShowDialogAsnyc("Error", response.Error, DialogButton.OK);
|
||||
}
|
||||
|
||||
await FocusTerminal();
|
||||
}
|
||||
|
||||
private async Task InvokeCloseRequested()
|
||||
{
|
||||
if (_applicationSettings.ConfirmClosingTabs)
|
||||
{
|
||||
var result = await _dialogService.ShowDialogAsnyc("Please confirm", "Are you sure you want to close this tab?", DialogButton.OK, DialogButton.Cancel);
|
||||
|
||||
if (result == DialogButton.Cancel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CloseRequested?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private async void OnApplicationSettingsChanged(object sender, EventArgs e)
|
||||
{
|
||||
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
_applicationSettings = _settingsService.GetApplicationSettings();
|
||||
});
|
||||
}
|
||||
|
||||
private async void OnCurrentThemeChanged(object sender, EventArgs e)
|
||||
{
|
||||
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
|
||||
{
|
||||
var currentTheme = _settingsService.GetCurrentTheme();
|
||||
await _terminalView.ChangeTheme(currentTheme.Colors);
|
||||
});
|
||||
}
|
||||
|
||||
private async void OnKeyboardCommandReceived(object sender, Command e)
|
||||
{
|
||||
if (e == Command.Copy)
|
||||
{
|
||||
var selection = await _terminalView.GetSelection();
|
||||
var dataPackage = new DataPackage();
|
||||
dataPackage.SetText(selection);
|
||||
Clipboard.SetContent(dataPackage);
|
||||
}
|
||||
else if (e == Command.Paste)
|
||||
{
|
||||
var content = Clipboard.GetContent();
|
||||
if (content.Contains(StandardDataFormats.Text))
|
||||
{
|
||||
var text = await content.GetTextAsync();
|
||||
await _terminalView.Write(text);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_keyboardCommandService.SendCommand(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnResizeOverlayTimerFinished(object sender, object e)
|
||||
@@ -68,34 +223,13 @@ namespace FluentTerminal.App.ViewModels
|
||||
ShowResizeOverlay = false;
|
||||
}
|
||||
|
||||
public async Task OnViewIsReady(ITerminalView terminalView)
|
||||
private async void OnTerminalOptionsChanged(object sender, EventArgs e)
|
||||
{
|
||||
_terminalView = terminalView;
|
||||
|
||||
var size = await _terminalView.CreateTerminal();
|
||||
var configuration = _settingsService.GetShellConfiguration();
|
||||
|
||||
var response = await _terminalService.CreateTerminal(size, configuration);
|
||||
|
||||
if (response.Success)
|
||||
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
|
||||
{
|
||||
_terminalId = response.Id;
|
||||
_terminalView.TerminalSizeChanged += OnTerminalSizeChanged;
|
||||
_terminalView.TerminalTitleChanged += OnTerminalTitleChanged;
|
||||
|
||||
await _terminalView.ConnectToSocket(response.WebSocketUrl);
|
||||
Initialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var dialog = new MessageDialog(response.Error, "Error");
|
||||
await dialog.ShowAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTerminalTitleChanged(object sender, string e)
|
||||
{
|
||||
Title = e;
|
||||
var options = _settingsService.GetTerminalOptions();
|
||||
await _terminalView.ChangeOptions(options);
|
||||
});
|
||||
}
|
||||
|
||||
private async void OnTerminalSizeChanged(object sender, TerminalSize e)
|
||||
@@ -106,7 +240,27 @@ namespace FluentTerminal.App.ViewModels
|
||||
}
|
||||
ResizeOverlayContent = $"{e.Columns} x {e.Rows}";
|
||||
ShowResizeOverlay = true;
|
||||
await _terminalService.ResizeTerminal(_terminalId, e);
|
||||
await _trayProcessCommunicationService.ResizeTerminal(_terminalId, e);
|
||||
}
|
||||
|
||||
private void OnTerminalTitleChanged(object sender, string e)
|
||||
{
|
||||
Title = e;
|
||||
}
|
||||
|
||||
private IEnumerable<KeyBinding> GetKeyBindingsCollection(KeyBindings keyBindings)
|
||||
{
|
||||
var list = new List<KeyBinding>();
|
||||
list.AddRange(keyBindings.CloseTab);
|
||||
list.AddRange(keyBindings.Copy);
|
||||
list.AddRange(keyBindings.NewTab);
|
||||
list.AddRange(keyBindings.NewWindow);
|
||||
list.AddRange(keyBindings.NextTab);
|
||||
list.AddRange(keyBindings.Paste);
|
||||
list.AddRange(keyBindings.PreviousTab);
|
||||
list.AddRange(keyBindings.ShowSettings);
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.App.Utilities;
|
||||
using FluentTerminal.Models;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using Microsoft.Toolkit.Uwp.Helpers;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
public class ThemeViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private string _author;
|
||||
private Color _background;
|
||||
private double _backgroundOpacity;
|
||||
private Color _black;
|
||||
private Color _blue;
|
||||
private Color _brightBlack;
|
||||
private Color _brightBlue;
|
||||
private Color _brightCyan;
|
||||
private Color _brightGreen;
|
||||
private Color _brightMagenta;
|
||||
private Color _brightRed;
|
||||
private Color _brightWhite;
|
||||
private Color _brightYellow;
|
||||
private Color _cursor;
|
||||
private Color _cursorAccent;
|
||||
private Color _cyan;
|
||||
private string _fallBackAuthor;
|
||||
private double _fallBackBackgroundOpacity;
|
||||
private TerminalColors _fallBackColors;
|
||||
private string _fallBackName;
|
||||
private Color _foreground;
|
||||
private Color _green;
|
||||
private bool _inEditMode;
|
||||
private bool _isActive;
|
||||
private Color _magenta;
|
||||
private string _name;
|
||||
private Color _red;
|
||||
private Color _selection;
|
||||
private TerminalTheme _theme;
|
||||
private Color _white;
|
||||
private Color _yellow;
|
||||
|
||||
public ThemeViewModel(TerminalTheme theme, ISettingsService settingsService, IDialogService dialogService)
|
||||
{
|
||||
_theme = theme;
|
||||
_settingsService = settingsService;
|
||||
_dialogService = dialogService;
|
||||
|
||||
Name = _theme.Name;
|
||||
Author = _theme.Author;
|
||||
Id = _theme.Id;
|
||||
BackgroundOpacity = _theme.BackgroundOpacity;
|
||||
|
||||
Black = _theme.Colors.Black.ToColor();
|
||||
Red = _theme.Colors.Red.ToColor();
|
||||
Green = _theme.Colors.Green.ToColor();
|
||||
Yellow = _theme.Colors.Yellow.ToColor();
|
||||
Blue = _theme.Colors.Blue.ToColor();
|
||||
Magenta = _theme.Colors.Magenta.ToColor();
|
||||
Cyan = _theme.Colors.Cyan.ToColor();
|
||||
White = _theme.Colors.White.ToColor();
|
||||
|
||||
BrightBlack = _theme.Colors.BrightBlack.ToColor();
|
||||
BrightRed = _theme.Colors.BrightRed.ToColor();
|
||||
BrightGreen = _theme.Colors.BrightGreen.ToColor();
|
||||
BrightYellow = _theme.Colors.BrightYellow.ToColor();
|
||||
BrightBlue = _theme.Colors.BrightBlue.ToColor();
|
||||
BrightMagenta = _theme.Colors.BrightMagenta.ToColor();
|
||||
BrightCyan = _theme.Colors.BrightCyan.ToColor();
|
||||
BrightWhite = _theme.Colors.BrightWhite.ToColor();
|
||||
|
||||
Background = _theme.Colors.Background.ToColor();
|
||||
Foreground = _theme.Colors.Foreground.ToColor();
|
||||
Cursor = _theme.Colors.Cursor.ToColor();
|
||||
CursorAccent = _theme.Colors.CursorAccent.ToColor();
|
||||
Selection = _theme.Colors.Selection.FromString();
|
||||
|
||||
SetActiveCommand = new RelayCommand(SetActive);
|
||||
DeleteCommand = new RelayCommand(async () => await Delete(), CanDelete);
|
||||
EditCommand = new RelayCommand(Edit, CanEdit);
|
||||
CancelEditCommand = new RelayCommand(async () => await CancelEdit());
|
||||
SaveChangesCommand = new RelayCommand(SaveChanges);
|
||||
}
|
||||
|
||||
public event EventHandler Activated;
|
||||
|
||||
public event EventHandler Deleted;
|
||||
|
||||
public string Author
|
||||
{
|
||||
get => _author;
|
||||
set => Set(ref _author, value);
|
||||
}
|
||||
|
||||
public Color Background
|
||||
{
|
||||
get => _background;
|
||||
set => Set(ref _background, value);
|
||||
}
|
||||
|
||||
public double BackgroundOpacity
|
||||
{
|
||||
get => _backgroundOpacity;
|
||||
set => Set(ref _backgroundOpacity, value);
|
||||
}
|
||||
|
||||
public Color Black
|
||||
{
|
||||
get => _black;
|
||||
set => Set(ref _black, value);
|
||||
}
|
||||
|
||||
public Color Blue
|
||||
{
|
||||
get => _blue;
|
||||
set => Set(ref _blue, value);
|
||||
}
|
||||
|
||||
public Color BrightBlack
|
||||
{
|
||||
get => _brightBlack;
|
||||
set => Set(ref _brightBlack, value);
|
||||
}
|
||||
|
||||
public Color BrightBlue
|
||||
{
|
||||
get => _brightBlue;
|
||||
set => Set(ref _brightBlue, value);
|
||||
}
|
||||
|
||||
public Color BrightCyan
|
||||
{
|
||||
get => _brightCyan;
|
||||
set => Set(ref _brightCyan, value);
|
||||
}
|
||||
|
||||
public Color BrightGreen
|
||||
{
|
||||
get => _brightGreen;
|
||||
set => Set(ref _brightGreen, value);
|
||||
}
|
||||
|
||||
public Color BrightMagenta
|
||||
{
|
||||
get => _brightMagenta;
|
||||
set => Set(ref _brightMagenta, value);
|
||||
}
|
||||
|
||||
public Color BrightRed
|
||||
{
|
||||
get => _brightRed;
|
||||
set => Set(ref _brightRed, value);
|
||||
}
|
||||
|
||||
public Color BrightWhite
|
||||
{
|
||||
get => _brightWhite;
|
||||
set => Set(ref _brightWhite, value);
|
||||
}
|
||||
|
||||
public Color BrightYellow
|
||||
{
|
||||
get => _brightYellow;
|
||||
set => Set(ref _brightYellow, value);
|
||||
}
|
||||
|
||||
public RelayCommand CancelEditCommand { get; }
|
||||
|
||||
public Color Cursor
|
||||
{
|
||||
get => _cursor;
|
||||
set => Set(ref _cursor, value);
|
||||
}
|
||||
|
||||
public Color CursorAccent
|
||||
{
|
||||
get => _cursorAccent;
|
||||
set => Set(ref _cursorAccent, value);
|
||||
}
|
||||
|
||||
public Color Cyan
|
||||
{
|
||||
get => _cyan;
|
||||
set => Set(ref _cyan, value);
|
||||
}
|
||||
|
||||
public RelayCommand DeleteCommand { get; }
|
||||
public RelayCommand EditCommand { get; }
|
||||
|
||||
public Color Foreground
|
||||
{
|
||||
get => _foreground;
|
||||
set => Set(ref _foreground, value);
|
||||
}
|
||||
|
||||
public Color Green
|
||||
{
|
||||
get => _green;
|
||||
set => Set(ref _green, value);
|
||||
}
|
||||
|
||||
public Guid Id { get; }
|
||||
|
||||
public bool InEditMode
|
||||
{
|
||||
get => _inEditMode;
|
||||
set => Set(ref _inEditMode, value);
|
||||
}
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get => _isActive;
|
||||
set => Set(ref _isActive, value);
|
||||
}
|
||||
|
||||
public Color Magenta
|
||||
{
|
||||
get => _magenta;
|
||||
set => Set(ref _magenta, value);
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => Set(ref _name, value);
|
||||
}
|
||||
|
||||
public Color Red
|
||||
{
|
||||
get => _red;
|
||||
set => Set(ref _red, value);
|
||||
}
|
||||
|
||||
public RelayCommand SaveChangesCommand { get; }
|
||||
|
||||
public Color Selection
|
||||
{
|
||||
get => _selection;
|
||||
set => Set(ref _selection, value);
|
||||
}
|
||||
|
||||
public RelayCommand SetActiveCommand { get; }
|
||||
|
||||
public Color White
|
||||
{
|
||||
get => _white;
|
||||
set => Set(ref _white, value);
|
||||
}
|
||||
|
||||
public Color Yellow
|
||||
{
|
||||
get => _yellow;
|
||||
set => Set(ref _yellow, value);
|
||||
}
|
||||
|
||||
public void SaveChanges()
|
||||
{
|
||||
_theme.Name = Name;
|
||||
_theme.Author = Author;
|
||||
_theme.BackgroundOpacity = BackgroundOpacity;
|
||||
|
||||
_theme.Colors.Black = Black.ToColorString(false);
|
||||
_theme.Colors.Red = Red.ToColorString(false);
|
||||
_theme.Colors.Green = Green.ToColorString(false);
|
||||
_theme.Colors.Yellow = Yellow.ToColorString(false);
|
||||
_theme.Colors.Blue = Blue.ToColorString(false);
|
||||
_theme.Colors.Magenta = Magenta.ToColorString(false);
|
||||
_theme.Colors.Cyan = Cyan.ToColorString(false);
|
||||
_theme.Colors.White = White.ToColorString(false);
|
||||
|
||||
_theme.Colors.BrightBlack = BrightBlack.ToColorString(false);
|
||||
_theme.Colors.BrightRed = BrightRed.ToColorString(false);
|
||||
_theme.Colors.BrightGreen = BrightGreen.ToColorString(false);
|
||||
_theme.Colors.BrightYellow = BrightYellow.ToColorString(false);
|
||||
_theme.Colors.BrightBlue = BrightBlue.ToColorString(false);
|
||||
_theme.Colors.BrightMagenta = BrightMagenta.ToColorString(false);
|
||||
_theme.Colors.BrightCyan = BrightCyan.ToColorString(false);
|
||||
_theme.Colors.BrightWhite = BrightWhite.ToColorString(false);
|
||||
|
||||
_theme.Colors.Background = Background.ToColorString(false);
|
||||
_theme.Colors.Foreground = Foreground.ToColorString(false);
|
||||
_theme.Colors.Cursor = Cursor.ToColorString(false);
|
||||
_theme.Colors.CursorAccent = CursorAccent.ToColorString(false);
|
||||
_theme.Colors.Selection = Selection.ToColorString(true);
|
||||
|
||||
_settingsService.SaveTheme(_theme);
|
||||
|
||||
InEditMode = false;
|
||||
}
|
||||
|
||||
private async Task CancelEdit()
|
||||
{
|
||||
var result = await _dialogService.ShowDialogAsnyc("Please confirm", "Are you sure you want to discard all changes?", DialogButton.OK, DialogButton.Cancel);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
Black = _fallBackColors.Black.ToColor();
|
||||
Red = _fallBackColors.Red.ToColor();
|
||||
Green = _fallBackColors.Green.ToColor();
|
||||
Yellow = _fallBackColors.Yellow.ToColor();
|
||||
Blue = _fallBackColors.Blue.ToColor();
|
||||
Magenta = _fallBackColors.Magenta.ToColor();
|
||||
Cyan = _fallBackColors.Cyan.ToColor();
|
||||
White = _fallBackColors.White.ToColor();
|
||||
|
||||
BrightBlack = _fallBackColors.BrightBlack.ToColor();
|
||||
BrightRed = _fallBackColors.BrightRed.ToColor();
|
||||
BrightGreen = _fallBackColors.BrightGreen.ToColor();
|
||||
BrightYellow = _fallBackColors.BrightYellow.ToColor();
|
||||
BrightBlue = _fallBackColors.BrightBlue.ToColor();
|
||||
BrightMagenta = _fallBackColors.BrightMagenta.ToColor();
|
||||
BrightCyan = _fallBackColors.BrightCyan.ToColor();
|
||||
BrightWhite = _fallBackColors.BrightWhite.ToColor();
|
||||
|
||||
Background = _fallBackColors.Background.ToColor();
|
||||
Foreground = _fallBackColors.Foreground.ToColor();
|
||||
Cursor = _fallBackColors.Cursor.ToColor();
|
||||
CursorAccent = _fallBackColors.CursorAccent.ToColor();
|
||||
Selection = _fallBackColors.Selection.FromString();
|
||||
|
||||
Name = _fallBackName;
|
||||
Author = _fallBackAuthor;
|
||||
BackgroundOpacity = _fallBackBackgroundOpacity;
|
||||
|
||||
InEditMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanDelete()
|
||||
{
|
||||
return !_theme.PreInstalled;
|
||||
}
|
||||
|
||||
private bool CanEdit()
|
||||
{
|
||||
return !_theme.PreInstalled;
|
||||
}
|
||||
|
||||
private async Task Delete()
|
||||
{
|
||||
var result = await _dialogService.ShowDialogAsnyc("Please confirm", "Are you sure you want to delete this theme?", DialogButton.OK, DialogButton.Cancel);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
Deleted?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private void Edit()
|
||||
{
|
||||
_fallBackColors = new TerminalColors(_theme.Colors);
|
||||
_fallBackName = Name;
|
||||
_fallBackAuthor = Author;
|
||||
_fallBackBackgroundOpacity = BackgroundOpacity;
|
||||
InEditMode = true;
|
||||
}
|
||||
|
||||
private void SetActive()
|
||||
{
|
||||
Activated?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
using Windows.UI;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using System;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
{
|
||||
public sealed class BindableColorsTitleBar : Control
|
||||
{
|
||||
private readonly ApplicationViewTitleBar _titleBar;
|
||||
private readonly UISettings _uiSettings;
|
||||
private readonly CoreDispatcher _dispatcher;
|
||||
|
||||
private bool _customValues;
|
||||
|
||||
private Color? _buttonForeground;
|
||||
private Color? _buttonHoverBackground;
|
||||
private Color? _buttonPressedBackground;
|
||||
private Color? _buttonHoverForeground;
|
||||
private Color? _buttonPressedForeground;
|
||||
private Color? _inactiveForeground;
|
||||
|
||||
public BindableColorsTitleBar()
|
||||
{
|
||||
_uiSettings = new UISettings();
|
||||
_uiSettings.ColorValuesChanged += OnColorValuesChanged;
|
||||
_titleBar = ApplicationView.GetForCurrentView().TitleBar;
|
||||
|
||||
_titleBar = ApplicationView.GetForCurrentView().TitleBar;
|
||||
_titleBar.ButtonBackgroundColor = Colors.Transparent;
|
||||
_titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
||||
_titleBar.ButtonForegroundColor = (Color)this.Resources["SystemBaseHighColor"];
|
||||
|
||||
_dispatcher = Window.Current.Dispatcher;
|
||||
|
||||
_buttonHoverBackground = _titleBar.ButtonHoverBackgroundColor = Color.FromArgb(24, 255, 255, 255);
|
||||
_buttonPressedBackground = _titleBar.ButtonPressedBackgroundColor = Color.FromArgb(48, 255, 255, 255);
|
||||
}
|
||||
|
||||
private async void OnColorValuesChanged(UISettings sender, object args)
|
||||
{
|
||||
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
if (!_customValues)
|
||||
{
|
||||
_titleBar.ButtonForegroundColor = (Color)this.Resources["SystemBaseHighColor"];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Color TitleBarForeground
|
||||
{
|
||||
get { return (Color)GetValue(TitleBarForegroundProperty); }
|
||||
set { SetValue(TitleBarForegroundProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TitleBarForegroundProperty =
|
||||
DependencyProperty.Register(nameof(TitleBarForeground), typeof(Color), typeof(BindableColorsTitleBar), new PropertyMetadata(Colors.Transparent, TitleBarForegroundChanged));
|
||||
|
||||
private static void TitleBarForegroundChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (dependencyObject is BindableColorsTitleBar titleBarControl)
|
||||
{
|
||||
var color = (Color)args.NewValue;
|
||||
|
||||
titleBarControl._buttonForeground = titleBarControl._titleBar.ButtonForegroundColor = color;
|
||||
titleBarControl._buttonPressedForeground = titleBarControl._titleBar.ButtonPressedForegroundColor = color;
|
||||
titleBarControl._buttonHoverForeground = titleBarControl._titleBar.ButtonHoverForegroundColor = color;
|
||||
|
||||
titleBarControl._inactiveForeground = titleBarControl._titleBar.InactiveForegroundColor = Color.FromArgb(128, color.R, color.G, color.B);
|
||||
}
|
||||
}
|
||||
|
||||
public void RestoreColors()
|
||||
{
|
||||
_titleBar.ButtonForegroundColor = _buttonForeground;
|
||||
_titleBar.ButtonHoverBackgroundColor = _buttonHoverBackground;
|
||||
_titleBar.ButtonPressedBackgroundColor = _buttonPressedBackground;
|
||||
_titleBar.ButtonPressedForegroundColor = _buttonPressedForeground;
|
||||
_titleBar.ButtonHoverForegroundColor = _buttonHoverForeground;
|
||||
_titleBar.InactiveForegroundColor = _inactiveForeground;
|
||||
|
||||
_customValues = true;
|
||||
}
|
||||
|
||||
public void ResetTitleBar()
|
||||
{
|
||||
_titleBar.ButtonForegroundColor = (Color)this.Resources["SystemBaseHighColor"];
|
||||
_titleBar.ButtonHoverBackgroundColor = null;
|
||||
_titleBar.ButtonPressedBackgroundColor = null;
|
||||
_titleBar.ButtonPressedForegroundColor = null;
|
||||
_titleBar.ButtonHoverForegroundColor = null;
|
||||
_titleBar.InactiveForegroundColor = null;
|
||||
|
||||
_customValues = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<ContentDialog
|
||||
x:Class="FluentTerminal.App.Views.CreateKeyBindingDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="400"
|
||||
PrimaryButtonText="OK"
|
||||
SecondaryButtonText="Cancel"
|
||||
mc:Ignorable="d">
|
||||
<StackPanel>
|
||||
<TextBlock Margin="0,0,0,24" Text="Enter your keybinding now" />
|
||||
<StackPanel x:Name="Root" Orientation="Horizontal">
|
||||
<Grid
|
||||
Width="48"
|
||||
Height="32"
|
||||
Margin="0,0,6,0"
|
||||
Background="{ThemeResource SystemControlBackgroundBaseLowBrush}"
|
||||
Visibility="{x:Bind KeyBinding.Ctrl, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="Ctrl" />
|
||||
</Grid>
|
||||
<Grid
|
||||
Width="48"
|
||||
Height="32"
|
||||
Margin="0,0,6,0"
|
||||
Background="{ThemeResource SystemControlBackgroundBaseLowBrush}"
|
||||
Visibility="{x:Bind KeyBinding.Alt, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="Alt" />
|
||||
</Grid>
|
||||
<Grid
|
||||
Width="48"
|
||||
Height="32"
|
||||
Margin="0,0,6,0"
|
||||
Background="{ThemeResource SystemControlBackgroundBaseLowBrush}"
|
||||
Visibility="{x:Bind KeyBinding.Shift, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="Shift" />
|
||||
</Grid>
|
||||
<Grid
|
||||
Width="48"
|
||||
Height="32"
|
||||
Margin="0,0,6,0"
|
||||
Background="{ThemeResource SystemControlBackgroundBaseLowBrush}"
|
||||
Visibility="{x:Bind KeyBinding.Key, Mode=OneWay, Converter={StaticResource ZeroToCollapsedConverter}}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind KeyBinding.Key, Mode=OneWay, Converter={StaticResource IntToExtendedVirtualKeyConverter}}" />
|
||||
</Grid>
|
||||
<HyperlinkButton
|
||||
x:Name="ResetButton"
|
||||
Margin="24,0,0,0"
|
||||
Command="{x:Bind ResetCommand}"
|
||||
Content="Reset"
|
||||
PreviewKeyDown="OnResetButtonPreviewKeyDown" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
@@ -0,0 +1,69 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.App.ViewModels.Settings;
|
||||
using FluentTerminal.Models;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using Windows.System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
{
|
||||
public sealed partial class CreateKeyBindingDialog : ContentDialog
|
||||
{
|
||||
public static readonly DependencyProperty KeyBindingProperty =
|
||||
DependencyProperty.Register(nameof(KeyBinding), typeof(KeyBindingViewModel), typeof(CreateKeyBindingDialog), new PropertyMetadata(null));
|
||||
|
||||
private readonly IDialogService _dialogService;
|
||||
|
||||
public CreateKeyBindingDialog(IDialogService dialogService)
|
||||
{
|
||||
_dialogService = dialogService;
|
||||
InitializeComponent();
|
||||
ResetCommand = new RelayCommand(Reset);
|
||||
PreviewKeyDown += RegisterKeyBindingDialog_PreviewKeyDown;
|
||||
Reset();
|
||||
}
|
||||
|
||||
public KeyBindingViewModel KeyBinding
|
||||
{
|
||||
get { return (KeyBindingViewModel)GetValue(KeyBindingProperty); }
|
||||
set { SetValue(KeyBindingProperty, value); }
|
||||
}
|
||||
|
||||
public RelayCommand ResetCommand { get; }
|
||||
|
||||
private void OnResetButtonPreviewKeyDown(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void RegisterKeyBindingDialog_PreviewKeyDown(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case VirtualKey.Control:
|
||||
KeyBinding.Ctrl = true;
|
||||
break;
|
||||
|
||||
case VirtualKey.Shift:
|
||||
KeyBinding.Shift = true;
|
||||
break;
|
||||
|
||||
case VirtualKey.Menu:
|
||||
KeyBinding.Alt = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
KeyBinding.Key = (int)e.Key;
|
||||
break;
|
||||
}
|
||||
ResetButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
KeyBinding = new KeyBindingViewModel(new KeyBinding(), _dialogService);
|
||||
ResetButton.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
@@ -8,8 +10,16 @@ namespace FluentTerminal.App.Views
|
||||
{
|
||||
event EventHandler<TerminalSize> TerminalSizeChanged;
|
||||
event EventHandler<string> TerminalTitleChanged;
|
||||
event EventHandler<Command> KeyboardCommandReceived;
|
||||
|
||||
Task<TerminalSize> CreateTerminal();
|
||||
Task ChangeTheme(TerminalColors theme);
|
||||
Task ChangeOptions(TerminalOptions options);
|
||||
Task ChangeKeyBindings(IEnumerable<KeyBinding> keyBindings);
|
||||
Task<TerminalSize> CreateTerminal(TerminalOptions options, TerminalColors theme, IEnumerable<KeyBinding> keyBindings);
|
||||
Task ConnectToSocket(string url);
|
||||
void Close();
|
||||
Task FocusTerminal();
|
||||
Task<string> GetSelection();
|
||||
Task Write(string text);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<UserControl
|
||||
x:Class="FluentTerminal.App.Views.KeyBindingsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:settings="using:FluentTerminal.App.ViewModels.Settings"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="400"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ItemsControl Grid.Row="0" ItemsSource="{x:Bind ViewModel.KeyBindings, Mode=OneWay}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="settings:KeyBindingViewModel">
|
||||
<StackPanel
|
||||
x:Name="Root"
|
||||
Margin="0,0,0,6"
|
||||
Orientation="Horizontal">
|
||||
<Grid
|
||||
Width="48"
|
||||
Height="32"
|
||||
Margin="0,0,6,0"
|
||||
Background="{ThemeResource SystemControlBackgroundBaseLowBrush}"
|
||||
Visibility="{x:Bind Ctrl, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="Ctrl" />
|
||||
</Grid>
|
||||
<Grid
|
||||
Width="48"
|
||||
Height="32"
|
||||
Margin="0,0,6,0"
|
||||
Background="{ThemeResource SystemControlBackgroundBaseLowBrush}"
|
||||
Visibility="{x:Bind Alt, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="Alt" />
|
||||
</Grid>
|
||||
<Grid
|
||||
Width="48"
|
||||
Height="32"
|
||||
Margin="0,0,6,0"
|
||||
Background="{ThemeResource SystemControlBackgroundBaseLowBrush}"
|
||||
Visibility="{x:Bind Shift, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="Shift" />
|
||||
</Grid>
|
||||
<Grid
|
||||
Width="64"
|
||||
Height="32"
|
||||
Margin="0,0,6,0"
|
||||
Background="{ThemeResource SystemControlBackgroundBaseLowBrush}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Key, Mode=OneWay, Converter={StaticResource IntToExtendedVirtualKeyConverter}}" />
|
||||
</Grid>
|
||||
<HyperlinkButton
|
||||
Margin="12,0,0,0"
|
||||
Command="{x:Bind EditCommand}"
|
||||
Content="Edit" />
|
||||
<HyperlinkButton
|
||||
Margin="12,0,0,0"
|
||||
Command="{x:Bind DeleteCommand}"
|
||||
Content="Delete" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,23 @@
|
||||
using FluentTerminal.App.ViewModels.Settings;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
{
|
||||
public sealed partial class KeyBindingsView : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty ViewModelProperty =
|
||||
DependencyProperty.Register(nameof(ViewModel), typeof(KeyBindingsViewModel), typeof(KeyBindingsView), new PropertyMetadata(null));
|
||||
|
||||
public KeyBindingsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public KeyBindingsViewModel ViewModel
|
||||
{
|
||||
get { return (KeyBindingsViewModel)GetValue(ViewModelProperty); }
|
||||
set { SetValue(ViewModelProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,48 +2,130 @@
|
||||
x:Class="FluentTerminal.App.Views.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:behaviors="using:FluentTerminal.App.Behaviors"
|
||||
xmlns:converters="using:FluentTerminal.App.Converters"
|
||||
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Background="{ThemeResource SystemControlAcrylicWindowBrush}"
|
||||
xmlns:viewmodels="using:FluentTerminal.App.ViewModels"
|
||||
RequestedTheme="Dark"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<converters:TerminalViewModelToViewConverter x:Key="TerminalViewModelToViewConverter" />
|
||||
</Page.Resources>
|
||||
<Grid x:Name="Root">
|
||||
<Grid.Background>
|
||||
<AcrylicBrush
|
||||
BackgroundSource="HostBackdrop"
|
||||
FallbackColor="{x:Bind ViewModel.Background, Mode=OneWay}"
|
||||
TintColor="{x:Bind ViewModel.Background, Mode=OneWay}"
|
||||
TintOpacity="{x:Bind ViewModel.BackgroundOpacity, Mode=OneWay}" />
|
||||
</Grid.Background>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Rectangle x:Name="TitleBar" Fill="Transparent" />
|
||||
<Grid
|
||||
Grid.Row="0"
|
||||
Height="{Binding CoreTitleBarHeight, Mode=OneWay}"
|
||||
Canvas.ZIndex="3">
|
||||
<Rectangle x:Name="TitleBar" Fill="Transparent" />
|
||||
<Grid Padding="{Binding CoreTitleBarPadding, Mode=OneWay}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Canvas.ZIndex="9"
|
||||
IsHitTestVisible="False"
|
||||
Style="{StaticResource WindowTitleTextBlockStyle}"
|
||||
Text="{x:Bind ViewModel.Title, Mode=OneWay}" />
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Command="{x:Bind ViewModel.ShowSettingsCommand}"
|
||||
Style="{StaticResource TitleBarButtonStyle}">
|
||||
<Viewbox Width="16" Height="16">
|
||||
<SymbolIcon Symbol="Setting" />
|
||||
</Viewbox>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
Margin="{Binding CoreTitleBarPadding, Mode=OneWay}"
|
||||
SizeChanged="Grid_SizeChanged">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
IsHitTestVisible="False"
|
||||
Style="{StaticResource WindowTitleTextBlockStyle}"
|
||||
Text="{x:Bind ViewModel.Title, Mode=OneWay}"
|
||||
Visibility="{x:Bind ViewModel.Terminals.Count, Mode=OneWay, Converter={StaticResource OneToVisibleConverter}}" />
|
||||
<ListView
|
||||
x:Name="Tabs"
|
||||
Grid.Column="0"
|
||||
AllowDrop="True"
|
||||
CanDragItems="True"
|
||||
CanReorderItems="True"
|
||||
ItemsSource="{x:Bind ViewModel.Terminals}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Auto"
|
||||
ScrollViewer.HorizontalScrollMode="Auto"
|
||||
SelectedItem="{x:Bind ViewModel.SelectedTerminal, Mode=TwoWay}"
|
||||
Visibility="{x:Bind ViewModel.Terminals.Count, Mode=OneWay, Converter={StaticResource OneToCollapsedConverter}}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="viewmodels:TerminalViewModel">
|
||||
<Grid
|
||||
Height="32"
|
||||
Margin="0"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Interactivity:Interaction.Behaviors>
|
||||
<behaviors:MiddleClickBehavior>
|
||||
<behaviors:MiddleClickBehavior.Actions>
|
||||
<core:InvokeCommandAction Command="{x:Bind CloseCommand}" />
|
||||
</behaviors:MiddleClickBehavior.Actions>
|
||||
</behaviors:MiddleClickBehavior>
|
||||
</Interactivity:Interaction.Behaviors>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="12,8,0,0"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Title, Mode=OneWay}" />
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Width="32"
|
||||
Command="{x:Bind CloseCommand}"
|
||||
Style="{StaticResource TitleBarButtonStyle}"
|
||||
ToolTipService.ToolTip="Close">
|
||||
<Viewbox Width="12" Height="12">
|
||||
<SymbolIcon Symbol="Cancel" />
|
||||
</Viewbox>
|
||||
</Button>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="MinWidth" Value="24" />
|
||||
<Setter Property="MinHeight" Value="32" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
||||
</Style>
|
||||
</ListView.ItemContainerStyle>
|
||||
<ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<ItemsStackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListView.ItemsPanel>
|
||||
</ListView>
|
||||
<StackPanel
|
||||
x:Name="TitleBarButtons"
|
||||
Grid.Column="2"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Command="{x:Bind ViewModel.AddTerminalCommand}"
|
||||
Style="{StaticResource TitleBarButtonStyle}"
|
||||
ToolTipService.ToolTip="New Tab">
|
||||
<Viewbox Width="12" Height="12">
|
||||
<SymbolIcon Symbol="Add" />
|
||||
</Viewbox>
|
||||
</Button>
|
||||
<Button
|
||||
HorizontalAlignment="Right"
|
||||
Command="{x:Bind ViewModel.ShowSettingsCommand}"
|
||||
Style="{StaticResource TitleBarButtonStyle}"
|
||||
ToolTipService.ToolTip="Settings">
|
||||
<Viewbox Width="12" Height="12">
|
||||
<SymbolIcon Symbol="Setting" />
|
||||
</Viewbox>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<ContentControl
|
||||
x:Name="TerminalContainer"
|
||||
|
||||
@@ -45,7 +45,9 @@ namespace FluentTerminal.App.Views
|
||||
Loaded += OnLoaded;
|
||||
Unloaded += OnUnloaded;
|
||||
Window.Current.Activated += OnWindowActivated;
|
||||
SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += OnCloseRequest;
|
||||
|
||||
ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(800, 600);
|
||||
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
@@ -56,11 +58,6 @@ namespace FluentTerminal.App.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCloseRequest(object sender, SystemNavigationCloseRequestedPreviewEventArgs e)
|
||||
{
|
||||
App.Instance.TerminalWindowClosed();
|
||||
}
|
||||
|
||||
private async void OnWindowActivated(object sender, WindowActivatedEventArgs e)
|
||||
{
|
||||
if (e.WindowActivationState != CoreWindowActivationState.Deactivated && TerminalContainer.Content is TerminalView terminal)
|
||||
@@ -106,5 +103,13 @@ namespace FluentTerminal.App.Views
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(CoreTitleBarPadding)));
|
||||
}
|
||||
}
|
||||
|
||||
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (sender is Grid grid)
|
||||
{
|
||||
Tabs.MaxWidth = grid.ActualWidth - grid.ColumnDefinitions[2].ActualWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,10 @@
|
||||
x:Class="FluentTerminal.App.Views.SettingsPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="using:FluentTerminal.App.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<converters:TrueToVisibleConverter x:Key="TrueToVisibleConverter" />
|
||||
<converters:FalseToVisibleConverter x:Key="FalseToVisibleConverter" />
|
||||
</Page.Resources>
|
||||
<Grid x:Name="Root" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid x:Name="Root">
|
||||
<TextBlock
|
||||
x:Name="AppTitle"
|
||||
Canvas.ZIndex="1"
|
||||
@@ -20,77 +15,65 @@
|
||||
Visibility="{Binding IsPaneOpen, ElementName=NavigationView, Converter={StaticResource TrueToVisibleConverter}}" />
|
||||
<NavigationView
|
||||
x:Name="NavigationView"
|
||||
AlwaysShowHeader="False"
|
||||
Canvas.ZIndex="0"
|
||||
CompactModeThresholdWidth="560"
|
||||
ExpandedModeThresholdWidth="560"
|
||||
IsSettingsVisible="False"
|
||||
Loaded="NavigationView_Loaded"
|
||||
OpenPaneLength="280"
|
||||
OpenPaneLength="200"
|
||||
SelectionChanged="NavigationView_SelectionChanged">
|
||||
<NavigationView.MenuItems>
|
||||
<NavigationViewItem
|
||||
Content="General"
|
||||
Icon="Setting"
|
||||
Tag="general" />
|
||||
<NavigationViewItem
|
||||
Content="Key Bindings"
|
||||
Icon="Setting"
|
||||
Tag="keyBindings" />
|
||||
<NavigationViewItem
|
||||
Content="Shell"
|
||||
Icon="Setting"
|
||||
Tag="shell" />
|
||||
<NavigationViewItem
|
||||
Content="Font"
|
||||
Icon="Setting"
|
||||
Tag="font" />
|
||||
<NavigationViewItem
|
||||
Content="Colors"
|
||||
Icon="Setting"
|
||||
Tag="colors" />
|
||||
<NavigationViewItem Content="General" Tag="general">
|
||||
<NavigationViewItem.Icon>
|
||||
<FontIcon
|
||||
FontFamily="/Assets/settingsicons.ttf#settingsicons"
|
||||
Glyph="e"
|
||||
ToolTipService.ToolTip="General" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
<NavigationViewItem Content="Terminal" Tag="terminal">
|
||||
<NavigationViewItem.Icon>
|
||||
<FontIcon
|
||||
FontFamily="/Assets/settingsicons.ttf#settingsicons"
|
||||
Glyph="d"
|
||||
ToolTipService.ToolTip="Terminal" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
<NavigationViewItem Content="Shell" Tag="shell">
|
||||
<NavigationViewItem.Icon>
|
||||
<FontIcon
|
||||
FontFamily="/Assets/settingsicons.ttf#settingsicons"
|
||||
Glyph="a"
|
||||
ToolTipService.ToolTip="Shell" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
<NavigationViewItem Content="Keybindings" Tag="keyBindings">
|
||||
<NavigationViewItem.Icon>
|
||||
<FontIcon
|
||||
FontFamily="/Assets/settingsicons.ttf#settingsicons"
|
||||
Glyph="b"
|
||||
ToolTipService.ToolTip="Keybindings" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
<NavigationViewItem Content="Themes" Tag="themes">
|
||||
<NavigationViewItem.Icon>
|
||||
<FontIcon
|
||||
FontFamily="/Assets/settingsicons.ttf#settingsicons"
|
||||
Glyph="c"
|
||||
ToolTipService.ToolTip="Themes" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
</NavigationView.MenuItems>
|
||||
<NavigationView.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Margin="24,10,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="{Binding CoreTitleBarHeight}" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Margin="0,-2,0,0"
|
||||
IsHitTestVisible="False"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="Settings"
|
||||
Visibility="{Binding IsPaneOpen, ElementName=NavigationView, Converter={StaticResource FalseToVisibleConverter}}" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="28"
|
||||
Style="{StaticResource TitleTextBlockStyle}"
|
||||
Text="{Binding SelectedItem.Content, ElementName=NavigationView}" />
|
||||
<CommandBar
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource SystemControlBackgroundAltHighBrush}"
|
||||
DefaultLabelPosition="Right">
|
||||
<AppBarButton
|
||||
Command="{Binding ViewModel.RestoreDefaultsCommand}"
|
||||
CommandParameter="{Binding SelectedItem.Tag, ElementName=NavigationView}"
|
||||
Icon="Undo"
|
||||
Label="Restore Defaults" />
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</NavigationView.HeaderTemplate>
|
||||
<Frame x:Name="ContentFrame" Margin="24" />
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Frame x:Name="ContentFrame" />
|
||||
<TextBlock
|
||||
Margin="12,8,0,0"
|
||||
IsHitTestVisible="False"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="Settings"
|
||||
Visibility="{Binding IsPaneOpen, ElementName=NavigationView, Converter={StaticResource FalseToVisibleConverter}}" />
|
||||
</Grid>
|
||||
</NavigationView>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -2,7 +2,6 @@
|
||||
using FluentTerminal.App.Views.SettingsPages;
|
||||
using System.Linq;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Core.Preview;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
@@ -13,19 +12,13 @@ namespace FluentTerminal.App.Views
|
||||
{
|
||||
public sealed partial class SettingsPage : Page
|
||||
{
|
||||
public double CoreTitleBarHeight { get; }
|
||||
|
||||
public SettingsViewModel ViewModel { get; private set; }
|
||||
|
||||
public SettingsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
Root.DataContext = this;
|
||||
|
||||
ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar;
|
||||
titleBar.ButtonBackgroundColor = Colors.Transparent;
|
||||
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
||||
titleBar.ButtonForegroundColor = (Color)this.Resources["SystemBaseHighColor"];
|
||||
ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(1024, 768);
|
||||
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
|
||||
|
||||
ApplicationView.GetForCurrentView().Title = "Settings";
|
||||
|
||||
@@ -36,6 +29,9 @@ namespace FluentTerminal.App.Views
|
||||
SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += SettingsPage_CloseRequested;
|
||||
}
|
||||
|
||||
public double CoreTitleBarHeight { get; }
|
||||
|
||||
public SettingsViewModel ViewModel { get; private set; }
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is SettingsViewModel viewModel)
|
||||
@@ -44,6 +40,40 @@ namespace FluentTerminal.App.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void NavigationView_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
NavigationView.SelectedItem = NavigationView.MenuItems.Cast<NavigationViewItemBase>().FirstOrDefault(m => m.Tag.ToString() == "general");
|
||||
}
|
||||
|
||||
private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
|
||||
{
|
||||
if (args.SelectedItem is NavigationViewItem item)
|
||||
{
|
||||
switch (item.Tag)
|
||||
{
|
||||
case "general":
|
||||
ContentFrame.Navigate(typeof(GeneralSettings), ViewModel.General);
|
||||
break;
|
||||
|
||||
case "shell":
|
||||
ContentFrame.Navigate(typeof(ShellSettings), ViewModel.Shell);
|
||||
break;
|
||||
|
||||
case "themes":
|
||||
ContentFrame.Navigate(typeof(ThemeSettings), ViewModel.Themes);
|
||||
break;
|
||||
|
||||
case "terminal":
|
||||
ContentFrame.Navigate(typeof(TerminalSettings), ViewModel.Terminal);
|
||||
break;
|
||||
|
||||
case "keyBindings":
|
||||
ContentFrame.Navigate(typeof(KeyBindingSettings), ViewModel.KeyBindings);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SettingsPage_CloseRequested(object sender, SystemNavigationCloseRequestedPreviewEventArgs e)
|
||||
{
|
||||
App.Instance.SettingsWindowClosed();
|
||||
@@ -53,35 +83,5 @@ namespace FluentTerminal.App.Views
|
||||
{
|
||||
AppTitle.Margin = new Thickness(CoreApplication.GetCurrentView().TitleBar.SystemOverlayLeftInset + 12, 8, 0, 0);
|
||||
}
|
||||
|
||||
private void NavigationView_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
NavigationView.SelectedItem = NavigationView.MenuItems.Cast<NavigationViewItemBase>().FirstOrDefault(m => m.Tag.ToString() == "shell");
|
||||
}
|
||||
|
||||
private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
|
||||
{
|
||||
if (args.SelectedItem is NavigationViewItem item)
|
||||
{
|
||||
switch (item.Tag)
|
||||
{
|
||||
case "general":
|
||||
ContentFrame.Navigate(typeof(GeneralSettings), ViewModel);
|
||||
break;
|
||||
case "shell":
|
||||
ContentFrame.Navigate(typeof(ShellSettings), ViewModel);
|
||||
break;
|
||||
case "colors":
|
||||
ContentFrame.Navigate(typeof(ColorSettings), ViewModel);
|
||||
break;
|
||||
case "font":
|
||||
ContentFrame.Navigate(typeof(FontSettings), ViewModel);
|
||||
break;
|
||||
case "keyBindings":
|
||||
ContentFrame.Navigate(typeof(KeyBindingSettings), ViewModel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<Page
|
||||
x:Class="FluentTerminal.App.Views.SettingsPages.ColorSettings"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:FluentTerminal.App.Views.SettingsPages"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
|
||||
</Page>
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// Die Elementvorlage "Leere Seite" wird unter https://go.microsoft.com/fwlink/?LinkId=234238 dokumentiert.
|
||||
|
||||
namespace FluentTerminal.App.Views.SettingsPages
|
||||
{
|
||||
/// <summary>
|
||||
/// Eine leere Seite, die eigenständig verwendet oder zu der innerhalb eines Rahmens navigiert werden kann.
|
||||
/// </summary>
|
||||
public sealed partial class ColorSettings : Page
|
||||
{
|
||||
public ColorSettings()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<Page
|
||||
x:Class="FluentTerminal.App.Views.SettingsPages.FontSettings"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:FluentTerminal.App.Views.SettingsPages"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
|
||||
</Page>
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// Die Elementvorlage "Leere Seite" wird unter https://go.microsoft.com/fwlink/?LinkId=234238 dokumentiert.
|
||||
|
||||
namespace FluentTerminal.App.Views.SettingsPages
|
||||
{
|
||||
/// <summary>
|
||||
/// Eine leere Seite, die eigenständig verwendet oder zu der innerhalb eines Rahmens navigiert werden kann.
|
||||
/// </summary>
|
||||
public sealed partial class FontSettings : Page
|
||||
{
|
||||
public FontSettings()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,49 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
NavigationCacheMode="Required"
|
||||
mc:Ignorable="d">
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="1" Margin="24,00,0,24">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="0,10,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="28"
|
||||
Style="{StaticResource TitleTextBlockStyle}"
|
||||
Text="General" />
|
||||
<CommandBar
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource SystemControlBackgroundAltHighBrush}"
|
||||
DefaultLabelPosition="Right">
|
||||
<AppBarButton
|
||||
Command="{x:Bind ViewModel.RestoreDefaultsCommand}"
|
||||
Icon="Undo"
|
||||
Label="Restore Defaults" />
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
<StackPanel Grid.Row="2" Margin="24,0,0,0">
|
||||
<TextBlock Margin="0,0,0,8" Text="Open new terminals as" />
|
||||
<RadioButton Content="Tabs" IsChecked="{x:Bind ViewModel.TabIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton
|
||||
Margin="0,0,0,24"
|
||||
Content="Windows"
|
||||
IsChecked="{x:Bind ViewModel.WindowIsSelected, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
Margin="0,0,0,24"
|
||||
Header="Ask before closing windows"
|
||||
IsOn="{x:Bind ViewModel.ConfirmClosingWindows, Mode=TwoWay}" />
|
||||
<ToggleSwitch Header="Ask before closing tabs" IsOn="{x:Bind ViewModel.ConfirmClosingTabs, Mode=TwoWay}" />
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -1,12 +1,24 @@
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using FluentTerminal.App.ViewModels.Settings;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace FluentTerminal.App.Views.SettingsPages
|
||||
{
|
||||
public sealed partial class GeneralSettings : Page
|
||||
{
|
||||
public GeneralPageViewModel ViewModel { get; private set; }
|
||||
|
||||
public GeneralSettings()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is GeneralPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,208 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:FluentTerminal.App.Views.SettingsPages"
|
||||
xmlns:enums="using:FluentTerminal.Models.Enums"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:views="using:FluentTerminal.App.Views"
|
||||
mc:Ignorable="d">
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="1" Margin="24,0,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="0,10,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="28"
|
||||
Style="{StaticResource TitleTextBlockStyle}"
|
||||
Text="Keybindings" />
|
||||
<CommandBar
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource SystemControlBackgroundAltHighBrush}"
|
||||
DefaultLabelPosition="Right">
|
||||
<AppBarButton Icon="Add" Label="Add">
|
||||
<AppBarButton.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem Command="{x:Bind ViewModel.AddCommand}" Text="New tab">
|
||||
<MenuFlyoutItem.CommandParameter>
|
||||
<enums:Command>NewTab</enums:Command>
|
||||
</MenuFlyoutItem.CommandParameter>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Command="{x:Bind ViewModel.AddCommand}" Text="Close tab">
|
||||
<MenuFlyoutItem.CommandParameter>
|
||||
<enums:Command>CloseTab</enums:Command>
|
||||
</MenuFlyoutItem.CommandParameter>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Command="{x:Bind ViewModel.AddCommand}" Text="Next tab">
|
||||
<MenuFlyoutItem.CommandParameter>
|
||||
<enums:Command>NextTab</enums:Command>
|
||||
</MenuFlyoutItem.CommandParameter>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Command="{x:Bind ViewModel.AddCommand}" Text="Previous tab">
|
||||
<MenuFlyoutItem.CommandParameter>
|
||||
<enums:Command>PreviousTab</enums:Command>
|
||||
</MenuFlyoutItem.CommandParameter>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Command="{x:Bind ViewModel.AddCommand}" Text="New window">
|
||||
<MenuFlyoutItem.CommandParameter>
|
||||
<enums:Command>NewWindow</enums:Command>
|
||||
</MenuFlyoutItem.CommandParameter>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Command="{x:Bind ViewModel.AddCommand}" Text="Show settings">
|
||||
<MenuFlyoutItem.CommandParameter>
|
||||
<enums:Command>ShowSettings</enums:Command>
|
||||
</MenuFlyoutItem.CommandParameter>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Command="{x:Bind ViewModel.AddCommand}" Text="Toggle window">
|
||||
<MenuFlyoutItem.CommandParameter>
|
||||
<enums:Command>ToggleWindow</enums:Command>
|
||||
</MenuFlyoutItem.CommandParameter>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Command="{x:Bind ViewModel.AddCommand}" Text="Copy">
|
||||
<MenuFlyoutItem.CommandParameter>
|
||||
<enums:Command>Copy</enums:Command>
|
||||
</MenuFlyoutItem.CommandParameter>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Command="{x:Bind ViewModel.AddCommand}" Text="Paste">
|
||||
<MenuFlyoutItem.CommandParameter>
|
||||
<enums:Command>Paste</enums:Command>
|
||||
</MenuFlyoutItem.CommandParameter>
|
||||
</MenuFlyoutItem>
|
||||
</MenuFlyout>
|
||||
</AppBarButton.Flyout>
|
||||
</AppBarButton>
|
||||
<AppBarButton
|
||||
Command="{x:Bind ViewModel.RestoreDefaultsCommand}"
|
||||
CommandParameter="keyBindings"
|
||||
Icon="Undo"
|
||||
Label="Restore Defaults" />
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
<ScrollViewer Grid.Row="2" Margin="24,24,0,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Margin="0,6,24,0"
|
||||
Text="New tab" />
|
||||
<views:KeyBindingsView
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,24"
|
||||
ViewModel="{x:Bind ViewModel.NewTab, Mode=OneWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="0,6,24,0"
|
||||
Text="Close tab" />
|
||||
<views:KeyBindingsView
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,24"
|
||||
ViewModel="{x:Bind ViewModel.CloseTab, Mode=OneWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="0,6,24,0"
|
||||
Text="Next tab" />
|
||||
<views:KeyBindingsView
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,24"
|
||||
ViewModel="{x:Bind ViewModel.NextTab, Mode=OneWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="0,6,24,0"
|
||||
Text="Previous tab" />
|
||||
<views:KeyBindingsView
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,24"
|
||||
ViewModel="{x:Bind ViewModel.PreviousTab, Mode=OneWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="0,6,24,0"
|
||||
Text="New window" />
|
||||
<views:KeyBindingsView
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,24"
|
||||
ViewModel="{x:Bind ViewModel.NewWindow, Mode=OneWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Margin="0,6,24,0"
|
||||
Text="Show settings" />
|
||||
<views:KeyBindingsView
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,24"
|
||||
ViewModel="{x:Bind ViewModel.ShowSettings, Mode=OneWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="6"
|
||||
Grid.Column="0"
|
||||
Margin="0,6,24,0"
|
||||
Text="Toggle window" />
|
||||
<views:KeyBindingsView
|
||||
Grid.Row="6"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,24"
|
||||
ViewModel="{x:Bind ViewModel.ToggleWindow, Mode=OneWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="7"
|
||||
Grid.Column="0"
|
||||
Margin="0,6,24,0"
|
||||
Text="Copy" />
|
||||
<views:KeyBindingsView
|
||||
Grid.Row="7"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,24"
|
||||
ViewModel="{x:Bind ViewModel.Copy, Mode=OneWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="0"
|
||||
Margin="0,6,24,0"
|
||||
Text="Paste" />
|
||||
<views:KeyBindingsView
|
||||
Grid.Row="8"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,24"
|
||||
ViewModel="{x:Bind ViewModel.Paste, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -1,30 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using FluentTerminal.App.ViewModels.Settings;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// Die Elementvorlage "Leere Seite" wird unter https://go.microsoft.com/fwlink/?LinkId=234238 dokumentiert.
|
||||
|
||||
namespace FluentTerminal.App.Views.SettingsPages
|
||||
{
|
||||
/// <summary>
|
||||
/// Eine leere Seite, die eigenständig verwendet oder zu der innerhalb eines Rahmens navigiert werden kann.
|
||||
/// </summary>
|
||||
public sealed partial class KeyBindingSettings : Page
|
||||
{
|
||||
public KeyBindingsPageViewModel ViewModel { get; private set; }
|
||||
|
||||
public KeyBindingSettings()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is KeyBindingsPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
}
|
||||
}
|
||||
|
||||
private void KeyBindingView_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,49 +4,81 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
NavigationCacheMode="Required"
|
||||
mc:Ignorable="d">
|
||||
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="1" Margin="24,00,0,24">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="0,10,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="28"
|
||||
Style="{StaticResource TitleTextBlockStyle}"
|
||||
Text="Shell" />
|
||||
<CommandBar
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource SystemControlBackgroundAltHighBrush}"
|
||||
DefaultLabelPosition="Right">
|
||||
<AppBarButton
|
||||
Command="{x:Bind ViewModel.RestoreDefaultsCommand}"
|
||||
Icon="Undo"
|
||||
Label="Restore Defaults" />
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
<StackPanel Grid.Row="2" Margin="24,0,0,0">
|
||||
|
||||
<TextBlock Margin="0,0,0,8" Text="Shell Type" />
|
||||
<RadioButton Content="PowerShell" IsChecked="{Binding ViewModel.PoweShellIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="CMD" IsChecked="{Binding ViewModel.CMDIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="Custom" IsChecked="{Binding ViewModel.CustomShellIsSelected, Mode=TwoWay}" />
|
||||
<TextBlock Margin="0,0,0,8" Text="Type" />
|
||||
<RadioButton Content="PowerShell" IsChecked="{x:Bind ViewModel.PoweShellIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="CMD" IsChecked="{x:Bind ViewModel.CMDIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="Custom" IsChecked="{x:Bind ViewModel.CustomShellIsSelected, Mode=TwoWay}" />
|
||||
|
||||
<StackPanel Margin="0,24,0,0" Orientation="Horizontal">
|
||||
<TextBox
|
||||
Width="400"
|
||||
Header="Custom Shell Location"
|
||||
IsEnabled="{x:Bind ViewModel.CustomShellIsSelected, Mode=OneWay}"
|
||||
IsSpellCheckEnabled="False"
|
||||
Text="{x:Bind ViewModel.CustomShellLocation, Mode=TwoWay}" />
|
||||
<Button
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Command="{x:Bind ViewModel.BrowseForCustomShellCommand}"
|
||||
Content="..."
|
||||
IsEnabled="{x:Bind ViewModel.CustomShellIsSelected, Mode=OneWay}"
|
||||
Style="{StaticResource ButtonRevealStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,24,0,0" Orientation="Horizontal">
|
||||
<TextBox
|
||||
Width="400"
|
||||
Header="Working Directory"
|
||||
IsSpellCheckEnabled="False"
|
||||
Text="{x:Bind ViewModel.WorkingDirectory, Mode=TwoWay}" />
|
||||
<Button
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Command="{x:Bind ViewModel.BrowseForWorkingDirectoryCommand}"
|
||||
Content="..."
|
||||
Style="{StaticResource ButtonRevealStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,24,0,0" Orientation="Horizontal">
|
||||
<TextBox
|
||||
Width="400"
|
||||
Header="Custom Shell Location"
|
||||
IsEnabled="{x:Bind ViewModel.CustomShellIsSelected, Mode=OneWay}"
|
||||
Text="{x:Bind ViewModel.CustomShellLocation, Mode=TwoWay}" />
|
||||
<Button
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Command="{x:Bind ViewModel.BrowseForCustomShellCommand}"
|
||||
Content="..."
|
||||
IsEnabled="{x:Bind ViewModel.CustomShellIsSelected, Mode=OneWay}"
|
||||
Style="{StaticResource ButtonRevealStyle}" />
|
||||
Margin="0,24,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Header="Arguments"
|
||||
IsSpellCheckEnabled="False"
|
||||
Text="{x:Bind ViewModel.Arguments, Mode=TwoWay}" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,24,0,0" Orientation="Horizontal">
|
||||
<TextBox
|
||||
Width="400"
|
||||
Header="Working Directory"
|
||||
Text="{x:Bind ViewModel.WorkingDirectory, Mode=TwoWay}" />
|
||||
<Button
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Command="{x:Bind ViewModel.BrowseForWorkingDirectoryCommand}"
|
||||
Content="..."
|
||||
Style="{StaticResource ButtonRevealStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBox
|
||||
Width="400"
|
||||
Margin="0,24,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Header="Arguments"
|
||||
Text="{x:Bind ViewModel.Arguments, Mode=TwoWay}" />
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -1,4 +1,4 @@
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using FluentTerminal.App.ViewModels.Settings;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace FluentTerminal.App.Views.SettingsPages
|
||||
{
|
||||
public sealed partial class ShellSettings : Page
|
||||
{
|
||||
public SettingsViewModel ViewModel { get; private set; }
|
||||
public ShellPageViewModel ViewModel { get; private set; }
|
||||
|
||||
public ShellSettings()
|
||||
{
|
||||
@@ -15,7 +15,7 @@ namespace FluentTerminal.App.Views.SettingsPages
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is SettingsViewModel viewModel)
|
||||
if (e.Parameter is ShellPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<Page
|
||||
x:Class="FluentTerminal.App.Views.SettingsPages.TerminalSettings"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="1" Margin="24,00,0,24">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="0,10,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="28"
|
||||
Style="{StaticResource TitleTextBlockStyle}"
|
||||
Text="Terminal" />
|
||||
<CommandBar
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource SystemControlBackgroundAltHighBrush}"
|
||||
DefaultLabelPosition="Right">
|
||||
<AppBarButton
|
||||
Command="{x:Bind ViewModel.RestoreDefaultsCommand}"
|
||||
Icon="Undo"
|
||||
Label="Restore Defaults" />
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
<StackPanel Grid.Row="2" Margin="24,0,0,0">
|
||||
<ComboBox
|
||||
Width="200"
|
||||
Margin="0,0,0,24"
|
||||
Header="Font Family"
|
||||
ItemsSource="{x:Bind ViewModel.Fonts}"
|
||||
SelectedValue="{x:Bind ViewModel.FontFamily, Mode=TwoWay}" />
|
||||
<ComboBox
|
||||
Width="200"
|
||||
Margin="0,0,0,24"
|
||||
Header="Font Size"
|
||||
ItemsSource="{x:Bind ViewModel.Sizes}"
|
||||
SelectedValue="{x:Bind ViewModel.FontSize, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
Margin="0,0,0,24"
|
||||
Header="Blinking Cursor"
|
||||
IsOn="{x:Bind ViewModel.CursorBlink, Mode=TwoWay}" />
|
||||
<TextBlock Margin="0,0,0,8" Text="Cursor Style" />
|
||||
<RadioButton Content="Block" IsChecked="{x:Bind ViewModel.BlockIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="Underline" IsChecked="{x:Bind ViewModel.UnderlineIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="Bar" IsChecked="{x:Bind ViewModel.BarIsSelected, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,24 @@
|
||||
using FluentTerminal.App.ViewModels.Settings;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace FluentTerminal.App.Views.SettingsPages
|
||||
{
|
||||
public sealed partial class TerminalSettings : Page
|
||||
{
|
||||
public TerminalSettings()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public TerminalPageViewModel ViewModel { get; private set; }
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is TerminalPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
<Page
|
||||
x:Class="FluentTerminal.App.Views.SettingsPages.ThemeSettings"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewmodels="using:FluentTerminal.App.ViewModels"
|
||||
xmlns:views="using:FluentTerminal.App.Views"
|
||||
mc:Ignorable="d">
|
||||
<Grid x:Name="Root">
|
||||
<Grid.Background>
|
||||
<AcrylicBrush
|
||||
BackgroundSource="HostBackdrop"
|
||||
FallbackColor="{x:Bind ViewModel.SelectedTheme.Background, Mode=OneWay}"
|
||||
TintColor="{x:Bind ViewModel.SelectedTheme.Background, Mode=OneWay}"
|
||||
TintOpacity="{x:Bind ViewModel.SelectedTheme.BackgroundOpacity, Mode=OneWay}" />
|
||||
</Grid.Background>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="160" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<views:BindableColorsTitleBar x:Name="TitleBar" TitleBarForeground="White" />
|
||||
<Border
|
||||
Grid.RowSpan="3"
|
||||
Grid.Column="0"
|
||||
Background="{ThemeResource SystemControlAcrylicWindowBrush}" />
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="0,0,0,24">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="24,10,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="28"
|
||||
Style="{StaticResource TitleTextBlockStyle}"
|
||||
Text="Themes" />
|
||||
<CommandBar
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="Transparent"
|
||||
DefaultLabelPosition="Right"
|
||||
Visibility="{x:Bind ViewModel.SelectedTheme.InEditMode, Mode=OneWay, Converter={StaticResource FalseToVisibleConverter}}">
|
||||
<AppBarButton
|
||||
Command="{x:Bind ViewModel.SelectedTheme.SetActiveCommand, Mode=OneWay}"
|
||||
Foreground="White"
|
||||
Icon="Accept"
|
||||
IsEnabled="{x:Bind ViewModel.SelectedTheme.IsActive, Mode=OneWay, Converter={StaticResource NegateConverter}}"
|
||||
Label="Set Active"
|
||||
Style="{StaticResource ThemeAppBarButtonStyle}" />
|
||||
<AppBarButton
|
||||
Command="{x:Bind ViewModel.SelectedTheme.EditCommand, Mode=OneWay}"
|
||||
Foreground="White"
|
||||
Icon="Edit"
|
||||
Label="Edit"
|
||||
Style="{StaticResource ThemeAppBarButtonStyle}" />
|
||||
<AppBarButton
|
||||
Command="{x:Bind ViewModel.SelectedTheme.DeleteCommand, Mode=OneWay}"
|
||||
Foreground="White"
|
||||
Icon="Delete"
|
||||
Label="Delete"
|
||||
Style="{StaticResource ThemeAppBarButtonStyle}" />
|
||||
</CommandBar>
|
||||
<CommandBar
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="Transparent"
|
||||
DefaultLabelPosition="Right"
|
||||
Visibility="{x:Bind ViewModel.SelectedTheme.InEditMode, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}">
|
||||
<AppBarButton
|
||||
Command="{x:Bind ViewModel.SelectedTheme.SaveChangesCommand, Mode=OneWay}"
|
||||
Foreground="White"
|
||||
Icon="Save"
|
||||
Label="Save"
|
||||
Style="{StaticResource ThemeAppBarButtonStyle}" />
|
||||
<AppBarButton
|
||||
Command="{x:Bind ViewModel.SelectedTheme.CancelEditCommand, Mode=OneWay}"
|
||||
Foreground="White"
|
||||
Icon="Cancel"
|
||||
Label="Cancel"
|
||||
Style="{StaticResource ThemeAppBarButtonStyle}" />
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
<StackPanel Grid.Row="2" Grid.Column="0">
|
||||
<ListView ItemsSource="{x:Bind ViewModel.Themes}" SelectedItem="{x:Bind ViewModel.SelectedTheme, Mode=TwoWay}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="viewmodels:ThemeViewModel">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="{x:Bind Name, Mode=OneWay}" />
|
||||
<Viewbox
|
||||
Grid.Column="1"
|
||||
Width="16"
|
||||
Height="16"
|
||||
HorizontalAlignment="Right">
|
||||
<SymbolIcon Symbol="Accept" Visibility="{x:Bind IsActive, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
</Style>
|
||||
</ListView.ItemContainerStyle>
|
||||
</ListView>
|
||||
<Button
|
||||
Height="48"
|
||||
Margin="0,12,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Left"
|
||||
Background="Transparent"
|
||||
Command="{x:Bind ViewModel.CreateThemeCommand}"
|
||||
Style="{StaticResource ButtonRevealStyle}">
|
||||
<Button.Content>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Viewbox
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="0,0,6,0">
|
||||
<SymbolIcon Symbol="Add" />
|
||||
</Viewbox>
|
||||
<TextBlock Text="Create New" />
|
||||
</StackPanel>
|
||||
</Button.Content>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<ContentControl
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="24,0,0,0"
|
||||
Content="{x:Bind ViewModel.SelectedTheme, Mode=TwoWay}">
|
||||
<ContentControl.ContentTemplate>
|
||||
<DataTemplate x:DataType="viewmodels:ThemeViewModel">
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
Style="{StaticResource SubtitleTextBlockStyle}"
|
||||
Text="{x:Bind Name, Mode=OneWay}"
|
||||
Visibility="{x:Bind InEditMode, Mode=OneWay, Converter={StaticResource FalseToVisibleConverter}}">
|
||||
<TextBlock.Foreground>
|
||||
<SolidColorBrush Color="{x:Bind Foreground, Mode=OneWay}" />
|
||||
</TextBlock.Foreground>
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
Foreground="White"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Author, Mode=OneWay}" />
|
||||
<TextBox
|
||||
Header="Name"
|
||||
RequestedTheme="Dark"
|
||||
Text="{x:Bind Name, Mode=TwoWay}"
|
||||
Visibility="{x:Bind InEditMode, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}" />
|
||||
<TextBox
|
||||
Margin="0,24,0,0"
|
||||
Header="Author"
|
||||
RequestedTheme="Dark"
|
||||
Text="{x:Bind Author, Mode=TwoWay}"
|
||||
Visibility="{x:Bind InEditMode, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}" />
|
||||
<Grid Margin="0,48,0,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.Resources>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Margin" Value="0,0,0,0" />
|
||||
<Setter Property="Width" Value="24" />
|
||||
<Setter Property="Height" Value="24" />
|
||||
</Style>
|
||||
</Grid.Resources>
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal">
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Black"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind Black, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Red"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind Red, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Green"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind Green, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Yellow"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind Yellow, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Blue"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind Blue, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Magenta"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind Magenta, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Cyan"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind Cyan, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="White"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind White, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal">
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Bright Black"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind BrightBlack, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Bright Red"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind BrightRed, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Bright Green"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind BrightGreen, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Bright Yellow"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind BrightYellow, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Bright Blue"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind BrightBlue, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Bright Magenta"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind BrightMagenta, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Bright Cyan"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind BrightCyan, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Bright White"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind BrightWhite, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal">
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Foreground"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind Foreground, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Background"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind Background, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Cursor"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind Cursor, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Cursor Accent"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
SelectedColor="{x:Bind CursorAccent, Mode=TwoWay}" />
|
||||
<views:TerminalColorPicker
|
||||
ColorName="Selection"
|
||||
EnableEditing="{x:Bind InEditMode, Mode=OneWay}"
|
||||
IsAlphaEnabled="True"
|
||||
SelectedColor="{x:Bind Selection, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Margin="0,6,0,0"
|
||||
Foreground="White"
|
||||
Text="Click on a color to edit"
|
||||
Visibility="{x:Bind InEditMode, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}" />
|
||||
</Grid>
|
||||
<Slider
|
||||
Margin="0,24,0,0"
|
||||
Header="Background Opacity"
|
||||
Maximum="1"
|
||||
Minimum="0"
|
||||
RequestedTheme="Dark"
|
||||
StepFrequency="0.01"
|
||||
Visibility="{x:Bind InEditMode, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}"
|
||||
Value="{x:Bind BackgroundOpacity, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ContentControl.ContentTemplate>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,31 @@
|
||||
using FluentTerminal.App.ViewModels.Settings;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace FluentTerminal.App.Views.SettingsPages
|
||||
{
|
||||
public sealed partial class ThemeSettings : Page
|
||||
{
|
||||
public ThemesPageViewModel ViewModel { get; private set; }
|
||||
|
||||
public ThemeSettings()
|
||||
{
|
||||
InitializeComponent();
|
||||
Root.DataContext = this;
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is ThemesPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
}
|
||||
TitleBar.RestoreColors();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||
{
|
||||
TitleBar.ResetTitleBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<UserControl
|
||||
x:Class="FluentTerminal.App.Views.TerminalColorPicker"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="24"
|
||||
d:DesignWidth="24"
|
||||
mc:Ignorable="d">
|
||||
<Button
|
||||
x:Name="Root"
|
||||
IsEnabled="{x:Bind EnableEditing, Mode=OneWay}"
|
||||
Style="{StaticResource ColorPreviewButtonStyle}"
|
||||
ToolTipService.ToolTip="{x:Bind ColorName}">
|
||||
<Button.Background>
|
||||
<SolidColorBrush Color="{x:Bind SelectedColor, Mode=OneWay}" />
|
||||
</Button.Background>
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,0,6"
|
||||
Style="{StaticResource TitleTextBlockStyle}"
|
||||
Text="{x:Bind ColorName}" />
|
||||
<ColorPicker
|
||||
x:Name="colorPicker"
|
||||
ColorChanged="ColorPicker_ColorChanged"
|
||||
IsAlphaEnabled="{x:Bind IsAlphaEnabled, Mode=OneWay}"
|
||||
IsColorChannelTextInputVisible="False" />
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,62 @@
|
||||
using Windows.UI;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
{
|
||||
public sealed partial class TerminalColorPicker : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty ColorNameProperty =
|
||||
DependencyProperty.Register(nameof(ColorName), typeof(string), typeof(TerminalColorPicker), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty EnableEditingProperty =
|
||||
DependencyProperty.Register(nameof(EnableEditing), typeof(bool), typeof(TerminalColorPicker), new PropertyMetadata(false));
|
||||
|
||||
public static readonly DependencyProperty IsAlphaEnabledProperty =
|
||||
DependencyProperty.Register(nameof(IsAlphaEnabled), typeof(bool), typeof(TerminalColorPicker), new PropertyMetadata(false));
|
||||
|
||||
public static readonly DependencyProperty SelectedColorProperty =
|
||||
DependencyProperty.Register(nameof(SelectedColor), typeof(Color), typeof(TerminalColorPicker), new PropertyMetadata(Colors.Transparent, (s, e) =>
|
||||
{
|
||||
if (s is TerminalColorPicker terminalColorPicker)
|
||||
{
|
||||
terminalColorPicker.colorPicker.Color = (Color)e.NewValue;
|
||||
}
|
||||
}));
|
||||
|
||||
public TerminalColorPicker()
|
||||
{
|
||||
InitializeComponent();
|
||||
Root.DataContext = this;
|
||||
}
|
||||
|
||||
public string ColorName
|
||||
{
|
||||
get { return (string)GetValue(ColorNameProperty); }
|
||||
set { SetValue(ColorNameProperty, value); }
|
||||
}
|
||||
|
||||
public bool EnableEditing
|
||||
{
|
||||
get { return (bool)GetValue(EnableEditingProperty); }
|
||||
set { SetValue(EnableEditingProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsAlphaEnabled
|
||||
{
|
||||
get { return (bool)GetValue(IsAlphaEnabledProperty); }
|
||||
set { SetValue(IsAlphaEnabledProperty, value); }
|
||||
}
|
||||
|
||||
public Color SelectedColor
|
||||
{
|
||||
get { return (Color)GetValue(SelectedColorProperty); }
|
||||
set { SetValue(SelectedColorProperty, value); }
|
||||
}
|
||||
|
||||
private void ColorPicker_ColorChanged(ColorPicker sender, ColorChangedEventArgs args)
|
||||
{
|
||||
SelectedColor = args.NewColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,11 @@
|
||||
x:Class="FluentTerminal.App.Views.TerminalView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="using:FluentTerminal.App.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:FluentTerminal.App.Views"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="400"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<converters:TrueToVisibleConverter x:Key="TrueToVisibleConverter" />
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid x:Name="WebViewContainer" Margin="12" />
|
||||
<Grid
|
||||
@@ -19,8 +14,10 @@
|
||||
Padding="6"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="{ThemeResource SystemControlAccentAcrylicWindowAccentMediumHighBrush}"
|
||||
Visibility="{x:Bind ViewModel.ShowResizeOverlay, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}">
|
||||
<Grid.Background>
|
||||
<SolidColorBrush Color="{ThemeResource SystemAccentColor}" />
|
||||
</Grid.Background>
|
||||
<TextBlock Foreground="White" Text="{x:Bind ViewModel.ResizeOverlayContent, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using FluentTerminal.RuntimeComponent.Interfaces;
|
||||
using FluentTerminal.RuntimeComponent.WebAllowedObjects;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.Foundation;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.Core.Preview;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
@@ -19,43 +25,77 @@ namespace FluentTerminal.App.Views
|
||||
{
|
||||
public sealed partial class TerminalView : UserControl, ITerminalView, ITerminalEventListener
|
||||
{
|
||||
private WebView _webView;
|
||||
|
||||
private SemaphoreSlim _loaded;
|
||||
|
||||
private MenuFlyoutItem _copyMenuItem;
|
||||
private BlockingCollection<Action> _dispatcherJobs;
|
||||
|
||||
public event EventHandler<TerminalSize> TerminalSizeChanged;
|
||||
public event EventHandler<string> TerminalTitleChanged;
|
||||
|
||||
public TerminalViewModel ViewModel { get; }
|
||||
private SemaphoreSlim _loaded;
|
||||
private MenuFlyoutItem _pasteMenuItem;
|
||||
private WebView _webView;
|
||||
|
||||
public TerminalView(TerminalViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
InitializeComponent();
|
||||
Loaded += OnLoaded;
|
||||
SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += OnCloseRequested; //todo move to mainpage
|
||||
_loaded = new SemaphoreSlim(0, 1);
|
||||
|
||||
JsonConvert.DefaultSettings = () =>
|
||||
{
|
||||
var settings = new JsonSerializerSettings
|
||||
{
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver(),
|
||||
};
|
||||
settings.Converters.Add(new StringEnumConverter(true));
|
||||
|
||||
return settings;
|
||||
};
|
||||
|
||||
StartMediatorTask();
|
||||
}
|
||||
|
||||
public async Task FocusWebView()
|
||||
public event EventHandler<Command> KeyboardCommandReceived;
|
||||
public event EventHandler<TerminalSize> TerminalSizeChanged;
|
||||
public event EventHandler<string> TerminalTitleChanged;
|
||||
|
||||
public TerminalViewModel ViewModel { get; }
|
||||
|
||||
public Task ChangeOptions(TerminalOptions options)
|
||||
{
|
||||
if (_webView != null)
|
||||
{
|
||||
_webView.Focus(FocusState.Programmatic);
|
||||
await ExecuteScriptAsync("document.focus();");
|
||||
}
|
||||
var serialized = JsonConvert.SerializeObject(options);
|
||||
return ExecuteScriptAsync($"changeOptions('{serialized}')");
|
||||
}
|
||||
|
||||
private void OnCloseRequested(object sender, SystemNavigationCloseRequestedPreviewEventArgs e)
|
||||
public Task ChangeTheme(TerminalColors theme)
|
||||
{
|
||||
_webView.Navigate(new Uri("about:blank"));
|
||||
var serialized = JsonConvert.SerializeObject(theme);
|
||||
return ExecuteScriptAsync($"changeTheme('{serialized}')");
|
||||
}
|
||||
|
||||
public Task ChangeKeyBindings(IEnumerable<KeyBinding> keyBindings)
|
||||
{
|
||||
var serialized = JsonConvert.SerializeObject(keyBindings);
|
||||
return ExecuteScriptAsync($"changeKeyBindings('{serialized}')");
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_webView?.Navigate(new Uri("about:blank"));
|
||||
_webView = null;
|
||||
}
|
||||
|
||||
public Task ConnectToSocket(string url)
|
||||
{
|
||||
return ExecuteScriptAsync($"connectToWebSocket('{url}');");
|
||||
}
|
||||
|
||||
public async Task<TerminalSize> CreateTerminal(TerminalOptions options, TerminalColors theme, IEnumerable<KeyBinding> keyBindings)
|
||||
{
|
||||
var serializedOptions = JsonConvert.SerializeObject(options);
|
||||
var serializedTheme = JsonConvert.SerializeObject(theme);
|
||||
var serializedKeyBindings = JsonConvert.SerializeObject(keyBindings);
|
||||
var size = await ExecuteScriptAsync($"createTerminal('{serializedOptions}', '{serializedTheme}', '{serializedKeyBindings}')");
|
||||
return JsonConvert.DeserializeObject<TerminalSize>(size);
|
||||
}
|
||||
|
||||
public Task<string> ExecuteScriptAsync(string script)
|
||||
{
|
||||
try
|
||||
@@ -69,6 +109,117 @@ namespace FluentTerminal.App.Views
|
||||
return Task.FromResult(string.Empty);
|
||||
}
|
||||
|
||||
public async Task FocusTerminal()
|
||||
{
|
||||
if (_webView != null)
|
||||
{
|
||||
_webView.Focus(FocusState.Programmatic);
|
||||
await ExecuteScriptAsync("document.focus();");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task FocusWebView()
|
||||
{
|
||||
if (_webView != null)
|
||||
{
|
||||
_webView.Focus(FocusState.Programmatic);
|
||||
await ExecuteScriptAsync("document.focus();");
|
||||
}
|
||||
}
|
||||
|
||||
public Task<string> GetSelection()
|
||||
{
|
||||
return ExecuteScriptAsync("term.getSelection()");
|
||||
}
|
||||
|
||||
public void OnKeyboardCommand(string command)
|
||||
{
|
||||
_dispatcherJobs.Add(() => KeyboardCommandReceived?.Invoke(this, Enum.Parse<Command>(command, true)));
|
||||
}
|
||||
|
||||
public void OnTerminalResized(int columns, int rows)
|
||||
{
|
||||
_dispatcherJobs.Add(() => TerminalSizeChanged?.Invoke(this, new TerminalSize { Columns = columns, Rows = rows }));
|
||||
}
|
||||
|
||||
public void OnTitleChanged(string title)
|
||||
{
|
||||
_dispatcherJobs.Add(() => TerminalTitleChanged?.Invoke(this, title));
|
||||
}
|
||||
|
||||
public Task Write(string text)
|
||||
{
|
||||
text = Convert.ToBase64String(Encoding.UTF8.GetBytes(text));
|
||||
return ExecuteScriptAsync($"paste('{text}')");
|
||||
}
|
||||
|
||||
private void _webView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
|
||||
{
|
||||
_loaded.Release();
|
||||
}
|
||||
|
||||
private void _webView_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
|
||||
{
|
||||
var bridge = new TerminalBridge(this);
|
||||
_webView.AddWebAllowedObject("terminalBridge", bridge);
|
||||
}
|
||||
|
||||
private void Copy_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
OnKeyboardCommand(Command.Copy.ToString());
|
||||
}
|
||||
|
||||
private async void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (WebViewContainer.Children.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_webView = new WebView(WebViewExecutionMode.SeparateThread)
|
||||
{
|
||||
DefaultBackgroundColor = Colors.Transparent
|
||||
};
|
||||
WebViewContainer.Children.Add(_webView);
|
||||
|
||||
_webView.NavigationCompleted += _webView_NavigationCompleted;
|
||||
_webView.NavigationStarting += _webView_NavigationStarting;
|
||||
|
||||
_copyMenuItem = new MenuFlyoutItem { Text = "Copy" };
|
||||
_copyMenuItem.Click += Copy_Click;
|
||||
|
||||
_pasteMenuItem = new MenuFlyoutItem { Text = "Paste" };
|
||||
_pasteMenuItem.Click += Paste_Click;
|
||||
|
||||
_webView.ContextFlyout = new MenuFlyout
|
||||
{
|
||||
Items = { _copyMenuItem, _pasteMenuItem }
|
||||
};
|
||||
|
||||
_webView.Navigate(new Uri("ms-appx-web:///Client/index.html"));
|
||||
|
||||
await _loaded.WaitAsync();
|
||||
|
||||
_webView.Focus(FocusState.Programmatic);
|
||||
|
||||
await ViewModel.OnViewIsReady(this);
|
||||
}
|
||||
|
||||
public void OnRightClick(int x, int y, bool hasSelection)
|
||||
{
|
||||
_dispatcherJobs.Add(() =>
|
||||
{
|
||||
var flyout = (MenuFlyout)_webView.ContextFlyout;
|
||||
_copyMenuItem.IsEnabled = hasSelection;
|
||||
flyout.ShowAt(_webView, new Point(x, y));
|
||||
});
|
||||
}
|
||||
|
||||
private void Paste_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
OnKeyboardCommand(Command.Paste.ToString());
|
||||
}
|
||||
|
||||
private void StartMediatorTask()
|
||||
{
|
||||
_dispatcherJobs = new BlockingCollection<Action>();
|
||||
@@ -88,56 +239,5 @@ namespace FluentTerminal.App.Views
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_webView = new WebView(WebViewExecutionMode.SeparateThread)
|
||||
{
|
||||
DefaultBackgroundColor = Colors.Transparent
|
||||
};
|
||||
WebViewContainer.Children.Add(_webView);
|
||||
|
||||
_webView.NavigationCompleted += _webView_NavigationCompleted;
|
||||
_webView.NavigationStarting += _webView_NavigationStarting;
|
||||
_webView.Navigate(new Uri("http://localhost:9000/Client/index.html"));
|
||||
|
||||
await _loaded.WaitAsync();
|
||||
|
||||
_webView.Focus(FocusState.Programmatic);
|
||||
|
||||
await ViewModel.OnViewIsReady(this);
|
||||
}
|
||||
|
||||
private void _webView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
|
||||
{
|
||||
_loaded.Release();
|
||||
}
|
||||
|
||||
private void _webView_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
|
||||
{
|
||||
var bridge = new TerminalBridge(this);
|
||||
_webView.AddWebAllowedObject("terminalBridge", bridge);
|
||||
}
|
||||
|
||||
public async Task<TerminalSize> CreateTerminal()
|
||||
{
|
||||
var size = await ExecuteScriptAsync($"createTerminal()");
|
||||
return JsonConvert.DeserializeObject<TerminalSize>(size);
|
||||
}
|
||||
|
||||
public Task ConnectToSocket(string url)
|
||||
{
|
||||
return ExecuteScriptAsync($"connectToWebSocket('{url}');");
|
||||
}
|
||||
|
||||
public void OnTerminalResized(int columns, int rows)
|
||||
{
|
||||
_dispatcherJobs.Add(() => TerminalSizeChanged?.Invoke(this, new TerminalSize { Columns = columns, Rows = rows }));
|
||||
}
|
||||
|
||||
public void OnTitleChanged(string title)
|
||||
{
|
||||
_dispatcherJobs.Add(() => TerminalTitleChanged?.Invoke(this, title));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
node_modules/
|
||||
dist/
|
||||
Vendored
-6630
File diff suppressed because it is too large.
Load diff
-12
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="xterm.css" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="terminal-container"></div>
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Vendored
-24
@@ -1,24 +0,0 @@
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
-ms-overflow-style: none;
|
||||
background: transparent;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
background: transparent;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#terminal-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.terminal {
|
||||
background: transparent !important;
|
||||
}
|
||||
Vendored
-125
@@ -1,125 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
||||
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
||||
* https://github.com/chjj/term.js
|
||||
* @license MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Originally forked from (with the author's permission):
|
||||
* Fabrice Bellard's javascript vt100 for jslinux:
|
||||
* http://bellard.org/jslinux/
|
||||
* Copyright (c) 2011 Fabrice Bellard
|
||||
* The original design remains. The terminal itself
|
||||
* has been extended to include xterm CSI codes, among
|
||||
* other features.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default styles for xterm.js
|
||||
*/
|
||||
|
||||
.xterm {
|
||||
font-family: courier-new, courier, monospace;
|
||||
font-feature-settings: "liga" 0;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.xterm.focus,
|
||||
.xterm:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.xterm .xterm-helpers {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
/**
|
||||
* The z-index of the helpers must be higher than the canvases in order for
|
||||
* IMEs to appear on top.
|
||||
*/
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.xterm .xterm-helper-textarea {
|
||||
/*
|
||||
* HACK: to fix IE's blinking cursor
|
||||
* Move textarea out of the screen to the far left, so that the cursor is not visible.
|
||||
*/
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
left: -9999em;
|
||||
top: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
z-index: -10;
|
||||
/** Prevent wrapping so the IME appears against the textarea at the correct position */
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.xterm .composition-view {
|
||||
/* TODO: Composition position got messed up somewhere */
|
||||
background: #000;
|
||||
color: #FFF;
|
||||
display: none;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.xterm .composition-view.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.xterm .xterm-viewport {
|
||||
/* On OS X this is required in order for the scroll bar to appear fully opaque */
|
||||
background-color: #000;
|
||||
overflow-y: scroll;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.xterm canvas {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.xterm .xterm-scroll-area {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.xterm .xterm-char-measure-element {
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
left: -9999em;
|
||||
}
|
||||
|
||||
.xterm.enable-mouse-events {
|
||||
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.xterm:not(.enable-mouse-events) {
|
||||
cursor: text;
|
||||
}
|
||||
Generated
+5
-6
@@ -2472,12 +2472,6 @@
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"raw-loader": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
|
||||
"integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=",
|
||||
"dev": true
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
||||
@@ -3018,6 +3012,11 @@
|
||||
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
|
||||
"dev": true
|
||||
},
|
||||
"xterm": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/xterm/-/xterm-3.1.0.tgz",
|
||||
"integrity": "sha512-xv4QQQAu8PjAPZE7m0h+i9X9z3vR82wPe0H3g4D9CbyDuQDNt1e+lxeTrkLwuMH3jcxqfHayu3Mu+iyQh62ECg=="
|
||||
},
|
||||
"y18n": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "xcopy /y /s ..\\xterm.js\\build\\xterm.css dist\\ && npx webpack --config webpack.config.js"
|
||||
"build": "xcopy /y /s node_modules\\xterm\\dist\\xterm.css dist\\ && xcopy /y /s src\\style.css dist\\ && xcopy /y /s src\\index.html dist\\ && npx webpack --config webpack.config.js"
|
||||
},
|
||||
"author": "FS Apps",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"webpack": "^3.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"xterm": "^3.1.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="xterm.css" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="terminal-container"></div>
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,7 +1,8 @@
|
||||
import * as Terminal from '../../xterm.js/build/xterm';
|
||||
import * as attach from '../../xterm.js/build/addons/attach/attach';
|
||||
import * as fit from '../../xterm.js/build/addons/fit/fit';
|
||||
import * as winptyCompat from '../../xterm.js/build/addons/winptyCompat/winptyCompat';
|
||||
import * as Terminal from '../node_modules/xterm/dist/xterm';
|
||||
import * as attach from '../node_modules/xterm/dist/addons/attach/attach';
|
||||
import * as fit from '../node_modules/xterm/dist/addons/fit/fit';
|
||||
import * as winptyCompat from '../node_modules/xterm/dist/addons/winptyCompat/winptyCompat';
|
||||
|
||||
|
||||
Terminal.applyAddon(attach);
|
||||
Terminal.applyAddon(fit);
|
||||
@@ -10,20 +11,29 @@ Terminal.applyAddon(winptyCompat);
|
||||
var term, socket;
|
||||
var terminalContainer = document.getElementById('terminal-container');
|
||||
|
||||
function start() {
|
||||
function createTerminal(options, theme, keyBindings) {
|
||||
while (terminalContainer.children.length) {
|
||||
terminalContainer.removeChild(terminalContainer.children[0]);
|
||||
}
|
||||
|
||||
term = new Terminal({
|
||||
cursorBlink: true,
|
||||
fontFamily: 'consolas',
|
||||
fontSize: 13,
|
||||
theme = JSON.parse(theme);
|
||||
theme.background = 'transparent';
|
||||
|
||||
window.keyBindings = JSON.parse(keyBindings);
|
||||
|
||||
options = JSON.parse(options);
|
||||
|
||||
var terminalOptions = {
|
||||
fontFamily: options.fontFamily,
|
||||
fontSize: options.fontSize,
|
||||
cursorStyle: options.cursorStyle,
|
||||
cursorBlink: options.cursorBlink,
|
||||
bellStyle: options.bellStyle,
|
||||
allowTransparency: true,
|
||||
theme: {
|
||||
background: "transparent"
|
||||
}
|
||||
});
|
||||
theme: theme
|
||||
};
|
||||
|
||||
term = new Terminal(terminalOptions);
|
||||
|
||||
window.term = term;
|
||||
|
||||
@@ -46,25 +56,85 @@ function start() {
|
||||
resizeTimeout = setTimeout(term.fit(), 500);
|
||||
}
|
||||
|
||||
window.onmouseup = function (e) {
|
||||
if (e.button == 2) {
|
||||
terminalBridge.notifyRightClick(e.clientX, e.clientY, term.hasSelection());
|
||||
}
|
||||
}
|
||||
|
||||
term.attachCustomKeyEventHandler(function (e) {
|
||||
for (var i = 0; i < window.keyBindings.length; i++) {
|
||||
var keyBinding = window.keyBindings[i];
|
||||
if (keyBinding.ctrl == e.ctrlKey
|
||||
&& keyBinding.alt == e.altKey
|
||||
&& keyBinding.shift == e.shiftKey
|
||||
&& keyBinding.key == e.keyCode) {
|
||||
if (document.visibilityState == 'visible') {
|
||||
e.preventDefault();
|
||||
terminalBridge.invokeCommand(keyBinding.command);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return JSON.stringify({
|
||||
rows: term.rows,
|
||||
columns: term.cols
|
||||
});
|
||||
}
|
||||
|
||||
function runRealTerminal() {
|
||||
function attachTerminal() {
|
||||
term.attach(socket);
|
||||
term._initialized = true;
|
||||
}
|
||||
|
||||
function createTerminal(configuration) {
|
||||
return start();
|
||||
}
|
||||
|
||||
function connectToWebSocket(url) {
|
||||
socket = new WebSocket(url);
|
||||
socket.onopen = runRealTerminal;
|
||||
socket.onopen = attachTerminal;
|
||||
}
|
||||
|
||||
function changeTheme(theme) {
|
||||
theme = JSON.parse(theme);
|
||||
theme.background = 'transparent';
|
||||
|
||||
term.setOption('theme', theme);
|
||||
}
|
||||
|
||||
function changeOptions(options) {
|
||||
options = JSON.parse(options);
|
||||
|
||||
term.setOption('bellStyle', options.bellStyle);
|
||||
term.setOption('cursorBlink', options.cursorBlink);
|
||||
term.setOption('cursorStyle', options.cursorStyle);
|
||||
term.setOption('fontFamily', options.fontFamily);
|
||||
term.setOption('fontSize', options.fontSize);
|
||||
}
|
||||
|
||||
function changeKeyBindings(keyBindings) {
|
||||
keyBindings = JSON.parse(keyBindings);
|
||||
window.keyBindings = keyBindings;
|
||||
}
|
||||
|
||||
function paste(content) {
|
||||
content = b64DecodeUnicode(content);
|
||||
term.send(content);
|
||||
}
|
||||
|
||||
function b64DecodeUnicode(str) {
|
||||
return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
|
||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
|
||||
}).join(''))
|
||||
}
|
||||
|
||||
document.oncontextmenu = function () {
|
||||
return false;
|
||||
};
|
||||
|
||||
window.createTerminal = createTerminal;
|
||||
window.connectToWebSocket = connectToWebSocket;
|
||||
window.changeTheme = changeTheme;
|
||||
window.changeOptions = changeOptions;
|
||||
window.changeKeyBindings = changeKeyBindings;
|
||||
window.paste = paste;
|
||||
@@ -21,4 +21,4 @@ body {
|
||||
|
||||
.terminal {
|
||||
background: transparent !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using FluentTerminal.Models.Enums;
|
||||
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class ApplicationSettings
|
||||
{
|
||||
public bool ConfirmClosingTabs { get; set; }
|
||||
public bool ConfirmClosingWindows { get; set; }
|
||||
public NewTerminalLocation NewTerminalLocation { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -6,5 +6,6 @@
|
||||
public bool Success { get; set; }
|
||||
public string WebSocketUrl { get; set; }
|
||||
public string Error { get; set; }
|
||||
public string ShellExecutableName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace FluentTerminal.Models.Enums
|
||||
{
|
||||
public enum BellStyle
|
||||
{
|
||||
None,
|
||||
Sound
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace FluentTerminal.Models.Enums
|
||||
{
|
||||
public enum Command
|
||||
{
|
||||
ToggleWindow,
|
||||
NextTab,
|
||||
PreviousTab,
|
||||
NewTab,
|
||||
CloseTab,
|
||||
NewWindow,
|
||||
ShowSettings,
|
||||
Copy,
|
||||
Paste
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace FluentTerminal.Models.Enums
|
||||
{
|
||||
public enum CursorStyle
|
||||
{
|
||||
Block,
|
||||
Underline,
|
||||
Bar
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
namespace FluentTerminal.Models.Enums
|
||||
{
|
||||
public enum ExtendedVirtualKey
|
||||
{
|
||||
None = 0,
|
||||
LeftButton = 1,
|
||||
RightButton = 2,
|
||||
Cancel = 3,
|
||||
MiddleButton = 4,
|
||||
XButton1 = 5,
|
||||
XButton2 = 6,
|
||||
Back = 8,
|
||||
Tab = 9,
|
||||
Clear = 12,
|
||||
Enter = 13,
|
||||
Shift = 16,
|
||||
Control = 17,
|
||||
Menu = 18,
|
||||
Pause = 19,
|
||||
CapitalLock = 20,
|
||||
Kana = 21,
|
||||
Hangul = 21,
|
||||
Junja = 23,
|
||||
Final = 24,
|
||||
Hanja = 25,
|
||||
Kanji = 25,
|
||||
Escape = 27,
|
||||
Convert = 28,
|
||||
NonConvert = 29,
|
||||
Accept = 30,
|
||||
ModeChange = 31,
|
||||
Space = 32,
|
||||
PageUp = 33,
|
||||
PageDown = 34,
|
||||
End = 35,
|
||||
Home = 36,
|
||||
Left = 37,
|
||||
Up = 38,
|
||||
Right = 39,
|
||||
Down = 40,
|
||||
Select = 41,
|
||||
Print = 42,
|
||||
Execute = 43,
|
||||
Snapshot = 44,
|
||||
Insert = 45,
|
||||
Delete = 46,
|
||||
Help = 47,
|
||||
Number0 = 48,
|
||||
Number1 = 49,
|
||||
Number2 = 50,
|
||||
Number3 = 51,
|
||||
Number4 = 52,
|
||||
Number5 = 53,
|
||||
Number6 = 54,
|
||||
Number7 = 55,
|
||||
Number8 = 56,
|
||||
Number9 = 57,
|
||||
A = 65,
|
||||
B = 66,
|
||||
C = 67,
|
||||
D = 68,
|
||||
E = 69,
|
||||
F = 70,
|
||||
G = 71,
|
||||
H = 72,
|
||||
I = 73,
|
||||
J = 74,
|
||||
K = 75,
|
||||
L = 76,
|
||||
M = 77,
|
||||
N = 78,
|
||||
O = 79,
|
||||
P = 80,
|
||||
Q = 81,
|
||||
R = 82,
|
||||
S = 83,
|
||||
T = 84,
|
||||
U = 85,
|
||||
V = 86,
|
||||
W = 87,
|
||||
X = 88,
|
||||
Y = 89,
|
||||
Z = 90,
|
||||
LeftWindows = 91,
|
||||
RightWindows = 92,
|
||||
Application = 93,
|
||||
Sleep = 95,
|
||||
NumberPad0 = 96,
|
||||
NumberPad1 = 97,
|
||||
NumberPad2 = 98,
|
||||
NumberPad3 = 99,
|
||||
NumberPad4 = 100,
|
||||
NumberPad5 = 101,
|
||||
NumberPad6 = 102,
|
||||
NumberPad7 = 103,
|
||||
NumberPad8 = 104,
|
||||
NumberPad9 = 105,
|
||||
Multiply = 106,
|
||||
Add = 107,
|
||||
Separator = 108,
|
||||
Subtract = 109,
|
||||
Decimal = 110,
|
||||
Divide = 111,
|
||||
F1 = 112,
|
||||
F2 = 113,
|
||||
F3 = 114,
|
||||
F4 = 115,
|
||||
F5 = 116,
|
||||
F6 = 117,
|
||||
F7 = 118,
|
||||
F8 = 119,
|
||||
F9 = 120,
|
||||
F10 = 121,
|
||||
F11 = 122,
|
||||
F12 = 123,
|
||||
F13 = 124,
|
||||
F14 = 125,
|
||||
F15 = 126,
|
||||
F16 = 127,
|
||||
F17 = 128,
|
||||
F18 = 129,
|
||||
F19 = 130,
|
||||
F20 = 131,
|
||||
F21 = 132,
|
||||
F22 = 133,
|
||||
F23 = 134,
|
||||
F24 = 135,
|
||||
NavigationView = 136,
|
||||
NavigationMenu = 137,
|
||||
NavigationUp = 138,
|
||||
NavigationDown = 139,
|
||||
NavigationLeft = 140,
|
||||
NavigationRight = 141,
|
||||
NavigationAccept = 142,
|
||||
NavigationCancel = 143,
|
||||
NumberKeyLock = 144,
|
||||
Scroll = 145,
|
||||
LeftShift = 160,
|
||||
RightShift = 161,
|
||||
LeftControl = 162,
|
||||
RightControl = 163,
|
||||
LeftMenu = 164,
|
||||
RightMenu = 165,
|
||||
GoBack = 166,
|
||||
GoForward = 167,
|
||||
Refresh = 168,
|
||||
Stop = 169,
|
||||
Search = 170,
|
||||
Favorites = 171,
|
||||
GoHome = 172,
|
||||
VolumeMute = 173,
|
||||
VolumeDown = 174,
|
||||
VolumeUp = 175,
|
||||
MediaNext = 176,
|
||||
MediaPrevious = 177,
|
||||
MediaStop = 178,
|
||||
MediaPlayPause = 179,
|
||||
Plus = 187,
|
||||
Comma = 188,
|
||||
Minus = 189,
|
||||
Period = 190,
|
||||
GamepadA = 195,
|
||||
GamepadB = 196,
|
||||
GamepadX = 197,
|
||||
GamepadY = 198,
|
||||
GamepadRightShoulder = 199,
|
||||
GamepadLeftShoulder = 200,
|
||||
GamepadLeftTrigger = 201,
|
||||
GamepadRightTrigger = 202,
|
||||
GamepadDPadUp = 203,
|
||||
GamepadDPadDown = 204,
|
||||
GamepadDPadLeft = 205,
|
||||
GamepadDPadRight = 206,
|
||||
GamepadMenu = 207,
|
||||
GamepadView = 208,
|
||||
GamepadLeftThumbstickButton = 209,
|
||||
GamepadRightThumbstickButton = 210,
|
||||
GamepadLeftThumbstickUp = 211,
|
||||
GamepadLeftThumbstickDown = 212,
|
||||
GamepadLeftThumbstickRight = 213,
|
||||
GamepadLeftThumbstickLeft = 214,
|
||||
GamepadRightThumbstickUp = 215,
|
||||
GamepadRightThumbstickDown = 216,
|
||||
GamepadRightThumbstickRight = 217,
|
||||
GamepadRightThumbstickLeft = 218
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace FluentTerminal.Models.Enums
|
||||
{
|
||||
public enum NewTerminalLocation
|
||||
{
|
||||
Tab,
|
||||
Window
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,11 @@
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Windows">
|
||||
<HintPath>..\..\..\..\..\..\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.16299.0\Windows.winmd</HintPath>
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,14 @@
|
||||
using FluentTerminal.Models.Enums;
|
||||
using Windows.System;
|
||||
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class KeyBinding
|
||||
{
|
||||
public Command Command { get; set; }
|
||||
public int Key { get; set; }
|
||||
public bool Ctrl { get; set; }
|
||||
public bool Alt { get; set; }
|
||||
public bool Shift { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class KeyBindings
|
||||
{
|
||||
public ICollection<KeyBinding> ToggleWindow { get; set; }
|
||||
public ICollection<KeyBinding> NextTab { get; set; }
|
||||
public ICollection<KeyBinding> PreviousTab { get; set; }
|
||||
public ICollection<KeyBinding> NewTab { get; set; }
|
||||
public ICollection<KeyBinding> CloseTab { get; set; }
|
||||
public ICollection<KeyBinding> NewWindow { get; set; }
|
||||
public ICollection<KeyBinding> ShowSettings { get; set; }
|
||||
public ICollection<KeyBinding> Copy { get; set; }
|
||||
public ICollection<KeyBinding> Paste { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class TerminalColors
|
||||
{
|
||||
public string Foreground { get; set; }
|
||||
public string Background { get; set; }
|
||||
public string Cursor { get; set; }
|
||||
public string CursorAccent { get; set; }
|
||||
public string Selection { get; set; }
|
||||
|
||||
public string Black { get; set; }
|
||||
public string Red { get; set; }
|
||||
public string Green { get; set; }
|
||||
public string Yellow { get; set; }
|
||||
public string Blue { get; set; }
|
||||
public string Magenta { get; set; }
|
||||
public string Cyan { get; set; }
|
||||
public string White { get; set; }
|
||||
|
||||
public string BrightBlack { get; set; }
|
||||
public string BrightRed { get; set; }
|
||||
public string BrightGreen { get; set; }
|
||||
public string BrightYellow { get; set; }
|
||||
public string BrightBlue { get; set; }
|
||||
public string BrightMagenta { get; set; }
|
||||
public string BrightCyan { get; set; }
|
||||
public string BrightWhite { get; set; }
|
||||
|
||||
public TerminalColors()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TerminalColors(TerminalColors other)
|
||||
{
|
||||
Foreground = other.Foreground;
|
||||
Background = other.Background;
|
||||
Cursor = other.Cursor;
|
||||
CursorAccent = other.CursorAccent;
|
||||
Selection = other.Selection;
|
||||
|
||||
Black = other.Black;
|
||||
Red = other.Red;
|
||||
Green = other.Green;
|
||||
Yellow = other.Yellow;
|
||||
Blue = other.Blue;
|
||||
Magenta = other.Magenta;
|
||||
Cyan = other.Cyan;
|
||||
White = other.White;
|
||||
|
||||
BrightBlack = other.BrightBlack;
|
||||
BrightRed = other.BrightRed;
|
||||
BrightGreen = other.BrightGreen;
|
||||
BrightYellow = other.BrightYellow;
|
||||
BrightBlue = other.BrightBlue;
|
||||
BrightMagenta = other.BrightMagenta;
|
||||
BrightCyan = other.BrightCyan;
|
||||
BrightWhite = other.BrightWhite;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using FluentTerminal.Models.Enums;
|
||||
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class TerminalOptions
|
||||
{
|
||||
public string FontFamily { get; set; }
|
||||
|
||||
public int FontSize { get; set; }
|
||||
|
||||
public CursorStyle CursorStyle { get; set; }
|
||||
|
||||
public bool CursorBlink { get; set; }
|
||||
|
||||
public BellStyle BellStyle { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class TerminalTheme
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Author { get; set; }
|
||||
public bool PreInstalled { get; set; }
|
||||
public double BackgroundOpacity { get; set; }
|
||||
public TerminalColors Colors { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.RuntimeComponent.Interfaces
|
||||
namespace FluentTerminal.RuntimeComponent.Interfaces
|
||||
{
|
||||
public interface ITerminalEventListener
|
||||
{
|
||||
void OnTerminalResized(int columns, int rows);
|
||||
|
||||
void OnTitleChanged(string title);
|
||||
|
||||
void OnKeyboardCommand(string command);
|
||||
|
||||
void OnRightClick(int x, int y, bool hasSelection);
|
||||
}
|
||||
}
|
||||
@@ -22,5 +22,15 @@ namespace FluentTerminal.RuntimeComponent.WebAllowedObjects
|
||||
{
|
||||
_terminalEventListener.OnTitleChanged(title);
|
||||
}
|
||||
|
||||
public void InvokeCommand(string command)
|
||||
{
|
||||
_terminalEventListener.OnKeyboardCommand(command);
|
||||
}
|
||||
|
||||
public void NotifyRightClick(int x, int y, bool hasSelection)
|
||||
{
|
||||
_terminalEventListener.OnRightClick(x, y, hasSelection);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large.
Load diff
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="xterm.css" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="terminal-container"></div>
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,125 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
||||
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
||||
* https://github.com/chjj/term.js
|
||||
* @license MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Originally forked from (with the author's permission):
|
||||
* Fabrice Bellard's javascript vt100 for jslinux:
|
||||
* http://bellard.org/jslinux/
|
||||
* Copyright (c) 2011 Fabrice Bellard
|
||||
* The original design remains. The terminal itself
|
||||
* has been extended to include xterm CSI codes, among
|
||||
* other features.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default styles for xterm.js
|
||||
*/
|
||||
|
||||
.xterm {
|
||||
font-family: courier-new, courier, monospace;
|
||||
font-feature-settings: "liga" 0;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.xterm.focus,
|
||||
.xterm:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.xterm .xterm-helpers {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
/**
|
||||
* The z-index of the helpers must be higher than the canvases in order for
|
||||
* IMEs to appear on top.
|
||||
*/
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.xterm .xterm-helper-textarea {
|
||||
/*
|
||||
* HACK: to fix IE's blinking cursor
|
||||
* Move textarea out of the screen to the far left, so that the cursor is not visible.
|
||||
*/
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
left: -9999em;
|
||||
top: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
z-index: -10;
|
||||
/** Prevent wrapping so the IME appears against the textarea at the correct position */
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.xterm .composition-view {
|
||||
/* TODO: Composition position got messed up somewhere */
|
||||
background: #000;
|
||||
color: #FFF;
|
||||
display: none;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.xterm .composition-view.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.xterm .xterm-viewport {
|
||||
/* On OS X this is required in order for the scroll bar to appear fully opaque */
|
||||
background-color: #000;
|
||||
overflow-y: scroll;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.xterm canvas {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.xterm .xterm-scroll-area {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.xterm .xterm-char-measure-element {
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
left: -9999em;
|
||||
}
|
||||
|
||||
.xterm.enable-mouse-events {
|
||||
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.xterm:not(.enable-mouse-events) {
|
||||
cursor: text;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.SystemTray.Services;
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Http;
|
||||
|
||||
namespace FluentTerminal.SystemTray.Controllers
|
||||
{
|
||||
public class KeyBindingsController : ApiController
|
||||
{
|
||||
private readonly ToggleWindowService _toggleWindowService;
|
||||
|
||||
public KeyBindingsController(ToggleWindowService toggleWindowService)
|
||||
{
|
||||
_toggleWindowService = toggleWindowService;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("keybindings/togglewindow")]
|
||||
public void PostToggleWindowKeyBindings([FromBody]IEnumerable<KeyBinding> keyBindings)
|
||||
{
|
||||
_toggleWindowService.SetHotKeys(keyBindings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,10 +112,13 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Controllers\KeyBindingsController.cs" />
|
||||
<Compile Include="Controllers\TerminalsController.cs" />
|
||||
<Compile Include="LoopbackEnabler.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\ToggleWindowService.cs" />
|
||||
<Compile Include="Services\NotificationService.cs" />
|
||||
<Compile Include="Services\TerminalSession.cs" />
|
||||
<Compile Include="Services\TerminalsManager.cs" />
|
||||
<Compile Include="Startup.cs" />
|
||||
@@ -152,11 +155,11 @@
|
||||
<PackageReference Include="Fleck">
|
||||
<Version>0.14.0.59</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost">
|
||||
<Version>5.2.3</Version>
|
||||
<PackageReference Include="GlobalHotKey">
|
||||
<Version>1.1.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Owin.StaticFiles">
|
||||
<Version>3.1.0</Version>
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost">
|
||||
<Version>5.2.4</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Unity.WebAPI">
|
||||
<Version>5.3.0</Version>
|
||||
@@ -172,18 +175,6 @@
|
||||
<Content Include="BinaryDependencies\x86\winpty-agent.exe" />
|
||||
<Content Include="BinaryDependencies\x86\winpty-debugserver.exe" />
|
||||
<Content Include="BinaryDependencies\x86\winpty.dll" />
|
||||
<Content Include="Client\bundle.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Client\index.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Client\style.css">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Client\xterm.css">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FluentTerminal.Models\FluentTerminal.Models.csproj">
|
||||
@@ -198,6 +189,7 @@ xcopy /y /s "$(ProjectDir)bin\$(PlatformName)\$(ConfigurationName)" "$(SolutionD
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>xcopy /y "$(SolutionDir)FluentTerminal.Client\dist" "$(ProjectDir)Client"</PreBuildEvent>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
Loaded 100 of 374 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user