Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7dcd8e1fbb | ||
|
|
37518cf88b | ||
|
|
ca0e22b8d0 | ||
|
|
074f5f9c7e | ||
|
|
0b40963c82 | ||
|
|
0b6b8a9968 | ||
|
|
47613454c7 | ||
|
|
96d063b4fd | ||
|
|
fec44fb0b5 | ||
|
|
58e7de5271 | ||
|
|
466b7a7503 | ||
|
|
50f9c84420 | ||
|
|
f07dae98ee | ||
|
|
1cc74f79b4 | ||
|
|
60c4f0518d | ||
|
|
f9fb05b194 | ||
|
|
d933f60b8b | ||
|
|
45bba6e2eb | ||
|
|
210aeedc25 | ||
|
|
acfb8e8883 |
No files matched your search
@@ -1,5 +1,6 @@
|
||||
# Project specific
|
||||
FluentTerminal.App/Win32
|
||||
FluentTerminal.SystemTray/Client
|
||||
|
||||
## 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
|
||||
@@ -4,6 +4,7 @@ using FluentTerminal.App.Services.Implementation;
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using FluentTerminal.App.Views;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
@@ -14,6 +15,7 @@ using Windows.UI.Core;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using IContainer = Autofac.IContainer;
|
||||
|
||||
namespace FluentTerminal.App
|
||||
{
|
||||
@@ -33,18 +35,21 @@ namespace FluentTerminal.App
|
||||
Instance = this;
|
||||
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterType<SettingsService>().As<ISettingsService>().InstancePerDependency();
|
||||
builder.RegisterType<SettingsService>().As<ISettingsService>().SingleInstance();
|
||||
builder.RegisterType<DefaultValueProvider>().As<IDefaultValueProvider>().SingleInstance();
|
||||
builder.RegisterType<TerminalService>().As<ITerminalService>().SingleInstance();
|
||||
builder.RegisterType<DialogService>().As<IDialogService>().SingleInstance();
|
||||
builder.RegisterType<MainViewModel>().InstancePerDependency();
|
||||
builder.RegisterType<SettingsViewModel>().InstancePerDependency();
|
||||
|
||||
_container = builder.Build();
|
||||
}
|
||||
|
||||
public async Task CreateNewTerminalWindow()
|
||||
public async Task CreateNewTerminalWindow(string startupDirectory)
|
||||
{
|
||||
var id = await CreateSecondaryView(typeof(MainPage), true);
|
||||
var viewModel = _container.Resolve<MainViewModel>();
|
||||
viewModel.AddTerminal(startupDirectory);
|
||||
var id = await CreateSecondaryView(typeof(MainPage), viewModel, true);
|
||||
await ApplicationViewSwitcher.TryShowAsStandaloneAsync(id);
|
||||
}
|
||||
|
||||
@@ -57,7 +62,8 @@ namespace FluentTerminal.App
|
||||
{
|
||||
if (_settingsWindowId == null)
|
||||
{
|
||||
_settingsWindowId = await CreateSecondaryView(typeof(SettingsPage), true);
|
||||
var viewModel = _container.Resolve<SettingsViewModel>();
|
||||
_settingsWindowId = await CreateSecondaryView(typeof(SettingsPage), viewModel, true);
|
||||
}
|
||||
await ApplicationViewSwitcher.TryShowAsStandaloneAsync(_settingsWindowId.Value);
|
||||
}
|
||||
@@ -71,27 +77,38 @@ namespace FluentTerminal.App
|
||||
{
|
||||
if (args is CommandLineActivatedEventArgs commandLineActivated)
|
||||
{
|
||||
var argument = commandLineActivated.Operation.Arguments.Trim();
|
||||
if (string.IsNullOrWhiteSpace(commandLineActivated.Operation.Arguments))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var arguments = commandLineActivated.Operation.Arguments.Split(' ', 2);
|
||||
var command = arguments[0];
|
||||
var parameter = arguments.Length > 1 ? arguments[1] : string.Empty;
|
||||
|
||||
if (_alreadyLaunched)
|
||||
{
|
||||
if (argument == "settings")
|
||||
if (command == "settings")
|
||||
{
|
||||
await ShowSettings();
|
||||
}
|
||||
else if (argument == "new")
|
||||
else if (command == "new")
|
||||
{
|
||||
await CreateNewTerminalWindow();
|
||||
await CreateNewTerminalWindow(parameter);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (argument == "settings")
|
||||
if (command == "settings")
|
||||
{
|
||||
CreateMainView(typeof(SettingsPage), true);
|
||||
var viewModel = _container.Resolve<SettingsViewModel>();
|
||||
await CreateMainView(typeof(SettingsPage), viewModel, true);
|
||||
}
|
||||
else if (argument == "new")
|
||||
else if (command == "new")
|
||||
{
|
||||
CreateMainView(typeof(MainPage), true);
|
||||
var viewModel = _container.Resolve<MainViewModel>();
|
||||
viewModel.AddTerminal(parameter);
|
||||
await CreateMainView(typeof(MainPage), viewModel, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,23 +128,27 @@ namespace FluentTerminal.App
|
||||
|
||||
protected override async void OnLaunched(LaunchActivatedEventArgs e)
|
||||
{
|
||||
var launch = FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync().AsTask();
|
||||
var clearCache = WebView.ClearTemporaryWebDataAsync().AsTask();
|
||||
await Task.WhenAll(launch, clearCache);
|
||||
|
||||
if (!_alreadyLaunched)
|
||||
{
|
||||
CreateMainView(typeof(MainPage), true);
|
||||
var viewModel = _container.Resolve<MainViewModel>();
|
||||
viewModel.AddTerminal(null);
|
||||
await CreateMainView(typeof(MainPage), viewModel, true);
|
||||
Window.Current.Activate();
|
||||
}
|
||||
else if (_openTerminalWindows == 0)
|
||||
{
|
||||
await CreateSecondaryView(typeof(MainPage), true);
|
||||
var viewModel = _container.Resolve<MainViewModel>();
|
||||
viewModel.AddTerminal(null);
|
||||
await CreateSecondaryView(typeof(MainPage), viewModel, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateMainView(Type pageType, bool extendViewIntoTitleBar)
|
||||
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)
|
||||
{
|
||||
@@ -138,25 +159,26 @@ namespace FluentTerminal.App
|
||||
if (rootFrame.Content == null)
|
||||
{
|
||||
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = extendViewIntoTitleBar;
|
||||
rootFrame.Navigate(pageType, GetViewModelForPageType(pageType));
|
||||
|
||||
if (pageType == typeof(MainPage))
|
||||
{
|
||||
_openTerminalWindows++;
|
||||
}
|
||||
|
||||
rootFrame.Navigate(pageType, viewModel);
|
||||
}
|
||||
_alreadyLaunched = true;
|
||||
Window.Current.Activate();
|
||||
}
|
||||
|
||||
private async Task<int> CreateSecondaryView(Type pageType, bool ExtendViewIntoTitleBar)
|
||||
private async Task<int> CreateSecondaryView(Type pageType, INotifyPropertyChanged viewModel, bool ExtendViewIntoTitleBar)
|
||||
{
|
||||
int windowId = 0;
|
||||
await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = ExtendViewIntoTitleBar;
|
||||
var frame = new Frame();
|
||||
frame.Navigate(pageType, GetViewModelForPageType(pageType));
|
||||
frame.Navigate(pageType, viewModel);
|
||||
Window.Current.Content = frame;
|
||||
Window.Current.Activate();
|
||||
|
||||
@@ -171,19 +193,6 @@ namespace FluentTerminal.App
|
||||
return windowId;
|
||||
}
|
||||
|
||||
private object GetViewModelForPageType(Type pageType)
|
||||
{
|
||||
if (pageType == typeof(MainPage))
|
||||
{
|
||||
return _container.Resolve<MainViewModel>();
|
||||
}
|
||||
else if (pageType == typeof(SettingsPage))
|
||||
{
|
||||
return _container.Resolve<SettingsViewModel>();
|
||||
}
|
||||
throw new Exception("No ViewModel defined for Page: " + pageType.Name);
|
||||
}
|
||||
|
||||
private void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
|
||||
{
|
||||
if (args.Request.Message.ContainsKey("exit"))
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,8 +100,11 @@
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Converters\FalseToVisibleConverter.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="Utilities\ApplicationDataContainerExtensions.cs" />
|
||||
<Compile Include="Services\IDefaultValueProvider.cs" />
|
||||
<Compile Include="Services\Implementation\DefaultValueProvider.cs" />
|
||||
@@ -109,11 +112,14 @@
|
||||
<Compile Include="Services\Implementation\TerminalService.cs" />
|
||||
<Compile Include="Services\ISettingsService.cs" />
|
||||
<Compile Include="Services\ITerminalService.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\ThemeViewModel.cs" />
|
||||
<Compile Include="ViewModels\TerminalViewModel.cs" />
|
||||
<Compile Include="Views\BindableColorsTitleBar.cs" />
|
||||
<Compile Include="Views\ITerminalView.cs" />
|
||||
<Compile Include="Views\MainPage.xaml.cs">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
@@ -122,11 +128,11 @@
|
||||
<Compile Include="Views\SettingsPage.xaml.cs">
|
||||
<DependentUpon>SettingsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPages\ColorSettings.xaml.cs">
|
||||
<DependentUpon>ColorSettings.xaml</DependentUpon>
|
||||
<Compile Include="Views\SettingsPages\ThemeSettings.xaml.cs">
|
||||
<DependentUpon>ThemeSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPages\FontSettings.xaml.cs">
|
||||
<DependentUpon>FontSettings.xaml</DependentUpon>
|
||||
<Compile Include="Views\SettingsPages\TerminalSettings.xaml.cs">
|
||||
<DependentUpon>TerminalSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPages\GeneralSettings.xaml.cs">
|
||||
<DependentUpon>GeneralSettings.xaml</DependentUpon>
|
||||
@@ -137,6 +143,9 @@
|
||||
<Compile Include="Views\SettingsPages\ShellSettings.xaml.cs">
|
||||
<DependentUpon>ShellSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\TerminalColorPicker.xaml.cs">
|
||||
<DependentUpon>TerminalColorPicker.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\TerminalView.xaml.cs">
|
||||
<DependentUpon>TerminalView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -352,11 +361,11 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPages\ColorSettings.xaml">
|
||||
<Page Include="Views\SettingsPages\ThemeSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPages\FontSettings.xaml">
|
||||
<Page Include="Views\SettingsPages\TerminalSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
@@ -372,6 +381,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\TerminalColorPicker.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\TerminalView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -384,12 +397,21 @@
|
||||
<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="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">
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
using FluentTerminal.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface IDefaultValueProvider
|
||||
{
|
||||
ShellConfiguration GetDefaultShellConfiguration();
|
||||
TerminalOptions GetDefaultTerminalOptions();
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,27 @@
|
||||
using FluentTerminal.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface ISettingsService
|
||||
{
|
||||
event EventHandler CurrentThemeChanged;
|
||||
event EventHandler TerminalOptionsChanged;
|
||||
|
||||
ShellConfiguration GetShellConfiguration();
|
||||
void SaveShellConfiguration(ShellConfiguration spawnConfiguration);
|
||||
void SaveShellConfiguration(ShellConfiguration shellConfiguration);
|
||||
|
||||
TerminalOptions GetTerminalOptions();
|
||||
void SaveTerminalOptions(TerminalOptions terminalOptions);
|
||||
|
||||
TerminalTheme GetCurrentTheme();
|
||||
Guid GetCurrentThemeId();
|
||||
TerminalTheme GetTheme(Guid id);
|
||||
void SaveCurrentThemeId(Guid id);
|
||||
|
||||
IEnumerable<TerminalTheme> GetThemes();
|
||||
void SaveTheme(TerminalTheme theme);
|
||||
void DeleteTheme(Guid id);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
@@ -15,5 +17,93 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
Arguments = string.Empty
|
||||
};
|
||||
}
|
||||
|
||||
public TerminalOptions GetDefaultTerminalOptions()
|
||||
{
|
||||
return new TerminalOptions
|
||||
{
|
||||
BellStyle = BellStyle.None,
|
||||
CursorBlink = true,
|
||||
CursorStyle = CursorStyle.Block,
|
||||
FontFamily = "Consolas",
|
||||
FontSize = 13
|
||||
};
|
||||
}
|
||||
|
||||
public Guid GetDefaultThemeId()
|
||||
{
|
||||
return Guid.Parse("281e4352-bb50-47b7-a691-2b13830df95e");
|
||||
}
|
||||
|
||||
public IEnumerable<TerminalTheme> GetPreInstalledThemes()
|
||||
{
|
||||
var defaultXterm = new TerminalTheme
|
||||
{
|
||||
Id = GetDefaultThemeId(),
|
||||
Author = "xterm.js",
|
||||
Name = "Xterm.js Default",
|
||||
PreInstalled = true,
|
||||
BackgroundOpacity = 0.8,
|
||||
Colors = new TerminalColors
|
||||
{
|
||||
Black = "#2e3436",
|
||||
Red = "#cc0000",
|
||||
Green = "#4e9a06",
|
||||
Yellow = "#c4a000",
|
||||
Blue = "#3465a4",
|
||||
Magenta = "#75507b",
|
||||
Cyan = "#06989a",
|
||||
White = "#d3d7cf",
|
||||
BrightBlack = "#555753",
|
||||
BrightRed = "#ef2929",
|
||||
BrightGreen = "#8ae234",
|
||||
BrightYellow = "#fce94f",
|
||||
BrightBlue = "#729fcf",
|
||||
BrightMagenta = "#ad7fa8",
|
||||
BrightCyan = "#34e2e2",
|
||||
BrightWhite = "#eeeeec",
|
||||
Foreground = "#ffffff",
|
||||
Background = "#000000",
|
||||
Cursor = "#ffffff",
|
||||
CursorAccent = "#000000",
|
||||
Selection = "rgba(255, 255, 255, 0.3)"
|
||||
}
|
||||
};
|
||||
|
||||
var powerShell = new TerminalTheme
|
||||
{
|
||||
Id = Guid.Parse("3571ce1b-31ce-4cf7-ae15-e0bff70c3eea"),
|
||||
Author = "Microsoft",
|
||||
Name = "PowerShell",
|
||||
PreInstalled = true,
|
||||
BackgroundOpacity = 0.8,
|
||||
Colors = new TerminalColors
|
||||
{
|
||||
Black = "#000000",
|
||||
Red = "#800000",
|
||||
Green = "#008000",
|
||||
Yellow = "#EEEDF0",
|
||||
Blue = "#000080",
|
||||
Magenta = "#012456",
|
||||
Cyan = "#008080",
|
||||
White = "#c0c0c0",
|
||||
BrightBlack = "#808080",
|
||||
BrightRed = "#ff0000",
|
||||
BrightGreen = "#00ff00",
|
||||
BrightYellow = "#ffff00",
|
||||
BrightBlue = "#0000ff",
|
||||
BrightMagenta = "#ff00ff",
|
||||
BrightCyan = "#00ffff",
|
||||
BrightWhite = "#ffffff",
|
||||
Foreground = "#ffffff",
|
||||
Background = "#012456",
|
||||
Cursor = "#fedba9",
|
||||
CursorAccent = "#000000",
|
||||
Selection = "#fedba9"
|
||||
}
|
||||
};
|
||||
|
||||
return new[] { defaultXterm, powerShell };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Popups;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
internal class DialogService : IDialogService
|
||||
{
|
||||
public async Task<DialogButton> ShowDialogAsnyc(string title, string content, params DialogButton[] buttons)
|
||||
{
|
||||
var dialog = new MessageDialog(content, title);
|
||||
|
||||
foreach (var button in buttons)
|
||||
{
|
||||
dialog.Commands.Add(new UICommand(button.ToString()));
|
||||
}
|
||||
|
||||
var result = await dialog.ShowAsync();
|
||||
|
||||
return Enum.Parse<DialogButton>(result.Label);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
using FluentTerminal.App.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentTerminal.App.Utilities;
|
||||
using FluentTerminal.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
@@ -8,13 +12,25 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private ApplicationDataContainer _localSettings;
|
||||
private ApplicationDataContainer _themes;
|
||||
private ApplicationDataContainer _roamingSettings;
|
||||
|
||||
public event EventHandler CurrentThemeChanged;
|
||||
public event EventHandler TerminalOptionsChanged;
|
||||
|
||||
public SettingsService(IDefaultValueProvider defaultValueProvider)
|
||||
{
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
_localSettings = ApplicationData.Current.LocalSettings;
|
||||
_roamingSettings = ApplicationData.Current.RoamingSettings;
|
||||
|
||||
_themes = _roamingSettings.CreateContainer("Themes", ApplicationDataCreateDisposition.Always);
|
||||
|
||||
foreach (var theme in _defaultValueProvider.GetPreInstalledThemes())
|
||||
{
|
||||
_themes.WriteValueAsJson(theme.Id.ToString(), theme);
|
||||
}
|
||||
|
||||
ApplicationData.Current.DataChanged += OnDataChanged;
|
||||
}
|
||||
|
||||
@@ -28,11 +44,67 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
return _localSettings.ReadValueFromJson(nameof(ShellConfiguration), _defaultValueProvider.GetDefaultShellConfiguration());
|
||||
}
|
||||
|
||||
public void SaveShellConfiguration(ShellConfiguration spawnConfiguration)
|
||||
public void SaveShellConfiguration(ShellConfiguration shellConfiguration)
|
||||
{
|
||||
_localSettings.WriteValueAsJson(nameof(ShellConfiguration), spawnConfiguration);
|
||||
_localSettings.WriteValueAsJson(nameof(ShellConfiguration), shellConfiguration);
|
||||
}
|
||||
|
||||
|
||||
public TerminalTheme GetCurrentTheme()
|
||||
{
|
||||
var id = GetCurrentThemeId();
|
||||
return GetTheme(id);
|
||||
}
|
||||
|
||||
public Guid GetCurrentThemeId()
|
||||
{
|
||||
if (_roamingSettings.Values.TryGetValue("CurrentTheme", out object value))
|
||||
{
|
||||
return (Guid)value;
|
||||
}
|
||||
return _defaultValueProvider.GetDefaultThemeId();
|
||||
}
|
||||
|
||||
public void SaveCurrentThemeId(Guid id)
|
||||
{
|
||||
_roamingSettings.Values["CurrentTheme"] = id;
|
||||
|
||||
CurrentThemeChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void SaveTheme(TerminalTheme theme)
|
||||
{
|
||||
_themes.WriteValueAsJson(theme.Id.ToString(), theme);
|
||||
|
||||
if (theme.Id == GetCurrentThemeId())
|
||||
{
|
||||
CurrentThemeChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteTheme(Guid id)
|
||||
{
|
||||
_themes.Values.Remove(id.ToString());
|
||||
}
|
||||
|
||||
public IEnumerable<TerminalTheme> GetThemes()
|
||||
{
|
||||
return _themes.Values.Select(x => JsonConvert.DeserializeObject<TerminalTheme>((string)x.Value)).ToList();
|
||||
}
|
||||
|
||||
public TerminalTheme GetTheme(Guid id)
|
||||
{
|
||||
return _themes.ReadValueFromJson(id.ToString(), default(TerminalTheme));
|
||||
}
|
||||
|
||||
public TerminalOptions GetTerminalOptions()
|
||||
{
|
||||
return _localSettings.ReadValueFromJson(nameof(TerminalOptions), _defaultValueProvider.GetDefaultTerminalOptions());
|
||||
}
|
||||
|
||||
public void SaveTerminalOptions(TerminalOptions terminalOptions)
|
||||
{
|
||||
_localSettings.WriteValueAsJson(nameof(TerminalOptions), terminalOptions);
|
||||
TerminalOptionsChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:input="using:Telerik.UI.Xaml.Controls.Input">
|
||||
|
||||
<Style
|
||||
x:Key="WindowTitleTextBlockStyle"
|
||||
@@ -11,6 +14,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 +72,279 @@
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ColorPreviewButtonStyle" TargetType="Button">
|
||||
<Setter Property="Width" Value="24" />
|
||||
<Setter Property="Height" Value="24" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="True" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
|
||||
<ContentPresenter
|
||||
x:Name="ContentPresenter"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTransitions="{TemplateBinding ContentTransitions}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ThemeAppBarButtonStyle" TargetType="AppBarButton">
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource AppBarButtonBorderBrush}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Top" />
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="Width" Value="68" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="True" />
|
||||
<Setter Property="AllowFocusOnInteraction" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="AppBarButton">
|
||||
<Grid
|
||||
x:Name="Root"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
MaxWidth="{TemplateBinding MaxWidth}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<Grid x:Name="ContentRoot" MinHeight="{ThemeResource AppBarThemeMinHeight}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Viewbox
|
||||
x:Name="ContentViewbox"
|
||||
Height="20"
|
||||
Margin="0,14,0,4"
|
||||
HorizontalAlignment="Stretch"
|
||||
AutomationProperties.AccessibilityView="Raw">
|
||||
<ContentPresenter
|
||||
x:Name="Content"
|
||||
Height="20"
|
||||
Content="{TemplateBinding Icon}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
</Viewbox>
|
||||
<TextBlock
|
||||
x:Name="TextLabel"
|
||||
Grid.Row="1"
|
||||
Margin="2,0,2,6"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
FontSize="12"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Text="{TemplateBinding Label}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
x:Name="OverflowTextLabel"
|
||||
Margin="12,0,12,0"
|
||||
Padding="0,5,0,7"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
FontSize="15"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Text="{TemplateBinding Label}"
|
||||
TextAlignment="Left"
|
||||
TextTrimming="Clip"
|
||||
TextWrapping="NoWrap"
|
||||
Visibility="Collapsed" />
|
||||
</Grid>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="ApplicationViewStates">
|
||||
<VisualState x:Name="FullSize" />
|
||||
<VisualState x:Name="Compact">
|
||||
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="LabelOnRight">
|
||||
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentViewbox" Storyboard.TargetProperty="Margin">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="12,14,0,14" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="MinHeight">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource AppBarThemeCompactHeight}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="(Grid.Row)">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="0" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="(Grid.Column)">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="1" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="TextAlignment">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Left" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Margin">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="8,15,12,17" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="LabelCollapsed">
|
||||
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="MinHeight">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource AppBarThemeCompactHeight}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Overflow">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentRoot.MinHeight" Value="0" />
|
||||
<Setter Target="ContentViewbox.Visibility" Value="Collapsed" />
|
||||
<Setter Target="TextLabel.Visibility" Value="Collapsed" />
|
||||
<Setter Target="OverflowTextLabel.Visibility" Value="Visible" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowWithToggleButtons">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentRoot.MinHeight" Value="0" />
|
||||
<Setter Target="ContentViewbox.Visibility" Value="Collapsed" />
|
||||
<Setter Target="TextLabel.Visibility" Value="Collapsed" />
|
||||
<Setter Target="OverflowTextLabel.Visibility" Value="Visible" />
|
||||
<Setter Target="OverflowTextLabel.Margin" Value="38,0,12,0" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowWithMenuIcons">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentRoot.MinHeight" Value="0" />
|
||||
<Setter Target="ContentViewbox.HorizontalAlignment" Value="Left" />
|
||||
<Setter Target="ContentViewbox.VerticalAlignment" Value="Center" />
|
||||
<Setter Target="ContentViewbox.Width" Value="16" />
|
||||
<Setter Target="ContentViewbox.Height" Value="16" />
|
||||
<Setter Target="ContentViewbox.Margin" Value="12,0,12,0" />
|
||||
<Setter Target="TextLabel.Visibility" Value="Collapsed" />
|
||||
<Setter Target="OverflowTextLabel.Visibility" Value="Visible" />
|
||||
<Setter Target="OverflowTextLabel.Margin" Value="38,0,12,0" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowWithToggleButtonsAndMenuIcons">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentRoot.MinHeight" Value="0" />
|
||||
<Setter Target="ContentViewbox.HorizontalAlignment" Value="Left" />
|
||||
<Setter Target="ContentViewbox.VerticalAlignment" Value="Center" />
|
||||
<Setter Target="ContentViewbox.Width" Value="16" />
|
||||
<Setter Target="ContentViewbox.Height" Value="16" />
|
||||
<Setter Target="ContentViewbox.Margin" Value="38,0,12,0" />
|
||||
<Setter Target="TextLabel.Visibility" Value="Collapsed" />
|
||||
<Setter Target="OverflowTextLabel.Visibility" Value="Visible" />
|
||||
<Setter Target="OverflowTextLabel.Margin" Value="76,0,12,0" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal">
|
||||
<Storyboard>
|
||||
<PointerUpThemeAnimation Storyboard.TargetName="OverflowTextLabel" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Root.Background" Value="{StaticResource TitleBarHoverBackgroundColor}" />
|
||||
<Setter Target="Root.BorderBrush" Value="{ThemeResource AppBarButtonBorderBrushPointerOver}" />
|
||||
</VisualState.Setters>
|
||||
|
||||
<Storyboard>
|
||||
<PointerUpThemeAnimation Storyboard.TargetName="OverflowTextLabel" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Pressed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Root.Background" Value="{StaticResource TitleBarPressedBackgroundColor}" />
|
||||
<Setter Target="Root.BorderBrush" Value="{ThemeResource AppBarButtonBorderBrushPressed}" />
|
||||
</VisualState.Setters>
|
||||
|
||||
<Storyboard>
|
||||
<PointerDownThemeAnimation Storyboard.TargetName="OverflowTextLabel" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Root.Background" Value="Transparent" />
|
||||
<Setter Target="Root.BorderBrush" Value="{ThemeResource AppBarButtonBorderBrushDisabled}" />
|
||||
<Setter Target="Content.Foreground" Value="{StaticResource DisabledForegroundColor}" />
|
||||
<Setter Target="TextLabel.Foreground" Value="{StaticResource DisabledForegroundColor}" />
|
||||
<Setter Target="OverflowTextLabel.Foreground" Value="{StaticResource DisabledForegroundColor}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowNormal">
|
||||
|
||||
<Storyboard>
|
||||
<PointerUpThemeAnimation Storyboard.TargetName="ContentRoot" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowPointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Root.Background" Value="{StaticResource TitleBarHoverBackgroundColor}" />
|
||||
<Setter Target="Root.BorderBrush" Value="{ThemeResource AppBarButtonBorderBrushPointerOver}" />
|
||||
</VisualState.Setters>
|
||||
|
||||
<Storyboard>
|
||||
<PointerUpThemeAnimation Storyboard.TargetName="ContentRoot" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OverflowPressed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Root.Background" Value="{StaticResource TitleBarPressedBackgroundColor}" />
|
||||
<Setter Target="Root.BorderBrush" Value="{ThemeResource AppBarButtonBorderBrushPressed}" />
|
||||
</VisualState.Setters>
|
||||
|
||||
<Storyboard>
|
||||
<PointerDownThemeAnimation Storyboard.TargetName="ContentRoot" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="InputModeStates">
|
||||
<VisualState x:Name="InputModeDefault" />
|
||||
<VisualState x:Name="TouchInputMode">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="OverflowTextLabel.Padding" Value="0,11,0,13" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="GameControllerInputMode">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="OverflowTextLabel.Padding" Value="0,11,0,13" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -1,4 +1,5 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace FluentTerminal.App.Utilities
|
||||
@@ -9,6 +10,11 @@ namespace FluentTerminal.App.Utilities
|
||||
{
|
||||
if (container.Values.TryGetValue(name, out object value))
|
||||
{
|
||||
if (fallbackValue == null)
|
||||
{
|
||||
fallbackValue = Activator.CreateInstance<T>();
|
||||
}
|
||||
|
||||
JsonConvert.PopulateObject((string)value, fallbackValue);
|
||||
}
|
||||
return fallbackValue;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using Microsoft.Toolkit.Uwp.Helpers;
|
||||
using System.Globalization;
|
||||
using Windows.UI;
|
||||
|
||||
namespace FluentTerminal.App.Utilities
|
||||
{
|
||||
public static class ColorExtensions
|
||||
{
|
||||
public static string ToColorString(this Color color, bool allowTransparency)
|
||||
{
|
||||
if (allowTransparency)
|
||||
{
|
||||
return $"rgba({color.R:G}, {color.G:G}, {color.B:G}, {ToDoubleString(color.A)})";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"#{color.R:X2}{color.G:X2}{color.B:X2}";
|
||||
}
|
||||
}
|
||||
|
||||
private static string ToDoubleString(byte alpha)
|
||||
{
|
||||
return (alpha / 256.0).ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public static Color FromString(this string colorString)
|
||||
{
|
||||
if (colorString.Contains("rgba("))
|
||||
{
|
||||
colorString = colorString.Replace("rgba(", string.Empty);
|
||||
colorString = colorString.Replace(")", string.Empty);
|
||||
|
||||
var parts = colorString.Split(", ");
|
||||
|
||||
return new Color
|
||||
{
|
||||
A = (byte)(int)(double.Parse(parts[3]) * 256.0),
|
||||
R = byte.Parse(parts[0]),
|
||||
G = byte.Parse(parts[1]),
|
||||
B = byte.Parse(parts[2])
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return colorString.ToColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,57 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.UI.Core;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
public class MainViewModel : ViewModelBase
|
||||
{
|
||||
private const string FallbackTitle = "Fluent Terminal";
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ITerminalService _terminalService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private string _background;
|
||||
private double _backgroundOpacity;
|
||||
private CoreDispatcher _dispatcher;
|
||||
private TerminalViewModel _selectedTerminal;
|
||||
private string _title;
|
||||
|
||||
public MainViewModel(ISettingsService settingsService, ITerminalService terminalService)
|
||||
public MainViewModel(ISettingsService settingsService, ITerminalService terminalService, IDialogService dialogService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_settingsService.CurrentThemeChanged += OnCurrentThemeChanged;
|
||||
_terminalService = terminalService;
|
||||
Title = "Fluent Terminal";
|
||||
_dialogService = dialogService;
|
||||
Title = FallbackTitle;
|
||||
|
||||
AddTerminalCommand = new RelayCommand(AddTerminal);
|
||||
var currentTheme = _settingsService.GetCurrentTheme();
|
||||
Background = currentTheme.Colors.Background;
|
||||
BackgroundOpacity = currentTheme.BackgroundOpacity;
|
||||
|
||||
AddTerminalCommand = new RelayCommand(() => AddTerminal(null));
|
||||
ShowSettingsCommand = new RelayCommand(async () => await ShowSettings());
|
||||
|
||||
AddTerminal();
|
||||
_dispatcher = CoreApplication.GetCurrentView().Dispatcher;
|
||||
}
|
||||
|
||||
public RelayCommand AddTerminalCommand { get; }
|
||||
public RelayCommand ShowSettingsCommand { get; }
|
||||
|
||||
public double BackgroundOpacity
|
||||
{
|
||||
get => _backgroundOpacity;
|
||||
set => Set(ref _backgroundOpacity, value);
|
||||
}
|
||||
|
||||
public string Background
|
||||
{
|
||||
get => _background;
|
||||
set => Set(ref _background, value);
|
||||
}
|
||||
|
||||
public TerminalViewModel SelectedTerminal
|
||||
{
|
||||
@@ -34,6 +59,8 @@ namespace FluentTerminal.App.ViewModels
|
||||
set => Set(ref _selectedTerminal, value);
|
||||
}
|
||||
|
||||
public RelayCommand ShowSettingsCommand { get; }
|
||||
|
||||
public ObservableCollection<TerminalViewModel> Terminals { get; } = new ObservableCollection<TerminalViewModel>();
|
||||
|
||||
public string Title
|
||||
@@ -42,14 +69,21 @@ namespace FluentTerminal.App.ViewModels
|
||||
set => Set(ref _title, value);
|
||||
}
|
||||
|
||||
private void AddTerminal()
|
||||
public void AddTerminal(string startupDirectory)
|
||||
{
|
||||
var terminal = new TerminalViewModel(_settingsService, _terminalService);
|
||||
var terminal = new TerminalViewModel(_settingsService, _terminalService, _dialogService, startupDirectory);
|
||||
terminal.PropertyChanged += (s, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(TerminalViewModel.Title) && Terminals.Count == 1)
|
||||
{
|
||||
Title = terminal.Title;
|
||||
if (string.IsNullOrWhiteSpace(terminal.Title))
|
||||
{
|
||||
Title = FallbackTitle;
|
||||
}
|
||||
else
|
||||
{
|
||||
Title = terminal.Title;
|
||||
}
|
||||
}
|
||||
};
|
||||
Terminals.Add(terminal);
|
||||
@@ -57,6 +91,16 @@ namespace FluentTerminal.App.ViewModels
|
||||
SelectedTerminal = terminal;
|
||||
}
|
||||
|
||||
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 Task ShowSettings()
|
||||
{
|
||||
return App.Instance.ShowSettings();
|
||||
|
||||
@@ -3,10 +3,13 @@ using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage.Pickers;
|
||||
using Windows.UI.Popups;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
@@ -14,24 +17,193 @@ namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private readonly IDialogService _dialogService;
|
||||
private ShellConfiguration _shellConfiguration;
|
||||
private TerminalOptions _terminalOptions;
|
||||
private ThemeViewModel _selectedTheme;
|
||||
|
||||
public SettingsViewModel(ISettingsService settingsService, IDefaultValueProvider defaultValueProvider)
|
||||
public SettingsViewModel(ISettingsService settingsService, IDefaultValueProvider defaultValueProvider, IDialogService dialogService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
|
||||
_dialogService = dialogService;
|
||||
BrowseForCustomShellCommand = new RelayCommand(async () => await BrowseForCustomShell());
|
||||
BrowseForWorkingDirectoryCommand = new RelayCommand(async () => await BrowseForWorkingDirectory());
|
||||
RestoreDefaultsCommand = new RelayCommand<string>(async (area) => await RestoreDefaults(area));
|
||||
CreateThemeCommand = new RelayCommand(CreateTheme);
|
||||
|
||||
_shellConfiguration = _settingsService.GetShellConfiguration();
|
||||
_terminalOptions = _settingsService.GetTerminalOptions();
|
||||
ShellType = _shellConfiguration.Shell;
|
||||
|
||||
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();
|
||||
|
||||
Fonts = CanvasTextFormat.GetSystemFontFamilies().OrderBy(s => s);
|
||||
|
||||
Sizes = Enumerable.Range(1, 72);
|
||||
}
|
||||
|
||||
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 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 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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public RelayCommand BrowseForCustomShellCommand { get; }
|
||||
public RelayCommand BrowseForWorkingDirectoryCommand { get; }
|
||||
public RelayCommand<string> RestoreDefaultsCommand { get; }
|
||||
public RelayCommand CreateThemeCommand { get; set; }
|
||||
|
||||
public ObservableCollection<ThemeViewModel> Themes { get; } = new ObservableCollection<ThemeViewModel>();
|
||||
|
||||
public IEnumerable<string> Fonts { get; }
|
||||
|
||||
public IEnumerable<int> Sizes { get; }
|
||||
|
||||
public ThemeViewModel SelectedTheme
|
||||
{
|
||||
get => _selectedTheme;
|
||||
set => Set(ref _selectedTheme, value);
|
||||
}
|
||||
|
||||
private CursorStyle CursorStyle
|
||||
{
|
||||
get => _terminalOptions.CursorStyle;
|
||||
set
|
||||
{
|
||||
if (_terminalOptions.CursorStyle != value)
|
||||
{
|
||||
_terminalOptions.CursorStyle = value;
|
||||
_settingsService.SaveTerminalOptions(_terminalOptions);
|
||||
RaisePropertyChanged();
|
||||
RaisePropertyChanged(nameof(BlockIsSelected));
|
||||
RaisePropertyChanged(nameof(BarIsSelected));
|
||||
RaisePropertyChanged(nameof(UnderlineIsSelected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool CursorBlink
|
||||
{
|
||||
get => _terminalOptions.CursorBlink;
|
||||
set
|
||||
{
|
||||
if (_terminalOptions.CursorBlink != value)
|
||||
{
|
||||
_terminalOptions.CursorBlink = value;
|
||||
_settingsService.SaveTerminalOptions(_terminalOptions);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int FontSize
|
||||
{
|
||||
get => _terminalOptions.FontSize;
|
||||
set
|
||||
{
|
||||
if (_terminalOptions.FontSize != value)
|
||||
{
|
||||
_terminalOptions.FontSize = value;
|
||||
_settingsService.SaveTerminalOptions(_terminalOptions);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string FontFamily
|
||||
{
|
||||
get => _terminalOptions.FontFamily;
|
||||
set
|
||||
{
|
||||
if (_terminalOptions.FontFamily != value)
|
||||
{
|
||||
_terminalOptions.FontFamily = value;
|
||||
_settingsService.SaveTerminalOptions(_terminalOptions);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool BlockIsSelected
|
||||
{
|
||||
get => CursorStyle == CursorStyle.Block;
|
||||
set => CursorStyle = CursorStyle.Block;
|
||||
}
|
||||
|
||||
public bool BarIsSelected
|
||||
{
|
||||
get => CursorStyle == CursorStyle.Bar;
|
||||
set => CursorStyle = CursorStyle.Bar;
|
||||
}
|
||||
|
||||
public bool UnderlineIsSelected
|
||||
{
|
||||
get => CursorStyle == CursorStyle.Underline;
|
||||
set => CursorStyle = CursorStyle.Underline;
|
||||
}
|
||||
|
||||
public bool CMDIsSelected
|
||||
{
|
||||
@@ -138,13 +310,9 @@ namespace FluentTerminal.App.ViewModels
|
||||
|
||||
private async Task RestoreDefaults(string area)
|
||||
{
|
||||
var dialog = new MessageDialog("Are you sure you want to restore default values for this page?", "Please confirm");
|
||||
dialog.Commands.Add(new UICommand("OK"));
|
||||
dialog.Commands.Add(new UICommand("Cancel"));
|
||||
var result = await _dialogService.ShowDialogAsnyc("Please confirm", "Are you sure you want to restore default values for this page?", DialogButton.OK, DialogButton.Cancel);
|
||||
|
||||
var result = await dialog.ShowAsync();
|
||||
|
||||
if (result.Label == "OK" && area == "shell")
|
||||
if (result == DialogButton.OK && area == "shell")
|
||||
{
|
||||
var defaults = _defaultValueProvider.GetDefaultShellConfiguration();
|
||||
ShellType = defaults.Shell;
|
||||
@@ -152,6 +320,14 @@ namespace FluentTerminal.App.ViewModels
|
||||
WorkingDirectory = defaults.WorkingDirectory;
|
||||
Arguments = defaults.Arguments;
|
||||
}
|
||||
else if(result == DialogButton.OK && area == "terminal")
|
||||
{
|
||||
var defaults = _defaultValueProvider.GetDefaultTerminalOptions();
|
||||
CursorBlink = defaults.CursorBlink;
|
||||
CursorStyle = defaults.CursorStyle;
|
||||
FontFamily = defaults.FontFamily;
|
||||
FontSize = defaults.FontSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,30 +4,49 @@ using FluentTerminal.Models;
|
||||
using GalaSoft.MvvmLight;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Popups;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
public class TerminalViewModel : ViewModelBase
|
||||
{
|
||||
private ITerminalView _terminalView;
|
||||
private string _title;
|
||||
private string _resizeOverlayContent;
|
||||
private bool _showResizeOverlay;
|
||||
private DispatcherTimer _resizeOverlayTimer;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ITerminalService _terminalService;
|
||||
private readonly IDialogService _dialogService;
|
||||
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(ISettingsService settingsService, ITerminalService terminalService, IDialogService dialogService, string startupDirectory)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_settingsService.CurrentThemeChanged += OnCurrentThemeChanged;
|
||||
_settingsService.TerminalOptionsChanged += OnTerminalOptionsChanged;
|
||||
_terminalService = terminalService;
|
||||
_dialogService = dialogService;
|
||||
_startupDirectory = startupDirectory;
|
||||
_resizeOverlayTimer = new DispatcherTimer();
|
||||
_resizeOverlayTimer.Interval = new TimeSpan(0, 0, 2);
|
||||
_resizeOverlayTimer.Tick += OnResizeOverlayTimerFinished;
|
||||
|
||||
_dispatcher = CoreApplication.GetCurrentView().Dispatcher;
|
||||
}
|
||||
|
||||
public int Id { get; private set; }
|
||||
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
public string Title
|
||||
public string ResizeOverlayContent
|
||||
{
|
||||
get => _title;
|
||||
set => Set(ref _title, value);
|
||||
get => _resizeOverlayContent;
|
||||
set => Set(ref _resizeOverlayContent, value);
|
||||
}
|
||||
|
||||
public bool ShowResizeOverlay
|
||||
@@ -47,34 +66,27 @@ namespace FluentTerminal.App.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public string ResizeOverlayContent
|
||||
public string Title
|
||||
{
|
||||
get => _resizeOverlayContent;
|
||||
set => Set(ref _resizeOverlayContent, value);
|
||||
}
|
||||
|
||||
public TerminalViewModel(ISettingsService settingsService, ITerminalService terminalService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_terminalService = terminalService;
|
||||
_resizeOverlayTimer = new DispatcherTimer();
|
||||
_resizeOverlayTimer.Interval = new TimeSpan(0, 0, 2);
|
||||
_resizeOverlayTimer.Tick += OnResizeOverlayTimerFinished;
|
||||
}
|
||||
|
||||
private void OnResizeOverlayTimerFinished(object sender, object e)
|
||||
{
|
||||
_resizeOverlayTimer.Stop();
|
||||
ShowResizeOverlay = false;
|
||||
get => _title;
|
||||
set => Set(ref _title, value);
|
||||
}
|
||||
|
||||
public async Task OnViewIsReady(ITerminalView terminalView)
|
||||
{
|
||||
_terminalView = terminalView;
|
||||
|
||||
var size = await _terminalView.CreateTerminal();
|
||||
var options = _settingsService.GetTerminalOptions();
|
||||
var theme = _settingsService.GetCurrentTheme();
|
||||
|
||||
var size = await _terminalView.CreateTerminal(options, theme.Colors);
|
||||
var configuration = _settingsService.GetShellConfiguration();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_startupDirectory))
|
||||
{
|
||||
configuration.WorkingDirectory = _startupDirectory;
|
||||
}
|
||||
|
||||
var response = await _terminalService.CreateTerminal(size, configuration);
|
||||
|
||||
if (response.Success)
|
||||
@@ -88,14 +100,32 @@ namespace FluentTerminal.App.ViewModels
|
||||
}
|
||||
else
|
||||
{
|
||||
var dialog = new MessageDialog(response.Error, "Error");
|
||||
await dialog.ShowAsync();
|
||||
await _dialogService.ShowDialogAsnyc("Error", response.Error, DialogButton.OK);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTerminalTitleChanged(object sender, string e)
|
||||
private async void OnCurrentThemeChanged(object sender, EventArgs e)
|
||||
{
|
||||
Title = e;
|
||||
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
|
||||
{
|
||||
var currentTheme = _settingsService.GetCurrentTheme();
|
||||
await _terminalView.ChangeTheme(currentTheme.Colors);
|
||||
});
|
||||
}
|
||||
|
||||
private async void OnTerminalOptionsChanged(object sender, EventArgs e)
|
||||
{
|
||||
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
|
||||
{
|
||||
var options = _settingsService.GetTerminalOptions();
|
||||
await _terminalView.ChangeOptions(options);
|
||||
});
|
||||
}
|
||||
|
||||
private void OnResizeOverlayTimerFinished(object sender, object e)
|
||||
{
|
||||
_resizeOverlayTimer.Stop();
|
||||
ShowResizeOverlay = false;
|
||||
}
|
||||
|
||||
private async void OnTerminalSizeChanged(object sender, TerminalSize e)
|
||||
@@ -108,5 +138,10 @@ namespace FluentTerminal.App.ViewModels
|
||||
ShowResizeOverlay = true;
|
||||
await _terminalService.ResizeTerminal(_terminalId, e);
|
||||
}
|
||||
|
||||
private void OnTerminalTitleChanged(object sender, string e)
|
||||
{
|
||||
Title = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,70 @@
|
||||
using Windows.UI;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
{
|
||||
public sealed class BindableColorsTitleBar : Control
|
||||
{
|
||||
private ApplicationViewTitleBar _titleBar;
|
||||
|
||||
private Color? _buttonForeground;
|
||||
private Color? _buttonHoverBackground;
|
||||
private Color? _buttonPressedBackground;
|
||||
private Color? _buttonHoverForeground;
|
||||
private Color? _buttonPressedForeground;
|
||||
private Color? _inactiveForeground;
|
||||
|
||||
public BindableColorsTitleBar()
|
||||
{
|
||||
DefaultStyleKey = typeof(BindableColorsTitleBar);
|
||||
_titleBar = ApplicationView.GetForCurrentView().TitleBar;
|
||||
_buttonHoverBackground = _titleBar.ButtonHoverBackgroundColor = Color.FromArgb(24, 255, 255, 255);
|
||||
_buttonPressedBackground = _titleBar.ButtonPressedBackgroundColor = Color.FromArgb(48, 255, 255, 255);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public void ResetTitleBar()
|
||||
{
|
||||
_titleBar.ButtonForegroundColor = (Color)this.Resources["SystemBaseHighColor"];
|
||||
_titleBar.ButtonHoverBackgroundColor = null;
|
||||
_titleBar.ButtonPressedBackgroundColor = null;
|
||||
_titleBar.ButtonPressedForegroundColor = null;
|
||||
_titleBar.ButtonHoverForegroundColor = null;
|
||||
_titleBar.InactiveForegroundColor = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,9 @@ namespace FluentTerminal.App.Views
|
||||
event EventHandler<TerminalSize> TerminalSizeChanged;
|
||||
event EventHandler<string> TerminalTitleChanged;
|
||||
|
||||
Task<TerminalSize> CreateTerminal();
|
||||
Task ChangeTheme(TerminalColors theme);
|
||||
Task ChangeOptions(TerminalOptions options);
|
||||
Task<TerminalSize> CreateTerminal(TerminalOptions options, TerminalColors theme);
|
||||
Task ConnectToSocket(string url);
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,19 @@
|
||||
xmlns:converters="using:FluentTerminal.App.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Background="{ThemeResource SystemControlAcrylicWindowBrush}"
|
||||
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="*" />
|
||||
|
||||
@@ -46,6 +46,9 @@ namespace FluentTerminal.App.Views
|
||||
Unloaded += OnUnloaded;
|
||||
Window.Current.Activated += OnWindowActivated;
|
||||
SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += OnCloseRequest;
|
||||
|
||||
ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(800, 600);
|
||||
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
|
||||
@@ -20,12 +20,13 @@
|
||||
Visibility="{Binding IsPaneOpen, ElementName=NavigationView, Converter={StaticResource TrueToVisibleConverter}}" />
|
||||
<NavigationView
|
||||
x:Name="NavigationView"
|
||||
AlwaysShowHeader="False"
|
||||
Canvas.ZIndex="0"
|
||||
CompactModeThresholdWidth="560"
|
||||
ExpandedModeThresholdWidth="560"
|
||||
IsSettingsVisible="False"
|
||||
Loaded="NavigationView_Loaded"
|
||||
OpenPaneLength="280"
|
||||
OpenPaneLength="200"
|
||||
SelectionChanged="NavigationView_SelectionChanged">
|
||||
<NavigationView.MenuItems>
|
||||
<NavigationViewItem
|
||||
@@ -33,64 +34,31 @@
|
||||
Icon="Setting"
|
||||
Tag="general" />
|
||||
<NavigationViewItem
|
||||
Content="Key Bindings"
|
||||
Content="Terminal"
|
||||
Icon="Setting"
|
||||
Tag="keyBindings" />
|
||||
Tag="terminal" />
|
||||
<NavigationViewItem
|
||||
Content="Shell"
|
||||
Icon="Setting"
|
||||
Tag="shell" />
|
||||
<NavigationViewItem
|
||||
Content="Font"
|
||||
Content="Key Bindings"
|
||||
Icon="Setting"
|
||||
Tag="font" />
|
||||
Tag="keyBindings" />
|
||||
<NavigationViewItem
|
||||
Content="Colors"
|
||||
Content="Themes"
|
||||
Icon="Setting"
|
||||
Tag="colors" />
|
||||
Tag="themes" />
|
||||
</NavigationView.MenuItems>
|
||||
<NavigationView.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Margin="24,10,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="{Binding CoreTitleBarHeight}" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Margin="0,-2,0,0"
|
||||
IsHitTestVisible="False"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="Settings"
|
||||
Visibility="{Binding IsPaneOpen, ElementName=NavigationView, Converter={StaticResource FalseToVisibleConverter}}" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="28"
|
||||
Style="{StaticResource TitleTextBlockStyle}"
|
||||
Text="{Binding SelectedItem.Content, ElementName=NavigationView}" />
|
||||
<CommandBar
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource SystemControlBackgroundAltHighBrush}"
|
||||
DefaultLabelPosition="Right">
|
||||
<AppBarButton
|
||||
Command="{Binding ViewModel.RestoreDefaultsCommand}"
|
||||
CommandParameter="{Binding SelectedItem.Tag, ElementName=NavigationView}"
|
||||
Icon="Undo"
|
||||
Label="Restore Defaults" />
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</NavigationView.HeaderTemplate>
|
||||
<Frame x:Name="ContentFrame" Margin="24" />
|
||||
<Grid>
|
||||
<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>
|
||||
@@ -27,7 +27,11 @@ namespace FluentTerminal.App.Views
|
||||
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
||||
titleBar.ButtonForegroundColor = (Color)this.Resources["SystemBaseHighColor"];
|
||||
|
||||
ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(1024, 768);
|
||||
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
|
||||
|
||||
ApplicationView.GetForCurrentView().Title = "Settings";
|
||||
|
||||
|
||||
CoreApplicationViewTitleBar coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
|
||||
coreTitleBar.LayoutMetricsChanged += TitleBar_LayoutMetricsChanged;
|
||||
@@ -71,11 +75,11 @@ namespace FluentTerminal.App.Views
|
||||
case "shell":
|
||||
ContentFrame.Navigate(typeof(ShellSettings), ViewModel);
|
||||
break;
|
||||
case "colors":
|
||||
ContentFrame.Navigate(typeof(ColorSettings), ViewModel);
|
||||
case "themes":
|
||||
ContentFrame.Navigate(typeof(ThemeSettings), ViewModel);
|
||||
break;
|
||||
case "font":
|
||||
ContentFrame.Navigate(typeof(FontSettings), ViewModel);
|
||||
case "terminal":
|
||||
ContentFrame.Navigate(typeof(TerminalSettings), ViewModel);
|
||||
break;
|
||||
case "keyBindings":
|
||||
ContentFrame.Navigate(typeof(KeyBindingSettings), ViewModel);
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
<Page
|
||||
x:Class="FluentTerminal.App.Views.SettingsPages.ColorSettings"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:FluentTerminal.App.Views.SettingsPages"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
|
||||
</Page>
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// Die Elementvorlage "Leere Seite" wird unter https://go.microsoft.com/fwlink/?LinkId=234238 dokumentiert.
|
||||
|
||||
namespace FluentTerminal.App.Views.SettingsPages
|
||||
{
|
||||
/// <summary>
|
||||
/// Eine leere Seite, die eigenständig verwendet oder zu der innerhalb eines Rahmens navigiert werden kann.
|
||||
/// </summary>
|
||||
public sealed partial class ColorSettings : Page
|
||||
{
|
||||
public ColorSettings()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<Page
|
||||
x:Class="FluentTerminal.App.Views.SettingsPages.FontSettings"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:FluentTerminal.App.Views.SettingsPages"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
|
||||
</Page>
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// Die Elementvorlage "Leere Seite" wird unter https://go.microsoft.com/fwlink/?LinkId=234238 dokumentiert.
|
||||
|
||||
namespace FluentTerminal.App.Views.SettingsPages
|
||||
{
|
||||
/// <summary>
|
||||
/// Eine leere Seite, die eigenständig verwendet oder zu der innerhalb eines Rahmens navigiert werden kann.
|
||||
/// </summary>
|
||||
public sealed partial class FontSettings : Page
|
||||
{
|
||||
public FontSettings()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,47 +6,81 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
NavigationCacheMode="Required"
|
||||
mc:Ignorable="d">
|
||||
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="1" Margin="24,00,0,24">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="0,10,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="28"
|
||||
Style="{StaticResource TitleTextBlockStyle}"
|
||||
Text="Shell" />
|
||||
<CommandBar
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource SystemControlBackgroundAltHighBrush}"
|
||||
DefaultLabelPosition="Right">
|
||||
<AppBarButton
|
||||
Command="{Binding ViewModel.RestoreDefaultsCommand}"
|
||||
CommandParameter="shell"
|
||||
Icon="Undo"
|
||||
Label="Restore Defaults" />
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
<StackPanel Grid.Row="2" Margin="24,0,0,0">
|
||||
|
||||
<TextBlock Margin="0,0,0,8" Text="Shell Type" />
|
||||
<RadioButton Content="PowerShell" IsChecked="{Binding ViewModel.PoweShellIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="CMD" IsChecked="{Binding ViewModel.CMDIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="Custom" IsChecked="{Binding ViewModel.CustomShellIsSelected, Mode=TwoWay}" />
|
||||
<TextBlock Margin="0,0,0,8" Text="Type" />
|
||||
<RadioButton Content="PowerShell" IsChecked="{Binding ViewModel.PoweShellIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="CMD" IsChecked="{Binding ViewModel.CMDIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="Custom" IsChecked="{Binding ViewModel.CustomShellIsSelected, Mode=TwoWay}" />
|
||||
|
||||
<StackPanel Margin="0,24,0,0" Orientation="Horizontal">
|
||||
<TextBox
|
||||
Width="400"
|
||||
Header="Custom Shell Location"
|
||||
IsEnabled="{x:Bind ViewModel.CustomShellIsSelected, Mode=OneWay}"
|
||||
IsSpellCheckEnabled="False"
|
||||
Text="{x:Bind ViewModel.CustomShellLocation, Mode=TwoWay}" />
|
||||
<Button
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Command="{x:Bind ViewModel.BrowseForCustomShellCommand}"
|
||||
Content="..."
|
||||
IsEnabled="{x:Bind ViewModel.CustomShellIsSelected, Mode=OneWay}"
|
||||
Style="{StaticResource ButtonRevealStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,24,0,0" Orientation="Horizontal">
|
||||
<TextBox
|
||||
Width="400"
|
||||
Header="Working Directory"
|
||||
IsSpellCheckEnabled="False"
|
||||
Text="{x:Bind ViewModel.WorkingDirectory, Mode=TwoWay}" />
|
||||
<Button
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Command="{x:Bind ViewModel.BrowseForWorkingDirectoryCommand}"
|
||||
Content="..."
|
||||
Style="{StaticResource ButtonRevealStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,24,0,0" Orientation="Horizontal">
|
||||
<TextBox
|
||||
Width="400"
|
||||
Header="Custom Shell Location"
|
||||
IsEnabled="{x:Bind ViewModel.CustomShellIsSelected, Mode=OneWay}"
|
||||
Text="{x:Bind ViewModel.CustomShellLocation, Mode=TwoWay}" />
|
||||
<Button
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Command="{x:Bind ViewModel.BrowseForCustomShellCommand}"
|
||||
Content="..."
|
||||
IsEnabled="{x:Bind ViewModel.CustomShellIsSelected, Mode=OneWay}"
|
||||
Style="{StaticResource ButtonRevealStyle}" />
|
||||
Margin="0,24,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Header="Arguments"
|
||||
IsSpellCheckEnabled="False"
|
||||
Text="{x:Bind ViewModel.Arguments, Mode=TwoWay}" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,24,0,0" Orientation="Horizontal">
|
||||
<TextBox
|
||||
Width="400"
|
||||
Header="Working Directory"
|
||||
Text="{x:Bind ViewModel.WorkingDirectory, Mode=TwoWay}" />
|
||||
<Button
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Command="{x:Bind ViewModel.BrowseForWorkingDirectoryCommand}"
|
||||
Content="..."
|
||||
Style="{StaticResource ButtonRevealStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBox
|
||||
Width="400"
|
||||
Margin="0,24,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Header="Arguments"
|
||||
Text="{x:Bind ViewModel.Arguments, Mode=TwoWay}" />
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,61 @@
|
||||
<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="{Binding ViewModel.RestoreDefaultsCommand}"
|
||||
CommandParameter="terminal"
|
||||
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="{Binding ViewModel.BlockIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="Underline" IsChecked="{Binding ViewModel.UnderlineIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="Bar" IsChecked="{Binding ViewModel.BarIsSelected, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,24 @@
|
||||
using FluentTerminal.App.ViewModels;
|
||||
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 SettingsViewModel ViewModel { get; private set; }
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is SettingsViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
<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:converters="using:FluentTerminal.App.Converters"
|
||||
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"
|
||||
NavigationCacheMode="Required"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<converters:NegateConverter x:Key="NegateConverter" />
|
||||
<converters:FalseToVisibleConverter x:Key="FalseToVisibleConverter" />
|
||||
<converters:TrueToVisibleConverter x:Key="TrueToVisibleConverter" />
|
||||
</Page.Resources>
|
||||
<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,32 @@
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace FluentTerminal.App.Views.SettingsPages
|
||||
{
|
||||
public sealed partial class ThemeSettings : Page
|
||||
{
|
||||
public SettingsViewModel ViewModel { get; private set; }
|
||||
|
||||
public ThemeSettings()
|
||||
{
|
||||
InitializeComponent();
|
||||
Root.DataContext = this;
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is SettingsViewModel 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ using FluentTerminal.Models;
|
||||
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.Diagnostics;
|
||||
@@ -38,6 +40,16 @@ namespace FluentTerminal.App.Views
|
||||
SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += OnCloseRequested; //todo move to mainpage
|
||||
_loaded = new SemaphoreSlim(0, 1);
|
||||
|
||||
JsonConvert.DefaultSettings = () => {
|
||||
var settings = new JsonSerializerSettings
|
||||
{
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver(),
|
||||
};
|
||||
settings.Converters.Add(new StringEnumConverter(true));
|
||||
|
||||
return settings;
|
||||
};
|
||||
|
||||
StartMediatorTask();
|
||||
}
|
||||
|
||||
@@ -52,7 +64,7 @@ namespace FluentTerminal.App.Views
|
||||
|
||||
private void OnCloseRequested(object sender, SystemNavigationCloseRequestedPreviewEventArgs e)
|
||||
{
|
||||
_webView.Navigate(new Uri("about:blank"));
|
||||
_webView?.Navigate(new Uri("about:blank"));
|
||||
_webView = null;
|
||||
}
|
||||
|
||||
@@ -119,9 +131,11 @@ namespace FluentTerminal.App.Views
|
||||
_webView.AddWebAllowedObject("terminalBridge", bridge);
|
||||
}
|
||||
|
||||
public async Task<TerminalSize> CreateTerminal()
|
||||
public async Task<TerminalSize> CreateTerminal(TerminalOptions options, TerminalColors theme)
|
||||
{
|
||||
var size = await ExecuteScriptAsync($"createTerminal()");
|
||||
var serializedOptions = JsonConvert.SerializeObject(options);
|
||||
var serializedTheme = JsonConvert.SerializeObject(theme);
|
||||
var size = await ExecuteScriptAsync($"createTerminal('{serializedOptions}', '{serializedTheme}')");
|
||||
return JsonConvert.DeserializeObject<TerminalSize>(size);
|
||||
}
|
||||
|
||||
@@ -139,5 +153,17 @@ namespace FluentTerminal.App.Views
|
||||
{
|
||||
_dispatcherJobs.Add(() => TerminalTitleChanged?.Invoke(this, title));
|
||||
}
|
||||
|
||||
public Task ChangeTheme(TerminalColors theme)
|
||||
{
|
||||
var serialized = JsonConvert.SerializeObject(theme);
|
||||
return ExecuteScriptAsync($"changeTheme('{serialized}')");
|
||||
}
|
||||
|
||||
public Task ChangeOptions(TerminalOptions options)
|
||||
{
|
||||
var serialized = JsonConvert.SerializeObject(options);
|
||||
return ExecuteScriptAsync($"changeOptions('{serialized}')");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
node_modules/
|
||||
dist/
|
||||
Vendored
+654
-348
File diff suppressed because it is too large.
Load diff
-12
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="xterm.css" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="terminal-container"></div>
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Vendored
+10
-1
@@ -96,9 +96,18 @@
|
||||
background-color: #000;
|
||||
overflow-y: scroll;
|
||||
cursor: default;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.xterm canvas {
|
||||
.xterm .xterm-screen {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.xterm .xterm-screen canvas {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
Generated
+5
-6
@@ -2472,12 +2472,6 @@
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"raw-loader": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
|
||||
"integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=",
|
||||
"dev": true
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
||||
@@ -3018,6 +3012,11 @@
|
||||
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
|
||||
"dev": true
|
||||
},
|
||||
"xterm": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/xterm/-/xterm-3.1.0.tgz",
|
||||
"integrity": "sha512-xv4QQQAu8PjAPZE7m0h+i9X9z3vR82wPe0H3g4D9CbyDuQDNt1e+lxeTrkLwuMH3jcxqfHayu3Mu+iyQh62ECg=="
|
||||
},
|
||||
"y18n": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "xcopy /y /s ..\\xterm.js\\build\\xterm.css dist\\ && npx webpack --config webpack.config.js"
|
||||
"build": "xcopy /y /s node_modules\\xterm\\dist\\xterm.css dist\\ && xcopy /y /s src\\style.css dist\\ && xcopy /y /s src\\index.html dist\\ && npx webpack --config webpack.config.js"
|
||||
},
|
||||
"author": "FS Apps",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"webpack": "^3.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"xterm": "^3.1.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="xterm.css" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="terminal-container"></div>
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,7 +1,8 @@
|
||||
import * as Terminal from '../../xterm.js/build/xterm';
|
||||
import * as attach from '../../xterm.js/build/addons/attach/attach';
|
||||
import * as fit from '../../xterm.js/build/addons/fit/fit';
|
||||
import * as winptyCompat from '../../xterm.js/build/addons/winptyCompat/winptyCompat';
|
||||
import * as Terminal from '../node_modules/xterm/dist/xterm';
|
||||
import * as attach from '../node_modules/xterm/dist/addons/attach/attach';
|
||||
import * as fit from '../node_modules/xterm/dist/addons/fit/fit';
|
||||
import * as winptyCompat from '../node_modules/xterm/dist/addons/winptyCompat/winptyCompat';
|
||||
|
||||
|
||||
Terminal.applyAddon(attach);
|
||||
Terminal.applyAddon(fit);
|
||||
@@ -10,20 +11,27 @@ Terminal.applyAddon(winptyCompat);
|
||||
var term, socket;
|
||||
var terminalContainer = document.getElementById('terminal-container');
|
||||
|
||||
function start() {
|
||||
function createTerminal(options, theme) {
|
||||
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';
|
||||
|
||||
options = JSON.parse(options);
|
||||
|
||||
var terminalOptions = {
|
||||
fontFamily: options.fontFamily,
|
||||
fontSize: options.fontSize,
|
||||
cursorStyle: options.cursorStyle,
|
||||
cursorBlink: options.cursorBlink,
|
||||
bellStyle: options.bellStyle,
|
||||
allowTransparency: true,
|
||||
theme: {
|
||||
background: "transparent"
|
||||
}
|
||||
});
|
||||
theme: theme
|
||||
};
|
||||
|
||||
term = new Terminal(terminalOptions);
|
||||
|
||||
window.term = term;
|
||||
|
||||
@@ -52,19 +60,34 @@ function start() {
|
||||
});
|
||||
}
|
||||
|
||||
function runRealTerminal() {
|
||||
function attachTerminal() {
|
||||
term.attach(socket);
|
||||
term._initialized = true;
|
||||
}
|
||||
|
||||
function createTerminal(configuration) {
|
||||
return start();
|
||||
}
|
||||
|
||||
function connectToWebSocket(url) {
|
||||
socket = new WebSocket(url);
|
||||
socket.onopen = runRealTerminal;
|
||||
socket.onopen = attachTerminal;
|
||||
}
|
||||
|
||||
function changeTheme(theme) {
|
||||
theme = JSON.parse(theme);
|
||||
theme.background = 'transparent';
|
||||
|
||||
term.setOption('theme', theme);
|
||||
}
|
||||
|
||||
function changeOptions(options) {
|
||||
options = JSON.parse(options);
|
||||
|
||||
term.setOption('bellStyle', options.bellStyle);
|
||||
term.setOption('cursorBlink', options.cursorBlink);
|
||||
term.setOption('cursorStyle', options.cursorStyle);
|
||||
term.setOption('fontFamily', options.fontFamily);
|
||||
term.setOption('fontSize', options.fontSize);
|
||||
}
|
||||
|
||||
window.createTerminal = createTerminal;
|
||||
window.connectToWebSocket = connectToWebSocket;
|
||||
window.changeTheme = changeTheme;
|
||||
window.changeOptions = changeOptions;
|
||||
@@ -21,4 +21,4 @@ body {
|
||||
|
||||
.terminal {
|
||||
background: transparent !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace FluentTerminal.Models.Enums
|
||||
{
|
||||
public enum BellStyle
|
||||
{
|
||||
None,
|
||||
Sound
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace FluentTerminal.Models.Enums
|
||||
{
|
||||
public enum CursorStyle
|
||||
{
|
||||
Block,
|
||||
Underline,
|
||||
Bar
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class TerminalColors
|
||||
{
|
||||
public string Foreground { get; set; }
|
||||
public string Background { get; set; }
|
||||
public string Cursor { get; set; }
|
||||
public string CursorAccent { get; set; }
|
||||
public string Selection { get; set; }
|
||||
|
||||
public string Black { get; set; }
|
||||
public string Red { get; set; }
|
||||
public string Green { get; set; }
|
||||
public string Yellow { get; set; }
|
||||
public string Blue { get; set; }
|
||||
public string Magenta { get; set; }
|
||||
public string Cyan { get; set; }
|
||||
public string White { get; set; }
|
||||
|
||||
public string BrightBlack { get; set; }
|
||||
public string BrightRed { get; set; }
|
||||
public string BrightGreen { get; set; }
|
||||
public string BrightYellow { get; set; }
|
||||
public string BrightBlue { get; set; }
|
||||
public string BrightMagenta { get; set; }
|
||||
public string BrightCyan { get; set; }
|
||||
public string BrightWhite { get; set; }
|
||||
|
||||
public TerminalColors()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TerminalColors(TerminalColors other)
|
||||
{
|
||||
Foreground = other.Foreground;
|
||||
Background = other.Background;
|
||||
Cursor = other.Cursor;
|
||||
CursorAccent = other.CursorAccent;
|
||||
Selection = other.Selection;
|
||||
|
||||
Black = other.Black;
|
||||
Red = other.Red;
|
||||
Green = other.Green;
|
||||
Yellow = other.Yellow;
|
||||
Blue = other.Blue;
|
||||
Magenta = other.Magenta;
|
||||
Cyan = other.Cyan;
|
||||
White = other.White;
|
||||
|
||||
BrightBlack = other.BrightBlack;
|
||||
BrightRed = other.BrightRed;
|
||||
BrightGreen = other.BrightGreen;
|
||||
BrightYellow = other.BrightYellow;
|
||||
BrightBlue = other.BrightBlue;
|
||||
BrightMagenta = other.BrightMagenta;
|
||||
BrightCyan = other.BrightCyan;
|
||||
BrightWhite = other.BrightWhite;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using FluentTerminal.Models.Enums;
|
||||
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class TerminalOptions
|
||||
{
|
||||
public string FontFamily { get; set; }
|
||||
|
||||
public int FontSize { get; set; }
|
||||
|
||||
public CursorStyle CursorStyle { get; set; }
|
||||
|
||||
public bool CursorBlink { get; set; }
|
||||
|
||||
public BellStyle BellStyle { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace FluentTerminal.Models
|
||||
{
|
||||
public class TerminalTheme
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Author { get; set; }
|
||||
public bool PreInstalled { get; set; }
|
||||
public double BackgroundOpacity { get; set; }
|
||||
public TerminalColors Colors { get; set; }
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large.
Load diff
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="xterm.css" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="terminal-container"></div>
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
-ms-overflow-style: none;
|
||||
background: transparent;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
background: transparent;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#terminal-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.terminal {
|
||||
background: transparent !important;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace FluentTerminal.SystemTray.Services
|
||||
}
|
||||
|
||||
string exe = GetShellLocation(request.Configuration);
|
||||
string args = $"\"{request.Configuration.Arguments}\"";
|
||||
string args = $"\"{exe}\" {request.Configuration.Arguments}";
|
||||
string cwd = GetWorkingDirectory(request.Configuration);
|
||||
spawnConfigHandle = winpty_spawn_config_new(WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, exe, args, cwd, null, out errorHandle);
|
||||
if (errorHandle != IntPtr.Zero)
|
||||
|
||||
@@ -3,8 +3,13 @@
|
||||
|
||||
A Terminal Emulator based on UWP and web technologies. This is far from finished, but feel free to tell my what you think about it.
|
||||
|
||||
## What is working so far:
|
||||
- General usage
|
||||
- Resizing
|
||||
- Configuration of the startup shell
|
||||
- Multiple windows
|
||||
|
||||
## Up Next:
|
||||
- resize support
|
||||
- basic configuration
|
||||
- global hotkeys
|
||||
- tabs and windows
|
||||
- Appearance configuration
|
||||
- Tabs
|
||||
- Key bindings
|
||||
@@ -1,16 +0,0 @@
|
||||
node_modules/
|
||||
*.swp
|
||||
.lock-wscript
|
||||
lib/
|
||||
Makefile.gyp
|
||||
*.Makefile
|
||||
*.target.gyp.mk
|
||||
*.node
|
||||
example/*.log
|
||||
docs/
|
||||
npm-debug.log
|
||||
/.idea/
|
||||
.env
|
||||
build/
|
||||
.vscode/
|
||||
.git/
|
||||
@@ -1,17 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
end_of_line = lf
|
||||
|
||||
[*.{j,t}s]
|
||||
max_line_length = 100
|
||||
|
||||
[*.css]
|
||||
indent_size = 4
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -1 +0,0 @@
|
||||
* text=auto
|
||||
Vendored
-11
@@ -1,11 +0,0 @@
|
||||
<!-- Enter your issue description here -->
|
||||
|
||||
## Details
|
||||
- Browser and browser version:
|
||||
- OS version:
|
||||
- xterm.js version:
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
1.
|
||||
2.
|
||||
@@ -1,28 +0,0 @@
|
||||
node_modules/
|
||||
*.swp
|
||||
.lock-wscript
|
||||
lib/
|
||||
Makefile.gyp
|
||||
*.Makefile
|
||||
*.target.gyp.mk
|
||||
*.node
|
||||
example/*.log
|
||||
docs/
|
||||
npm-debug.log
|
||||
/.idea/
|
||||
.env
|
||||
build/
|
||||
.vscode/
|
||||
.DS_Store
|
||||
fixtures/typings-test/*.js
|
||||
|
||||
# Directories needed for code coverage
|
||||
/coverage/
|
||||
|
||||
# Keep legacy files out of the repo, this can be removed when we merge v3 into master
|
||||
dist/
|
||||
src/utils/TestUtils.ts
|
||||
src/xterm.js
|
||||
|
||||
# Keep the demo builds out of Git
|
||||
demo/dist/
|
||||
Whitespace-only changes.
@@ -1,7 +0,0 @@
|
||||
Antonis Kalipetis <akalipetis@sourcelair.com>
|
||||
Antonis Kalipetis <akalipetis@sourcelair.com> <akalipetis@gmail.com>
|
||||
Daniel Imms <daimms@microsoft.com> <tyriar@tyriar.com>
|
||||
Paris Kasidiaris <paris@sourcelair.com>
|
||||
Paris Kasidiaris <pariskasidiaris@gmail.com>
|
||||
Thanasis Daglis <thanasis@sourcelair.com>
|
||||
Thanasis Daglis <thanasis@sourcelair.com> <ath.daglis@gmail.com>
|
||||
@@ -1,16 +0,0 @@
|
||||
node_modules/
|
||||
*.swp
|
||||
.lock-wscript
|
||||
lib/*.test.js
|
||||
lib/*.test.js.map
|
||||
lib/test/
|
||||
Makefile.gyp
|
||||
*.Makefile
|
||||
*.target.gyp.mk
|
||||
*.node
|
||||
example/*.log
|
||||
docs/
|
||||
npm-debug.log
|
||||
/.idea/
|
||||
.env
|
||||
build/
|
||||
@@ -1,20 +0,0 @@
|
||||
language: node_js
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
node_js:
|
||||
- 6
|
||||
before_install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq install g++-4.8 ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export CXX=g++-4.8 ; fi
|
||||
- npm install -g npm@5.1.0
|
||||
env:
|
||||
matrix:
|
||||
- NPM_COMMAND=lint
|
||||
- NPM_COMMAND=test
|
||||
notifications:
|
||||
email: false
|
||||
script: npm run $NPM_COMMAND
|
||||
after_success: npm run coveralls
|
||||
@@ -1,92 +0,0 @@
|
||||
List of xterm.js contributors. Updated before every release.
|
||||
|
||||
Aleksandr Andrienko <aandrienko@codenvy.com>
|
||||
Aleksandr Andriienko <oandriie@redhat.com>
|
||||
Alessandro Nadalin <alessandro.nadalin@gmail.com>
|
||||
Alexander Olsson <noseglid@gmail.com>
|
||||
Alexey Kontsevoy <alexey@gravitational.com>
|
||||
Anish Athalye <me@anishathalye.com>
|
||||
Anthony Lapenna <lapenna.anthony@gmail.com>
|
||||
Antonis Kalipetis <akalipetis@sourcelair.com>
|
||||
Anton Skshidlevsky <meefik@gmail.com>
|
||||
Anton Yurovskykh <anton.yurovskykh@gmail.com>
|
||||
Artem Arbatskiy <artyom.arbatskiy@gmail.com>
|
||||
Austin Robertson <austinrobertson@gmail.com>
|
||||
ayapi <colors.aya@gmail.com>
|
||||
Ben Hall <ben@benhall.me.uk>
|
||||
Benjamin Fischer <benjamin.fischer@rwth-aachen.de>
|
||||
Bill Church <billchurch@users.noreply.github.com>
|
||||
Bob Reid <bobreid@Bobs-MacBook-Pro.local>
|
||||
bottleofwater <nison.mael+bottleofwater@gmail.com>
|
||||
Brian Mock <brian@mockbrian.com>
|
||||
Bruno Ribeito <b.m.fernandes.ribeiro@gmail.com>
|
||||
Carson Anderson <carson@betterservers.com>
|
||||
CHaBou <chabup@delean.fr>
|
||||
Christian Budde Christensen <budde377@gmail.com>
|
||||
Christof Marti <chrmarti@microsoft.com>
|
||||
Christopher Jeffrey <chjjeffrey@gmail.com>
|
||||
coderaiser <mnemonic.enemy@gmail.com>
|
||||
Dan Brown <jdanbrown@gmail.com>
|
||||
Daniel Griffen <daniel@griffen.io>
|
||||
Daniel Imms <daimms@microsoft.com>
|
||||
Daniel Risacher <drisacher@gmail.com>
|
||||
Dan Kaplun <dbkaplun@twitch.tv>
|
||||
Darin Morrison <freebroccolo@users.noreply.github.com>
|
||||
dcylabs <dcylabs@gmail.com>
|
||||
Dominik Csapak <d.csapak@proxmox.com>
|
||||
Edgar Andrés Margffoy Tuay <andfoy@gmail.com>
|
||||
Elliot Saba <staticfloat@gmail.com>
|
||||
Exile <exile@chamber.ee>
|
||||
Felipe Gasper <felipe@felipegasper.com>
|
||||
ficristo <ficristo.work@gmail.com>
|
||||
Gary Ritchie <gary@rstudio.com>
|
||||
hiro-su <h.sugipon@gmail.com>
|
||||
Ian Lewis <ianlewis@google.com>
|
||||
imoses <ido@twiggle.com>
|
||||
InDieTasten <indietasten@gmail.com>
|
||||
irokas <akasidiari@inf.uth.gr>
|
||||
Jakob Gillich <jakob@gillich.me>
|
||||
Jean Bruenn <himself@jeanbruenn.info>
|
||||
Jeremy Danyow <jedanyow@microsoft.com>
|
||||
Joao Moreno <jomo@microsoft.com>
|
||||
Joao Moreno <mail@joaomoreno.com>
|
||||
Johannes Zellner <johannes@nebulon.de>
|
||||
Jon Masters <jon.masters@sky.com>
|
||||
Jörg Breitbart <jerch@rockborn.de>
|
||||
Justin Mecham <justin@mecham.me>
|
||||
Kirill Merkushev <lanwen@yandex.ru>
|
||||
Luca <LucaT1@users.noreply.github.com>
|
||||
Lucian Buzzo <lucian.buzzo@gmail.com>
|
||||
Lukas Drgon <lukas.drgon@gmail.com>
|
||||
Maël Nison <nison.mael@gmail.com>
|
||||
Marc Dumais <marc.dumais@ericsson.com>
|
||||
Martin Chloride <i@martincl2.me>
|
||||
Martin Koppehel <martin.koppehel@st.ovgu.de>
|
||||
Martin Wang <jiahaow@ca.ibm.com>
|
||||
Matt Bierner <matb@microsoft.com>
|
||||
Michael Irwin <mikesir87@gmail.com>
|
||||
Mikko Karvonen <mikko.karvonen@arm.com>
|
||||
mofux <t.zilz@mofux.org>
|
||||
Nicolas Ramz <nicolas.ramz@gmail.com>
|
||||
npezza93 <npezza93@gmail.com>
|
||||
Oleksandr Andriienko <oandriie@redhat.com>
|
||||
Paris Kasidiaris <pariskasidiaris@gmail.com>
|
||||
Paris Kasidiaris <paris@sourcelair.com>
|
||||
Peter Baumgarten <me@peterbaumgarten.com>
|
||||
Rick Baker <rick@ricktbaker.com>
|
||||
runarberg <runar@greenqloud.com>
|
||||
Samuel Williams <samuel.williams@oriontransfer.co.nz>
|
||||
Saswat Das <saswatds@users.noreply.github.com>
|
||||
Saul Costa <saul@codevolve.com>
|
||||
Shuanglei Tao <tsl0922@gmail.com>
|
||||
Steven Silvester <steven.silvester@ieee.org>
|
||||
stuicey <stuicey@users.noreply.github.com>
|
||||
t-amqi <umberos@gmail.com>
|
||||
Thanasis Daglis <thanasis@sourcelair.com>
|
||||
thomas <thomas@kreativkonzentrat.de>
|
||||
Thomas Zilz <t.zilz@mofux.org>
|
||||
Tine Jozelj <tine.jozelj@outlook.com>
|
||||
Tyler Jewell <tjewell@codenvy.com>
|
||||
Vincent Woo <me@vincentwoo.com>
|
||||
yutaka <shigure@refy.net>
|
||||
YuviPanda <yuvipanda@gmail.com>
|
||||
@@ -1,52 +0,0 @@
|
||||
# How to contribute to xterm.js
|
||||
|
||||
- [Opening issues for bug reports or feature requests](#opening-issues)
|
||||
- [Contributing code](#contributing-code)
|
||||
|
||||
## Opening issues
|
||||
|
||||
The preferred way to report bugs or request features is to use
|
||||
[GitHub issues](http://github.com/sourcelair/xterm.js/issues). Before
|
||||
opening an issue, read these pointers.
|
||||
|
||||
### Opening issues effectively
|
||||
|
||||
- Include information about **the browser in which the problem occurred**. Even
|
||||
if you tested several browsers, and the problem occurred in all of them,
|
||||
mention this fact in the bug report. Also include browser version numbers and
|
||||
the operating system that you're on.
|
||||
|
||||
- Mention which release of xterm.js you're using. Preferably, try also with
|
||||
the current HEAD of the master branch, to ensure the problem has not already been
|
||||
fixed.
|
||||
|
||||
- Mention precisely what went wrong. What did you expect to happen? What happened instead? Describe the
|
||||
exact steps a maintainer has to take to make the problem occur.
|
||||
|
||||
- If the problem can not be reproduced in the [demo of xterm.js](README.md#demo), please provide an HTML document that demonstrates the problem.
|
||||
|
||||
- Be polite. Issues with an indignant or belligerent tone tend to be moved to the
|
||||
bottom of the pile.
|
||||
|
||||
## Contributing code
|
||||
|
||||
- Make sure you have a [GitHub account](https://github.com/join)
|
||||
- Fork [xterm.js](https://github.com/sourcelair/xterm.js/)
|
||||
([how to fork a repo](https://help.github.com/articles/fork-a-repo))
|
||||
- Make your changes
|
||||
- If your changes are easy to test or likely to regress, add tests. Tests go into `test`, directory.
|
||||
- Follow the general code style of the rest of the project (see below).
|
||||
- Submit a pull request
|
||||
([how to create a pull request](https://help.github.com/articles/fork-a-repo)).
|
||||
Don't put more than one feature/fix in a single pull request.
|
||||
|
||||
By contributing code to xterm.js you
|
||||
|
||||
- agree to license the contributed code under xterm.js' [MIT
|
||||
license](LICENSE).
|
||||
|
||||
- confirm that you have the right to contribute and license the code
|
||||
in question. (Either you hold all rights on the code, or the rights
|
||||
holder has explicitly granted the right to use it like this,
|
||||
through a compatible open source license or through a direct
|
||||
agreement with you.)
|
||||
@@ -1,19 +0,0 @@
|
||||
FROM node:6
|
||||
MAINTAINER Paris Kasidiaris <paris@sourcelair.com>
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Set an entrypoint, to automatically install node modules
|
||||
ENTRYPOINT ["/bin/bash", "-c", "if [[ ! -d node_modules ]]; then npm install; fi; exec \"${@:0}\";"]
|
||||
CMD ["npm", "run", "start"]
|
||||
|
||||
# First, install dependencies to improve layer caching
|
||||
COPY package.json /usr/src/app/
|
||||
RUN npm install
|
||||
|
||||
# Add the code
|
||||
COPY . /usr/src/app
|
||||
|
||||
# Run the tests and build, to make sure everything is working nicely
|
||||
RUN npm run build && npm run test
|
||||
@@ -1,20 +0,0 @@
|
||||
Copyright (c) 2014-2016, SourceLair Private Company (https://www.sourcelair.com)
|
||||
Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/)
|
||||
|
||||
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.
|
||||
@@ -1 +0,0 @@
|
||||
web: npm start
|
||||
@@ -1,170 +0,0 @@
|
||||
# [](https://xtermjs.org)
|
||||
|
||||
[](https://travis-ci.org/xtermjs/xterm.js) [](https://coveralls.io/github/sourcelair/xterm.js) [](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://www.jsdelivr.com/package/npm/xterm)
|
||||
|
||||
Xterm.js is a terminal front-end component written in JavaScript that works in the browser.
|
||||
|
||||
It enables applications to provide fully featured terminals to their users and create great development experiences.
|
||||
|
||||
## Features
|
||||
- **Text-based application support**: Use xterm.js to work with applications like `bash`, `git` etc.
|
||||
- **Curses-based application support**: Use xterm.js to work with applications like `vim`, `tmux` etc.
|
||||
- **Mouse events support**: Xterm.js captures mouse events like click and scroll and passes them to the terminal's back-end controlling process
|
||||
- **CJK (Chinese, Japanese, Korean) character support**: Xterm.js renders CJK characters seamlessly
|
||||
- **IME support**: Insert international (including CJK) characters using IME input with your keyboard
|
||||
- **Self-contained library**: Xterm.js works on its own. It does not require any external libraries like jQuery or React to work
|
||||
- **Modular, event-based API**: Lets you build addons and themes with ease
|
||||
|
||||
## What xterm.js is not
|
||||
- Xterm.js is not a terminal application that you can download and use on your computer
|
||||
- Xterm.js is not `bash`. Xterm.js can be connected to processes like `bash` and let you interact with them (provide input, receive output)
|
||||
|
||||
## Getting Started
|
||||
|
||||
First you need to install the module, we ship exclusively through [npm](https://www.npmjs.com/) so you need that installed and then add xterm.js as a dependency by running:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to the head of your html page. Then create a `<div id="terminal"></div>` onto which xterm can attach itself.
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="node_modules/xterm/dist/xterm.css" />
|
||||
<script src="node_modules/xterm/dist/xterm.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="terminal"></div>
|
||||
<script>
|
||||
var term = new Terminal();
|
||||
term.open(document.getElementById('terminal'));
|
||||
term.write('Hello from \033[1;3;31mxterm.js\033[0m $ ')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Finally instantiate the `Terminal` object and then call the `open` function with the DOM object of the `div`.
|
||||
|
||||
### Importing
|
||||
|
||||
The proposed way to load xterm.js is via the ES6 module syntax.
|
||||
|
||||
```javascript
|
||||
import { Terminal } from 'xterm';
|
||||
```
|
||||
|
||||
*Note: There are currently no typings for addons so you will need to upcast if using TypeScript, eg. `(<any>xterm).fit()`.*
|
||||
|
||||
### Addons
|
||||
|
||||
Addons are JavaScript modules that extend the `Terminal` prototype with new methods and attributes to provide additional functionality. There are a handful available in the main repository in the `src/addons` directory and you can even write your own, by using xterm.js' public API.
|
||||
|
||||
To use an addon, just import the JavaScript module and pass it to `Terminal`'s `applyAddon` method:
|
||||
|
||||
```javascript
|
||||
import { Terminal } from xterm;
|
||||
import * as fit from 'xterm/lib/addons/fit/fit';
|
||||
|
||||
|
||||
Terminal.applyAddon(fit);
|
||||
|
||||
var xterm = new Terminal(); // Instantiate the terminal
|
||||
xterm.fit(); // Use the `fit` method, provided by the `fit` addon
|
||||
```
|
||||
|
||||
## Browser Support
|
||||
|
||||
Since xterm.js is typically implemented as a developer tool, only modern browsers are supported officially. Here is a list of the versions we aim to support:
|
||||
|
||||
- Chrome latest
|
||||
- Edge latest
|
||||
- Firefox latest
|
||||
- Safari latest
|
||||
- IE11
|
||||
|
||||
Xterm.js works seamlessly in Electron apps and may even work on earlier versions of the browsers but these are the browsers we strive to keep working.
|
||||
|
||||
## Real-world uses
|
||||
Xterm.js is used in several world-class applications to provide great terminal experiences.
|
||||
|
||||
- [**SourceLair**](https://www.sourcelair.com/): In-browser IDE that provides its users with fully-featured Linux terminals based on xterm.js
|
||||
- [**Microsoft Visual Studio Code**](http://code.visualstudio.com/): Modern, versatile and powerful open source code editor that provides an integrated terminal based on xterm.js
|
||||
- [**ttyd**](https://github.com/tsl0922/ttyd): A command-line tool for sharing terminal over the web, with fully-featured terminal emulation based on xterm.js
|
||||
- [**Katacoda**](https://www.katacoda.com/): Katacoda is an Interactive Learning Platform for software developers, covering the latest Cloud Native technologies.
|
||||
- [**Eclipse Che**](http://www.eclipse.org/che): Developer workspace server, cloud IDE, and Eclipse next-generation IDE.
|
||||
- [**Codenvy**](http://www.codenvy.com): Cloud workspaces for development teams.
|
||||
- [**CoderPad**](https://coderpad.io): Online interviewing platform for programmers. Run code in many programming languages, with results displayed by `xterm.js`.
|
||||
- [**WebSSH2**](https://github.com/billchurch/WebSSH2): A web based SSH2 client using `xterm.js`, socket.io, and ssh2.
|
||||
- [**Spyder Terminal**](https://github.com/spyder-ide/spyder-terminal): A full fledged system terminal embedded on Spyder IDE.
|
||||
- [**Cloud Commander**](https://cloudcmd.io "Cloud Commander"): Orthodox web file manager with console and editor.
|
||||
- [**Codevolve**](https://www.codevolve.com "Codevolve"): Online platform for interactive coding and web development courses. Live container-backed terminal uses `xterm.js`.
|
||||
- [**RStudio**](https://www.rstudio.com/products/RStudio "RStudio"): RStudio is an integrated development environment (IDE) for R.
|
||||
- [**Terminal for Atom**](https://github.com/jsmecham/atom-terminal-tab): A simple terminal for the Atom text editor.
|
||||
- [**Eclipse Orion**](https://orionhub.org): A modern, open source software development environment that runs in the cloud. Code, deploy and run in the cloud.
|
||||
- [**Gravitational Teleport**](https://github.com/gravitational/teleport): Gravitational Teleport is a modern SSH server for remotely accessing clusters of Linux servers via SSH or HTTPS.
|
||||
- [**Hexlet**](https://en.hexlet.io): Practical programming courses (JavaScript, PHP, Unix, databases, functional programming). A steady path from the first line of code to the first job.
|
||||
- [**Selenoid UI**](https://github.com/aerokube/selenoid-ui): Simple UI for the scallable golang implementation of Selenium Hub named Selenoid. We use XTerm for streaming logs over websockets from docker containers.
|
||||
- [**Portainer**](https://portainer.io): Simple management UI for Docker.
|
||||
- [**SSHy**](https://github.com/stuicey/SSHy): HTML5 Based SSHv2 Web Client with E2E encryption utilising `xterm.js`, SJCL & websockets.
|
||||
- [**JupyterLab**](https://github.com/jupyterlab/jupyterlab): An extensible
|
||||
computational environment for Jupyter, supporting interactive data science and scientific computing across all programming languages.
|
||||
- [**Theia**](https://github.com/theia-ide/theia): Theia is a cloud & desktop IDE framework implemented in TypeScript.
|
||||
- [**Opshell**](https://github.com/ricktbaker/opshell) Ops Helper tool to make life easier working with AWS instances across multiple organizations.
|
||||
- [**Proxmox VE**](https://www.proxmox.com/en/proxmox-ve): Proxmox VE is a complete open-source platform for enterprise virtualization. It uses xterm.js for container terminals and the host shell.
|
||||
- [**Script Runner**](https://github.com/ioquatix/script-runner): Run scripts (or a shell) in Atom.
|
||||
- [**Whack Whack Terminal**](https://github.com/Microsoft/WhackWhackTerminal): Terminal emulator for Visual Studio 2017.
|
||||
- [**VTerm**](https://github.com/vterm/vterm): Extensible terminal emulator based on Electron and React.
|
||||
- [**electerm**](http://electerm.html5beta.com): electerm is a terminal/ssh/sftp client(mac, win, linux) based on electron/node-pty/xterm.
|
||||
- [**Kubebox**](https://github.com/astefanutti/kubebox): Terminal console for Kubernetes clusters.
|
||||
|
||||
Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it in our list.
|
||||
|
||||
## Demo
|
||||
|
||||
### Linux or macOS
|
||||
|
||||
First, be sure that a C++ compiler such as GCC-C++ or Clang is installed, then run these commands:
|
||||
|
||||
```
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
Then open http://0.0.0.0:3000 in a web browser.
|
||||
|
||||
### Windows
|
||||
|
||||
First, ensure [node-gyp](https://github.com/nodejs/node-gyp) is installed and configured correctly, then run these commands.
|
||||
|
||||
```
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
Then open http://127.0.0.1:3000 in a web browser.
|
||||
|
||||
*Note: Do not use ConEmu, as it seems to break the demo for some reason.*
|
||||
|
||||
## Releases
|
||||
|
||||
Xterm.js follows a monthly release cycle roughly.
|
||||
|
||||
The existing releases are available at this GitHub repo's [Releases](https://github.com/sourcelair/xterm.js/releases), while the roadmap is available as [Milestones](https://github.com/sourcelair/xterm.js/milestones).
|
||||
|
||||
## Development and Contribution
|
||||
|
||||
Xterm.js is maintained by [SourceLair](https://www.sourcelair.com/) and a few external contributors, but we would love to receive contributions from everyone!
|
||||
|
||||
To contribute either code, documentation or issues to xterm.js please read the [Contributing document](CONTRIBUTING.md) beforehand. The development of xterm.js does not require any special tool. All you need is an editor that supports JavaScript/TypeScript and a browser. You will need Node.js installed locally to get all the features working in the demo.
|
||||
|
||||
## License Agreement
|
||||
|
||||
If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work.
|
||||
|
||||
Copyright (c) 2014-2017, SourceLair, Private Company ([www.sourcelair.com](https://www.sourcelair.com/home)) (MIT License)
|
||||
|
||||
Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
||||
@@ -1,88 +0,0 @@
|
||||
var express = require('express');
|
||||
var app = express();
|
||||
var expressWs = require('express-ws')(app);
|
||||
var os = require('os');
|
||||
var pty = require('node-pty');
|
||||
|
||||
var terminals = {},
|
||||
logs = {};
|
||||
|
||||
app.use('/build', express.static(__dirname + '/../build'));
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.sendFile(__dirname + '/index.html');
|
||||
});
|
||||
|
||||
app.get('/style.css', function(req, res){
|
||||
res.sendFile(__dirname + '/style.css');
|
||||
});
|
||||
|
||||
app.get('/dist/bundle.js', function(req, res){
|
||||
res.sendFile(__dirname + '/dist/bundle.js');
|
||||
});
|
||||
|
||||
app.get('/dist/bundle.js.map', function(req, res){
|
||||
res.sendFile(__dirname + '/dist/bundle.js.map');
|
||||
});
|
||||
|
||||
app.post('/terminals', function (req, res) {
|
||||
var cols = parseInt(req.query.cols),
|
||||
rows = parseInt(req.query.rows),
|
||||
term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
|
||||
name: 'xterm-color',
|
||||
cols: cols || 80,
|
||||
rows: rows || 24,
|
||||
cwd: process.env.PWD,
|
||||
env: process.env
|
||||
});
|
||||
|
||||
console.log('Created terminal with PID: ' + term.pid);
|
||||
terminals[term.pid] = term;
|
||||
logs[term.pid] = '';
|
||||
term.on('data', function(data) {
|
||||
logs[term.pid] += data;
|
||||
});
|
||||
res.send(term.pid.toString());
|
||||
res.end();
|
||||
});
|
||||
|
||||
app.post('/terminals/:pid/size', function (req, res) {
|
||||
var pid = parseInt(req.params.pid),
|
||||
cols = parseInt(req.query.cols),
|
||||
rows = parseInt(req.query.rows),
|
||||
term = terminals[pid];
|
||||
|
||||
term.resize(cols, rows);
|
||||
console.log('Resized terminal ' + pid + ' to ' + cols + ' cols and ' + rows + ' rows.');
|
||||
res.end();
|
||||
});
|
||||
|
||||
app.ws('/terminals/:pid', function (ws, req) {
|
||||
var term = terminals[parseInt(req.params.pid)];
|
||||
console.log('Connected to terminal ' + term.pid);
|
||||
ws.send(logs[term.pid]);
|
||||
|
||||
term.on('data', function(data) {
|
||||
try {
|
||||
ws.send(data);
|
||||
} catch (ex) {
|
||||
// The WebSocket is not open, ignore
|
||||
}
|
||||
});
|
||||
ws.on('message', function(msg) {
|
||||
term.write(msg);
|
||||
});
|
||||
ws.on('close', function () {
|
||||
term.kill();
|
||||
console.log('Closed terminal ' + term.pid);
|
||||
// Clean things up
|
||||
delete terminals[term.pid];
|
||||
delete logs[term.pid];
|
||||
});
|
||||
});
|
||||
|
||||
var port = process.env.PORT || 3000,
|
||||
host = os.platform() === 'win32' ? '127.0.0.1' : '0.0.0.0';
|
||||
|
||||
console.log('App listening to http://' + host + ':' + port);
|
||||
app.listen(port, host);
|
||||
@@ -1,70 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>xterm.js demo</title>
|
||||
<link rel="stylesheet" href="/build/xterm.css" />
|
||||
<link rel="stylesheet" href="/build/addons/fullscreen/fullscreen.css" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.auto.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/1.0.0/fetch.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>xterm.js: xterm, in the browser</h1>
|
||||
<div id="terminal-container"></div>
|
||||
<div>
|
||||
<h2>Actions</h2>
|
||||
<p>
|
||||
<label>Find next <input id="find-next"/></label>
|
||||
<label>Find previous <input id="find-previous"/></label>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Options</h2>
|
||||
<p>
|
||||
<label><input type="checkbox" id="option-cursor-blink"> cursorBlink</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
cursorStyle
|
||||
<select id="option-cursor-style">
|
||||
<option value="block">block</option>
|
||||
<option value="underline">underline</option>
|
||||
<option value="bar">bar</option>
|
||||
</select>
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
bellStyle
|
||||
<select id="option-bell-style">
|
||||
<option value="">none</option>
|
||||
<option value="sound">sound</option>
|
||||
<option value="visual">visual</option>
|
||||
<option value="both">both</option>
|
||||
</select>
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>scrollback <input type="number" id="option-scrollback" value="1000" /></label>
|
||||
</p>
|
||||
<p>
|
||||
<label>tabStopWidth <input type="number" id="option-tabstopwidth" value="8" /></label>
|
||||
</p>
|
||||
<div>
|
||||
<h3>Size</h3>
|
||||
<div>
|
||||
<div style="display: inline-block; margin-right: 16px;">
|
||||
<label for="cols">Columns</label>
|
||||
<input type="number" id="cols" />
|
||||
</div>
|
||||
<div style="display: inline-block; margin-right: 16px;">
|
||||
<label for="rows">Rows</label>
|
||||
<input type="number" id="rows" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><strong>Attention:</strong> The demo is a barebones implementation and is designed for xterm.js evaluation purposes only. Exposing the demo to the public as is would introduce security risks for the host.</p>
|
||||
<script src="dist/bundle.js" defer ></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,179 +0,0 @@
|
||||
import * as Terminal from '../build/xterm';
|
||||
import * as attach from '../build/addons/attach/attach';
|
||||
import * as fit from '../build/addons/fit/fit';
|
||||
import * as fullscreen from '../build/addons/fullscreen/fullscreen';
|
||||
import * as search from '../build/addons/search/search';
|
||||
import * as winptyCompat from '../build/addons/winptyCompat/winptyCompat';
|
||||
|
||||
|
||||
Terminal.applyAddon(attach);
|
||||
Terminal.applyAddon(fit);
|
||||
Terminal.applyAddon(fullscreen);
|
||||
Terminal.applyAddon(search);
|
||||
Terminal.applyAddon(winptyCompat);
|
||||
|
||||
|
||||
var term,
|
||||
protocol,
|
||||
socketURL,
|
||||
socket,
|
||||
pid;
|
||||
|
||||
var terminalContainer = document.getElementById('terminal-container'),
|
||||
actionElements = {
|
||||
findNext: document.querySelector('#find-next'),
|
||||
findPrevious: document.querySelector('#find-previous')
|
||||
},
|
||||
optionElements = {
|
||||
cursorBlink: document.querySelector('#option-cursor-blink'),
|
||||
cursorStyle: document.querySelector('#option-cursor-style'),
|
||||
scrollback: document.querySelector('#option-scrollback'),
|
||||
tabstopwidth: document.querySelector('#option-tabstopwidth'),
|
||||
bellStyle: document.querySelector('#option-bell-style')
|
||||
},
|
||||
colsElement = document.getElementById('cols'),
|
||||
rowsElement = document.getElementById('rows');
|
||||
|
||||
function setTerminalSize() {
|
||||
var cols = parseInt(colsElement.value, 10);
|
||||
var rows = parseInt(rowsElement.value, 10);
|
||||
var viewportElement = document.querySelector('.xterm-viewport');
|
||||
var scrollBarWidth = viewportElement.offsetWidth - viewportElement.clientWidth;
|
||||
var width = (cols * term.renderer.dimensions.actualCellWidth + 20 /*room for scrollbar*/).toString() + 'px';
|
||||
var height = (rows * term.renderer.dimensions.actualCellHeight).toString() + 'px';
|
||||
|
||||
terminalContainer.style.width = width;
|
||||
terminalContainer.style.height = height;
|
||||
term.resize(cols, rows);
|
||||
}
|
||||
|
||||
colsElement.addEventListener('change', setTerminalSize);
|
||||
rowsElement.addEventListener('change', setTerminalSize);
|
||||
|
||||
actionElements.findNext.addEventListener('keypress', function (e) {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
term.findNext(actionElements.findNext.value);
|
||||
}
|
||||
});
|
||||
actionElements.findPrevious.addEventListener('keypress', function (e) {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
term.findPrevious(actionElements.findPrevious.value);
|
||||
}
|
||||
});
|
||||
|
||||
optionElements.cursorBlink.addEventListener('change', function () {
|
||||
term.setOption('cursorBlink', optionElements.cursorBlink.checked);
|
||||
});
|
||||
optionElements.cursorStyle.addEventListener('change', function () {
|
||||
term.setOption('cursorStyle', optionElements.cursorStyle.value);
|
||||
});
|
||||
optionElements.bellStyle.addEventListener('change', function () {
|
||||
term.setOption('bellStyle', optionElements.bellStyle.value);
|
||||
});
|
||||
optionElements.scrollback.addEventListener('change', function () {
|
||||
term.setOption('scrollback', parseInt(optionElements.scrollback.value, 10));
|
||||
});
|
||||
optionElements.tabstopwidth.addEventListener('change', function () {
|
||||
term.setOption('tabStopWidth', parseInt(optionElements.tabstopwidth.value, 10));
|
||||
});
|
||||
|
||||
createTerminal();
|
||||
|
||||
function createTerminal() {
|
||||
// Clean terminal
|
||||
while (terminalContainer.children.length) {
|
||||
terminalContainer.removeChild(terminalContainer.children[0]);
|
||||
}
|
||||
term = new Terminal({
|
||||
cursorBlink: optionElements.cursorBlink.checked,
|
||||
scrollback: parseInt(optionElements.scrollback.value, 10),
|
||||
tabStopWidth: parseInt(optionElements.tabstopwidth.value, 10)
|
||||
});
|
||||
window.term = term; // Expose `term` to window for debugging purposes
|
||||
term.on('resize', function (size) {
|
||||
if (!pid) {
|
||||
return;
|
||||
}
|
||||
var cols = size.cols,
|
||||
rows = size.rows,
|
||||
url = '/terminals/' + pid + '/size?cols=' + cols + '&rows=' + rows;
|
||||
|
||||
fetch(url, {method: 'POST'});
|
||||
});
|
||||
protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
|
||||
socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/';
|
||||
|
||||
term.open(terminalContainer);
|
||||
term.winptyCompatInit();
|
||||
term.fit();
|
||||
term.focus();
|
||||
|
||||
// fit is called within a setTimeout, cols and rows need this.
|
||||
setTimeout(function () {
|
||||
colsElement.value = term.cols;
|
||||
rowsElement.value = term.rows;
|
||||
|
||||
// Set terminal size again to set the specific dimensions on the demo
|
||||
setTerminalSize();
|
||||
|
||||
fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) {
|
||||
|
||||
res.text().then(function (processId) {
|
||||
pid = processId;
|
||||
socketURL += processId;
|
||||
socket = new WebSocket(socketURL);
|
||||
socket.onopen = runRealTerminal;
|
||||
socket.onclose = runFakeTerminal;
|
||||
socket.onerror = runFakeTerminal;
|
||||
});
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function runRealTerminal() {
|
||||
term.attach(socket);
|
||||
term._initialized = true;
|
||||
}
|
||||
|
||||
function runFakeTerminal() {
|
||||
if (term._initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
term._initialized = true;
|
||||
|
||||
var shellprompt = '$ ';
|
||||
|
||||
term.prompt = function () {
|
||||
term.write('\r\n' + shellprompt);
|
||||
};
|
||||
|
||||
term.writeln('Welcome to xterm.js');
|
||||
term.writeln('This is a local terminal emulation, without a real terminal in the back-end.');
|
||||
term.writeln('Type some keys and commands to play around.');
|
||||
term.writeln('');
|
||||
term.prompt();
|
||||
|
||||
term.on('key', function (key, ev) {
|
||||
var printable = (
|
||||
!ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey
|
||||
);
|
||||
|
||||
if (ev.keyCode == 13) {
|
||||
term.prompt();
|
||||
} else if (ev.keyCode == 8) {
|
||||
// Do not delete the prompt
|
||||
if (term.x > 2) {
|
||||
term.write('\b \b');
|
||||
}
|
||||
} else if (printable) {
|
||||
term.write(key);
|
||||
}
|
||||
});
|
||||
|
||||
term.on('paste', function (data, ev) {
|
||||
term.write(data);
|
||||
});
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
body {
|
||||
font-family: helvetica, sans-serif, arial;
|
||||
font-size: 1em;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#terminal-container {
|
||||
width: 800px;
|
||||
height: 450px;
|
||||
margin: 0 auto;
|
||||
padding: 2px;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
volumes:
|
||||
- ./:/usr/src/app
|
||||
ports:
|
||||
- ${XTERMJS_PORT:3000}:3000
|
||||
@@ -1,21 +0,0 @@
|
||||
All tests are made for 80x25 terminal. Make sure to run tests with 80x25.
|
||||
|
||||
Create .text files from xterm (expected output)
|
||||
- open xterm
|
||||
- resize xterm to 80x25
|
||||
- run `python run_tests.py`
|
||||
- copy & paste whole window output into editor
|
||||
- add 26th empty line (due to line handling in toString) - not a bug, a feature ;)
|
||||
- advance to next test with ^D
|
||||
|
||||
|
||||
Known problems
|
||||
##############
|
||||
|
||||
|
||||
t0031-HBP:
|
||||
- no documentation at all about CSIj found - skipping
|
||||
|
||||
t0050-ICH:
|
||||
- bug in xterm? (cant ICH last real char, always sticks to last col)
|
||||
- text used from https://github.com/MarkLodato/vt100-parser/blob/master/test/t0050-ICH.text
|
||||
@@ -1,6 +0,0 @@
|
||||
!"#$%&'()*+,-./
|
||||
0123456789:;<=>?
|
||||
@ABCDEFGHIJKLMNO
|
||||
PQRSTUVWXYZ[\]^_
|
||||
`abcdefghijklmno
|
||||
pqrstuvwxyz{|}~
|
||||
@@ -1,25 +0,0 @@
|
||||
!"#$%&'()*+,-./
|
||||
0123456789:;<=>?
|
||||
@ABCDEFGHIJKLMNO
|
||||
PQRSTUVWXYZ[\]^_
|
||||
`abcdefghijklmno
|
||||
pqrstuvwxyz{|}~
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
|
||||
!
|
||||
"
|
||||
#
|
||||
$
|
||||
%
|
||||
&
|
||||
'
|
||||
(
|
||||
)
|
||||
*
|
||||
+
|
||||
,
|
||||
-
|
||||
.
|
||||
/
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
:
|
||||
;
|
||||
<
|
||||
=
|
||||
>
|
||||
?
|
||||
@
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
E
|
||||
F
|
||||
G
|
||||
H
|
||||
I
|
||||
J
|
||||
K
|
||||
L
|
||||
M
|
||||
N
|
||||
O
|
||||
P
|
||||
Q
|
||||
R
|
||||
S
|
||||
T
|
||||
U
|
||||
V
|
||||
W
|
||||
X
|
||||
Y
|
||||
Z
|
||||
[
|
||||
\
|
||||
]
|
||||
^
|
||||
_
|
||||
`
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
f
|
||||
g
|
||||
h
|
||||
i
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
r
|
||||
s
|
||||
t
|
||||
u
|
||||
v
|
||||
w
|
||||
x
|
||||
y
|
||||
z
|
||||
{
|
||||
|
|
||||
}
|
||||
~
|
||||
@@ -1,25 +0,0 @@
|
||||
g
|
||||
h
|
||||
i
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
r
|
||||
s
|
||||
t
|
||||
u
|
||||
v
|
||||
w
|
||||
x
|
||||
y
|
||||
z
|
||||
{
|
||||
|
|
||||
}
|
||||
~
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
abcdefghijklmnopqrstuvwxyz0123456789
|
||||
@@ -1,25 +0,0 @@
|
||||
abcdefghijklmnopqrstuvwxyz0123456789
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
a
|
||||
ab
|
||||
abc
|
||||
abcd
|
||||
abcde
|
||||
abcdef
|
||||
abcdefg
|
||||
abcdefgh
|
||||
abcdefghi
|
||||
abcdefghij
|
||||
abcdefghijk
|
||||
abcdefghijkl
|
||||
abcdefghijklm
|
||||
abcdefghijklmn
|
||||
abcdefghijklmno
|
||||
abcdefghijklmnop
|
||||
abcdefghijklmnopq
|
||||
abcdefghijklmnopqr
|
||||
abcdefghijklmnopqrs
|
||||
abcdefghijklmnopqrst
|
||||
abcdefghijklmnopqrstu
|
||||
abcdefghijklmnopqrstuv
|
||||
abcdefghijklmnopqrstuvw
|
||||
abcdefghijklmnopqrstuvwx
|
||||
abcdefghijklmnopqrstuvwxy
|
||||
abcdefghijklmnopqrstuvwxyz
|
||||
abcdefghijklmnopqrstuvwxyzA
|
||||
abcdefghijklmnopqrstuvwxyzAB
|
||||
abcdefghijklmnopqrstuvwxyzABC
|
||||
abcdefghijklmnopqrstuvwxyzABCD
|
||||
abcdefghijklmnopqrstuvwxyzABCDE
|
||||
abcdefghijklmnopqrstuvwxyzABCDEF
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFG
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGH
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHI
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJ
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJK
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKL
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLM
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTU
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890a
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890ab
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abc
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcd
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcde
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdef
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijk
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijkl
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmn
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrs
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrst
|
||||
@@ -1,25 +0,0 @@
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890a
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890ab
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abc
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcd
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcde
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdef
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijk
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijkl
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmn
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
|
||||
r
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
|
||||
rs
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq
|
||||
rst
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
26
|
||||
@@ -1,25 +0,0 @@
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
26
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
f
|
||||
g
|
||||
h
|
||||
i
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
r
|
||||
s
|
||||
t
|
||||
u
|
||||
v
|
||||
w
|
||||
x
|
||||
y
|
||||
z
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
E
|
||||
F
|
||||
G
|
||||
H
|
||||
I
|
||||
J
|
||||
K
|
||||
L
|
||||
M
|
||||
N
|
||||
O
|
||||
P
|
||||
Q
|
||||
R
|
||||
S
|
||||
T
|
||||
U
|
||||
V
|
||||
W
|
||||
X
|
||||
Y
|
||||
Z
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
0
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
f
|
||||
g
|
||||
h
|
||||
i
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
r
|
||||
s
|
||||
t
|
||||
@@ -1,25 +0,0 @@
|
||||
7
|
||||
8
|
||||
9
|
||||
0
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
f
|
||||
g
|
||||
h
|
||||
i
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
r
|
||||
s
|
||||
t
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
1␍x
|
||||
2␍x
|
||||
3␍x
|
||||
4␍x
|
||||
5␍x
|
||||
6␍x
|
||||
7␍x
|
||||
@@ -1,25 +0,0 @@
|
||||
x
|
||||
x2
|
||||
x 3
|
||||
x 4
|
||||
x 5
|
||||
x 6
|
||||
x 7
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
b␍a
|
||||
@@ -1,25 +0,0 @@
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
a b
|
||||
|
||||
a
|
||||
|
||||
ab
|
||||
|
||||
Loaded 100 of 329 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user