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 | ||
|
|
9b61d11f6a | ||
|
|
49ee8489d6 | ||
|
|
7b485ce407 | ||
|
|
66465b525f | ||
|
|
9c5d8c27fd | ||
|
|
4ae3be544b | ||
|
|
e32e0398ee | ||
|
|
fab22f2479 | ||
|
|
b2151c69ab | ||
|
|
f5fba8517a |
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>
|
||||
@@ -1,6 +1,14 @@
|
||||
using FluentTerminal.App.Views;
|
||||
using Autofac;
|
||||
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;
|
||||
@@ -11,56 +19,135 @@ using Windows.UI.Core;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
using IContainer = Autofac.IContainer;
|
||||
|
||||
namespace FluentTerminal.App
|
||||
{
|
||||
sealed partial class App : Application
|
||||
{
|
||||
public App()
|
||||
{
|
||||
InitializeComponent();
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
public static BackgroundTaskDeferral AppServiceDeferral = null;
|
||||
public static AppServiceConnection Connection = null;
|
||||
public static App Instance;
|
||||
int? _settingsWindowId;
|
||||
int idCreate = 0;
|
||||
List<int> idSaved = new List<int>();
|
||||
private bool _alreadyLaunched;
|
||||
private IContainer _container;
|
||||
private int? _settingsWindowId;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private ApplicationSettings _applicationSettings;
|
||||
|
||||
protected override async void OnLaunched(LaunchActivatedEventArgs e)
|
||||
private List<MainViewModel> _mainViewModels;
|
||||
|
||||
public App()
|
||||
{
|
||||
var launch = FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync().AsTask();
|
||||
var clearCache = WebView.ClearTemporaryWebDataAsync().AsTask();
|
||||
_mainViewModels = new List<MainViewModel>();
|
||||
|
||||
await Task.WhenAll(launch, clearCache);
|
||||
InitializeComponent();
|
||||
Instance = this;
|
||||
|
||||
Frame rootFrame = Window.Current.Content as Frame;
|
||||
if (rootFrame == null)
|
||||
{
|
||||
rootFrame = new Frame();
|
||||
rootFrame.NavigationFailed += OnNavigationFailed;
|
||||
Window.Current.Content = rootFrame;
|
||||
}
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterType<SettingsService>().As<ISettingsService>().SingleInstance();
|
||||
builder.RegisterType<DefaultValueProvider>().As<IDefaultValueProvider>().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();
|
||||
|
||||
if (rootFrame.Content == null)
|
||||
_container = builder.Build();
|
||||
|
||||
_settingsService = _container.Resolve<ISettingsService>();
|
||||
_settingsService.ApplicationSettingsChanged += OnApplicationSettingsChanged;
|
||||
|
||||
_applicationSettings = _settingsService.GetApplicationSettings();
|
||||
}
|
||||
|
||||
private void OnApplicationSettingsChanged(object sender, EventArgs e)
|
||||
{
|
||||
_applicationSettings = _settingsService.GetApplicationSettings();
|
||||
}
|
||||
|
||||
public async Task CreateNewTerminalWindow(string startupDirectory)
|
||||
{
|
||||
var id = await CreateSecondaryView<MainViewModel>(typeof(MainPage), true, startupDirectory);
|
||||
await ApplicationViewSwitcher.TryShowAsStandaloneAsync(id);
|
||||
}
|
||||
|
||||
public void SettingsWindowClosed()
|
||||
{
|
||||
_settingsWindowId = null;
|
||||
}
|
||||
|
||||
public async Task ShowSettings()
|
||||
{
|
||||
if (_settingsWindowId == null)
|
||||
{
|
||||
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
|
||||
rootFrame.Navigate(typeof(MainPage), e.Arguments);
|
||||
idSaved.Add(ApplicationView.GetForCurrentView().Id);
|
||||
_settingsWindowId = await CreateSecondaryView<SettingsViewModel>(typeof(SettingsPage), true, null);
|
||||
}
|
||||
else if (false) //todo: add option to create new windows on launch
|
||||
await ApplicationViewSwitcher.TryShowAsStandaloneAsync(_settingsWindowId.Value);
|
||||
}
|
||||
|
||||
public void TerminalWindowClosed(MainViewModel viewModel)
|
||||
{
|
||||
_mainViewModels.Remove(viewModel);
|
||||
}
|
||||
|
||||
protected override async void OnActivated(IActivatedEventArgs args)
|
||||
{
|
||||
if (args is CommandLineActivatedEventArgs commandLineActivated)
|
||||
{
|
||||
await CreateNewWindow(typeof(MainPage), true);
|
||||
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 (command == "settings")
|
||||
{
|
||||
await ShowSettings();
|
||||
}
|
||||
else if (command == "new")
|
||||
{
|
||||
if (_applicationSettings.NewTerminalLocation == NewTerminalLocation.Tab && _mainViewModels.Any())
|
||||
{
|
||||
await _mainViewModels.Last().AddTerminal(parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
await CreateNewTerminalWindow(parameter);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (command == "settings")
|
||||
{
|
||||
var viewModel = _container.Resolve<SettingsViewModel>();
|
||||
await CreateMainView(typeof(SettingsPage), viewModel, true);
|
||||
}
|
||||
else if (command == "new")
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Window.Current.Activate();
|
||||
}
|
||||
|
||||
protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
|
||||
{
|
||||
// connection established from the fulltrust process
|
||||
base.OnBackgroundActivated(args);
|
||||
if (args.TaskInstance.TriggerDetails is AppServiceTriggerDetails details)
|
||||
{
|
||||
@@ -71,6 +158,75 @@ 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);
|
||||
|
||||
Frame rootFrame = Window.Current.Content as Frame;
|
||||
if (rootFrame == null)
|
||||
{
|
||||
rootFrame = new Frame();
|
||||
Window.Current.Content = rootFrame;
|
||||
}
|
||||
|
||||
if (rootFrame.Content == null)
|
||||
{
|
||||
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = extendViewIntoTitleBar;
|
||||
|
||||
if (viewModel is MainViewModel mainViewModel)
|
||||
{
|
||||
_mainViewModels.Add(mainViewModel);
|
||||
}
|
||||
|
||||
rootFrame.Navigate(pageType, viewModel);
|
||||
}
|
||||
_alreadyLaunched = true;
|
||||
Window.Current.Activate();
|
||||
}
|
||||
|
||||
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, viewModel);
|
||||
Window.Current.Content = frame;
|
||||
Window.Current.Activate();
|
||||
|
||||
windowId = ApplicationView.GetForCurrentView().Id;
|
||||
});
|
||||
|
||||
if (viewModel is MainViewModel mainViewModel && parameter is string directory)
|
||||
{
|
||||
_mainViewModels.Add(mainViewModel);
|
||||
await mainViewModel.AddTerminal(directory);
|
||||
}
|
||||
|
||||
return windowId;
|
||||
}
|
||||
|
||||
private void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
|
||||
{
|
||||
if (args.Request.Message.ContainsKey("exit"))
|
||||
@@ -86,49 +242,5 @@ namespace FluentTerminal.App
|
||||
AppServiceDeferral.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int> CreateNewWindow(Type pageType, bool ExtendViewIntoTitleBar)
|
||||
{
|
||||
var create = CoreApplication.CreateNewView();
|
||||
await create.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = ExtendViewIntoTitleBar;
|
||||
var frame = new Frame();
|
||||
frame.Navigate(pageType, null);
|
||||
Window.Current.Content = frame;
|
||||
Window.Current.Activate();
|
||||
|
||||
idCreate = ApplicationView.GetForCurrentView().Id;
|
||||
});
|
||||
|
||||
for (int i = idSaved.Count - 1; i >= 0; i--)
|
||||
if (await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
|
||||
idCreate, ViewSizePreference.Default,
|
||||
idSaved[i], ViewSizePreference.Default)
|
||||
) break;
|
||||
|
||||
idSaved.Add(idCreate);
|
||||
return idCreate;
|
||||
}
|
||||
|
||||
public async Task ShowNew()
|
||||
{
|
||||
var id = await CreateNewWindow(typeof(MainPage), true);
|
||||
bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(id);
|
||||
}
|
||||
|
||||
public async Task ShowSettings()
|
||||
{
|
||||
if (_settingsWindowId == null)
|
||||
{
|
||||
_settingsWindowId = await CreateNewWindow(typeof(Views.SettingsPage), false);
|
||||
}
|
||||
bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(_settingsWindowId.Value);
|
||||
}
|
||||
|
||||
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
|
||||
{
|
||||
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -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,27 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace FluentTerminal.App.Converters
|
||||
{
|
||||
public class FalseToVisibleConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is Boolean collapsed)
|
||||
{
|
||||
return collapsed ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is Visibility visibility)
|
||||
{
|
||||
return visibility == Visibility.Collapsed;
|
||||
}
|
||||
return 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using FluentTerminal.App.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace FluentTerminal.App.Converters
|
||||
{
|
||||
internal class TerminalViewModelToViewConverter : IValueConverter
|
||||
{
|
||||
private Dictionary<int, TerminalView> _viewDictionary;
|
||||
|
||||
public TerminalViewModelToViewConverter()
|
||||
{
|
||||
_viewDictionary = new Dictionary<int, TerminalView>();
|
||||
}
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is TerminalViewModel terminal)
|
||||
{
|
||||
if (_viewDictionary.TryGetValue(terminal.Id, out TerminalView view))
|
||||
{
|
||||
return view;
|
||||
}
|
||||
|
||||
var newView = new TerminalView(terminal);
|
||||
_viewDictionary.Add(terminal.Id, newView);
|
||||
return newView;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace FluentTerminal.App.Converters
|
||||
{
|
||||
public class TrueToVisibleConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is Boolean visible)
|
||||
{
|
||||
return visible ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is Visibility visibility)
|
||||
{
|
||||
return visibility == Visibility.Visible;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
|
||||
<PackageCertificateKeyFile>FluentTerminal.App_StoreKey.pfx</PackageCertificateKeyFile>
|
||||
<PackageCertificateThumbprint>8FA8EF727E767FAE5409DDD1694C1CEE054A2962</PackageCertificateThumbprint>
|
||||
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
|
||||
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<AppxBundlePlatforms>x86|x64</AppxBundlePlatforms>
|
||||
</PropertyGroup>
|
||||
@@ -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,23 +102,217 @@
|
||||
<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\TrayProcessCommunicationService.cs" />
|
||||
<Compile Include="Services\ISettingsService.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\TerminalPage.xaml.cs">
|
||||
<DependentUpon>TerminalPage.xaml</DependentUpon>
|
||||
<Compile Include="Views\SettingsPages\ThemeSettings.xaml.cs">
|
||||
<DependentUpon>ThemeSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPages\TerminalSettings.xaml.cs">
|
||||
<DependentUpon>TerminalSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPages\GeneralSettings.xaml.cs">
|
||||
<DependentUpon>GeneralSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPages\KeyBindingSettings.xaml.cs">
|
||||
<DependentUpon>KeyBindingSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<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>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
<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.Host.HttpListener.dll" />
|
||||
<Content Include="Win32\Microsoft.Owin.Hosting.dll" />
|
||||
<Content Include="Win32\Microsoft.Win32.Primitives.dll" />
|
||||
<Content Include="Win32\netstandard.dll" />
|
||||
<Content Include="Win32\Newtonsoft.Json.dll" />
|
||||
<Content Include="Win32\Owin.dll" />
|
||||
<Content Include="Win32\System.AppContext.dll" />
|
||||
<Content Include="Win32\System.Collections.Concurrent.dll" />
|
||||
<Content Include="Win32\System.Collections.dll" />
|
||||
<Content Include="Win32\System.Collections.NonGeneric.dll" />
|
||||
<Content Include="Win32\System.Collections.Specialized.dll" />
|
||||
<Content Include="Win32\System.ComponentModel.dll" />
|
||||
<Content Include="Win32\System.ComponentModel.EventBasedAsync.dll" />
|
||||
<Content Include="Win32\System.ComponentModel.Primitives.dll" />
|
||||
<Content Include="Win32\System.ComponentModel.TypeConverter.dll" />
|
||||
<Content Include="Win32\System.Console.dll" />
|
||||
<Content Include="Win32\System.Data.Common.dll" />
|
||||
<Content Include="Win32\System.Diagnostics.Contracts.dll" />
|
||||
<Content Include="Win32\System.Diagnostics.Debug.dll" />
|
||||
<Content Include="Win32\System.Diagnostics.FileVersionInfo.dll" />
|
||||
<Content Include="Win32\System.Diagnostics.Process.dll" />
|
||||
<Content Include="Win32\System.Diagnostics.StackTrace.dll" />
|
||||
<Content Include="Win32\System.Diagnostics.TextWriterTraceListener.dll" />
|
||||
<Content Include="Win32\System.Diagnostics.Tools.dll" />
|
||||
<Content Include="Win32\System.Diagnostics.TraceSource.dll" />
|
||||
<Content Include="Win32\System.Diagnostics.Tracing.dll" />
|
||||
<Content Include="Win32\System.Drawing.Primitives.dll" />
|
||||
<Content Include="Win32\System.Dynamic.Runtime.dll" />
|
||||
<Content Include="Win32\System.Globalization.Calendars.dll" />
|
||||
<Content Include="Win32\System.Globalization.dll" />
|
||||
<Content Include="Win32\System.Globalization.Extensions.dll" />
|
||||
<Content Include="Win32\System.IO.Compression.dll" />
|
||||
<Content Include="Win32\System.IO.Compression.ZipFile.dll" />
|
||||
<Content Include="Win32\System.IO.dll" />
|
||||
<Content Include="Win32\System.IO.FileSystem.dll" />
|
||||
<Content Include="Win32\System.IO.FileSystem.DriveInfo.dll" />
|
||||
<Content Include="Win32\System.IO.FileSystem.Primitives.dll" />
|
||||
<Content Include="Win32\System.IO.FileSystem.Watcher.dll" />
|
||||
<Content Include="Win32\System.IO.IsolatedStorage.dll" />
|
||||
<Content Include="Win32\System.IO.MemoryMappedFiles.dll" />
|
||||
<Content Include="Win32\System.IO.Pipes.dll" />
|
||||
<Content Include="Win32\System.IO.UnmanagedMemoryStream.dll" />
|
||||
<Content Include="Win32\System.Linq.dll" />
|
||||
<Content Include="Win32\System.Linq.Expressions.dll" />
|
||||
<Content Include="Win32\System.Linq.Parallel.dll" />
|
||||
<Content Include="Win32\System.Linq.Queryable.dll" />
|
||||
<Content Include="Win32\System.Net.Http.dll" />
|
||||
<Content Include="Win32\System.Net.Http.Formatting.dll" />
|
||||
<Content Include="Win32\System.Net.NameResolution.dll" />
|
||||
<Content Include="Win32\System.Net.NetworkInformation.dll" />
|
||||
<Content Include="Win32\System.Net.Ping.dll" />
|
||||
<Content Include="Win32\System.Net.Primitives.dll" />
|
||||
<Content Include="Win32\System.Net.Requests.dll" />
|
||||
<Content Include="Win32\System.Net.Security.dll" />
|
||||
<Content Include="Win32\System.Net.Sockets.dll" />
|
||||
<Content Include="Win32\System.Net.WebHeaderCollection.dll" />
|
||||
<Content Include="Win32\System.Net.WebSockets.Client.dll" />
|
||||
<Content Include="Win32\System.Net.WebSockets.dll" />
|
||||
<Content Include="Win32\System.ObjectModel.dll" />
|
||||
<Content Include="Win32\System.Reflection.dll" />
|
||||
<Content Include="Win32\System.Reflection.Extensions.dll" />
|
||||
<Content Include="Win32\System.Reflection.Primitives.dll" />
|
||||
<Content Include="Win32\System.Resources.Reader.dll" />
|
||||
<Content Include="Win32\System.Resources.ResourceManager.dll" />
|
||||
<Content Include="Win32\System.Resources.Writer.dll" />
|
||||
<Content Include="Win32\System.Runtime.CompilerServices.VisualC.dll" />
|
||||
<Content Include="Win32\System.Runtime.dll" />
|
||||
<Content Include="Win32\System.Runtime.Extensions.dll" />
|
||||
<Content Include="Win32\System.Runtime.Handles.dll" />
|
||||
<Content Include="Win32\System.Runtime.InteropServices.dll" />
|
||||
<Content Include="Win32\System.Runtime.InteropServices.RuntimeInformation.dll" />
|
||||
<Content Include="Win32\System.Runtime.Numerics.dll" />
|
||||
<Content Include="Win32\System.Runtime.Serialization.Formatters.dll" />
|
||||
<Content Include="Win32\System.Runtime.Serialization.Json.dll" />
|
||||
<Content Include="Win32\System.Runtime.Serialization.Primitives.dll" />
|
||||
<Content Include="Win32\System.Runtime.Serialization.Xml.dll" />
|
||||
<Content Include="Win32\System.Security.Claims.dll" />
|
||||
<Content Include="Win32\System.Security.Cryptography.Algorithms.dll" />
|
||||
<Content Include="Win32\System.Security.Cryptography.Csp.dll" />
|
||||
<Content Include="Win32\System.Security.Cryptography.Encoding.dll" />
|
||||
<Content Include="Win32\System.Security.Cryptography.Primitives.dll" />
|
||||
<Content Include="Win32\System.Security.Cryptography.X509Certificates.dll" />
|
||||
<Content Include="Win32\System.Security.Principal.dll" />
|
||||
<Content Include="Win32\System.Security.SecureString.dll" />
|
||||
<Content Include="Win32\System.Text.Encoding.dll" />
|
||||
<Content Include="Win32\System.Text.Encoding.Extensions.dll" />
|
||||
<Content Include="Win32\System.Text.RegularExpressions.dll" />
|
||||
<Content Include="Win32\System.Threading.dll" />
|
||||
<Content Include="Win32\System.Threading.Overlapped.dll" />
|
||||
<Content Include="Win32\System.Threading.Tasks.dll" />
|
||||
<Content Include="Win32\System.Threading.Tasks.Parallel.dll" />
|
||||
<Content Include="Win32\System.Threading.Thread.dll" />
|
||||
<Content Include="Win32\System.Threading.ThreadPool.dll" />
|
||||
<Content Include="Win32\System.Threading.Timer.dll" />
|
||||
<Content Include="Win32\System.ValueTuple.dll" />
|
||||
<Content Include="Win32\System.Web.Http.dll" />
|
||||
<Content Include="Win32\System.Web.Http.Owin.dll" />
|
||||
<Content Include="Win32\System.Xml.ReaderWriter.dll" />
|
||||
<Content Include="Win32\System.Xml.XDocument.dll" />
|
||||
<Content Include="Win32\System.Xml.XmlDocument.dll" />
|
||||
<Content Include="Win32\System.Xml.XmlSerializer.dll" />
|
||||
<Content Include="Win32\System.Xml.XPath.dll" />
|
||||
<Content Include="Win32\System.Xml.XPath.XDocument.dll" />
|
||||
<Content Include="Win32\Unity.Abstractions.dll" />
|
||||
<Content Include="Win32\Unity.Abstractions.pdb" />
|
||||
<Content Include="Win32\Unity.Configuration.dll" />
|
||||
<Content Include="Win32\Unity.Configuration.pdb" />
|
||||
<Content Include="Win32\Unity.Container.dll" />
|
||||
<Content Include="Win32\Unity.Container.pdb" />
|
||||
<Content Include="Win32\Unity.Interception.Configuration.dll" />
|
||||
<Content Include="Win32\Unity.Interception.Configuration.pdb" />
|
||||
<Content Include="Win32\Unity.Interception.dll" />
|
||||
<Content Include="Win32\Unity.Interception.pdb" />
|
||||
<Content Include="Win32\Unity.RegistrationByConvention.dll" />
|
||||
<Content Include="Win32\Unity.RegistrationByConvention.pdb" />
|
||||
<Content Include="Win32\Unity.ServiceLocation.dll" />
|
||||
<Content Include="Win32\Unity.ServiceLocation.pdb" />
|
||||
<Content Include="Win32\Unity.WebApi.dll" />
|
||||
<Content Include="Win32\winpty-agent.exe" />
|
||||
<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>
|
||||
@@ -166,57 +363,16 @@
|
||||
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-400.png" />
|
||||
<None Include="Package.StoreAssociation.xml" />
|
||||
<Content Include="Properties\Default.rd.xml" />
|
||||
<Content Include="Assets\LockScreenLogo.scale-200.png" />
|
||||
<Content Include="Assets\SplashScreen.scale-200.png" />
|
||||
<Content Include="Assets\Square150x150Logo.scale-200.png" />
|
||||
<Content Include="Assets\Square44x44Logo.scale-200.png" />
|
||||
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||
<Content Include="Assets\StoreLogo.png" />
|
||||
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
|
||||
<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="Win32\CommonServiceLocator.dll" />
|
||||
<Content Include="Win32\CommonServiceLocator.pdb" />
|
||||
<Content Include="Win32\Fleck.dll" />
|
||||
<Content Include="Win32\FluentTerminal.SystemTray.exe" />
|
||||
<Content Include="Win32\FluentTerminal.SystemTray.pdb" />
|
||||
<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\Newtonsoft.Json.dll" />
|
||||
<Content Include="Win32\Owin.dll" />
|
||||
<Content Include="Win32\System.Net.Http.Formatting.dll" />
|
||||
<Content Include="Win32\System.Web.Http.dll" />
|
||||
<Content Include="Win32\System.Web.Http.Owin.dll" />
|
||||
<Content Include="Win32\Unity.Abstractions.dll" />
|
||||
<Content Include="Win32\Unity.Abstractions.pdb" />
|
||||
<Content Include="Win32\Unity.Configuration.dll" />
|
||||
<Content Include="Win32\Unity.Configuration.pdb" />
|
||||
<Content Include="Win32\Unity.Container.dll" />
|
||||
<Content Include="Win32\Unity.Container.pdb" />
|
||||
<Content Include="Win32\Unity.Interception.Configuration.dll" />
|
||||
<Content Include="Win32\Unity.Interception.Configuration.pdb" />
|
||||
<Content Include="Win32\Unity.Interception.dll" />
|
||||
<Content Include="Win32\Unity.Interception.pdb" />
|
||||
<Content Include="Win32\Unity.RegistrationByConvention.dll" />
|
||||
<Content Include="Win32\Unity.RegistrationByConvention.pdb" />
|
||||
<Content Include="Win32\Unity.ServiceLocation.dll" />
|
||||
<Content Include="Win32\Unity.ServiceLocation.pdb" />
|
||||
<Content Include="Win32\Unity.WebApi.dll" />
|
||||
<Content Include="Win32\winpty-agent.exe" />
|
||||
<Content Include="Win32\winpty-debugserver.exe" />
|
||||
<Content Include="Win32\winpty.dll" />
|
||||
<Content Include="Win32\winpty.NET.dll" />
|
||||
</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>
|
||||
@@ -226,33 +382,95 @@
|
||||
<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\TerminalPage.xaml">
|
||||
<Page Include="Views\SettingsPages\ThemeSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPages\TerminalSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPages\GeneralSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPages\KeyBindingSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPages\ShellSettings.xaml">
|
||||
<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>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Autofac">
|
||||
<Version>4.6.2</Version>
|
||||
</PackageReference>
|
||||
<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">
|
||||
<Name>Windows Desktop Extensions for the UWP</Name>
|
||||
</SDKReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FluentTerminal.Models\FluentTerminal.Models.csproj">
|
||||
<Project>{5EA40453-A0AA-449E-8406-D6EA51D7E70E}</Project>
|
||||
<Name>FluentTerminal.Models</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\FluentTerminal.RuntimeComponent\FluentTerminal.RuntimeComponent.csproj">
|
||||
<Project>{BAAE6239-343F-454C-977F-F81F91715961}</Project>
|
||||
<Name>FluentTerminal.RuntimeComponent</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>mkdir "$(SolutionDir)\FluentTerminal.App\bin\$(PlatformName)\$(ConfigurationName)\AppX\Win32" 2> NULL
|
||||
xcopy /y /s "$(SolutionDir)FluentTerminal.SystemTray\bin\$(PlatformName)\$(ConfigurationName)" "$(SolutionDir)\FluentTerminal.App\bin\$(PlatformName)\$(ConfigurationName)\AppX\Win32"
|
||||
</PostBuildEvent>
|
||||
<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.
|
||||
|
||||
@@ -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: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.3.0" />
|
||||
<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.7.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="f7225014-f405-4342-ad2e-ebf6ac60ea2c" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>Fluent Terminal</DisplayName>
|
||||
@@ -23,13 +23,18 @@
|
||||
<uap:ShowOn Tile="square310x310Logo" />
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\AppIcons\SplashScreen.png" />
|
||||
<uap:SplashScreen Image="Assets\AppIcons\SplashScreen.png" uap5:Optional="true" />
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
<uap:Extension Category="windows.appService">
|
||||
<uap:AppService Name="FluentTerminalAppService" />
|
||||
</uap:Extension>
|
||||
<desktop:Extension Category="windows.fullTrustProcess" Executable="Win32\FluentTerminal.SystemTray.exe" />
|
||||
<uap5:Extension Category="windows.appExecutionAlias" Executable="FluentTerminal.App.exe" EntryPoint="FluentTerminal.App.App">
|
||||
<uap5:AppExecutionAlias>
|
||||
<uap5:ExecutionAlias Alias="flute.exe" />
|
||||
</uap5:AppExecutionAlias>
|
||||
</uap5:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
@@ -0,0 +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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +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 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using FluentTerminal.Models;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface ITrayProcessCommunicationService
|
||||
{
|
||||
Task<CreateTerminalResponse> CreateTerminal(TerminalSize size, ShellConfiguration shellConfiguration);
|
||||
Task ResizeTerminal(int id, TerminalSize size);
|
||||
Task UpdateToggleWindowKeyBindings();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
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
|
||||
{
|
||||
Shell = ShellType.PowerShell,
|
||||
CustomShellLocation = string.Empty,
|
||||
WorkingDirectory = string.Empty,
|
||||
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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
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
|
||||
{
|
||||
internal class SettingsService : ISettingsService
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
private void OnDataChanged(ApplicationData sender, object args)
|
||||
{
|
||||
//todo handle data changed for roaming settings
|
||||
}
|
||||
|
||||
public ShellConfiguration GetShellConfiguration()
|
||||
{
|
||||
return _localSettings.ReadValueFromJson(nameof(ShellConfiguration), _defaultValueProvider.GetDefaultShellConfiguration());
|
||||
}
|
||||
|
||||
public void SaveShellConfiguration(ShellConfiguration shellConfiguration)
|
||||
{
|
||||
_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using FluentTerminal.App.Utilities;
|
||||
using FluentTerminal.Models;
|
||||
using Windows.Web.Http;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
internal class TrayProcessCommunicationService : ITrayProcessCommunicationService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
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)
|
||||
{
|
||||
var request = new CreateTerminalRequest
|
||||
{
|
||||
Size = size,
|
||||
Configuration = shellConfiguration
|
||||
};
|
||||
|
||||
var response = await _httpClient.PostAsync(new Uri($"http://localhost:9000/terminals"), HttpJsonContent.From(request));
|
||||
var createTerminalResponse = await response.Content.ReadAs<CreateTerminalResponse>();
|
||||
|
||||
return createTerminalResponse;
|
||||
}
|
||||
|
||||
public Task ResizeTerminal(int id, TerminalSize size)
|
||||
{
|
||||
return _httpClient.PostAsync(new Uri($"http://localhost:9000/terminals/{id}/resize"), HttpJsonContent.From(size)).AsTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -0,0 +1,29 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace FluentTerminal.App.Utilities
|
||||
{
|
||||
public static class ApplicationDataContainerExtensions
|
||||
{
|
||||
public static T ReadValueFromJson<T>(this ApplicationDataContainer container, string name, T fallbackValue)
|
||||
{
|
||||
if (container.Values.TryGetValue(name, out object value))
|
||||
{
|
||||
if (fallbackValue == null)
|
||||
{
|
||||
fallbackValue = Activator.CreateInstance<T>();
|
||||
}
|
||||
|
||||
JsonConvert.PopulateObject((string)value, fallbackValue);
|
||||
}
|
||||
return fallbackValue;
|
||||
}
|
||||
|
||||
public static void WriteValueAsJson<T>(this ApplicationDataContainer container, string name, T value)
|
||||
{
|
||||
var serialized = JsonConvert.SerializeObject(value);
|
||||
container.Values[name] = serialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Newtonsoft.Json;
|
||||
using Windows.Web.Http;
|
||||
|
||||
namespace FluentTerminal.App.Utilities
|
||||
{
|
||||
public static class HttpJsonContent
|
||||
{
|
||||
public static HttpStringContent From(object content)
|
||||
{
|
||||
var serialized = JsonConvert.SerializeObject(content);
|
||||
return new HttpStringContent(serialized, Windows.Storage.Streams.UnicodeEncoding.Utf8, "application/json");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Web.Http;
|
||||
|
||||
namespace FluentTerminal.App.Utilities
|
||||
{
|
||||
public static class IHttpContentExtensions
|
||||
{
|
||||
public static async Task<T> ReadAs<T>(this IHttpContent content)
|
||||
{
|
||||
var contentBody = await content.ReadAsStringAsync();
|
||||
return JsonConvert.DeserializeObject<T>(contentBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
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 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, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService, IKeyboardCommandService keyboardCommandService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_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(null));
|
||||
ShowSettingsCommand = new RelayCommand(async () => await ShowSettings());
|
||||
|
||||
Terminals.CollectionChanged += OnTerminalsCollectionChanged;
|
||||
|
||||
Title = "Fluent Terminal";
|
||||
|
||||
_dispatcher = CoreApplication.GetCurrentView().Dispatcher;
|
||||
SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += OnCloseRequest;
|
||||
}
|
||||
|
||||
public RelayCommand AddTerminalCommand { 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
|
||||
{
|
||||
if (Set(ref _selectedTerminal, value))
|
||||
{
|
||||
SelectedTerminal?.FocusTerminal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RelayCommand ShowSettingsCommand { get; }
|
||||
|
||||
public ObservableCollection<TerminalViewModel> Terminals { get; } = new ObservableCollection<TerminalViewModel>();
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => _title;
|
||||
set => Set(ref _title, value);
|
||||
}
|
||||
|
||||
public Task AddTerminal(string startupDirectory)
|
||||
{
|
||||
return _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
var terminal = new TerminalViewModel(GetNextTerminalId(), _settingsService, _trayProcessCommunicationService, _dialogService, _keyboardCommandService, _applicationSettings, startupDirectory);
|
||||
terminal.CloseRequested += OnTerminalCloseRequested;
|
||||
terminal.TitleChanged += OnTitleChanged;
|
||||
Terminals.Add(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()
|
||||
{
|
||||
return App.Instance.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.App.ViewModels.Settings;
|
||||
using GalaSoft.MvvmLight;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
public class SettingsViewModel : ViewModelBase
|
||||
{
|
||||
public SettingsViewModel(ISettingsService settingsService, IDefaultValueProvider defaultValueProvider, IDialogService dialogService, ITrayProcessCommunicationService trayProcessCommunicationService)
|
||||
{
|
||||
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 GeneralPageViewModel General { get; }
|
||||
public KeyBindingsPageViewModel KeyBindings { get; }
|
||||
public TerminalPageViewModel Terminal { get; }
|
||||
public ShellPageViewModel Shell { get; }
|
||||
public ThemesPageViewModel Themes { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
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.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;
|
||||
|
||||
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 DefaultTitle { get; private set; } = "Fluent Terminal";
|
||||
|
||||
public string ResizeOverlayContent
|
||||
{
|
||||
get => _resizeOverlayContent;
|
||||
set => Set(ref _resizeOverlayContent, value);
|
||||
}
|
||||
|
||||
public bool ShowResizeOverlay
|
||||
{
|
||||
get => _showResizeOverlay;
|
||||
set
|
||||
{
|
||||
Set(ref _showResizeOverlay, value);
|
||||
if (value)
|
||||
{
|
||||
if (_resizeOverlayTimer.IsEnabled)
|
||||
{
|
||||
_resizeOverlayTimer.Stop();
|
||||
}
|
||||
_resizeOverlayTimer.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => _title;
|
||||
set
|
||||
{
|
||||
value = string.IsNullOrWhiteSpace(value) ? DefaultTitle: value;
|
||||
|
||||
if (Set(ref _title, value))
|
||||
{
|
||||
TitleChanged?.Invoke(this, Title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CloseView()
|
||||
{
|
||||
_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)
|
||||
{
|
||||
_resizeOverlayTimer.Stop();
|
||||
ShowResizeOverlay = false;
|
||||
}
|
||||
|
||||
private async void OnTerminalOptionsChanged(object sender, EventArgs e)
|
||||
{
|
||||
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
|
||||
{
|
||||
var options = _settingsService.GetTerminalOptions();
|
||||
await _terminalView.ChangeOptions(options);
|
||||
});
|
||||
}
|
||||
|
||||
private async void OnTerminalSizeChanged(object sender, TerminalSize e)
|
||||
{
|
||||
if (!Initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ResizeOverlayContent = $"{e.Columns} x {e.Rows}";
|
||||
ShowResizeOverlay = true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
{
|
||||
public interface ITerminalView
|
||||
{
|
||||
event EventHandler<TerminalSize> TerminalSizeChanged;
|
||||
event EventHandler<string> TerminalTitleChanged;
|
||||
event EventHandler<Command> KeyboardCommandReceived;
|
||||
|
||||
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,44 +2,136 @@
|
||||
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"
|
||||
Style="{StaticResource WindowTitleTextBlockStyle}"
|
||||
Text="Fluent Terminal" />
|
||||
<!--<Button
|
||||
Grid.Column="2"
|
||||
Click="OnSettingsButtonClick"
|
||||
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>
|
||||
<Frame x:Name="RootFrame" Grid.Row="1" />
|
||||
<ContentControl
|
||||
x:Name="TerminalContainer"
|
||||
Grid.Row="1"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Content="{x:Bind ViewModel.SelectedTerminal, Mode=OneWay, Converter={StaticResource TerminalViewModelToViewConverter}}" />
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -1,10 +1,13 @@
|
||||
using System.ComponentModel;
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using System.ComponentModel;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.Core.Preview;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
{
|
||||
@@ -31,6 +34,8 @@ namespace FluentTerminal.App.Views
|
||||
}
|
||||
}
|
||||
|
||||
public MainViewModel ViewModel { get; private set; }
|
||||
|
||||
public MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -40,11 +45,22 @@ namespace FluentTerminal.App.Views
|
||||
Loaded += OnLoaded;
|
||||
Unloaded += OnUnloaded;
|
||||
Window.Current.Activated += OnWindowActivated;
|
||||
|
||||
ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(800, 600);
|
||||
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is MainViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnWindowActivated(object sender, WindowActivatedEventArgs e)
|
||||
{
|
||||
if (e.WindowActivationState != CoreWindowActivationState.Deactivated && RootFrame.Content is TerminalPage terminal)
|
||||
if (e.WindowActivationState != CoreWindowActivationState.Deactivated && TerminalContainer.Content is TerminalView terminal)
|
||||
{
|
||||
await terminal.FocusWebView();
|
||||
}
|
||||
@@ -59,7 +75,6 @@ namespace FluentTerminal.App.Views
|
||||
{
|
||||
coreTitleBar.LayoutMetricsChanged += OnLayoutMetricsChanged;
|
||||
UpdateLayoutMetrics();
|
||||
RootFrame.Navigate(typeof(TerminalPage));
|
||||
}
|
||||
|
||||
private void OnLayoutMetricsChanged(CoreApplicationViewTitleBar sender, object e)
|
||||
@@ -89,9 +104,12 @@ namespace FluentTerminal.App.Views
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnSettingsButtonClick(object sender, RoutedEventArgs e)
|
||||
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
await App.Instance.ShowSettings();
|
||||
if (sender is Grid grid)
|
||||
{
|
||||
Tabs.MaxWidth = grid.ActualWidth - grid.ColumnDefinitions[2].ActualWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,77 @@
|
||||
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"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<TextBlock Text="Settings" />
|
||||
<Grid x:Name="Root">
|
||||
<TextBlock
|
||||
x:Name="AppTitle"
|
||||
Canvas.ZIndex="1"
|
||||
IsHitTestVisible="False"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="Settings"
|
||||
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="200"
|
||||
SelectionChanged="NavigationView_SelectionChanged">
|
||||
<NavigationView.MenuItems>
|
||||
<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>
|
||||
<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>
|
||||
</Page>
|
||||
@@ -1,4 +1,12 @@
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using FluentTerminal.App.Views.SettingsPages;
|
||||
using System.Linq;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.UI.Core.Preview;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
{
|
||||
@@ -6,7 +14,74 @@ namespace FluentTerminal.App.Views
|
||||
{
|
||||
public SettingsPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
InitializeComponent();
|
||||
Root.DataContext = this;
|
||||
|
||||
ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(1024, 768);
|
||||
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
|
||||
|
||||
ApplicationView.GetForCurrentView().Title = "Settings";
|
||||
|
||||
CoreApplicationViewTitleBar coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
|
||||
coreTitleBar.LayoutMetricsChanged += TitleBar_LayoutMetricsChanged;
|
||||
CoreTitleBarHeight = coreTitleBar.Height;
|
||||
|
||||
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)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
private void TitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar sender, object args)
|
||||
{
|
||||
AppTitle.Margin = new Thickness(CoreApplication.GetCurrentView().TitleBar.SystemOverlayLeftInset + 12, 8, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<Page
|
||||
x:Class="FluentTerminal.App.Views.SettingsPages.GeneralSettings"
|
||||
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="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>
|
||||
@@ -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 GeneralSettings : Page
|
||||
{
|
||||
public GeneralPageViewModel ViewModel { get; private set; }
|
||||
|
||||
public GeneralSettings()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is GeneralPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
<Page
|
||||
x:Class="FluentTerminal.App.Views.SettingsPages.KeyBindingSettings"
|
||||
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: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>
|
||||
|
||||
<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>
|
||||
@@ -0,0 +1,30 @@
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using FluentTerminal.App.ViewModels.Settings;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace FluentTerminal.App.Views.SettingsPages
|
||||
{
|
||||
public sealed partial class KeyBindingSettings : Page
|
||||
{
|
||||
public KeyBindingsPageViewModel ViewModel { get; private set; }
|
||||
|
||||
public KeyBindingSettings()
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<Page
|
||||
x:Class="FluentTerminal.App.Views.SettingsPages.ShellSettings"
|
||||
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="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="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>
|
||||
|
||||
<TextBox
|
||||
Width="400"
|
||||
Margin="0,24,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Header="Arguments"
|
||||
IsSpellCheckEnabled="False"
|
||||
Text="{x:Bind ViewModel.Arguments, 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 ShellSettings : Page
|
||||
{
|
||||
public ShellPageViewModel ViewModel { get; private set; }
|
||||
|
||||
public ShellSettings()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<Page
|
||||
x:Class="FluentTerminal.App.Views.TerminalPage"
|
||||
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 x:Name="WebViewContainer" Margin="12" />
|
||||
</Page>
|
||||
@@ -1,65 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Core.Preview;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
{
|
||||
public sealed partial class TerminalPage : Page
|
||||
{
|
||||
private WebView _webView;
|
||||
|
||||
public TerminalPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += OnLoaded;
|
||||
SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += OnCloseRequested;
|
||||
}
|
||||
|
||||
public async Task FocusWebView()
|
||||
{
|
||||
if (_webView != null)
|
||||
{
|
||||
_webView.Focus(FocusState.Programmatic);
|
||||
await ExecuteScriptAsync("document.focus();");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCloseRequested(object sender, SystemNavigationCloseRequestedPreviewEventArgs e)
|
||||
{
|
||||
_webView.Navigate(new Uri("about:blank"));
|
||||
_webView = null;
|
||||
}
|
||||
|
||||
public Task<string> ExecuteScriptAsync(string script)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _webView.InvokeScriptAsync("eval", new[]
|
||||
{
|
||||
"try {" + script + "} catch(error) {}"
|
||||
}).AsTask();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine($"Exception while running:\n \"{script}\"\n\n {e}");
|
||||
}
|
||||
return Task.FromResult(string.Empty);
|
||||
}
|
||||
|
||||
private async void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_webView = new WebView(WebViewExecutionMode.SeparateThread)
|
||||
{
|
||||
DefaultBackgroundColor = Colors.Transparent
|
||||
};
|
||||
WebViewContainer.Children.Add(_webView);
|
||||
|
||||
_webView.Navigate(new Uri("http://localhost:9000/Client/index.html"));
|
||||
_webView.Focus(FocusState.Programmatic);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<UserControl
|
||||
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:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="400"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<Grid x:Name="WebViewContainer" Margin="12" />
|
||||
<Grid
|
||||
Margin="12"
|
||||
Padding="6"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
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>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,243 @@
|
||||
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.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
{
|
||||
public sealed partial class TerminalView : UserControl, ITerminalView, ITerminalEventListener
|
||||
{
|
||||
private MenuFlyoutItem _copyMenuItem;
|
||||
private BlockingCollection<Action> _dispatcherJobs;
|
||||
private SemaphoreSlim _loaded;
|
||||
private MenuFlyoutItem _pasteMenuItem;
|
||||
private WebView _webView;
|
||||
|
||||
public TerminalView(TerminalViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
InitializeComponent();
|
||||
Loaded += OnLoaded;
|
||||
_loaded = new SemaphoreSlim(0, 1);
|
||||
|
||||
JsonConvert.DefaultSettings = () =>
|
||||
{
|
||||
var settings = new JsonSerializerSettings
|
||||
{
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver(),
|
||||
};
|
||||
settings.Converters.Add(new StringEnumConverter(true));
|
||||
|
||||
return settings;
|
||||
};
|
||||
|
||||
StartMediatorTask();
|
||||
}
|
||||
|
||||
public event EventHandler<Command> KeyboardCommandReceived;
|
||||
public event EventHandler<TerminalSize> TerminalSizeChanged;
|
||||
public event EventHandler<string> TerminalTitleChanged;
|
||||
|
||||
public TerminalViewModel ViewModel { get; }
|
||||
|
||||
public Task ChangeOptions(TerminalOptions options)
|
||||
{
|
||||
var serialized = JsonConvert.SerializeObject(options);
|
||||
return ExecuteScriptAsync($"changeOptions('{serialized}')");
|
||||
}
|
||||
|
||||
public Task ChangeTheme(TerminalColors theme)
|
||||
{
|
||||
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
|
||||
{
|
||||
return _webView.InvokeScriptAsync("eval", new[] { script }).AsTask();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine($"Exception while running:\n \"{script}\"\n\n {e}");
|
||||
}
|
||||
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>();
|
||||
var dispatcher = CoreApplication.GetCurrentView().CoreWindow.Dispatcher;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
foreach (var job in _dispatcherJobs.GetConsumingEnumerable())
|
||||
{
|
||||
try
|
||||
{
|
||||
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => job.Invoke());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
node_modules/
|
||||
dist/
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,58 +1,140 @@
|
||||
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);
|
||||
Terminal.applyAddon(winptyCompat);
|
||||
|
||||
var term, protocol, socketURL, socket;
|
||||
var term, socket;
|
||||
var terminalContainer = document.getElementById('terminal-container');
|
||||
|
||||
createTerminal();
|
||||
|
||||
function createTerminal() {
|
||||
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"
|
||||
}
|
||||
});
|
||||
window.term = term; // Expose `term` to window for debugging purposes
|
||||
theme: theme
|
||||
};
|
||||
|
||||
term = new Terminal(terminalOptions);
|
||||
|
||||
window.term = term;
|
||||
|
||||
term.on('resize', function (size) {
|
||||
if (!socketURL) {
|
||||
return;
|
||||
}
|
||||
var cols = size.cols,
|
||||
rows = size.rows,
|
||||
url = 'http://localhost:9000/terminals/' + pid + '/size?cols=' + cols + '&rows=' + rows;
|
||||
fetch(url, {method: 'POST'});
|
||||
terminalBridge.notifySizeChanged(term.cols, term.rows);
|
||||
});
|
||||
|
||||
term.on('title', function (title) {
|
||||
terminalBridge.notifyTitleChanged(title);
|
||||
});
|
||||
protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
|
||||
|
||||
term.open(terminalContainer);
|
||||
term.winptyCompatInit();
|
||||
term.fit();
|
||||
term.focus();
|
||||
|
||||
fetch('http://localhost:9000/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) {
|
||||
console.log("got response");
|
||||
res.text().then(function (url) {
|
||||
socketURL = JSON.parse(url);
|
||||
socket = new WebSocket(socketURL);
|
||||
socket.onopen = runRealTerminal;
|
||||
});
|
||||
});
|
||||
var resizeTimeout;
|
||||
window.onresize = function () {
|
||||
clearTimeout(resizeTimeout);
|
||||
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 connectToWebSocket(url) {
|
||||
socket = new WebSocket(url);
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class CreateTerminalRequest
|
||||
{
|
||||
public TerminalSize Size { get; set; }
|
||||
public ShellConfiguration Configuration { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class CreateTerminalResponse
|
||||
{
|
||||
public int Id { get; set; }
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace FluentTerminal.Models.Enums
|
||||
{
|
||||
public enum ShellType
|
||||
{
|
||||
CMD,
|
||||
PowerShell,
|
||||
Custom
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<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,12 @@
|
||||
using FluentTerminal.Models.Enums;
|
||||
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class ShellConfiguration
|
||||
{
|
||||
public string Arguments { get; set; }
|
||||
public ShellType Shell { get; set; }
|
||||
public string CustomShellLocation { get; set; }
|
||||
public string WorkingDirectory { 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,8 @@
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class TerminalSize
|
||||
{
|
||||
public int Columns { get; set; }
|
||||
public int Rows { 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; }
|
||||
}
|
||||
}
|
||||