Compare commits
42
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc7e069f11 | ||
|
|
94a0eac58f | ||
|
|
9af0556d6c | ||
|
|
b14ca2c4ed | ||
|
|
89c1a5a614 | ||
|
|
3e32f611e8 | ||
|
|
07e65ce2bf | ||
|
|
f2a48487f1 | ||
|
|
c9d0cc7368 | ||
|
|
eecc2e8243 | ||
|
|
5c1896cd3b | ||
|
|
e0cde7fe0f | ||
|
|
2d4d0bc23a | ||
|
|
9a5bff3d37 | ||
|
|
28f212b7d6 | ||
|
|
bfad59fa7a | ||
|
|
f0e8f01d30 | ||
|
|
3ffd94e99d | ||
|
|
1be49d27ab | ||
|
|
4f43f64783 | ||
|
|
e7997a5272 | ||
|
|
507138364e | ||
|
|
0a4a1baeba | ||
|
|
14d111c4de | ||
|
|
db73d7e1cb | ||
|
|
825e9883d7 | ||
|
|
b2866c34df | ||
|
|
58e3ab9115 | ||
|
|
2b66b3c87f | ||
|
|
4505504732 | ||
|
|
567da9b0a3 | ||
|
|
7ccc36b121 | ||
|
|
559bf9d394 | ||
|
|
cee34dfb63 | ||
|
|
55995bd7a9 | ||
|
|
36edfddf74 | ||
|
|
188046e60a | ||
|
|
5338f3cae8 | ||
|
|
624146ecd7 | ||
|
|
8f711d1a9e | ||
|
|
b50090060b | ||
|
|
7db2321a82 |
No files matched your search
@@ -2,6 +2,7 @@
|
||||
FluentTerminal.App/Win32
|
||||
FluentTerminal.App/Client/
|
||||
FluentTerminal.Client/dist
|
||||
/.sonarqube
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
using FluentAssertions;
|
||||
using FluentTerminal.App.Services.Implementation;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace FluentTerminal.App.Services.Test
|
||||
{
|
||||
public class DefaultValueProviderTests
|
||||
{
|
||||
public static IEnumerable<object[]> Commands => System.Enum.GetValues(typeof(Command)).Cast<Command>().Select(x => new object[] { x });
|
||||
|
||||
[Fact]
|
||||
public void GetDefaultApplicationSettings_Default_DoesNotReturnNull()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var applicationSettings = defaultValueProvider.GetDefaultApplicationSettings();
|
||||
|
||||
applicationSettings.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(Commands))]
|
||||
public void GetDefaultKeyBindings_AllCommands_ReturnsANonEmptyList(Command command)
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var keyBindings = defaultValueProvider.GetDefaultKeyBindings(command);
|
||||
|
||||
keyBindings.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDefaultShellProfileId_Default_DoesNotReturnEmptyGuid()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var defaultShellProfileId = defaultValueProvider.GetDefaultShellProfileId();
|
||||
|
||||
defaultShellProfileId.Should().NotBeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDefaultShellProfileId_Default_IdIsOneOfThePreInstalledShellProfiles()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
var shellProfiles = defaultValueProvider.GetPreinstalledShellProfiles();
|
||||
|
||||
var defaultShellProfileId = defaultValueProvider.GetDefaultShellProfileId();
|
||||
|
||||
shellProfiles.Select(x => x.Id).Should().Contain(defaultShellProfileId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDefaultTerminalOptions_Default_DoesNotReturnNull()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var defaultTerminalOptions = defaultValueProvider.GetDefaultTerminalOptions();
|
||||
|
||||
defaultTerminalOptions.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDefaultThemeId_Default_DoesNotReturnEmptyGuid()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var defaultThemeId = defaultValueProvider.GetDefaultThemeId();
|
||||
|
||||
defaultThemeId.Should().NotBeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDefaultThemeId_Default_IdIsOneOfThePreInstalledThemes()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
var themes = defaultValueProvider.GetPreInstalledThemes();
|
||||
|
||||
var defaultThemeId = defaultValueProvider.GetDefaultThemeId();
|
||||
|
||||
themes.Select(x => x.Id).Should().Contain(defaultThemeId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreinstalledShellProfiles_Default_ReturnsANonEmptyList()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var shellProfiles = defaultValueProvider.GetPreinstalledShellProfiles();
|
||||
|
||||
shellProfiles.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreinstalledShellProfiles_Default_HaveUniqueIds()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var shellProfiles = defaultValueProvider.GetPreinstalledShellProfiles();
|
||||
|
||||
shellProfiles.Select(x => x.Id).Should().OnlyHaveUniqueItems();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreinstalledShellProfiles_Default_HavePreInstalledSetToTrue()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var shellProfiles = defaultValueProvider.GetPreinstalledShellProfiles();
|
||||
|
||||
shellProfiles.Select(x => x.PreInstalled).Should().AllBeEquivalentTo(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreinstalledShellProfiles_Default_HaveNonEmptyLocations()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var shellProfiles = defaultValueProvider.GetPreinstalledShellProfiles();
|
||||
|
||||
shellProfiles.Select(x => x.Location).Should().NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreInstalledThemes_Default_ReturnsANonEmptyList()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var themes = defaultValueProvider.GetPreInstalledThemes();
|
||||
|
||||
themes.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreinstalledThemes_Default_HaveUniqueIds()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var themes = defaultValueProvider.GetPreInstalledThemes();
|
||||
|
||||
themes.Select(x => x.Id).Should().OnlyHaveUniqueItems();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreinstalledThemes_Default_HavePreInstalledSetToTrue()
|
||||
{
|
||||
var defaultValueProvider = new DefaultValueProvider();
|
||||
|
||||
var themes = defaultValueProvider.GetPreInstalledThemes();
|
||||
|
||||
themes.Select(x => x.PreInstalled).Should().AllBeEquivalentTo(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AutoFixture;
|
||||
using AutoFixture;
|
||||
using FluentAssertions;
|
||||
using FluentTerminal.App.Services.Dialogs;
|
||||
using FluentTerminal.App.Services.Implementation;
|
||||
using Moq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace FluentTerminal.App.Services.Test
|
||||
@@ -20,41 +20,77 @@ namespace FluentTerminal.App.Services.Test
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShowDialogAsync_TitleIsEmpty_ThrowsArgumentNullException()
|
||||
public void ShowCreateKeyBindingDialog_Default_UsesCreateKeyBindingDialog()
|
||||
{
|
||||
var createKeyBindingDialog = new Mock<ICreateKeyBindingDialog>();
|
||||
var dialogService = new DialogService(Mock.Of<IShellProfileSelectionDialog>, Mock.Of<IMessageDialog>, () => createKeyBindingDialog.Object);
|
||||
|
||||
dialogService.ShowCreateKeyBindingDialog();
|
||||
|
||||
createKeyBindingDialog.Verify(x => x.CreateKeyBinding(), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShowMessageDialogAsnyc_TitleIsEmpty_ThrowsArgumentNullException()
|
||||
{
|
||||
var title = string.Empty;
|
||||
var content = _fixture.Create<string>();
|
||||
var buttons = _fixture.CreateMany<DialogButton>(2);
|
||||
var dialogService = new DialogService(() => Mock.Of<IShellProfileSelectionDialog>(), () => Mock.Of<IMessageDialog>(), () => Mock.Of<ICreateKeyBindingDialog>());
|
||||
var dialogService = new DialogService(Mock.Of<IShellProfileSelectionDialog>, Mock.Of<IMessageDialog>, Mock.Of<ICreateKeyBindingDialog>);
|
||||
|
||||
Func<Task<DialogButton>> invoke = () => dialogService.ShowMessageDialogAsnyc(title, content, buttons.ElementAt(0), buttons.ElementAt(1));
|
||||
Func<Task<DialogButton>> showMessageDialogAsnyc = () => dialogService.ShowMessageDialogAsnyc(title, content, buttons.ElementAt(0), buttons.ElementAt(1));
|
||||
|
||||
invoke.Should().Throw<ArgumentNullException>().And.ParamName.Should().Be("title");
|
||||
showMessageDialogAsnyc.Should().Throw<ArgumentNullException>().And.ParamName.Should().Be("title");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShowDialogAsync_ContentIsEmpty_ThrowsArgumentNullException()
|
||||
public void ShowMessageDialogAsnyc_ContentIsEmpty_ThrowsArgumentNullException()
|
||||
{
|
||||
var title = _fixture.Create<string>();
|
||||
var content = string.Empty;
|
||||
var buttons = _fixture.CreateMany<DialogButton>(2);
|
||||
var dialogService = new DialogService(() => Mock.Of<IShellProfileSelectionDialog>(), () => Mock.Of<IMessageDialog>(), () => Mock.Of<ICreateKeyBindingDialog>());
|
||||
var dialogService = new DialogService(Mock.Of<IShellProfileSelectionDialog>, Mock.Of<IMessageDialog>, Mock.Of<ICreateKeyBindingDialog>);
|
||||
|
||||
Func<Task<DialogButton>> invoke = () => dialogService.ShowMessageDialogAsnyc(title, content, buttons.ElementAt(0), buttons.ElementAt(1));
|
||||
Func<Task<DialogButton>> showMessageDialogAsnyc = () => dialogService.ShowMessageDialogAsnyc(title, content, buttons.ElementAt(0), buttons.ElementAt(1));
|
||||
|
||||
invoke.Should().Throw<ArgumentNullException>().And.ParamName.Should().Be("content");
|
||||
showMessageDialogAsnyc.Should().Throw<ArgumentNullException>().And.ParamName.Should().Be("content");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShowDialogAsync_NoButtonsPassed_ThrowsArgumentException()
|
||||
public void ShowMessageDialogAsnyc_NoButtonsPassed_ThrowsArgumentException()
|
||||
{
|
||||
var title = _fixture.Create<string>();
|
||||
var content = _fixture.Create<string>();
|
||||
var dialogService = new DialogService(() => Mock.Of<IShellProfileSelectionDialog>(), () => Mock.Of<IMessageDialog>(), () => Mock.Of<ICreateKeyBindingDialog>());
|
||||
var dialogService = new DialogService(Mock.Of<IShellProfileSelectionDialog>, Mock.Of<IMessageDialog>, Mock.Of<ICreateKeyBindingDialog>);
|
||||
|
||||
Func<Task<DialogButton>> invoke = () => dialogService.ShowMessageDialogAsnyc(title, content);
|
||||
Func<Task<DialogButton>> showMessageDialogAsnyc = () => dialogService.ShowMessageDialogAsnyc(title, content);
|
||||
|
||||
invoke.Should().Throw<ArgumentException>().And.ParamName.Should().Be("buttons");
|
||||
showMessageDialogAsnyc.Should().Throw<ArgumentException>().And.ParamName.Should().Be("buttons");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShowMessageDialogAsnyc_Default_UsesMessageDialog()
|
||||
{
|
||||
var title = _fixture.Create<string>();
|
||||
var content = _fixture.Create<string>();
|
||||
var buttons = _fixture.CreateMany<DialogButton>(2);
|
||||
var messageDialog = new Mock<IMessageDialog>();
|
||||
var dialogService = new DialogService(Mock.Of<IShellProfileSelectionDialog>, () => messageDialog.Object, Mock.Of<ICreateKeyBindingDialog>);
|
||||
|
||||
dialogService.ShowMessageDialogAsnyc(title, content, buttons.ElementAt(0), buttons.ElementAt(1));
|
||||
|
||||
messageDialog.Verify(x => x.ShowAsync(), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShowProfileSelectionDialogAsync_Default_UsesShellProfileSelectionDialog()
|
||||
{
|
||||
var shellProfileSelectionDialog = new Mock<IShellProfileSelectionDialog>();
|
||||
var dialogService = new DialogService(() => shellProfileSelectionDialog.Object, Mock.Of<IMessageDialog>, Mock.Of<ICreateKeyBindingDialog>);
|
||||
|
||||
dialogService.ShowProfileSelectionDialogAsync();
|
||||
|
||||
shellProfileSelectionDialog.Verify(x => x.SelectProfile(), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,16 +6,27 @@
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="TestData\AdventureTime.itermcolors" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoFixture" Version="4.4.0" />
|
||||
<PackageReference Include="FluentAssertions" Version="5.4.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
||||
<PackageReference Include="Moq" Version="4.8.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="xunit" Version="2.3.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestData\AdventureTime.itermcolors">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FluentTerminal.App.Services\FluentTerminal.App.Services.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
using AutoFixture;
|
||||
using FluentAssertions;
|
||||
using FluentTerminal.App.Services.Implementation;
|
||||
using FluentTerminal.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace FluentTerminal.App.Services.Test
|
||||
{
|
||||
public class FluentTerminalThemeParserTests
|
||||
{
|
||||
private readonly Fixture _fixture;
|
||||
|
||||
public FluentTerminalThemeParserTests()
|
||||
{
|
||||
_fixture = new Fixture();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Parse_ValidFileStream_ReturnsTheme()
|
||||
{
|
||||
var theme = _fixture.Create<TerminalTheme>();
|
||||
var serialized = JsonConvert.SerializeObject(theme);
|
||||
var stream = new MemoryStream(Encoding.UTF8.GetBytes(serialized));
|
||||
var parser = new FluentTerminalThemeParser();
|
||||
|
||||
var parsedTheme = await parser.Parse(theme.Name, stream);
|
||||
|
||||
parsedTheme.Name.Should().Be(theme.Name);
|
||||
parsedTheme.Author.Should().Be(theme.Author);
|
||||
parsedTheme.PreInstalled.Should().Be(false);
|
||||
parsedTheme.Colors.Should().BeEquivalentTo(theme.Colors);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_InvalidFileStream_ThrowsException()
|
||||
{
|
||||
var fileName = _fixture.Create<string>();
|
||||
var serialized = _fixture.Create<string>();
|
||||
var stream = new MemoryStream(Encoding.UTF8.GetBytes(serialized));
|
||||
var parser = new FluentTerminalThemeParser();
|
||||
|
||||
Func<Task<TerminalTheme>> parse = () => parser.Parse(fileName, stream);
|
||||
|
||||
parse.Should().Throw<Exception>();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
public void Parse_InvalidFileName_ThrowsArgumentNullException(string fileName)
|
||||
{
|
||||
var theme = _fixture.Create<TerminalTheme>();
|
||||
var serialized = JsonConvert.SerializeObject(theme);
|
||||
var stream = new MemoryStream(Encoding.UTF8.GetBytes(serialized));
|
||||
var parser = new FluentTerminalThemeParser();
|
||||
|
||||
Func<Task<TerminalTheme>> parse = () => parser.Parse(fileName, stream);
|
||||
|
||||
parse.Should().Throw<ArgumentNullException>().And.ParamName.Should().Be("fileName");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_FileStreamIsNull_ThrowsArgumentNullException()
|
||||
{
|
||||
var fileName = _fixture.Create<string>();
|
||||
Stream stream = null;
|
||||
var parser = new FluentTerminalThemeParser();
|
||||
|
||||
Func<Task<TerminalTheme>> parse = () => parser.Parse(fileName, stream);
|
||||
|
||||
parse.Should().Throw<ArgumentNullException>().And.ParamName.Should().Be("fileContent");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using AutoFixture;
|
||||
using FluentAssertions;
|
||||
using FluentTerminal.App.Services.Implementation;
|
||||
using FluentTerminal.Models;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace FluentTerminal.App.Services.Test
|
||||
{
|
||||
public class ITermThemeParserTests
|
||||
{
|
||||
private readonly Fixture _fixture;
|
||||
|
||||
public ITermThemeParserTests()
|
||||
{
|
||||
_fixture = new Fixture();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
public void Parse_InvalidFileName_ThrowsArgumentNullException(string fileName)
|
||||
{
|
||||
var stream = typeof(ITermThemeParserTests).Assembly.GetManifestResourceStream("FluentTerminal.App.Services.Test.TestData.AdventureTime.itermcolors");
|
||||
var parser = new ITermThemeParser();
|
||||
|
||||
Func<Task<TerminalTheme>> parse = () => parser.Parse(fileName, stream);
|
||||
|
||||
parse.Should().Throw<ArgumentNullException>().And.ParamName.Should().Be("fileName");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_FileStreamIsNull_ThrowsArgumentNullException()
|
||||
{
|
||||
var fileName = _fixture.Create<string>();
|
||||
Stream stream = null;
|
||||
var parser = new ITermThemeParser();
|
||||
|
||||
Func<Task<TerminalTheme>> parse = () => parser.Parse(fileName, stream);
|
||||
|
||||
parse.Should().Throw<ArgumentNullException>().And.ParamName.Should().Be("fileContent");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_InvalidFileStream_ThrowsException()
|
||||
{
|
||||
var fileName = _fixture.Create<string>();
|
||||
var serialized = _fixture.Create<string>();
|
||||
var stream = new MemoryStream(Encoding.UTF8.GetBytes(serialized));
|
||||
var parser = new ITermThemeParser();
|
||||
|
||||
Func<Task<TerminalTheme>> parse = () => parser.Parse(fileName, stream);
|
||||
|
||||
parse.Should().Throw<Exception>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Parse_ValidThemeFile_ParsesCorrectly()
|
||||
{
|
||||
var fileName = _fixture.Create<string>();
|
||||
var stream = typeof(ITermThemeParserTests).Assembly.GetManifestResourceStream("FluentTerminal.App.Services.Test.TestData.AdventureTime.itermcolors");
|
||||
var parser = new ITermThemeParser();
|
||||
|
||||
var theme = await parser.Parse(fileName, stream);
|
||||
|
||||
theme.Colors.Background.ToLower().Should().Be("#1f1d45");
|
||||
theme.Colors.Cursor.ToLower().Should().Be("#efbf38");
|
||||
theme.Colors.Foreground.ToLower().Should().Be("#f8dcc0");
|
||||
theme.Colors.Black.ToLower().Should().Be("#050404");
|
||||
theme.Colors.Red.ToLower().Should().Be("#bd0013");
|
||||
theme.Colors.Green.ToLower().Should().Be("#4ab118");
|
||||
theme.Colors.Yellow.ToLower().Should().Be("#e7741e");
|
||||
theme.Colors.Blue.ToLower().Should().Be("#0f4ac6");
|
||||
theme.Colors.Magenta.ToLower().Should().Be("#665993");
|
||||
theme.Colors.Cyan.ToLower().Should().Be("#70a598");
|
||||
theme.Colors.White.ToLower().Should().Be("#f8dcc0");
|
||||
theme.Colors.BrightBlack.ToLower().Should().Be("#4e7cbf");
|
||||
theme.Colors.BrightRed.ToLower().Should().Be("#fc5f5a");
|
||||
theme.Colors.BrightGreen.ToLower().Should().Be("#9eff6e");
|
||||
theme.Colors.BrightYellow.ToLower().Should().Be("#efc11a");
|
||||
theme.Colors.BrightBlue.ToLower().Should().Be("#1997c6");
|
||||
theme.Colors.BrightMagenta.ToLower().Should().Be("#9b5953");
|
||||
theme.Colors.BrightCyan.ToLower().Should().Be("#c8faf4");
|
||||
theme.Colors.BrightWhite.ToLower().Should().Be("#f6f5fb");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,4 +66,4 @@ namespace FluentTerminal.App.Services.Test
|
||||
invoke.Should().Throw<KeyNotFoundException>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,761 @@
|
||||
using AutoFixture;
|
||||
using FluentAssertions;
|
||||
using FluentTerminal.App.Services.Implementation;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace FluentTerminal.App.Services.Test
|
||||
{
|
||||
public class SettingsServiceTests
|
||||
{
|
||||
private readonly Fixture _fixture;
|
||||
|
||||
public SettingsServiceTests()
|
||||
{
|
||||
_fixture = new Fixture();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_Default_WritesAllPreinstalledThemesInThemeContainer()
|
||||
{
|
||||
var themes = _fixture.CreateMany<TerminalTheme>(3);
|
||||
var defaultValueProvider = new Mock<IDefaultValueProvider>();
|
||||
defaultValueProvider.Setup(x => x.GetPreInstalledThemes()).Returns(themes);
|
||||
var themesContainer = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
Themes = themesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
|
||||
new SettingsService(defaultValueProvider.Object, applicationDataContainers);
|
||||
|
||||
defaultValueProvider.Verify(x => x.GetPreInstalledThemes(), Times.Once);
|
||||
foreach (var theme in themes)
|
||||
{
|
||||
themesContainer.Verify(x => x.WriteValueAsJson(theme.Id.ToString(), theme), Times.Once);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_Default_WritesAllPreinstalledShellProfilesInShellProfilesContainer()
|
||||
{
|
||||
var shellProfiles = _fixture.CreateMany<ShellProfile>(3);
|
||||
var defaultValueProvider = new Mock<IDefaultValueProvider>();
|
||||
defaultValueProvider.Setup(x => x.GetPreinstalledShellProfiles()).Returns(shellProfiles);
|
||||
var shellProfilesContainer = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
ShellProfiles = shellProfilesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
|
||||
new SettingsService(defaultValueProvider.Object, applicationDataContainers);
|
||||
|
||||
defaultValueProvider.Verify(x => x.GetPreinstalledShellProfiles(), Times.Once);
|
||||
foreach (var shellProfile in shellProfiles)
|
||||
{
|
||||
shellProfilesContainer.Verify(x => x.WriteValueAsJson(shellProfile.Id.ToString(), shellProfile), Times.Once);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCurrentThemeId_ValueExistsInRoamingSettings_ReturnsCurrentThemeId()
|
||||
{
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
var currentThemeId = (object)_fixture.Create<Guid>();
|
||||
roamingSettings.Setup(x => x.TryGetValue(SettingsService.CurrentThemeKey, out currentThemeId)).Returns(true);
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetCurrentThemeId();
|
||||
|
||||
result.Should().Be((Guid)currentThemeId);
|
||||
roamingSettings.Verify(x => x.TryGetValue(SettingsService.CurrentThemeKey, out currentThemeId), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCurrentThemeId_ValueDoesNotExistInRoamingSettings_ReturnsDefaultThemeIdFromDefaultValueProvider()
|
||||
{
|
||||
var defaultValueProvider = new Mock<IDefaultValueProvider>();
|
||||
var defaultThemeId = _fixture.Create<Guid>();
|
||||
defaultValueProvider.Setup(x => x.GetDefaultThemeId()).Returns(defaultThemeId);
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
var currentThemeId = (object)_fixture.Create<Guid>();
|
||||
roamingSettings.Setup(x => x.TryGetValue(SettingsService.CurrentThemeKey, out currentThemeId)).Returns(false);
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider.Object, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetCurrentThemeId();
|
||||
|
||||
result.Should().Be(defaultThemeId);
|
||||
defaultValueProvider.Verify(x => x.GetDefaultThemeId(), Times.Once);
|
||||
roamingSettings.Verify(x => x.TryGetValue(SettingsService.CurrentThemeKey, out currentThemeId), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveCurrentThemeId_Default_SetsValueOnRoamingSettings()
|
||||
{
|
||||
var currentThemeId = _fixture.Create<Guid>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
settingsService.SaveCurrentThemeId(currentThemeId);
|
||||
|
||||
roamingSettings.Verify(x => x.SetValue(SettingsService.CurrentThemeKey, currentThemeId), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveCurrentThemeId_Default_InvokesCurrentThemeChangedEvent()
|
||||
{
|
||||
var currentThemeId = _fixture.Create<Guid>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var currentThemeChangedEventInvoked = false;
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
settingsService.CurrentThemeChanged += (s, e) => currentThemeChangedEventInvoked = true;
|
||||
|
||||
settingsService.SaveCurrentThemeId(currentThemeId);
|
||||
|
||||
currentThemeChangedEventInvoked.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveTheme_Default_WritesToThemesContainer()
|
||||
{
|
||||
var theme = _fixture.Create<TerminalTheme>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var themesContainer = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
Themes = themesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
settingsService.SaveTheme(theme);
|
||||
|
||||
themesContainer.Verify(x => x.WriteValueAsJson(theme.Id.ToString(), theme), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveTheme_ThemeIsCurrentTheme_InvokesCurrentThemeChangedEvent()
|
||||
{
|
||||
var theme = _fixture.Create<TerminalTheme>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var themesContainer = new Mock<IApplicationDataContainer>();
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
var currentThemeId = (object)theme.Id;
|
||||
roamingSettings.Setup(x => x.TryGetValue(SettingsService.CurrentThemeKey, out currentThemeId)).Returns(true);
|
||||
var currentThemeChangedEventInvoked = false;
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
Themes = themesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
settingsService.CurrentThemeChanged += (s, e) => currentThemeChangedEventInvoked = true;
|
||||
|
||||
settingsService.SaveTheme(theme);
|
||||
|
||||
currentThemeChangedEventInvoked.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeleteTheme_Default_CallsDeleteOnThemesContainer()
|
||||
{
|
||||
var themeId = _fixture.Create<Guid>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var themesContainer = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
Themes = themesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
settingsService.DeleteTheme(themeId);
|
||||
|
||||
themesContainer.Verify(x => x.Delete(themeId.ToString()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetThemes_Default_CallsGetAllOnThemesContainer()
|
||||
{
|
||||
var themes = _fixture.CreateMany<TerminalTheme>(3);
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var themesContainer = new Mock<IApplicationDataContainer>();
|
||||
themesContainer.Setup(x => x.GetAll()).Returns(themes.Select(JsonConvert.SerializeObject));
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
Themes = themesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetThemes();
|
||||
|
||||
result.Should().BeEquivalentTo(themes);
|
||||
themesContainer.Verify(x => x.GetAll(), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetTheme_ValidThemeId_ReturnsThemeFromThemesContainer()
|
||||
{
|
||||
var theme = _fixture.Create<TerminalTheme>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var themesContainer = new Mock<IApplicationDataContainer>();
|
||||
themesContainer.Setup(x => x.ReadValueFromJson(theme.Id.ToString(), default(TerminalTheme))).Returns(theme);
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
Themes = themesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetTheme(theme.Id);
|
||||
|
||||
result.Should().BeEquivalentTo(theme);
|
||||
themesContainer.Verify(x => x.ReadValueFromJson(theme.Id.ToString(), default(TerminalTheme)), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetTheme_UnknownThemeId_ReturnsNull()
|
||||
{
|
||||
var themeId = _fixture.Create<Guid>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var themesContainer = new Mock<IApplicationDataContainer>();
|
||||
themesContainer.Setup(x => x.ReadValueFromJson(themeId.ToString(), default(TerminalTheme))).Returns(value: null);
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
Themes = themesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetTheme(themeId);
|
||||
|
||||
result.Should().BeNull();
|
||||
themesContainer.Verify(x => x.ReadValueFromJson(themeId.ToString(), default(TerminalTheme)), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetTerminalOptions_Default_ReturnsTerminalOptionsFromRoamingSettings()
|
||||
{
|
||||
var terminalOptions = _fixture.Create<TerminalOptions>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
roamingSettings.Setup(x => x.ReadValueFromJson(nameof(TerminalOptions), It.IsAny<TerminalOptions>())).Returns(terminalOptions);
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetTerminalOptions();
|
||||
|
||||
result.Should().BeEquivalentTo(terminalOptions);
|
||||
roamingSettings.Verify(x => x.ReadValueFromJson(nameof(TerminalOptions), It.IsAny<TerminalOptions>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveTerminalOptions_Default_WritesToRoamingSettings()
|
||||
{
|
||||
var terminalOptions = _fixture.Create<TerminalOptions>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
settingsService.SaveTerminalOptions(terminalOptions);
|
||||
|
||||
roamingSettings.Verify(x => x.WriteValueAsJson(nameof(TerminalOptions), terminalOptions), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveTerminalOptions_Default_InvokesTerminalOptionsChangedEvent()
|
||||
{
|
||||
var terminalOptions = _fixture.Create<TerminalOptions>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
var terminalOptionsChangedEventInvoked = false;
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
settingsService.TerminalOptionsChanged += (s, e) => terminalOptionsChangedEventInvoked = true;
|
||||
|
||||
settingsService.SaveTerminalOptions(terminalOptions);
|
||||
|
||||
terminalOptionsChangedEventInvoked.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetApplicationSettings_Default_ReturnsApplicationSettingsFromRoamingSettings()
|
||||
{
|
||||
var applicationSettings = _fixture.Create<ApplicationSettings>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
roamingSettings.Setup(x => x.ReadValueFromJson(nameof(ApplicationSettings), It.IsAny<ApplicationSettings>())).Returns(applicationSettings);
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetApplicationSettings();
|
||||
|
||||
result.Should().BeEquivalentTo(applicationSettings);
|
||||
roamingSettings.Verify(x => x.ReadValueFromJson(nameof(ApplicationSettings), It.IsAny<ApplicationSettings>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveApplicationSettings_Default_WritesToRoamingSettings()
|
||||
{
|
||||
var applicationSettings = _fixture.Create<ApplicationSettings>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
settingsService.SaveApplicationSettings(applicationSettings);
|
||||
|
||||
roamingSettings.Verify(x => x.WriteValueAsJson(nameof(ApplicationSettings), applicationSettings), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveApplicationSettings_Default_InvokesApplicationSettingsChangedEvent()
|
||||
{
|
||||
var applicationSettings = _fixture.Create<ApplicationSettings>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
var applicationSettingsChangedEventInvoked = false;
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
settingsService.ApplicationSettingsChanged += (s, e) => applicationSettingsChangedEventInvoked = true;
|
||||
|
||||
settingsService.SaveApplicationSettings(applicationSettings);
|
||||
|
||||
applicationSettingsChangedEventInvoked.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetKeyBindings_KeyBindingsInKeyBindingsContainer_ReturnsKeyBindingsFromKeyBindingsContainer()
|
||||
{
|
||||
var keyBindings = _fixture.CreateMany<KeyBinding>(5);
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var keyBindingsContainer = new Mock<IApplicationDataContainer>();
|
||||
foreach (var keyBinding in keyBindings)
|
||||
{
|
||||
keyBindingsContainer.Setup(x => x.ReadValueFromJson<Collection<KeyBinding>>(keyBinding.Command.ToString(), null)).Returns(new Collection<KeyBinding> { keyBinding });
|
||||
}
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
KeyBindings = keyBindingsContainer.Object,
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetKeyBindings();
|
||||
|
||||
foreach (var keyBinding in keyBindings)
|
||||
{
|
||||
keyBindingsContainer.Verify(x => x.ReadValueFromJson<Collection<KeyBinding>>(keyBinding.Command.ToString(), null), Times.Once);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetKeyBindings_KeyBindingsNotInKeyBindingsContainer_ReturnsKeyBindingsFromDefaultValueProvider()
|
||||
{
|
||||
var keyBindings = _fixture.CreateMany<KeyBinding>(5);
|
||||
var defaultValueProvider = new Mock<IDefaultValueProvider>();
|
||||
var keyBindingsContainer = new Mock<IApplicationDataContainer>();
|
||||
foreach (var keyBinding in keyBindings)
|
||||
{
|
||||
keyBindingsContainer.Setup(x => x.ReadValueFromJson<Collection<KeyBinding>>(keyBinding.Command.ToString(), null)).Returns(new Collection<KeyBinding> { keyBinding });
|
||||
}
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
KeyBindings = keyBindingsContainer.Object,
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider.Object, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetKeyBindings();
|
||||
|
||||
foreach (Command command in Enum.GetValues(typeof(Command)))
|
||||
{
|
||||
if (keyBindings.Select(x => x.Command).Contains(command))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
defaultValueProvider.Verify(x => x.GetDefaultKeyBindings(command), Times.Once);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveKeyBindings_Default_WritesToKeyBindingsContainer()
|
||||
{
|
||||
var command = _fixture.Create<Command>();
|
||||
var keyBindings = _fixture.Create<ICollection<KeyBinding>>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var keyBindingsContainer = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
KeyBindings = keyBindingsContainer.Object,
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
settingsService.SaveKeyBindings(command, keyBindings);
|
||||
|
||||
keyBindingsContainer.Verify(x => x.WriteValueAsJson(command.ToString(), keyBindings), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveKeyBindings_Default_InvokesKeyBindingsChangedEvent()
|
||||
{
|
||||
var command = _fixture.Create<Command>();
|
||||
var keyBindings = _fixture.Create<Collection<KeyBinding>>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var keyBindingsContainer = new Mock<IApplicationDataContainer>();
|
||||
var keyBindingsChangedEventInvoked = false;
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
KeyBindings = keyBindingsContainer.Object,
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
settingsService.KeyBindingsChanged += (s, e) => keyBindingsChangedEventInvoked = true;
|
||||
|
||||
settingsService.SaveKeyBindings(command, keyBindings);
|
||||
|
||||
keyBindingsChangedEventInvoked.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResetKeyBindings_Default_WritesToKeyBindingsContainerFromDefaultValueProvider()
|
||||
{
|
||||
var defaultValueProvider = new Mock<IDefaultValueProvider>();
|
||||
var keyBindingsContainer = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
KeyBindings = keyBindingsContainer.Object,
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider.Object, applicationDataContainers);
|
||||
|
||||
settingsService.ResetKeyBindings();
|
||||
|
||||
foreach (Command command in Enum.GetValues(typeof(Command)))
|
||||
{
|
||||
keyBindingsContainer.Verify(x => x.WriteValueAsJson(command.ToString(), It.IsAny<ICollection<KeyBinding>>()), Times.Once);
|
||||
defaultValueProvider.Verify(x => x.GetDefaultKeyBindings(command), Times.Once);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResetKeyBindings_Default_InvokesKeyBindingsChangedEvent()
|
||||
{
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var keyBindingsContainer = new Mock<IApplicationDataContainer>();
|
||||
var keyBindingsChangedEventInvoked = false;
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
KeyBindings = keyBindingsContainer.Object,
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
settingsService.KeyBindingsChanged += (s, e) => keyBindingsChangedEventInvoked = true;
|
||||
|
||||
settingsService.ResetKeyBindings();
|
||||
|
||||
keyBindingsChangedEventInvoked.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDefaultShellProfileId_ValueExistsInRoamingSettings_ReturnsDefaultShellProfileId()
|
||||
{
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var localSettings = new Mock<IApplicationDataContainer>();
|
||||
var defaultShellProfileId = (object)_fixture.Create<Guid>();
|
||||
localSettings.Setup(x => x.TryGetValue(SettingsService.DefaultShellProfileKey, out defaultShellProfileId)).Returns(true);
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
LocalSettings = localSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetDefaultShellProfileId();
|
||||
|
||||
result.Should().Be((Guid)defaultShellProfileId);
|
||||
localSettings.Verify(x => x.TryGetValue(SettingsService.DefaultShellProfileKey, out defaultShellProfileId), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDefaultShellProfileId_ValueDoesNotExistInRoamingSettings_ReturnsDefaultShellProfileIdFromDefaultValueProvider()
|
||||
{
|
||||
var defaultValueProvider = new Mock<IDefaultValueProvider>();
|
||||
var defaultShellProfileId = _fixture.Create<Guid>();
|
||||
defaultValueProvider.Setup(x => x.GetDefaultShellProfileId()).Returns(defaultShellProfileId);
|
||||
var localSettings = new Mock<IApplicationDataContainer>();
|
||||
var currentDefaultShellProfileId = (object)_fixture.Create<Guid>();
|
||||
localSettings.Setup(x => x.TryGetValue(SettingsService.DefaultShellProfileKey, out currentDefaultShellProfileId)).Returns(false);
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
LocalSettings = localSettings.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider.Object, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetDefaultShellProfileId();
|
||||
|
||||
result.Should().Be(defaultShellProfileId);
|
||||
defaultValueProvider.Verify(x => x.GetDefaultShellProfileId(), Times.Once);
|
||||
localSettings.Verify(x => x.TryGetValue(SettingsService.DefaultShellProfileKey, out currentDefaultShellProfileId), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetShellProfiles_Default_CallsGetAllOnShellProfilesContainer()
|
||||
{
|
||||
var shellProfiles = _fixture.CreateMany<ShellProfile>(3);
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var shellProfilesContainer = new Mock<IApplicationDataContainer>();
|
||||
shellProfilesContainer.Setup(x => x.GetAll()).Returns(shellProfiles.Select(JsonConvert.SerializeObject));
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
ShellProfiles = shellProfilesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetShellProfiles();
|
||||
|
||||
result.Should().BeEquivalentTo(shellProfiles);
|
||||
shellProfilesContainer.Verify(x => x.GetAll(), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveShellProfile_Default_WritesToShellProfilesContainer()
|
||||
{
|
||||
var shellProfile = _fixture.Create<ShellProfile>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var shellProfilesContainer = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
ShellProfiles = shellProfilesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
settingsService.SaveShellProfile(shellProfile);
|
||||
|
||||
shellProfilesContainer.Verify(x => x.WriteValueAsJson(shellProfile.Id.ToString(), shellProfile), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeleteShellProfile_Default_CallsDeleteOnShellProfilesContainer()
|
||||
{
|
||||
var shellProfileId = _fixture.Create<Guid>();
|
||||
var defaultValueProvider = Mock.Of<IDefaultValueProvider>();
|
||||
var shellProfilesContainer = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
ShellProfiles = shellProfilesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
Themes = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
var settingsService = new SettingsService(defaultValueProvider, applicationDataContainers);
|
||||
|
||||
settingsService.DeleteShellProfile(shellProfileId);
|
||||
|
||||
shellProfilesContainer.Verify(x => x.Delete(shellProfileId.ToString()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDefaultShellProfile_ProfileNotFound_DefaultShellProfileIdGetsResetToDefault()
|
||||
{
|
||||
var currentShellProfileId = (object)_fixture.Create<Guid>();
|
||||
var defaultShellProfile = _fixture.Create<ShellProfile>();
|
||||
var defaultValueProvider = new Mock<IDefaultValueProvider>();
|
||||
defaultValueProvider.Setup(x => x.GetDefaultShellProfileId()).Returns(defaultShellProfile.Id);
|
||||
var shellProfilesContainer = new Mock<IApplicationDataContainer>();
|
||||
var localSettings = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
ShellProfiles = shellProfilesContainer.Object,
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = localSettings.Object,
|
||||
Themes = Mock.Of<IApplicationDataContainer>()
|
||||
};
|
||||
shellProfilesContainer.Setup(x => x.ReadValueFromJson(currentShellProfileId.ToString(), default(ShellProfile))).Returns(value: null);
|
||||
shellProfilesContainer.Setup(x => x.ReadValueFromJson(defaultShellProfile.Id.ToString(), default(ShellProfile))).Returns(defaultShellProfile);
|
||||
localSettings.Setup(x => x.TryGetValue(SettingsService.DefaultShellProfileKey, out currentShellProfileId)).Returns(true);
|
||||
var settingsService = new SettingsService(defaultValueProvider.Object, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetDefaultShellProfile();
|
||||
|
||||
result.Should().Be(defaultShellProfile);
|
||||
localSettings.Verify(x => x.SetValue(SettingsService.DefaultShellProfileKey, defaultShellProfile.Id), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCurrentTheme_ThemeNotFound_CurrentThemeIdGetsResetToDefault()
|
||||
{
|
||||
var currentThemeId = (object)_fixture.Create<Guid>();
|
||||
var defaultTheme = _fixture.Create<TerminalTheme>();
|
||||
var defaultValueProvider = new Mock<IDefaultValueProvider>();
|
||||
defaultValueProvider.Setup(x => x.GetDefaultThemeId()).Returns(defaultTheme.Id);
|
||||
var themesContainer = new Mock<IApplicationDataContainer>();
|
||||
var roamingSettings = new Mock<IApplicationDataContainer>();
|
||||
var applicationDataContainers = new ApplicationDataContainers
|
||||
{
|
||||
ShellProfiles = Mock.Of<IApplicationDataContainer>(),
|
||||
KeyBindings = Mock.Of<IApplicationDataContainer>(),
|
||||
LocalSettings = Mock.Of<IApplicationDataContainer>(),
|
||||
RoamingSettings = roamingSettings.Object,
|
||||
Themes = themesContainer.Object
|
||||
};
|
||||
themesContainer.Setup(x => x.ReadValueFromJson(currentThemeId.ToString(), default(TerminalTheme))).Returns(value: null);
|
||||
themesContainer.Setup(x => x.ReadValueFromJson(defaultTheme.Id.ToString(), default(TerminalTheme))).Returns(defaultTheme);
|
||||
roamingSettings.Setup(x => x.TryGetValue(SettingsService.CurrentThemeKey, out currentThemeId)).Returns(true);
|
||||
var settingsService = new SettingsService(defaultValueProvider.Object, applicationDataContainers);
|
||||
|
||||
var result = settingsService.GetCurrentTheme();
|
||||
|
||||
result.Should().Be(defaultTheme);
|
||||
roamingSettings.Verify(x => x.SetValue(SettingsService.CurrentThemeKey, defaultTheme.Id), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Ansi 0 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.016337040811777115</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.016232240945100784</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.020433688536286354</real>
|
||||
</dict>
|
||||
<key>Ansi 1 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.075083047151565552</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.0</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.73976802825927734</real>
|
||||
</dict>
|
||||
<key>Ansi 10 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.43171143531799316</real>
|
||||
<key>Green Component</key>
|
||||
<real>1</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.61819148063659668</real>
|
||||
</dict>
|
||||
<key>Ansi 11 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.10242157429456711</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.7578997015953064</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.93761706352233887</real>
|
||||
</dict>
|
||||
<key>Ansi 12 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.77801346778869629</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.59102588891983032</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.096501544117927551</real>
|
||||
</dict>
|
||||
<key>Ansi 13 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.32394066452980042</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.34950375556945801</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.60686224699020386</real>
|
||||
</dict>
|
||||
<key>Ansi 14 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.95550096035003662</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.97915208339691162</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.78500419855117798</real>
|
||||
</dict>
|
||||
<key>Ansi 15 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.98438382148742676</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.96043074131011963</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.96449893712997437</real>
|
||||
</dict>
|
||||
<key>Ansi 2 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.092498354613780975</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.6950421929359436</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.28945007920265198</real>
|
||||
</dict>
|
||||
<key>Ansi 3 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.1164485365152359</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.45553147792816162</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.90543299913406372</real>
|
||||
</dict>
|
||||
<key>Ansi 4 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.77829605340957642</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.28880593180656433</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.059818677604198456</real>
|
||||
</dict>
|
||||
<key>Ansi 5 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.57602518796920776</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.35004982352256775</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.40191537141799927</real>
|
||||
</dict>
|
||||
<key>Ansi 6 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.59465551376342773</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.64633101224899292</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.43781715631484985</real>
|
||||
</dict>
|
||||
<key>Ansi 7 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.75428962707519531</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.86175870895385742</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.97308963537216187</real>
|
||||
</dict>
|
||||
<key>Ansi 8 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.7491685152053833</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.48549851775169373</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.30726605653762817</real>
|
||||
</dict>
|
||||
<key>Ansi 9 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.35247993469238281</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.37095117568969727</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.98876720666885376</real>
|
||||
</dict>
|
||||
<key>Background Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.27054747939109802</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.11274909973144531</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.12003477662801743</real>
|
||||
</dict>
|
||||
<key>Bold Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.075083047151565552</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.0</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.73976802825927734</real>
|
||||
</dict>
|
||||
<key>Cursor Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.21945112943649292</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.74987590312957764</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.93704277276992798</real>
|
||||
</dict>
|
||||
<key>Cursor Text Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.037519864737987518</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.032785907387733459</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.02988031692802906</real>
|
||||
</dict>
|
||||
<key>Foreground Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.75428962707519531</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.86175870895385742</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.97308963537216187</real>
|
||||
</dict>
|
||||
<key>Selected Text Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.767447829246521</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.85237473249435425</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.95287787914276123</real>
|
||||
</dict>
|
||||
<key>Selection Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.30699285864830017</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.41871801018714905</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.43789717555046082</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,45 @@
|
||||
using AutoFixture;
|
||||
using FluentAssertions;
|
||||
using FluentTerminal.App.Services.Implementation;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace FluentTerminal.App.Services.Test
|
||||
{
|
||||
public class ThemeParserFactoryTests
|
||||
{
|
||||
private readonly Fixture _fixture;
|
||||
|
||||
public ThemeParserFactoryTests()
|
||||
{
|
||||
_fixture = new Fixture();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetParser_SupportedFileType_ReturnsParser()
|
||||
{
|
||||
var supportedFileType = _fixture.Create<string>();
|
||||
var parser = new Mock<IThemeParser>();
|
||||
parser.Setup(x => x.SupportedFileTypes).Returns(new string[] { supportedFileType });
|
||||
var themeParserFactory = new ThemeParserFactory(new IThemeParser[] { parser.Object });
|
||||
|
||||
var result = themeParserFactory.GetParser(supportedFileType);
|
||||
|
||||
parser.Should().Be(parser);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetParser_UnsupportedFileType_ReturnsNull()
|
||||
{
|
||||
var unSupportedFileType = _fixture.Create<string>();
|
||||
var supportedFileType = _fixture.Create<string>();
|
||||
var parser = new Mock<IThemeParser>();
|
||||
parser.Setup(x => x.SupportedFileTypes).Returns(new string[] { supportedFileType });
|
||||
var themeParserFactory = new ThemeParserFactory(new IThemeParser[] { parser.Object });
|
||||
|
||||
var result = themeParserFactory.GetParser(unSupportedFileType);
|
||||
|
||||
result.Should().BeNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
using AutoFixture;
|
||||
using FluentAssertions;
|
||||
using FluentTerminal.App.Services.Implementation;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using FluentTerminal.Models.Requests;
|
||||
using FluentTerminal.Models.Responses;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace FluentTerminal.App.Services.Test
|
||||
{
|
||||
public class TrayProcessCommunicationServiceTests
|
||||
{
|
||||
private readonly Fixture _fixture;
|
||||
|
||||
public TrayProcessCommunicationServiceTests()
|
||||
{
|
||||
_fixture = new Fixture();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateTerminal_Default_ReturnsResponseFromAppServiceConnection()
|
||||
{
|
||||
var settingsService = new Mock<ISettingsService>();
|
||||
var keyBindings = _fixture.CreateMany<KeyBinding>(3);
|
||||
settingsService.Setup(x => x.GetKeyBindings()).Returns(new Dictionary<Command, ICollection<KeyBinding>>
|
||||
{
|
||||
[Command.ToggleWindow] = keyBindings.ToList()
|
||||
});
|
||||
var appServiceConnection = new Mock<IAppServiceConnection>();
|
||||
var response = _fixture.Create<CreateTerminalResponse>();
|
||||
var responseMessage = new Dictionary<string, string>
|
||||
{
|
||||
[MessageKeys.Type] = _fixture.Create<string>(),
|
||||
[MessageKeys.Content] = JsonConvert.SerializeObject(response)
|
||||
};
|
||||
appServiceConnection.Setup(x => x.SendMessageAsync(It.IsAny<IDictionary<string, string>>())).Returns(Task.FromResult((IDictionary<string, string>)responseMessage));
|
||||
var terminalSize = _fixture.Create<TerminalSize>();
|
||||
var shellProfile = _fixture.Create<ShellProfile>();
|
||||
var trayProcessCommunicationService = new TrayProcessCommunicationService(settingsService.Object);
|
||||
trayProcessCommunicationService.Initialize(appServiceConnection.Object);
|
||||
|
||||
var result = await trayProcessCommunicationService.CreateTerminal(terminalSize, shellProfile);
|
||||
|
||||
result.Should().BeEquivalentTo(response);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResizeTerminal_Default_SendsResizeTerminalRequest()
|
||||
{
|
||||
var terminalId = _fixture.Create<int>();
|
||||
var terminalSize = _fixture.Create<TerminalSize>();
|
||||
var settingsService = new Mock<ISettingsService>();
|
||||
var keyBindings = _fixture.CreateMany<KeyBinding>(3);
|
||||
settingsService.Setup(x => x.GetKeyBindings()).Returns(new Dictionary<Command, ICollection<KeyBinding>>
|
||||
{
|
||||
[Command.ToggleWindow] = keyBindings.ToList()
|
||||
});
|
||||
var appServiceConnection = new Mock<IAppServiceConnection>();
|
||||
var trayProcessCommunicationService = new TrayProcessCommunicationService(settingsService.Object);
|
||||
trayProcessCommunicationService.Initialize(appServiceConnection.Object);
|
||||
|
||||
await trayProcessCommunicationService.ResizeTerminal(terminalId, terminalSize);
|
||||
|
||||
appServiceConnection.Verify(x => x.SendMessageAsync(It.Is<IDictionary<string, string>>(d => d[MessageKeys.Type] == nameof(ResizeTerminalRequest))), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WriteText_Default_SendsWriteTextRequest()
|
||||
{
|
||||
var terminalId = _fixture.Create<int>();
|
||||
var text = _fixture.Create<string>();
|
||||
var settingsService = new Mock<ISettingsService>();
|
||||
var keyBindings = _fixture.CreateMany<KeyBinding>(3);
|
||||
settingsService.Setup(x => x.GetKeyBindings()).Returns(new Dictionary<Command, ICollection<KeyBinding>>
|
||||
{
|
||||
[Command.ToggleWindow] = keyBindings.ToList()
|
||||
});
|
||||
var appServiceConnection = new Mock<IAppServiceConnection>();
|
||||
var trayProcessCommunicationService = new TrayProcessCommunicationService(settingsService.Object);
|
||||
trayProcessCommunicationService.Initialize(appServiceConnection.Object);
|
||||
|
||||
await trayProcessCommunicationService.WriteText(terminalId, text);
|
||||
|
||||
appServiceConnection.Verify(x => x.SendMessageAsync(It.Is<IDictionary<string, string>>(d => d[MessageKeys.Type] == nameof(WriteTextRequest))), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CloseTerminal_Default_SendsTerminalExitedRequest()
|
||||
{
|
||||
var terminalId = _fixture.Create<int>();
|
||||
var settingsService = new Mock<ISettingsService>();
|
||||
var keyBindings = _fixture.CreateMany<KeyBinding>(3);
|
||||
settingsService.Setup(x => x.GetKeyBindings()).Returns(new Dictionary<Command, ICollection<KeyBinding>>
|
||||
{
|
||||
[Command.ToggleWindow] = keyBindings.ToList()
|
||||
});
|
||||
var appServiceConnection = new Mock<IAppServiceConnection>();
|
||||
var trayProcessCommunicationService = new TrayProcessCommunicationService(settingsService.Object);
|
||||
trayProcessCommunicationService.Initialize(appServiceConnection.Object);
|
||||
|
||||
await trayProcessCommunicationService.CloseTerminal(terminalId);
|
||||
|
||||
appServiceConnection.Verify(x => x.SendMessageAsync(It.Is<IDictionary<string, string>>(d => d[MessageKeys.Type] == nameof(TerminalExitedRequest))), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnMessageReceived_TerminalExitedRequest_InvokesTerminalExitedEvent()
|
||||
{
|
||||
var terminalId = _fixture.Create<int>();
|
||||
var receivedTerminalId = 0;
|
||||
var terminalExitedEventCalled = false;
|
||||
var request = new TerminalExitedRequest
|
||||
{
|
||||
TerminalId = terminalId
|
||||
};
|
||||
var message = new Dictionary<string, string>
|
||||
{
|
||||
[MessageKeys.Type] = nameof(TerminalExitedRequest),
|
||||
[MessageKeys.Content] = JsonConvert.SerializeObject(request)
|
||||
};
|
||||
var settingsService = new Mock<ISettingsService>();
|
||||
var keyBindings = _fixture.CreateMany<KeyBinding>(3);
|
||||
settingsService.Setup(x => x.GetKeyBindings()).Returns(new Dictionary<Command, ICollection<KeyBinding>>
|
||||
{
|
||||
[Command.ToggleWindow] = keyBindings.ToList()
|
||||
});
|
||||
var trayProcessCommunicationService = new TrayProcessCommunicationService(settingsService.Object);
|
||||
var appServiceConnection = new Mock<IAppServiceConnection>();
|
||||
trayProcessCommunicationService.Initialize(appServiceConnection.Object);
|
||||
trayProcessCommunicationService.TerminalExited += (s, e) =>
|
||||
{
|
||||
terminalExitedEventCalled = true;
|
||||
receivedTerminalId = e;
|
||||
};
|
||||
|
||||
appServiceConnection.Raise(x => x.MessageReceived += null, null, message);
|
||||
|
||||
terminalExitedEventCalled.Should().BeTrue();
|
||||
receivedTerminalId.Should().Be(terminalId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnMessageReceived_DisplayTerminalOutputRequest_InvokesCorrectOutputHandler()
|
||||
{
|
||||
var terminalId = _fixture.Create<int>();
|
||||
var output = _fixture.Create<string>();
|
||||
var receivedOutput = string.Empty;
|
||||
var request = new DisplayTerminalOutputRequest
|
||||
{
|
||||
TerminalId = terminalId,
|
||||
Output = output
|
||||
};
|
||||
var message = new Dictionary<string, string>
|
||||
{
|
||||
[MessageKeys.Type] = nameof(DisplayTerminalOutputRequest),
|
||||
[MessageKeys.Content] = JsonConvert.SerializeObject(request)
|
||||
};
|
||||
var settingsService = new Mock<ISettingsService>();
|
||||
var keyBindings = _fixture.CreateMany<KeyBinding>(3);
|
||||
settingsService.Setup(x => x.GetKeyBindings()).Returns(new Dictionary<Command, ICollection<KeyBinding>>
|
||||
{
|
||||
[Command.ToggleWindow] = keyBindings.ToList()
|
||||
});
|
||||
var trayProcessCommunicationService = new TrayProcessCommunicationService(settingsService.Object);
|
||||
var appServiceConnection = new Mock<IAppServiceConnection>();
|
||||
trayProcessCommunicationService.Initialize(appServiceConnection.Object);
|
||||
trayProcessCommunicationService.SubscribeForTerminalOutput(terminalId, o =>
|
||||
{
|
||||
receivedOutput = o;
|
||||
});
|
||||
|
||||
appServiceConnection.Raise(x => x.MessageReceived += null, null, message);
|
||||
|
||||
receivedOutput.Should().Be(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -1,11 +1,10 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace FluentTerminal.App.Adapters
|
||||
namespace FluentTerminal.App.Services.Adapters
|
||||
{
|
||||
public class ApplicationDataContainerAdapter : IApplicationDataContainer
|
||||
{
|
||||
@@ -50,7 +49,6 @@ namespace FluentTerminal.App.Adapters
|
||||
return _applicationDataContainer.Values.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
|
||||
public void WriteValueAsJson<T>(string name, T value)
|
||||
{
|
||||
_applicationDataContainer.Values[name] = JsonConvert.SerializeObject(value);
|
||||
@@ -8,4 +8,4 @@
|
||||
public IApplicationDataContainer KeyBindings { get; set; }
|
||||
public IApplicationDataContainer ShellProfiles { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
public const string ThemesContainerName = "Themes";
|
||||
public const string KeyBindingsContainerName = "KeyBindings";
|
||||
public const string ShellProfilesContainerName = "ShellProfiles";
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,4 @@ namespace FluentTerminal.App.Services.Dialogs
|
||||
{
|
||||
Task<KeyBinding> CreateKeyBinding();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,4 +11,4 @@ namespace FluentTerminal.App.Services.Dialogs
|
||||
|
||||
Task<DialogButton> ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,4 +9,4 @@ namespace FluentTerminal.App.Services.Dialogs
|
||||
|
||||
Task<ShellProfile> SelectProfile();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,4 @@
|
||||
{
|
||||
public bool Cancelled { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<LangVersion>7.1</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<LangVersion>7.1</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -21,4 +14,15 @@
|
||||
<ProjectReference Include="..\FluentTerminal.Models\FluentTerminal.Models.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Windows.Foundation.FoundationContract">
|
||||
<HintPath>$(MSBuildProgramFiles32)\Windows Kits\10\References\10.0.16299.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Windows.Foundation.UniversalApiContract">
|
||||
<HintPath>$(MSBuildProgramFiles32)\Windows Kits\10\References\10.0.16299.0\Windows.Foundation.UniversalApiContract\5.0.0.0\Windows.Foundation.UniversalApiContract.winmd</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,10 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface IAppServiceConnection
|
||||
{
|
||||
event EventHandler<IDictionary<string, string>> MessageReceived;
|
||||
|
||||
Task<IDictionary<string, string>> SendMessageAsync(IDictionary<string, string> message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,4 +16,4 @@ namespace FluentTerminal.App.Services
|
||||
|
||||
IEnumerable<object> GetAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,9 @@ namespace FluentTerminal.App.Services
|
||||
string Title { get; set; }
|
||||
|
||||
Task RunOnDispatcherThread(Action action);
|
||||
|
||||
Task<bool> TryClose();
|
||||
|
||||
bool ToggleFullScreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ namespace FluentTerminal.App.Services
|
||||
public interface IClipboardService
|
||||
{
|
||||
Task<string> GetText();
|
||||
|
||||
void SetText(string text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,20 @@ namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface IDefaultValueProvider
|
||||
{
|
||||
IEnumerable<ShellProfile> GetPreinstalledShellProfiles();
|
||||
Guid GetDefaultShellProfileId();
|
||||
TerminalOptions GetDefaultTerminalOptions();
|
||||
ICollection<KeyBinding> GetDefaultKeyBindings(Command command);
|
||||
ApplicationSettings GetDefaultApplicationSettings();
|
||||
|
||||
ICollection<KeyBinding> GetDefaultKeyBindings(Command command);
|
||||
|
||||
Guid GetDefaultShellProfileId();
|
||||
|
||||
IEnumerable<TabTheme> GetDefaultTabThemes();
|
||||
|
||||
TerminalOptions GetDefaultTerminalOptions();
|
||||
|
||||
Guid GetDefaultThemeId();
|
||||
|
||||
IEnumerable<ShellProfile> GetPreinstalledShellProfiles();
|
||||
|
||||
IEnumerable<TerminalTheme> GetPreInstalledThemes();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,4 +17,4 @@ namespace FluentTerminal.App.Services
|
||||
|
||||
Task<KeyBinding> ShowCreateKeyBindingDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ namespace FluentTerminal.App.Services
|
||||
public interface IDispatcherTimer
|
||||
{
|
||||
void Start();
|
||||
|
||||
void Stop();
|
||||
|
||||
TimeSpan Interval { get; set; }
|
||||
@@ -12,4 +13,4 @@ namespace FluentTerminal.App.Services
|
||||
|
||||
event EventHandler<object> Tick;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,4 +12,4 @@ namespace FluentTerminal.App.Services
|
||||
|
||||
Task SaveTextFile(string name, string fileTypeDescription, string fileType, string content);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ namespace FluentTerminal.App.Services
|
||||
public interface IKeyboardCommandService
|
||||
{
|
||||
void RegisterCommandHandler(Command command, Action handler);
|
||||
|
||||
void SendCommand(Command command);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,36 +7,30 @@ namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface ISettingsService
|
||||
{
|
||||
event EventHandler<Guid> CurrentThemeChanged;
|
||||
event EventHandler<TerminalOptions> TerminalOptionsChanged;
|
||||
event EventHandler<ApplicationSettings> ApplicationSettingsChanged;
|
||||
event EventHandler<Guid> CurrentThemeChanged;
|
||||
event EventHandler KeyBindingsChanged;
|
||||
|
||||
Guid GetDefaultShellProfileId();
|
||||
ShellProfile GetDefaultShellProfile();
|
||||
void SaveDefaultShellProfileId(Guid id);
|
||||
|
||||
IEnumerable<ShellProfile> GetShellProfiles();
|
||||
void SaveShellProfile(ShellProfile shellProfile);
|
||||
event EventHandler<TerminalOptions> TerminalOptionsChanged;
|
||||
void DeleteShellProfile(Guid id);
|
||||
|
||||
TerminalOptions GetTerminalOptions();
|
||||
void SaveTerminalOptions(TerminalOptions terminalOptions);
|
||||
|
||||
void DeleteTheme(Guid id);
|
||||
ApplicationSettings GetApplicationSettings();
|
||||
void SaveApplicationSettings(ApplicationSettings applicationSettings);
|
||||
|
||||
IDictionary<Command, ICollection<KeyBinding>> GetKeyBindings();
|
||||
void SaveKeyBindings(Command command, ICollection<KeyBinding> keyBindings);
|
||||
void ResetKeyBindings();
|
||||
|
||||
TerminalTheme GetCurrentTheme();
|
||||
Guid GetCurrentThemeId();
|
||||
ShellProfile GetDefaultShellProfile();
|
||||
Guid GetDefaultShellProfileId();
|
||||
IDictionary<Command, ICollection<KeyBinding>> GetKeyBindings();
|
||||
IEnumerable<ShellProfile> GetShellProfiles();
|
||||
IEnumerable<TabTheme> GetTabThemes();
|
||||
TerminalOptions GetTerminalOptions();
|
||||
TerminalTheme GetTheme(Guid id);
|
||||
void SaveCurrentThemeId(Guid id);
|
||||
|
||||
IEnumerable<TerminalTheme> GetThemes();
|
||||
void ResetKeyBindings();
|
||||
void SaveApplicationSettings(ApplicationSettings applicationSettings);
|
||||
void SaveCurrentThemeId(Guid id);
|
||||
void SaveDefaultShellProfileId(Guid id);
|
||||
void SaveKeyBindings(Command command, ICollection<KeyBinding> keyBindings);
|
||||
void SaveShellProfile(ShellProfile shellProfile);
|
||||
void SaveTerminalOptions(TerminalOptions terminalOptions);
|
||||
void SaveTheme(TerminalTheme theme);
|
||||
void DeleteTheme(Guid id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using FluentTerminal.Models.Enums;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface IStartupTaskService
|
||||
{
|
||||
Task DisableStartupTask();
|
||||
Task<StartupTaskStatus> EnableStartupTask();
|
||||
Task<StartupTaskStatus> GetStatus();
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,4 @@ namespace FluentTerminal.App.Services
|
||||
{
|
||||
IEnumerable<string> GetSystemFontFamilies();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,31 @@ namespace FluentTerminal.App.Services
|
||||
public interface ITerminalView
|
||||
{
|
||||
event EventHandler<TerminalSize> TerminalSizeChanged;
|
||||
|
||||
event EventHandler<string> TerminalTitleChanged;
|
||||
|
||||
event EventHandler<Command> KeyboardCommandReceived;
|
||||
|
||||
Task ChangeTheme(TerminalColors theme);
|
||||
|
||||
Task ChangeOptions(TerminalOptions options);
|
||||
|
||||
Task ChangeKeyBindings(IEnumerable<KeyBinding> keyBindings);
|
||||
|
||||
Task<TerminalSize> CreateTerminal(TerminalOptions options, TerminalColors theme, IEnumerable<KeyBinding> keyBindings);
|
||||
|
||||
Task ConnectToSocket(string url);
|
||||
|
||||
void Close();
|
||||
|
||||
Task FocusTerminal();
|
||||
|
||||
Task<string> GetSelection();
|
||||
Task Write(string text);
|
||||
|
||||
Task FindNext(string searchText);
|
||||
|
||||
Task FindPrevious(string searchText);
|
||||
|
||||
void FocusSearchTextBox();
|
||||
}
|
||||
}
|
||||
@@ -11,4 +11,4 @@ namespace FluentTerminal.App.Services
|
||||
|
||||
Task<TerminalTheme> Parse(string fileName, Stream fileContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,4 +8,4 @@ namespace FluentTerminal.App.Services
|
||||
|
||||
IThemeParser GetParser(string fileType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,26 @@
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Responses;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public interface ITrayProcessCommunicationService
|
||||
{
|
||||
Task Initialize(IAppServiceConnection appServiceConnection);
|
||||
event EventHandler<int> TerminalExited;
|
||||
|
||||
void Initialize(IAppServiceConnection appServiceConnection);
|
||||
|
||||
Task<CreateTerminalResponse> CreateTerminal(TerminalSize size, ShellProfile shellProfile);
|
||||
|
||||
Task ResizeTerminal(int id, TerminalSize size);
|
||||
|
||||
Task UpdateToggleWindowKeyBindings();
|
||||
|
||||
Task WriteText(int terminalId, string text);
|
||||
|
||||
void SubscribeForTerminalOutput(int terminalId, Action<string> callback);
|
||||
|
||||
Task CloseTerminal(int terminalId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,14 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
ConfirmClosingTabs = false,
|
||||
ConfirmClosingWindows = false,
|
||||
UnderlineSelectedTab = false,
|
||||
NewTerminalLocation = NewTerminalLocation.Tab
|
||||
InactiveTabColorMode = InactiveTabColorMode.Background,
|
||||
NewTerminalLocation = NewTerminalLocation.Tab,
|
||||
TabsPosition = TabsPosition.Top,
|
||||
CopyOnSelect = false,
|
||||
MouseMiddleClickAction = MouseAction.None,
|
||||
MouseRightClickAction = MouseAction.ContextMenu,
|
||||
AlwaysShowTabs = false,
|
||||
ShowNewOutputIndicator = false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,7 +30,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
switch (command)
|
||||
{
|
||||
case Command.ToggleWindow:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -36,7 +43,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.NextTab:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -49,7 +56,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.PreviousTab:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -61,8 +68,29 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
}
|
||||
};
|
||||
|
||||
case Command.SwitchToTerm1:
|
||||
case Command.SwitchToTerm2:
|
||||
case Command.SwitchToTerm3:
|
||||
case Command.SwitchToTerm4:
|
||||
case Command.SwitchToTerm5:
|
||||
case Command.SwitchToTerm6:
|
||||
case Command.SwitchToTerm7:
|
||||
case Command.SwitchToTerm8:
|
||||
case Command.SwitchToTerm9:
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
Command = command,
|
||||
Ctrl = true,
|
||||
Alt = false,
|
||||
Shift = false,
|
||||
Key = (int)ExtendedVirtualKey.Number1 + (command - Command.SwitchToTerm1)
|
||||
}
|
||||
};
|
||||
|
||||
case Command.NewTab:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -75,7 +103,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.ConfigurableNewTab:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -88,7 +116,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.CloseTab:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -101,7 +129,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.NewWindow:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -114,7 +142,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.ShowSettings:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -127,7 +155,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.Copy:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -140,7 +168,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.Paste:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -153,7 +181,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.Search:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -166,7 +194,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.ToggleFullScreen:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -179,7 +207,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.SelectAll:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -192,7 +220,7 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
};
|
||||
|
||||
case Command.Clear:
|
||||
return new List<KeyBinding>
|
||||
return new List<KeyBinding>
|
||||
{
|
||||
new KeyBinding
|
||||
{
|
||||
@@ -213,6 +241,59 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
return Guid.Parse("813f2298-210a-481a-bdbf-c17bc637a3e2");
|
||||
}
|
||||
|
||||
public IEnumerable<TabTheme> GetDefaultTabThemes()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
new TabTheme
|
||||
{
|
||||
Id = 0,
|
||||
Name = "None",
|
||||
BackgroundOpacity = double.NaN,
|
||||
BackgroundPointerOverOpacity = double.NaN,
|
||||
BackgroundPressedOpacity = double.NaN,
|
||||
BackgroundSelectedOpacity = double.NaN,
|
||||
BackgroundSelectedPointerOverOpacity = double.NaN,
|
||||
BackgroundSelectedPressedOpacity = double.NaN
|
||||
},
|
||||
new TabTheme
|
||||
{
|
||||
Id = 1,
|
||||
Name = "Red",
|
||||
Color = "#E81123"
|
||||
},
|
||||
new TabTheme
|
||||
{
|
||||
Id = 2,
|
||||
Name = "Green",
|
||||
Color = "#10893E"
|
||||
},
|
||||
new TabTheme
|
||||
{
|
||||
Id = 3,
|
||||
Name = "Blue",
|
||||
Color = "#0078D7"
|
||||
},
|
||||
new TabTheme
|
||||
{
|
||||
Id = 4,
|
||||
Name = "Purple",
|
||||
Color = "#881798"
|
||||
},
|
||||
new TabTheme
|
||||
{
|
||||
Id = 5,
|
||||
Name = "Orange",
|
||||
Color = "#FF8C00"
|
||||
},
|
||||
new TabTheme
|
||||
{
|
||||
Id = 6,
|
||||
Name = "Teal",
|
||||
Color = "#00B7C3"
|
||||
}
|
||||
};
|
||||
}
|
||||
public TerminalOptions GetDefaultTerminalOptions()
|
||||
{
|
||||
return new TerminalOptions
|
||||
@@ -411,18 +492,18 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
CursorAccent = "#000000",
|
||||
Selection = "#4DABEDC1",
|
||||
Black = "#300A24",
|
||||
Red = "#3465A4",
|
||||
Red = "#CC0000",
|
||||
Green = "#4E9A06",
|
||||
Yellow = "#06989A",
|
||||
Blue = "#CC0000",
|
||||
Blue = "#3465A4",
|
||||
Magenta = "#75507B",
|
||||
Cyan = "#C4A000",
|
||||
White = "#D3D7CF",
|
||||
BrightBlack = "#554E53",
|
||||
BrightRed = "#729FCF",
|
||||
BrightRed = "#EF2929",
|
||||
BrightGreen = "#8AE234",
|
||||
BrightYellow = "#34E2E2",
|
||||
BrightBlue = "#EF2929",
|
||||
BrightBlue = "#729FCF",
|
||||
BrightMagenta = "#AD7FA8",
|
||||
BrightCyan = "#FCE94F",
|
||||
BrightWhite = "#EEEEEE"
|
||||
@@ -432,4 +513,4 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
return new[] { defaultXterm, powerShell, homebrew, tomorrow, ubuntu };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using FluentTerminal.App.Services.Dialogs;
|
||||
using FluentTerminal.App.Services.Dialogs;
|
||||
using FluentTerminal.Models;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
@@ -61,4 +61,4 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
return dialog.SelectProfile();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using FluentTerminal.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using FluentTerminal.Models;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
@@ -13,6 +13,16 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
|
||||
public async Task<TerminalTheme> Parse(string fileName, Stream fileContent)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(fileName))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fileName));
|
||||
}
|
||||
|
||||
if (fileContent == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fileContent));
|
||||
}
|
||||
|
||||
using (var streamReader = new StreamReader(fileContent))
|
||||
{
|
||||
var content = await streamReader.ReadToEndAsync();
|
||||
@@ -25,4 +35,4 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,16 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
|
||||
public async Task<TerminalTheme> Parse(string fileName, Stream fileContent)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(fileName))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fileName));
|
||||
}
|
||||
|
||||
if (fileContent == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fileContent));
|
||||
}
|
||||
|
||||
var node = PList.Load(fileContent) as DictionaryNode ?? throw new ParseThemeException("Root node was not a dictionary.");
|
||||
|
||||
return new TerminalTheme
|
||||
@@ -124,4 +134,4 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
return (alpha / 256.0).ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FluentTerminal.Models.Enums;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
@@ -35,4 +35,4 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
throw new KeyNotFoundException($"No handler registered for command: {command}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
@@ -14,17 +14,11 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
public const string DefaultShellProfileKey = "DefaultShellProfile";
|
||||
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private readonly IApplicationDataContainer _localSettings;
|
||||
private readonly IApplicationDataContainer _themes;
|
||||
private readonly IApplicationDataContainer _keyBindings;
|
||||
private readonly IApplicationDataContainer _shellProfiles;
|
||||
private readonly IApplicationDataContainer _localSettings;
|
||||
private readonly IApplicationDataContainer _roamingSettings;
|
||||
|
||||
public event EventHandler<Guid> CurrentThemeChanged;
|
||||
public event EventHandler<TerminalOptions> TerminalOptionsChanged;
|
||||
public event EventHandler<ApplicationSettings> ApplicationSettingsChanged;
|
||||
public event EventHandler KeyBindingsChanged;
|
||||
|
||||
private readonly IApplicationDataContainer _shellProfiles;
|
||||
private readonly IApplicationDataContainer _themes;
|
||||
public SettingsService(IDefaultValueProvider defaultValueProvider, ApplicationDataContainers containers)
|
||||
{
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
@@ -37,19 +31,54 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
|
||||
foreach (var theme in _defaultValueProvider.GetPreInstalledThemes())
|
||||
{
|
||||
_themes.WriteValueAsJson(theme.Id.ToString(), theme);
|
||||
if (GetTheme(theme.Id) == null)
|
||||
{
|
||||
_themes.WriteValueAsJson(theme.Id.ToString(), theme);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var shellProfile in _defaultValueProvider.GetPreinstalledShellProfiles())
|
||||
{
|
||||
_shellProfiles.WriteValueAsJson(shellProfile.Id.ToString(), shellProfile);
|
||||
if (GetShellProfile(shellProfile.Id) == null)
|
||||
{
|
||||
_shellProfiles.WriteValueAsJson(shellProfile.Id.ToString(), shellProfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<ApplicationSettings> ApplicationSettingsChanged;
|
||||
|
||||
public event EventHandler<Guid> CurrentThemeChanged;
|
||||
|
||||
public event EventHandler KeyBindingsChanged;
|
||||
|
||||
public event EventHandler<TerminalOptions> TerminalOptionsChanged;
|
||||
public void DeleteShellProfile(Guid id)
|
||||
{
|
||||
_shellProfiles.Delete(id.ToString());
|
||||
}
|
||||
|
||||
public void DeleteTheme(Guid id)
|
||||
{
|
||||
_themes.Delete(id.ToString());
|
||||
}
|
||||
|
||||
public ApplicationSettings GetApplicationSettings()
|
||||
{
|
||||
return _roamingSettings.ReadValueFromJson(nameof(ApplicationSettings), _defaultValueProvider.GetDefaultApplicationSettings());
|
||||
}
|
||||
|
||||
public TerminalTheme GetCurrentTheme()
|
||||
{
|
||||
var id = GetCurrentThemeId();
|
||||
return GetTheme(id);
|
||||
var theme = GetTheme(id);
|
||||
if (theme == null)
|
||||
{
|
||||
id = _defaultValueProvider.GetDefaultThemeId();
|
||||
SaveCurrentThemeId(id);
|
||||
theme = GetTheme(id);
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
public Guid GetCurrentThemeId()
|
||||
@@ -61,6 +90,85 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
return _defaultValueProvider.GetDefaultThemeId();
|
||||
}
|
||||
|
||||
public ShellProfile GetDefaultShellProfile()
|
||||
{
|
||||
var id = GetDefaultShellProfileId();
|
||||
var profile = _shellProfiles.ReadValueFromJson(id.ToString(), default(ShellProfile));
|
||||
if (profile == null)
|
||||
{
|
||||
id = _defaultValueProvider.GetDefaultShellProfileId();
|
||||
SaveDefaultShellProfileId(id);
|
||||
profile = _shellProfiles.ReadValueFromJson(id.ToString(), default(ShellProfile));
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
|
||||
public ShellProfile GetShellProfile(Guid id)
|
||||
{
|
||||
return _shellProfiles.ReadValueFromJson(id.ToString(), default(ShellProfile));
|
||||
}
|
||||
|
||||
public Guid GetDefaultShellProfileId()
|
||||
{
|
||||
if (_localSettings.TryGetValue(DefaultShellProfileKey, out object value))
|
||||
{
|
||||
return (Guid)value;
|
||||
}
|
||||
return _defaultValueProvider.GetDefaultShellProfileId();
|
||||
}
|
||||
|
||||
public IDictionary<Command, ICollection<KeyBinding>> GetKeyBindings()
|
||||
{
|
||||
var keyBindings = new Dictionary<Command, ICollection<KeyBinding>>();
|
||||
foreach (Command command in Enum.GetValues(typeof(Command)))
|
||||
{
|
||||
keyBindings.Add(command, _keyBindings.ReadValueFromJson<Collection<KeyBinding>>(command.ToString(), null) ?? _defaultValueProvider.GetDefaultKeyBindings(command));
|
||||
}
|
||||
|
||||
return keyBindings;
|
||||
}
|
||||
|
||||
public IEnumerable<ShellProfile> GetShellProfiles()
|
||||
{
|
||||
return _shellProfiles.GetAll().Select(x => JsonConvert.DeserializeObject<ShellProfile>((string)x)).ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<TabTheme> GetTabThemes()
|
||||
{
|
||||
return _defaultValueProvider.GetDefaultTabThemes();
|
||||
}
|
||||
|
||||
public TerminalOptions GetTerminalOptions()
|
||||
{
|
||||
return _roamingSettings.ReadValueFromJson(nameof(TerminalOptions), _defaultValueProvider.GetDefaultTerminalOptions());
|
||||
}
|
||||
|
||||
public TerminalTheme GetTheme(Guid id)
|
||||
{
|
||||
return _themes.ReadValueFromJson(id.ToString(), default(TerminalTheme));
|
||||
}
|
||||
|
||||
public IEnumerable<TerminalTheme> GetThemes()
|
||||
{
|
||||
return _themes.GetAll().Select(x => JsonConvert.DeserializeObject<TerminalTheme>((string)x)).ToList();
|
||||
}
|
||||
|
||||
public void ResetKeyBindings()
|
||||
{
|
||||
foreach (Command command in Enum.GetValues(typeof(Command)))
|
||||
{
|
||||
_keyBindings.WriteValueAsJson(command.ToString(), _defaultValueProvider.GetDefaultKeyBindings(command));
|
||||
}
|
||||
|
||||
KeyBindingsChanged?.Invoke(this, System.EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void SaveApplicationSettings(ApplicationSettings applicationSettings)
|
||||
{
|
||||
_roamingSettings.WriteValueAsJson(nameof(ApplicationSettings), applicationSettings);
|
||||
ApplicationSettingsChanged?.Invoke(this, applicationSettings);
|
||||
}
|
||||
|
||||
public void SaveCurrentThemeId(Guid id)
|
||||
{
|
||||
_roamingSettings.SetValue(CurrentThemeKey, id);
|
||||
@@ -68,6 +176,28 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
CurrentThemeChanged?.Invoke(this, id);
|
||||
}
|
||||
|
||||
public void SaveDefaultShellProfileId(Guid id)
|
||||
{
|
||||
_localSettings.SetValue(DefaultShellProfileKey, id);
|
||||
}
|
||||
|
||||
public void SaveKeyBindings(Command command, ICollection<KeyBinding> keyBindings)
|
||||
{
|
||||
_keyBindings.WriteValueAsJson(command.ToString(), keyBindings);
|
||||
KeyBindingsChanged?.Invoke(this, System.EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void SaveShellProfile(ShellProfile shellProfile)
|
||||
{
|
||||
_shellProfiles.WriteValueAsJson(shellProfile.Id.ToString(), shellProfile);
|
||||
}
|
||||
|
||||
public void SaveTerminalOptions(TerminalOptions terminalOptions)
|
||||
{
|
||||
_roamingSettings.WriteValueAsJson(nameof(TerminalOptions), terminalOptions);
|
||||
TerminalOptionsChanged?.Invoke(this, terminalOptions);
|
||||
}
|
||||
|
||||
public void SaveTheme(TerminalTheme theme)
|
||||
{
|
||||
_themes.WriteValueAsJson(theme.Id.ToString(), theme);
|
||||
@@ -77,107 +207,5 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
CurrentThemeChanged?.Invoke(this, theme.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteTheme(Guid id)
|
||||
{
|
||||
_themes.Delete(id.ToString());
|
||||
}
|
||||
|
||||
public IEnumerable<TerminalTheme> GetThemes()
|
||||
{
|
||||
return _themes.GetAll().Select(x => JsonConvert.DeserializeObject<TerminalTheme>((string)x)).ToList();
|
||||
}
|
||||
|
||||
public TerminalTheme GetTheme(Guid id)
|
||||
{
|
||||
return _themes.ReadValueFromJson(id.ToString(), default(TerminalTheme));
|
||||
}
|
||||
|
||||
public TerminalOptions GetTerminalOptions()
|
||||
{
|
||||
return _roamingSettings.ReadValueFromJson(nameof(TerminalOptions), _defaultValueProvider.GetDefaultTerminalOptions());
|
||||
}
|
||||
|
||||
public void SaveTerminalOptions(TerminalOptions terminalOptions)
|
||||
{
|
||||
_roamingSettings.WriteValueAsJson(nameof(TerminalOptions), terminalOptions);
|
||||
TerminalOptionsChanged?.Invoke(this, terminalOptions);
|
||||
}
|
||||
|
||||
public ApplicationSettings GetApplicationSettings()
|
||||
{
|
||||
return _roamingSettings.ReadValueFromJson(nameof(ApplicationSettings), _defaultValueProvider.GetDefaultApplicationSettings());
|
||||
}
|
||||
|
||||
public void SaveApplicationSettings(ApplicationSettings applicationSettings)
|
||||
{
|
||||
_roamingSettings.WriteValueAsJson(nameof(ApplicationSettings), applicationSettings);
|
||||
ApplicationSettingsChanged?.Invoke(this, applicationSettings);
|
||||
}
|
||||
|
||||
public IDictionary<Command, ICollection<KeyBinding>> GetKeyBindings()
|
||||
{
|
||||
var keyBindings = new Dictionary<Command, ICollection<KeyBinding>>();
|
||||
foreach (var value in Enum.GetValues(typeof(Command)))
|
||||
{
|
||||
var command = (Command)value;
|
||||
keyBindings.Add(command, _keyBindings.ReadValueFromJson<Collection<KeyBinding>>(command.ToString(), null) ?? _defaultValueProvider.GetDefaultKeyBindings(command));
|
||||
}
|
||||
|
||||
return keyBindings;
|
||||
}
|
||||
|
||||
public void SaveKeyBindings(Command command, ICollection<KeyBinding> keyBindings)
|
||||
{
|
||||
_keyBindings.WriteValueAsJson(command.ToString(), keyBindings);
|
||||
_roamingSettings.WriteValueAsJson(nameof(KeyBindings), keyBindings);
|
||||
KeyBindingsChanged?.Invoke(this, System.EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void ResetKeyBindings()
|
||||
{
|
||||
foreach (var value in Enum.GetValues(typeof(Command)))
|
||||
{
|
||||
var command = (Command)value;
|
||||
_keyBindings.WriteValueAsJson(command.ToString(), _defaultValueProvider.GetDefaultKeyBindings(command));
|
||||
}
|
||||
|
||||
KeyBindingsChanged?.Invoke(this, System.EventArgs.Empty);
|
||||
}
|
||||
|
||||
public Guid GetDefaultShellProfileId()
|
||||
{
|
||||
if (_roamingSettings.TryGetValue(DefaultShellProfileKey, out object value))
|
||||
{
|
||||
return (Guid)value;
|
||||
}
|
||||
return _defaultValueProvider.GetDefaultShellProfileId();
|
||||
}
|
||||
|
||||
public ShellProfile GetDefaultShellProfile()
|
||||
{
|
||||
var id = GetDefaultShellProfileId();
|
||||
return _shellProfiles.ReadValueFromJson(id.ToString(), default(ShellProfile));
|
||||
}
|
||||
|
||||
public void SaveDefaultShellProfileId(Guid id)
|
||||
{
|
||||
_roamingSettings.SetValue(DefaultShellProfileKey, id);
|
||||
}
|
||||
|
||||
public IEnumerable<ShellProfile> GetShellProfiles()
|
||||
{
|
||||
return _shellProfiles.GetAll().Select(x => JsonConvert.DeserializeObject<ShellProfile>((string)x)).ToList();
|
||||
}
|
||||
|
||||
public void SaveShellProfile(ShellProfile shellProfile)
|
||||
{
|
||||
_shellProfiles.WriteValueAsJson(shellProfile.Id.ToString(), shellProfile);
|
||||
}
|
||||
|
||||
public void DeleteShellProfile(Guid id)
|
||||
{
|
||||
_shellProfiles.Delete(id.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,4 +20,4 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
return _parsers.FirstOrDefault(p => p.SupportedFileTypes.Contains(fileType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using FluentTerminal.Models.Requests;
|
||||
using FluentTerminal.Models.Responses;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
@@ -12,10 +14,14 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
private IAppServiceConnection _appServiceConnection;
|
||||
private Dictionary<int, Action<string>> _terminalOutputHandlers;
|
||||
|
||||
public event EventHandler<int> TerminalExited;
|
||||
|
||||
public TrayProcessCommunicationService(ISettingsService settingsService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_terminalOutputHandlers = new Dictionary<int, Action<string>>();
|
||||
}
|
||||
|
||||
public async Task<CreateTerminalResponse> CreateTerminal(TerminalSize size, ShellProfile shellProfile)
|
||||
@@ -26,21 +32,41 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
Profile = shellProfile
|
||||
};
|
||||
|
||||
var message = new Dictionary<string, string>
|
||||
{
|
||||
{ MessageKeys.Type, MessageTypes.CreateTerminalRequest },
|
||||
{ MessageKeys.Content, JsonConvert.SerializeObject(request) }
|
||||
};
|
||||
|
||||
var responseMessage = await _appServiceConnection.SendMessageAsync(message);
|
||||
var responseMessage = await _appServiceConnection.SendMessageAsync(CreateMessage(request));
|
||||
|
||||
return JsonConvert.DeserializeObject<CreateTerminalResponse>(responseMessage[MessageKeys.Content]);
|
||||
}
|
||||
|
||||
public Task Initialize(IAppServiceConnection appServiceConnection)
|
||||
public void Initialize(IAppServiceConnection appServiceConnection)
|
||||
{
|
||||
_appServiceConnection = appServiceConnection;
|
||||
return UpdateToggleWindowKeyBindings();
|
||||
_appServiceConnection.MessageReceived += OnMessageReceived;
|
||||
}
|
||||
|
||||
private void OnMessageReceived(object sender, IDictionary<string, string> e)
|
||||
{
|
||||
var messageType = e[MessageKeys.Type];
|
||||
var messageContent = e[MessageKeys.Content];
|
||||
|
||||
if (messageType == nameof(DisplayTerminalOutputRequest))
|
||||
{
|
||||
var request = JsonConvert.DeserializeObject<DisplayTerminalOutputRequest>(messageContent);
|
||||
|
||||
if (_terminalOutputHandlers.ContainsKey(request.TerminalId))
|
||||
{
|
||||
_terminalOutputHandlers[request.TerminalId].Invoke(request.Output);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("output was not handled: " + request.Output);
|
||||
}
|
||||
}
|
||||
else if (messageType == nameof(TerminalExitedRequest))
|
||||
{
|
||||
var request = JsonConvert.DeserializeObject<TerminalExitedRequest>(messageContent);
|
||||
|
||||
TerminalExited?.Invoke(this, request.TerminalId);
|
||||
}
|
||||
}
|
||||
|
||||
public Task ResizeTerminal(int id, TerminalSize size)
|
||||
@@ -51,13 +77,12 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
NewSize = size
|
||||
};
|
||||
|
||||
var message = new Dictionary<string, string>
|
||||
{
|
||||
{ MessageKeys.Type, MessageTypes.ResizeTerminalRequest },
|
||||
{ MessageKeys.Content, JsonConvert.SerializeObject(request) }
|
||||
};
|
||||
return _appServiceConnection.SendMessageAsync(CreateMessage(request));
|
||||
}
|
||||
|
||||
return _appServiceConnection.SendMessageAsync(message);
|
||||
public void SubscribeForTerminalOutput(int terminalId, Action<string> callback)
|
||||
{
|
||||
_terminalOutputHandlers[terminalId] = callback;
|
||||
}
|
||||
|
||||
public Task UpdateToggleWindowKeyBindings()
|
||||
@@ -69,13 +94,37 @@ namespace FluentTerminal.App.Services.Implementation
|
||||
KeyBindings = keyBindings
|
||||
};
|
||||
|
||||
var message = new Dictionary<string, string>
|
||||
return _appServiceConnection.SendMessageAsync(CreateMessage(request));
|
||||
}
|
||||
|
||||
public Task WriteText(int id, string text)
|
||||
{
|
||||
var request = new WriteTextRequest
|
||||
{
|
||||
{ MessageKeys.Type, MessageTypes.SetToggleWindowKeyBindingsRequest },
|
||||
{ MessageKeys.Content, JsonConvert.SerializeObject(request) }
|
||||
TerminalId = id,
|
||||
Text = text
|
||||
};
|
||||
|
||||
return _appServiceConnection.SendMessageAsync(message);
|
||||
return _appServiceConnection.SendMessageAsync(CreateMessage(request));
|
||||
}
|
||||
|
||||
public Task CloseTerminal(int terminalId)
|
||||
{
|
||||
var request = new TerminalExitedRequest
|
||||
{
|
||||
TerminalId = terminalId
|
||||
};
|
||||
|
||||
return _appServiceConnection.SendMessageAsync(CreateMessage(request));
|
||||
}
|
||||
|
||||
private IDictionary<string, string> CreateMessage(object content)
|
||||
{
|
||||
return new Dictionary<string, string>
|
||||
{
|
||||
[MessageKeys.Type] = content.GetType().Name,
|
||||
[MessageKeys.Content] = JsonConvert.SerializeObject(content)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,4 +18,4 @@ namespace FluentTerminal.App.Services.Utilities
|
||||
return value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,4 +24,4 @@ namespace FluentTerminal.App.Services.Utilities
|
||||
return property;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
using FluentTerminal.App.ViewModels.Utilities;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Infrastructure
|
||||
{
|
||||
public class AsyncCommand : IAsyncCommand
|
||||
{
|
||||
public event EventHandler CanExecuteChanged;
|
||||
|
||||
private bool _isExecuting;
|
||||
private readonly Func<Task> _execute;
|
||||
private readonly Func<bool> _canExecute;
|
||||
private readonly IErrorHandler _errorHandler;
|
||||
|
||||
public AsyncCommand(
|
||||
Func<Task> execute,
|
||||
Func<bool> canExecute = null,
|
||||
IErrorHandler errorHandler = null)
|
||||
{
|
||||
_execute = execute;
|
||||
_canExecute = canExecute;
|
||||
_errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
public bool CanExecute()
|
||||
{
|
||||
return !_isExecuting && (_canExecute?.Invoke() ?? true);
|
||||
}
|
||||
|
||||
public async Task ExecuteAsync()
|
||||
{
|
||||
if (CanExecute())
|
||||
{
|
||||
try
|
||||
{
|
||||
_isExecuting = true;
|
||||
await _execute();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isExecuting = false;
|
||||
}
|
||||
}
|
||||
|
||||
RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
public void RaiseCanExecuteChanged()
|
||||
{
|
||||
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#region Explicit implementations
|
||||
bool ICommand.CanExecute(object parameter)
|
||||
{
|
||||
return CanExecute();
|
||||
}
|
||||
|
||||
void ICommand.Execute(object parameter)
|
||||
{
|
||||
ExecuteAsync().FireAndForgetSafeAsync(_errorHandler);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class AsyncCommand<T> : IAsyncCommand<T>
|
||||
{
|
||||
public event EventHandler CanExecuteChanged;
|
||||
|
||||
private bool _isExecuting;
|
||||
private readonly Func<T, Task> _execute;
|
||||
private readonly Func<T, bool> _canExecute;
|
||||
private readonly IErrorHandler _errorHandler;
|
||||
|
||||
public AsyncCommand(Func<T, Task> execute, Func<T, bool> canExecute = null, IErrorHandler errorHandler = null)
|
||||
{
|
||||
_execute = execute;
|
||||
_canExecute = canExecute;
|
||||
_errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
public bool CanExecute(T parameter)
|
||||
{
|
||||
return !_isExecuting && (_canExecute?.Invoke(parameter) ?? true);
|
||||
}
|
||||
|
||||
public async Task ExecuteAsync(T parameter)
|
||||
{
|
||||
if (CanExecute(parameter))
|
||||
{
|
||||
try
|
||||
{
|
||||
_isExecuting = true;
|
||||
await _execute(parameter);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isExecuting = false;
|
||||
}
|
||||
}
|
||||
|
||||
RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
public void RaiseCanExecuteChanged()
|
||||
{
|
||||
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#region Explicit implementations
|
||||
bool ICommand.CanExecute(object parameter)
|
||||
{
|
||||
return CanExecute((T)parameter);
|
||||
}
|
||||
|
||||
void ICommand.Execute(object parameter)
|
||||
{
|
||||
ExecuteAsync((T)parameter).FireAndForgetSafeAsync(_errorHandler);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// based on: https://github.com/johnthiriet/AsyncVoid
|
||||
/// </summary>
|
||||
public interface IAsyncCommand : ICommand
|
||||
{
|
||||
Task ExecuteAsync();
|
||||
bool CanExecute();
|
||||
}
|
||||
|
||||
public interface IAsyncCommand<T> : ICommand
|
||||
{
|
||||
Task ExecuteAsync(T parameter);
|
||||
bool CanExecute(T parameter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Infrastructure
|
||||
{
|
||||
public interface IErrorHandler
|
||||
{
|
||||
void HandleError(Exception ex);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -13,23 +14,18 @@ namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
public class MainViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IApplicationView _applicationView;
|
||||
private readonly IClipboardService _clipboardService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IDispatcherTimer _dispatcherTimer;
|
||||
private readonly IKeyboardCommandService _keyboardCommandService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ITrayProcessCommunicationService _trayProcessCommunicationService;
|
||||
private ApplicationSettings _applicationSettings;
|
||||
private string _background;
|
||||
private double _backgroundOpacity;
|
||||
private int _nextTerminalId;
|
||||
private TerminalViewModel _selectedTerminal;
|
||||
private string _title;
|
||||
private readonly IApplicationView _applicationView;
|
||||
private readonly IDispatcherTimer _dispatcherTimer;
|
||||
private readonly IClipboardService _clipboardService;
|
||||
|
||||
public event EventHandler Closed;
|
||||
public event EventHandler NewWindowRequested;
|
||||
public event EventHandler ShowSettingsRequested;
|
||||
private TabsPosition _tabsPosition;
|
||||
|
||||
public MainViewModel(ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService, IKeyboardCommandService keyboardCommandService,
|
||||
IApplicationView applicationView, IDispatcherTimer dispatcherTimer, IClipboardService clipboardService)
|
||||
@@ -47,8 +43,18 @@ namespace FluentTerminal.App.ViewModels
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.NewTab, () => AddTerminal(null, false));
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.ConfigurableNewTab, () => AddTerminal(null, true));
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.CloseTab, CloseCurrentTab);
|
||||
|
||||
// Add all of the commands for switching to a tab of a given ID, if there's one open there
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
Command switchCmd = Command.SwitchToTerm1 + i;
|
||||
int tabNumber = i;
|
||||
Action handler = () => SelectTabNumber(tabNumber);
|
||||
_keyboardCommandService.RegisterCommandHandler(switchCmd, handler);
|
||||
}
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.NextTab, SelectNextTab);
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.PreviousTab, SelectPreviousTab);
|
||||
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.NewWindow, NewWindow);
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.ShowSettings, ShowSettings);
|
||||
_keyboardCommandService.RegisterCommandHandler(Command.ToggleFullScreen, ToggleFullScreen);
|
||||
@@ -57,27 +63,39 @@ namespace FluentTerminal.App.ViewModels
|
||||
Background = currentTheme.Colors.Background;
|
||||
BackgroundOpacity = options.BackgroundOpacity;
|
||||
_applicationSettings = _settingsService.GetApplicationSettings();
|
||||
TabsPosition = _applicationSettings.TabsPosition;
|
||||
|
||||
AddTerminalCommand = new RelayCommand(() => AddTerminal(null, false));
|
||||
ShowSettingsCommand = new RelayCommand(ShowSettings);
|
||||
|
||||
Terminals.CollectionChanged += OnTerminalsCollectionChanged;
|
||||
|
||||
Title = "Fluent Terminal";
|
||||
|
||||
_applicationView.CloseRequested += OnCloseRequest;
|
||||
Terminals.CollectionChanged += OnTerminalsCollectionChanged;
|
||||
}
|
||||
|
||||
private async void OnTerminalOptionsChanged(object sender, TerminalOptions e)
|
||||
private void OnTerminalsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
await _applicationView.RunOnDispatcherThread(() =>
|
||||
{
|
||||
BackgroundOpacity = e.BackgroundOpacity;
|
||||
});
|
||||
RaisePropertyChanged(nameof(ShowTabsOnTop));
|
||||
RaisePropertyChanged(nameof(ShowTabsOnBottom));
|
||||
}
|
||||
|
||||
public event EventHandler Closed;
|
||||
|
||||
public event EventHandler NewWindowRequested;
|
||||
|
||||
public event EventHandler ShowSettingsRequested;
|
||||
|
||||
public RelayCommand AddTerminalCommand { get; }
|
||||
|
||||
public bool ShowTabsOnTop
|
||||
{
|
||||
get => TabsPosition == TabsPosition.Top && (Terminals.Count > 1 || _applicationSettings.AlwaysShowTabs);
|
||||
}
|
||||
|
||||
public bool ShowTabsOnBottom
|
||||
{
|
||||
get => TabsPosition == TabsPosition.Bottom && (Terminals.Count > 1 || _applicationSettings.AlwaysShowTabs);
|
||||
}
|
||||
|
||||
public string Background
|
||||
{
|
||||
get => _background;
|
||||
@@ -112,14 +130,14 @@ namespace FluentTerminal.App.ViewModels
|
||||
|
||||
public RelayCommand ShowSettingsCommand { get; }
|
||||
|
||||
public ObservableCollection<TerminalViewModel> Terminals { get; } = new ObservableCollection<TerminalViewModel>();
|
||||
|
||||
public string Title
|
||||
public TabsPosition TabsPosition
|
||||
{
|
||||
get => _title;
|
||||
set => Set(ref _title, value);
|
||||
get => _tabsPosition;
|
||||
set => Set(ref _tabsPosition, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<TerminalViewModel> Terminals { get; } = new ObservableCollection<TerminalViewModel>();
|
||||
|
||||
public Task AddTerminal(string startupDirectory, bool showProfileSelection)
|
||||
{
|
||||
return _applicationView.RunOnDispatcherThread(async () =>
|
||||
@@ -139,10 +157,9 @@ namespace FluentTerminal.App.ViewModels
|
||||
profile = _settingsService.GetDefaultShellProfile();
|
||||
}
|
||||
|
||||
var terminal = new TerminalViewModel(GetNextTerminalId(), _settingsService, _trayProcessCommunicationService, _dialogService, _keyboardCommandService,
|
||||
var terminal = new TerminalViewModel(_settingsService, _trayProcessCommunicationService, _dialogService, _keyboardCommandService,
|
||||
_applicationSettings, startupDirectory, profile, _applicationView, _dispatcherTimer, _clipboardService);
|
||||
terminal.CloseRequested += OnTerminalCloseRequested;
|
||||
terminal.TitleChanged += OnTitleChanged;
|
||||
terminal.Closed += OnTerminalCloseRequested;
|
||||
Terminals.Add(terminal);
|
||||
|
||||
SelectedTerminal = terminal;
|
||||
@@ -162,11 +179,6 @@ namespace FluentTerminal.App.ViewModels
|
||||
SelectedTerminal?.CloseCommand.Execute(null);
|
||||
}
|
||||
|
||||
private int GetNextTerminalId()
|
||||
{
|
||||
return _nextTerminalId++;
|
||||
}
|
||||
|
||||
private void NewWindow()
|
||||
{
|
||||
NewWindowRequested?.Invoke(this, EventArgs.Empty);
|
||||
@@ -174,7 +186,13 @@ namespace FluentTerminal.App.ViewModels
|
||||
|
||||
private async void OnApplicationSettingsChanged(object sender, ApplicationSettings e)
|
||||
{
|
||||
await _applicationView.RunOnDispatcherThread(() => _applicationSettings = e);
|
||||
await _applicationView.RunOnDispatcherThread(() =>
|
||||
{
|
||||
_applicationSettings = e;
|
||||
TabsPosition = e.TabsPosition;
|
||||
RaisePropertyChanged(nameof(ShowTabsOnTop));
|
||||
RaisePropertyChanged(nameof(ShowTabsOnBottom));
|
||||
});
|
||||
}
|
||||
|
||||
private async Task OnCloseRequest(object sender, CancelableEventArgs e)
|
||||
@@ -228,19 +246,19 @@ namespace FluentTerminal.App.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTerminalsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
private async void OnTerminalOptionsChanged(object sender, TerminalOptions e)
|
||||
{
|
||||
if (Terminals.Any())
|
||||
await _applicationView.RunOnDispatcherThread(() =>
|
||||
{
|
||||
Title = Terminals.First().Title;
|
||||
}
|
||||
BackgroundOpacity = e.BackgroundOpacity;
|
||||
});
|
||||
}
|
||||
|
||||
private void OnTitleChanged(object sender, string e)
|
||||
private void SelectTabNumber(int tabNumber)
|
||||
{
|
||||
if (sender is TerminalViewModel terminal && Terminals.First() == terminal)
|
||||
if (tabNumber < Terminals.Count)
|
||||
{
|
||||
Title = e;
|
||||
SelectedTerminal = Terminals[tabNumber];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +280,7 @@ namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
ShowSettingsRequested?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
|
||||
private void ToggleFullScreen()
|
||||
{
|
||||
_applicationView.ToggleFullScreen();
|
||||
|
||||
@@ -9,22 +9,76 @@ namespace FluentTerminal.App.ViewModels.Settings
|
||||
{
|
||||
public class GeneralPageViewModel : ViewModelBase
|
||||
{
|
||||
private readonly ApplicationSettings _applicationSettings;
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ApplicationSettings _applicationSettings;
|
||||
private readonly IStartupTaskService _startupTaskService;
|
||||
private bool _canEnableStartupTask;
|
||||
private bool _editingNewTerminalLocation;
|
||||
private bool _editingTabsPosition;
|
||||
private bool _editingInactiveTabColorMode;
|
||||
private bool _startupTaskEnabled;
|
||||
private string _startupTaskErrorMessage;
|
||||
|
||||
public GeneralPageViewModel(ISettingsService settingsService, IDialogService dialogService, IDefaultValueProvider defaultValueProvider)
|
||||
public GeneralPageViewModel(ISettingsService settingsService, IDialogService dialogService, IDefaultValueProvider defaultValueProvider, IStartupTaskService startupTaskService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_dialogService = dialogService;
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
_startupTaskService = startupTaskService;
|
||||
|
||||
_applicationSettings = _settingsService.GetApplicationSettings();
|
||||
|
||||
RestoreDefaultsCommand = new RelayCommand(async () => await RestoreDefaults().ConfigureAwait(false));
|
||||
}
|
||||
|
||||
public async Task OnNavigatedTo()
|
||||
{
|
||||
var startupTaskStatus = await _startupTaskService.GetStatus();
|
||||
SetStartupTaskPropertiesForStatus(startupTaskStatus);
|
||||
}
|
||||
|
||||
public bool AlwaysShowTabs
|
||||
{
|
||||
get => _applicationSettings.AlwaysShowTabs;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.AlwaysShowTabs != value)
|
||||
{
|
||||
_applicationSettings.AlwaysShowTabs = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowNewOutputIndicator
|
||||
{
|
||||
get => _applicationSettings.ShowNewOutputIndicator;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.ShowNewOutputIndicator != value)
|
||||
{
|
||||
_applicationSettings.ShowNewOutputIndicator = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool BottomIsSelected
|
||||
{
|
||||
get => TabsPosition == TabsPosition.Bottom;
|
||||
set => TabsPosition = TabsPosition.Bottom;
|
||||
}
|
||||
|
||||
public bool CanEnableStartupTask
|
||||
{
|
||||
get => _canEnableStartupTask;
|
||||
set => Set(ref _canEnableStartupTask, value);
|
||||
}
|
||||
|
||||
public bool ConfirmClosingTabs
|
||||
{
|
||||
get => _applicationSettings.ConfirmClosingTabs;
|
||||
@@ -53,20 +107,6 @@ namespace FluentTerminal.App.ViewModels.Settings
|
||||
}
|
||||
}
|
||||
|
||||
public bool UnderlineSelectedTab
|
||||
{
|
||||
get => _applicationSettings.UnderlineSelectedTab;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.UnderlineSelectedTab != value)
|
||||
{
|
||||
_applicationSettings.UnderlineSelectedTab = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public NewTerminalLocation NewTerminalLocation
|
||||
{
|
||||
get => _applicationSettings.NewTerminalLocation;
|
||||
@@ -87,12 +127,100 @@ namespace FluentTerminal.App.ViewModels.Settings
|
||||
|
||||
public RelayCommand RestoreDefaultsCommand { get; }
|
||||
|
||||
public bool StartupTaskEnabled
|
||||
{
|
||||
get => _startupTaskEnabled;
|
||||
set
|
||||
{
|
||||
if (_startupTaskEnabled != value)
|
||||
{
|
||||
_startupTaskEnabled = value;
|
||||
RaisePropertyChanged(nameof(StartupTaskEnabled));
|
||||
SetStartupTaskState(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string StartupTaskErrorMessage
|
||||
{
|
||||
get => _startupTaskErrorMessage;
|
||||
set => Set(ref _startupTaskErrorMessage, value);
|
||||
}
|
||||
|
||||
public bool TabIsSelected
|
||||
{
|
||||
get => NewTerminalLocation == NewTerminalLocation.Tab;
|
||||
set => NewTerminalLocation = NewTerminalLocation.Tab;
|
||||
}
|
||||
|
||||
public TabsPosition TabsPosition
|
||||
{
|
||||
get => _applicationSettings.TabsPosition;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.TabsPosition != value && !_editingTabsPosition)
|
||||
{
|
||||
_editingTabsPosition = true;
|
||||
_applicationSettings.TabsPosition = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
RaisePropertyChanged(nameof(TopIsSelected));
|
||||
RaisePropertyChanged(nameof(BottomIsSelected));
|
||||
_editingTabsPosition = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TopIsSelected
|
||||
{
|
||||
get => TabsPosition == TabsPosition.Top;
|
||||
set => TabsPosition = TabsPosition.Top;
|
||||
}
|
||||
|
||||
public bool UnderlineSelectedTab
|
||||
{
|
||||
get => _applicationSettings.UnderlineSelectedTab;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.UnderlineSelectedTab != value)
|
||||
{
|
||||
_applicationSettings.UnderlineSelectedTab = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool BackgroundIsSelected
|
||||
{
|
||||
get => InactiveTabColorMode == InactiveTabColorMode.Background;
|
||||
set => InactiveTabColorMode = InactiveTabColorMode.Background;
|
||||
}
|
||||
|
||||
public bool UnderlinedIsSelected
|
||||
{
|
||||
get => InactiveTabColorMode == InactiveTabColorMode.Underlined;
|
||||
set => InactiveTabColorMode = InactiveTabColorMode.Underlined;
|
||||
}
|
||||
|
||||
public InactiveTabColorMode InactiveTabColorMode
|
||||
{
|
||||
get => _applicationSettings.InactiveTabColorMode;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.InactiveTabColorMode != value && !_editingInactiveTabColorMode)
|
||||
{
|
||||
_editingInactiveTabColorMode = true;
|
||||
_applicationSettings.InactiveTabColorMode = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
RaisePropertyChanged(nameof(BackgroundIsSelected));
|
||||
RaisePropertyChanged(nameof(UnderlinedIsSelected));
|
||||
_editingInactiveTabColorMode = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool WindowIsSelected
|
||||
{
|
||||
get => NewTerminalLocation == NewTerminalLocation.Window;
|
||||
@@ -101,7 +229,7 @@ namespace FluentTerminal.App.ViewModels.Settings
|
||||
|
||||
private async Task RestoreDefaults()
|
||||
{
|
||||
var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to restore the general settings?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(false);
|
||||
var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to restore the general settings?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(true);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
@@ -109,8 +237,56 @@ namespace FluentTerminal.App.ViewModels.Settings
|
||||
ConfirmClosingWindows = defaults.ConfirmClosingWindows;
|
||||
ConfirmClosingTabs = defaults.ConfirmClosingTabs;
|
||||
UnderlineSelectedTab = defaults.UnderlineSelectedTab;
|
||||
InactiveTabColorMode = defaults.InactiveTabColorMode;
|
||||
NewTerminalLocation = defaults.NewTerminalLocation;
|
||||
AlwaysShowTabs = defaults.AlwaysShowTabs;
|
||||
ShowNewOutputIndicator = defaults.ShowNewOutputIndicator;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetStartupTaskPropertiesForStatus(StartupTaskStatus startupTaskStatus)
|
||||
{
|
||||
switch (startupTaskStatus)
|
||||
{
|
||||
case StartupTaskStatus.Enabled:
|
||||
StartupTaskEnabled = true;
|
||||
StartupTaskErrorMessage = string.Empty;
|
||||
CanEnableStartupTask = true;
|
||||
break;
|
||||
|
||||
case StartupTaskStatus.Disabled:
|
||||
StartupTaskEnabled = false;
|
||||
StartupTaskErrorMessage = string.Empty;
|
||||
CanEnableStartupTask = true;
|
||||
break;
|
||||
|
||||
case StartupTaskStatus.DisabledByUser:
|
||||
StartupTaskEnabled = false;
|
||||
StartupTaskErrorMessage = "Disabled by user. Please reactivate it in the Startup tab of the Task Manager.";
|
||||
CanEnableStartupTask = false;
|
||||
break;
|
||||
|
||||
case StartupTaskStatus.DisabledByPolicy:
|
||||
StartupTaskEnabled = false;
|
||||
StartupTaskErrorMessage = "Disabled by policy.";
|
||||
CanEnableStartupTask = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SetStartupTaskState(bool enabled)
|
||||
{
|
||||
StartupTaskStatus status;
|
||||
if (enabled)
|
||||
{
|
||||
status = await _startupTaskService.EnableStartupTask();
|
||||
}
|
||||
else
|
||||
{
|
||||
_startupTaskService.DisableStartupTask();
|
||||
status = await _startupTaskService.GetStatus();
|
||||
}
|
||||
SetStartupTaskPropertiesForStatus(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Settings
|
||||
{
|
||||
public class MousePageViewModel : ViewModelBase
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IDefaultValueProvider _defaultValueProvider;
|
||||
private readonly ApplicationSettings _applicationSettings;
|
||||
private bool _editingMouseRightClickAction;
|
||||
private bool _editingMouseMiddleClickAction;
|
||||
|
||||
public MousePageViewModel(ISettingsService settingsService, IDialogService dialogService, IDefaultValueProvider defaultValueProvider)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_dialogService = dialogService;
|
||||
_defaultValueProvider = defaultValueProvider;
|
||||
_applicationSettings = _settingsService.GetApplicationSettings();
|
||||
|
||||
RestoreDefaultsCommand = new RelayCommand(async () => await RestoreDefaults().ConfigureAwait(false));
|
||||
}
|
||||
|
||||
public bool CopyOnSelect
|
||||
{
|
||||
get => _applicationSettings.CopyOnSelect;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.CopyOnSelect != value)
|
||||
{
|
||||
_applicationSettings.CopyOnSelect = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MouseAction MouseRightClickAction
|
||||
{
|
||||
get => _applicationSettings.MouseRightClickAction;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.MouseRightClickAction != value && !_editingMouseRightClickAction)
|
||||
{
|
||||
_editingMouseRightClickAction = true;
|
||||
_applicationSettings.MouseRightClickAction = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
RaisePropertyChanged(nameof(MouseRightClickNoneIsSelected));
|
||||
RaisePropertyChanged(nameof(MouseRightClickContextMenuIsSelected));
|
||||
RaisePropertyChanged(nameof(MouseRightClickPasteIsSelected));
|
||||
_editingMouseRightClickAction = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool MouseRightClickNoneIsSelected
|
||||
{
|
||||
get => MouseRightClickAction == MouseAction.None;
|
||||
set => MouseRightClickAction = MouseAction.None;
|
||||
}
|
||||
|
||||
public bool MouseRightClickContextMenuIsSelected
|
||||
{
|
||||
get => MouseRightClickAction == MouseAction.ContextMenu;
|
||||
set => MouseRightClickAction = MouseAction.ContextMenu;
|
||||
}
|
||||
|
||||
public bool MouseRightClickPasteIsSelected
|
||||
{
|
||||
get => MouseRightClickAction == MouseAction.Paste;
|
||||
set => MouseRightClickAction = MouseAction.Paste;
|
||||
}
|
||||
|
||||
public MouseAction MouseMiddleClickAction
|
||||
{
|
||||
get => _applicationSettings.MouseMiddleClickAction;
|
||||
set
|
||||
{
|
||||
if (_applicationSettings.MouseMiddleClickAction != value && !_editingMouseMiddleClickAction)
|
||||
{
|
||||
_editingMouseMiddleClickAction = true;
|
||||
_applicationSettings.MouseMiddleClickAction = value;
|
||||
_settingsService.SaveApplicationSettings(_applicationSettings);
|
||||
RaisePropertyChanged();
|
||||
RaisePropertyChanged(nameof(MouseMiddleClickNoneIsSelected));
|
||||
RaisePropertyChanged(nameof(MouseMiddleClickContextMenuIsSelected));
|
||||
RaisePropertyChanged(nameof(MouseMiddleClickPasteIsSelected));
|
||||
_editingMouseMiddleClickAction = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool MouseMiddleClickNoneIsSelected
|
||||
{
|
||||
get => MouseMiddleClickAction == MouseAction.None;
|
||||
set => MouseMiddleClickAction = MouseAction.None;
|
||||
}
|
||||
|
||||
public bool MouseMiddleClickContextMenuIsSelected
|
||||
{
|
||||
get => MouseMiddleClickAction == MouseAction.ContextMenu;
|
||||
set => MouseMiddleClickAction = MouseAction.ContextMenu;
|
||||
}
|
||||
|
||||
public bool MouseMiddleClickPasteIsSelected
|
||||
{
|
||||
get => MouseMiddleClickAction == MouseAction.Paste;
|
||||
set => MouseMiddleClickAction = MouseAction.Paste;
|
||||
}
|
||||
|
||||
public RelayCommand RestoreDefaultsCommand { get; }
|
||||
|
||||
private async Task RestoreDefaults()
|
||||
{
|
||||
var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to restore the mouse settings?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(true);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
var defaults = _defaultValueProvider.GetDefaultApplicationSettings();
|
||||
CopyOnSelect = defaults.CopyOnSelect;
|
||||
MouseMiddleClickAction = defaults.MouseMiddleClickAction;
|
||||
MouseRightClickAction = defaults.MouseRightClickAction;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ namespace FluentTerminal.App.ViewModels.Settings
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IFileSystemService _fileSystemService;
|
||||
private ShellProfileViewModel _selectedShellProfile;
|
||||
|
||||
|
||||
public ProfilesPageViewModel(ISettingsService settingsService, IDialogService dialogService, IDefaultValueProvider defaultValueProvider, IFileSystemService fileSystemService)
|
||||
{
|
||||
|
||||
@@ -211,4 +211,4 @@ namespace FluentTerminal.App.ViewModels.Settings
|
||||
_terminalOptions = _settingsService.GetTerminalOptions();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,14 @@ namespace FluentTerminal.App.ViewModels
|
||||
public class SettingsViewModel : ViewModelBase
|
||||
{
|
||||
public SettingsViewModel(ISettingsService settingsService, IDefaultValueProvider defaultValueProvider, IDialogService dialogService,
|
||||
ITrayProcessCommunicationService trayProcessCommunicationService, IThemeParserFactory themeParserFactory, ISystemFontService systemFontService, IFileSystemService fileSystemService)
|
||||
ITrayProcessCommunicationService trayProcessCommunicationService, IThemeParserFactory themeParserFactory, ISystemFontService systemFontService, IFileSystemService fileSystemService, IStartupTaskService startupTaskService)
|
||||
{
|
||||
KeyBindings = new KeyBindingsPageViewModel(settingsService, dialogService, defaultValueProvider, trayProcessCommunicationService);
|
||||
General = new GeneralPageViewModel(settingsService, dialogService, defaultValueProvider);
|
||||
General = new GeneralPageViewModel(settingsService, dialogService, defaultValueProvider, startupTaskService);
|
||||
Shell = new ProfilesPageViewModel(settingsService, dialogService, defaultValueProvider, fileSystemService);
|
||||
Terminal = new TerminalPageViewModel(settingsService, dialogService, defaultValueProvider, systemFontService);
|
||||
Themes = new ThemesPageViewModel(settingsService, dialogService, defaultValueProvider, themeParserFactory, fileSystemService);
|
||||
Mouse = new MousePageViewModel(settingsService, dialogService, defaultValueProvider);
|
||||
}
|
||||
|
||||
public event EventHandler Closed;
|
||||
@@ -24,6 +25,7 @@ namespace FluentTerminal.App.ViewModels
|
||||
public ProfilesPageViewModel Shell { get; }
|
||||
public TerminalPageViewModel Terminal { get; }
|
||||
public ThemesPageViewModel Themes { get; }
|
||||
public MousePageViewModel Mouse { get; }
|
||||
|
||||
public void Close()
|
||||
{
|
||||
|
||||
@@ -1,28 +1,33 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.App.ViewModels.Infrastructure;
|
||||
using FluentTerminal.Models;
|
||||
using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
public class ShellProfileViewModel : ViewModelBase
|
||||
{
|
||||
private readonly ShellProfile _shellProfile;
|
||||
private string _name;
|
||||
private string _arguments;
|
||||
private string _location;
|
||||
private string _workingDirectory;
|
||||
private string _fallbackName;
|
||||
private string _fallbackArguments;
|
||||
private string _fallbackLocation;
|
||||
private string _fallbackWorkingDirectory;
|
||||
private bool _isDefault;
|
||||
private bool _inEditMode;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IFileSystemService _fileSystemService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ShellProfile _shellProfile;
|
||||
private string _arguments;
|
||||
private string _fallbackArguments;
|
||||
private string _fallbackLocation;
|
||||
private string _fallbackName;
|
||||
private int _fallbackTabThemeId;
|
||||
private string _fallbackWorkingDirectory;
|
||||
private bool _inEditMode;
|
||||
private bool _isDefault;
|
||||
private string _location;
|
||||
private string _name;
|
||||
private TabTheme _selectedTabTheme;
|
||||
private string _workingDirectory;
|
||||
|
||||
public ShellProfileViewModel(ShellProfile shellProfile, ISettingsService settingsService, IDialogService dialogService, IFileSystemService fileSystemService)
|
||||
{
|
||||
@@ -31,39 +36,39 @@ namespace FluentTerminal.App.ViewModels
|
||||
_dialogService = dialogService;
|
||||
_fileSystemService = fileSystemService;
|
||||
|
||||
TabThemes = new ObservableCollection<TabTheme>(settingsService.GetTabThemes());
|
||||
|
||||
Id = shellProfile.Id;
|
||||
Name = shellProfile.Name;
|
||||
Arguments = shellProfile.Arguments;
|
||||
Location = shellProfile.Location;
|
||||
WorkingDirectory = shellProfile.WorkingDirectory;
|
||||
SelectedTabTheme = TabThemes.FirstOrDefault(t => t.Id == shellProfile.TabThemeId);
|
||||
PreInstalled = shellProfile.PreInstalled;
|
||||
|
||||
SetDefaultCommand = new RelayCommand(SetDefault);
|
||||
DeleteCommand = new RelayCommand(async () => await Delete().ConfigureAwait(false), CanDelete);
|
||||
EditCommand = new RelayCommand(Edit, CanEdit);
|
||||
CancelEditCommand = new RelayCommand(async () => await CancelEdit().ConfigureAwait(false));
|
||||
DeleteCommand = new AsyncCommand(Delete, CanDelete);
|
||||
EditCommand = new RelayCommand(Edit);
|
||||
CancelEditCommand = new AsyncCommand(CancelEdit);
|
||||
SaveChangesCommand = new RelayCommand(SaveChanges);
|
||||
BrowseForCustomShellCommand = new RelayCommand(async () => await BrowseForCustomShell().ConfigureAwait(false));
|
||||
BrowseForWorkingDirectoryCommand = new RelayCommand(async () => await BrowseForWorkingDirectory().ConfigureAwait(false));
|
||||
BrowseForCustomShellCommand = new AsyncCommand(BrowseForCustomShell);
|
||||
BrowseForWorkingDirectoryCommand = new AsyncCommand(BrowseForWorkingDirectory);
|
||||
}
|
||||
|
||||
public event EventHandler Deleted;
|
||||
public event EventHandler SetAsDefault;
|
||||
|
||||
public RelayCommand DeleteCommand { get; }
|
||||
public IAsyncCommand BrowseForCustomShellCommand { get; }
|
||||
public IAsyncCommand BrowseForWorkingDirectoryCommand { get; }
|
||||
public IAsyncCommand CancelEditCommand { get; }
|
||||
public IAsyncCommand DeleteCommand { get; }
|
||||
public RelayCommand EditCommand { get; }
|
||||
public RelayCommand SaveChangesCommand { get; }
|
||||
public RelayCommand CancelEditCommand { get; }
|
||||
public RelayCommand SetDefaultCommand { get; }
|
||||
public RelayCommand BrowseForCustomShellCommand { get; }
|
||||
public RelayCommand BrowseForWorkingDirectoryCommand { get; }
|
||||
|
||||
public Guid Id { get; }
|
||||
public ObservableCollection<TabTheme> TabThemes { get; }
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => Set(ref _name, value);
|
||||
}
|
||||
public bool PreInstalled { get; }
|
||||
|
||||
public string Arguments
|
||||
{
|
||||
@@ -71,16 +76,12 @@ namespace FluentTerminal.App.ViewModels
|
||||
set => Set(ref _arguments, value);
|
||||
}
|
||||
|
||||
public string Location
|
||||
{
|
||||
get => _location;
|
||||
set => Set(ref _location, value);
|
||||
}
|
||||
public Guid Id { get; }
|
||||
|
||||
public string WorkingDirectory
|
||||
public bool InEditMode
|
||||
{
|
||||
get => _workingDirectory;
|
||||
set => Set(ref _workingDirectory, value);
|
||||
get => _inEditMode;
|
||||
set => Set(ref _inEditMode, value);
|
||||
}
|
||||
|
||||
public bool IsDefault
|
||||
@@ -89,10 +90,34 @@ namespace FluentTerminal.App.ViewModels
|
||||
set => Set(ref _isDefault, value);
|
||||
}
|
||||
|
||||
public bool InEditMode
|
||||
public string Location
|
||||
{
|
||||
get => _inEditMode;
|
||||
set => Set(ref _inEditMode, value);
|
||||
get => _location;
|
||||
set => Set(ref _location, value);
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => Set(ref _name, value);
|
||||
}
|
||||
|
||||
public TabTheme SelectedTabTheme
|
||||
{
|
||||
get => _selectedTabTheme;
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
Set(ref _selectedTabTheme, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string WorkingDirectory
|
||||
{
|
||||
get => _workingDirectory;
|
||||
set => Set(ref _workingDirectory, value);
|
||||
}
|
||||
|
||||
public void SaveChanges()
|
||||
@@ -101,61 +126,13 @@ namespace FluentTerminal.App.ViewModels
|
||||
_shellProfile.Location = Location;
|
||||
_shellProfile.Name = Name;
|
||||
_shellProfile.WorkingDirectory = WorkingDirectory;
|
||||
_shellProfile.TabThemeId = SelectedTabTheme.Id;
|
||||
|
||||
_settingsService.SaveShellProfile(_shellProfile);
|
||||
|
||||
InEditMode = false;
|
||||
}
|
||||
|
||||
private async Task CancelEdit()
|
||||
{
|
||||
var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to discard all changes?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(true);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
Arguments = _fallbackArguments;
|
||||
Location = _fallbackLocation;
|
||||
Name = _fallbackName;
|
||||
WorkingDirectory = _fallbackWorkingDirectory;
|
||||
|
||||
InEditMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Edit()
|
||||
{
|
||||
_fallbackArguments = Arguments;
|
||||
_fallbackLocation = Location;
|
||||
_fallbackName = Name;
|
||||
_fallbackWorkingDirectory = WorkingDirectory;
|
||||
InEditMode = true;
|
||||
}
|
||||
|
||||
private bool CanDelete()
|
||||
{
|
||||
return !_shellProfile.PreInstalled;
|
||||
}
|
||||
|
||||
private bool CanEdit()
|
||||
{
|
||||
return !_shellProfile.PreInstalled;
|
||||
}
|
||||
|
||||
private async Task Delete()
|
||||
{
|
||||
var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to delete this theme?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(true);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
Deleted?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetDefault()
|
||||
{
|
||||
SetAsDefault?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private async Task BrowseForCustomShell()
|
||||
{
|
||||
var file = await _fileSystemService.OpenFile(new[] { ".exe" }).ConfigureAwait(true);
|
||||
@@ -173,5 +150,51 @@ namespace FluentTerminal.App.ViewModels
|
||||
WorkingDirectory = directory;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CancelEdit()
|
||||
{
|
||||
var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to discard all changes?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(true);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
Arguments = _fallbackArguments;
|
||||
Location = _fallbackLocation;
|
||||
Name = _fallbackName;
|
||||
WorkingDirectory = _fallbackWorkingDirectory;
|
||||
SelectedTabTheme = TabThemes.FirstOrDefault(t => t.Id == _fallbackTabThemeId);
|
||||
|
||||
InEditMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanDelete()
|
||||
{
|
||||
return !_shellProfile.PreInstalled;
|
||||
}
|
||||
|
||||
private async Task Delete()
|
||||
{
|
||||
var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to delete this theme?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(true);
|
||||
|
||||
if (result == DialogButton.OK)
|
||||
{
|
||||
Deleted?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private void Edit()
|
||||
{
|
||||
_fallbackArguments = _shellProfile.Arguments;
|
||||
_fallbackLocation = _shellProfile.Location;
|
||||
_fallbackName = _shellProfile.Name;
|
||||
_fallbackWorkingDirectory = _shellProfile.WorkingDirectory;
|
||||
_fallbackTabThemeId = _shellProfile.TabThemeId;
|
||||
InEditMode = true;
|
||||
}
|
||||
|
||||
private void SetDefault()
|
||||
{
|
||||
SetAsDefault?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,88 +6,101 @@ using GalaSoft.MvvmLight;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
public class TerminalViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IApplicationView _applicationView;
|
||||
private readonly IClipboardService _clipboardService;
|
||||
private readonly ManualResetEventSlim _connectedEvent;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IKeyboardCommandService _keyboardCommandService;
|
||||
private readonly IDispatcherTimer _resizeOverlayTimer;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ITrayProcessCommunicationService _trayProcessCommunicationService;
|
||||
private ApplicationSettings _applicationSettings;
|
||||
private string _resizeOverlayContent;
|
||||
private bool _showResizeOverlay;
|
||||
private readonly ShellProfile _shellProfile;
|
||||
private readonly string _startupDirectory;
|
||||
private readonly ITrayProcessCommunicationService _trayProcessCommunicationService;
|
||||
private bool _isSelected;
|
||||
private bool _newOutput;
|
||||
private string _resizeOverlayContent;
|
||||
private string _searchText;
|
||||
private bool _showResizeOverlay;
|
||||
private bool _showSearchPanel;
|
||||
private TabTheme _tabTheme;
|
||||
private int _terminalId;
|
||||
private ITerminalView _terminalView;
|
||||
private string _title;
|
||||
private readonly ShellProfile _shellProfile;
|
||||
private bool _showSearchPanel;
|
||||
private string _searchText;
|
||||
private bool _isSelected;
|
||||
private readonly IApplicationView _applicationView;
|
||||
private readonly IDispatcherTimer _resizeOverlayTimer;
|
||||
private readonly IClipboardService _clipboardService;
|
||||
private IWebSocketConnection _webSocket;
|
||||
private NamedPipeClientStream _namedPipe;
|
||||
|
||||
public TerminalViewModel(int id, ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService,
|
||||
public TerminalViewModel(ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService,
|
||||
IKeyboardCommandService keyboardCommandService, ApplicationSettings applicationSettings, string startupDirectory, ShellProfile shellProfile,
|
||||
IApplicationView applicationView, IDispatcherTimer dispatcherTimer, IClipboardService clipboardService)
|
||||
{
|
||||
Id = id;
|
||||
Title = DefaultTitle;
|
||||
|
||||
_connectedEvent = new ManualResetEventSlim(false);
|
||||
|
||||
_settingsService = settingsService;
|
||||
_settingsService.CurrentThemeChanged += OnCurrentThemeChanged;
|
||||
_settingsService.TerminalOptionsChanged += OnTerminalOptionsChanged;
|
||||
_settingsService.ApplicationSettingsChanged += OnApplicationSettingsChanged;
|
||||
_settingsService.KeyBindingsChanged += OnKeyBindingsChanged;
|
||||
|
||||
_trayProcessCommunicationService = trayProcessCommunicationService;
|
||||
_trayProcessCommunicationService.TerminalExited += OnTerminalExited;
|
||||
|
||||
_dialogService = dialogService;
|
||||
_keyboardCommandService = keyboardCommandService;
|
||||
_applicationSettings = applicationSettings;
|
||||
ApplicationSettings = applicationSettings;
|
||||
_startupDirectory = startupDirectory;
|
||||
_shellProfile = shellProfile;
|
||||
_applicationView = applicationView;
|
||||
_clipboardService = clipboardService;
|
||||
|
||||
TabThemes = new ObservableCollection<TabTheme>(_settingsService.GetTabThemes());
|
||||
TabTheme = TabThemes.FirstOrDefault(t => t.Id == _shellProfile.TabThemeId);
|
||||
|
||||
_resizeOverlayTimer = dispatcherTimer;
|
||||
_resizeOverlayTimer.Interval = new TimeSpan(0, 0, 2);
|
||||
_resizeOverlayTimer.Tick += OnResizeOverlayTimerFinished;
|
||||
|
||||
CloseCommand = new RelayCommand(async () => await InvokeCloseRequested().ConfigureAwait(false));
|
||||
CloseCommand = new RelayCommand(async () => await TryClose().ConfigureAwait(false));
|
||||
FindNextCommand = new RelayCommand(async () => await FindNext().ConfigureAwait(false));
|
||||
FindPreviousCommand = new RelayCommand(async () => await FindPrevious().ConfigureAwait(false));
|
||||
CloseSearchPanelCommand = new RelayCommand(CloseSearchPanel);
|
||||
|
||||
SelectTabThemeCommand = new RelayCommand<string>(SelectTabTheme);
|
||||
}
|
||||
|
||||
private async void OnKeyBindingsChanged(object sender, EventArgs e)
|
||||
public event EventHandler Closed;
|
||||
|
||||
public ApplicationSettings ApplicationSettings { get; private set; }
|
||||
|
||||
public TabTheme BackgroundTabTheme
|
||||
{
|
||||
var keyBindings = _settingsService.GetKeyBindings();
|
||||
await _applicationView.RunOnDispatcherThread(async () =>
|
||||
{
|
||||
await _terminalView.ChangeKeyBindings(FlattenKeyBindings(keyBindings)).ConfigureAwait(false);
|
||||
});
|
||||
// The effective background theme depends on whether it is selected (use the theme), or if it is inactive
|
||||
// (if we're set to underline inactive tabs, use the null theme).
|
||||
get => IsSelected || (!IsSelected && ApplicationSettings.InactiveTabColorMode == InactiveTabColorMode.Background) ?
|
||||
_tabTheme :
|
||||
_settingsService.GetTabThemes().FirstOrDefault(t => t.Color == null);
|
||||
}
|
||||
|
||||
public event EventHandler CloseRequested;
|
||||
|
||||
public event EventHandler<string> TitleChanged;
|
||||
|
||||
public RelayCommand CloseCommand { get; }
|
||||
|
||||
public RelayCommand FindPreviousCommand { get; }
|
||||
public RelayCommand FindNextCommand { get; }
|
||||
public RelayCommand CloseSearchPanelCommand { get; }
|
||||
|
||||
public string DefaultTitle { get; private set; } = string.Empty;
|
||||
|
||||
public RelayCommand FindNextCommand { get; }
|
||||
|
||||
public RelayCommand FindPreviousCommand { get; }
|
||||
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get => _isSelected;
|
||||
@@ -95,29 +108,24 @@ namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
if (Set(ref _isSelected, value))
|
||||
{
|
||||
if (IsSelected)
|
||||
{
|
||||
_applicationView.Title = Title;
|
||||
_applicationView.RunOnDispatcherThread(() => NewOutput = false);
|
||||
}
|
||||
RaisePropertyChanged(nameof(IsUnderlined));
|
||||
RaisePropertyChanged(nameof(BackgroundTabTheme));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUnderlined => IsSelected && _applicationSettings.UnderlineSelectedTab;
|
||||
public bool IsUnderlined => (IsSelected && ApplicationSettings.UnderlineSelectedTab) ||
|
||||
(!IsSelected && ApplicationSettings.InactiveTabColorMode == InactiveTabColorMode.Underlined && TabTheme.Color != null);
|
||||
|
||||
public int Id { get; }
|
||||
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
public string DefaultTitle { get; private set; } = "Fluent Terminal";
|
||||
|
||||
public string SearchText
|
||||
public bool NewOutput
|
||||
{
|
||||
get => _searchText;
|
||||
set => Set(ref _searchText, value);
|
||||
}
|
||||
|
||||
public bool ShowSearchPanel
|
||||
{
|
||||
get => _showSearchPanel;
|
||||
set => Set(ref _showSearchPanel, value);
|
||||
get => _newOutput;
|
||||
set => Set(ref _newOutput, value);
|
||||
}
|
||||
|
||||
public string ResizeOverlayContent
|
||||
@@ -126,6 +134,14 @@ namespace FluentTerminal.App.ViewModels
|
||||
set => Set(ref _resizeOverlayContent, value);
|
||||
}
|
||||
|
||||
public string SearchText
|
||||
{
|
||||
get => _searchText;
|
||||
set => Set(ref _searchText, value);
|
||||
}
|
||||
|
||||
public RelayCommand<string> SelectTabThemeCommand { get; }
|
||||
|
||||
public bool ShowResizeOverlay
|
||||
{
|
||||
get => _showResizeOverlay;
|
||||
@@ -143,6 +159,25 @@ namespace FluentTerminal.App.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowSearchPanel
|
||||
{
|
||||
get => _showSearchPanel;
|
||||
set => Set(ref _showSearchPanel, value);
|
||||
}
|
||||
|
||||
public TabTheme TabTheme
|
||||
{
|
||||
get => _tabTheme;
|
||||
set
|
||||
{
|
||||
Set(ref _tabTheme, value);
|
||||
RaisePropertyChanged(nameof(IsUnderlined));
|
||||
RaisePropertyChanged(nameof(BackgroundTabTheme));
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<TabTheme> TabThemes { get; }
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => _title;
|
||||
@@ -150,16 +185,22 @@ namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
value = string.IsNullOrWhiteSpace(value) ? DefaultTitle : value;
|
||||
|
||||
if (Set(ref _title, value))
|
||||
if (Set(ref _title, value) && IsSelected)
|
||||
{
|
||||
TitleChanged?.Invoke(this, Title);
|
||||
_applicationView.Title = Title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CloseView()
|
||||
public async Task CloseView()
|
||||
{
|
||||
_terminalView.Close();
|
||||
await _trayProcessCommunicationService.CloseTerminal(_terminalId).ConfigureAwait(true);
|
||||
}
|
||||
|
||||
public void CopyText(string text)
|
||||
{
|
||||
_clipboardService.SetText(text);
|
||||
}
|
||||
|
||||
public Task FocusTerminal()
|
||||
@@ -191,39 +232,28 @@ namespace FluentTerminal.App.ViewModels
|
||||
_terminalView.TerminalTitleChanged += OnTerminalTitleChanged;
|
||||
_terminalView.KeyboardCommandReceived += OnKeyboardCommandReceived;
|
||||
|
||||
_trayProcessCommunicationService.SubscribeForTerminalOutput(_terminalId, t =>
|
||||
{
|
||||
_connectedEvent.Wait();
|
||||
_webSocket.Send(t);
|
||||
if (!IsSelected && ApplicationSettings.ShowNewOutputIndicator)
|
||||
{
|
||||
_applicationView.RunOnDispatcherThread(() => NewOutput = true);
|
||||
}
|
||||
});
|
||||
|
||||
DefaultTitle = response.ShellExecutableName;
|
||||
Title = DefaultTitle;
|
||||
|
||||
_namedPipe = new NamedPipeClientStream(".", response.PipeName, PipeDirection.InOut, PipeOptions.None);
|
||||
if (!_namedPipe.IsConnected)
|
||||
{
|
||||
_namedPipe.Connect();
|
||||
}
|
||||
|
||||
var webSocketUrl = "ws://127.0.0.1:" + response.Port;
|
||||
var webSocketUrl = "ws://127.0.0.1:" + response.Id;
|
||||
var webSocketServer = new WebSocketServer(webSocketUrl);
|
||||
webSocketServer.Start(socket =>
|
||||
{
|
||||
_webSocket = socket;
|
||||
socket.OnOpen = () =>
|
||||
{
|
||||
Console.WriteLine("open");
|
||||
//_connectedEvent.Set();
|
||||
};
|
||||
socket.OnClose = () =>
|
||||
{
|
||||
Console.WriteLine("closing");
|
||||
_namedPipe.Close();
|
||||
};
|
||||
socket.OnMessage = message =>
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes(message);
|
||||
_namedPipe.Write(bytes, 0, bytes.Length);
|
||||
};
|
||||
socket.OnOpen = () => _connectedEvent.Set();
|
||||
socket.OnMessage = message => _trayProcessCommunicationService.WriteText(_terminalId, message);
|
||||
});
|
||||
|
||||
ListenToNamedPipe();
|
||||
|
||||
await _terminalView.ConnectToSocket(webSocketUrl).ConfigureAwait(true);
|
||||
Initialized = true;
|
||||
}
|
||||
@@ -235,47 +265,35 @@ namespace FluentTerminal.App.ViewModels
|
||||
await FocusTerminal().ConfigureAwait(true);
|
||||
}
|
||||
|
||||
private void ListenToNamedPipe()
|
||||
private void CloseSearchPanel()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var reader = new StreamReader(_namedPipe);
|
||||
do
|
||||
{
|
||||
var offset = 0;
|
||||
var buffer = new char[1024];
|
||||
var readChars = await reader.ReadAsync(buffer, offset, buffer.Length - offset);
|
||||
if (readChars > 0)
|
||||
{
|
||||
await _webSocket.Send(new String(buffer));
|
||||
}
|
||||
}
|
||||
while (!reader.EndOfStream);
|
||||
_webSocket.Close();
|
||||
});
|
||||
SearchText = string.Empty;
|
||||
ShowSearchPanel = false;
|
||||
_terminalView.FocusTerminal();
|
||||
}
|
||||
|
||||
private async Task InvokeCloseRequested()
|
||||
private Task FindNext()
|
||||
{
|
||||
if (_applicationSettings.ConfirmClosingTabs)
|
||||
{
|
||||
var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to close this tab?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(true);
|
||||
return _terminalView.FindNext(SearchText);
|
||||
}
|
||||
|
||||
if (result == DialogButton.Cancel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
private Task FindPrevious()
|
||||
{
|
||||
return _terminalView.FindPrevious(SearchText);
|
||||
}
|
||||
|
||||
CloseRequested?.Invoke(this, EventArgs.Empty);
|
||||
private IEnumerable<KeyBinding> FlattenKeyBindings(IDictionary<Command, ICollection<KeyBinding>> keyBindings)
|
||||
{
|
||||
return keyBindings.Values.SelectMany(k => k);
|
||||
}
|
||||
|
||||
private async void OnApplicationSettingsChanged(object sender, ApplicationSettings e)
|
||||
{
|
||||
await _applicationView.RunOnDispatcherThread(() =>
|
||||
{
|
||||
_applicationSettings = e;
|
||||
ApplicationSettings = e;
|
||||
RaisePropertyChanged(nameof(IsUnderlined));
|
||||
RaisePropertyChanged(nameof(BackgroundTabTheme));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -283,11 +301,23 @@ namespace FluentTerminal.App.ViewModels
|
||||
{
|
||||
await _applicationView.RunOnDispatcherThread(async () =>
|
||||
{
|
||||
RaisePropertyChanged(nameof(IsUnderlined));
|
||||
RaisePropertyChanged(nameof(BackgroundTabTheme));
|
||||
|
||||
var currentTheme = _settingsService.GetTheme(e);
|
||||
await _terminalView.ChangeTheme(currentTheme.Colors).ConfigureAwait(true);
|
||||
});
|
||||
}
|
||||
|
||||
private async void OnKeyBindingsChanged(object sender, EventArgs e)
|
||||
{
|
||||
var keyBindings = _settingsService.GetKeyBindings();
|
||||
await _applicationView.RunOnDispatcherThread(async () =>
|
||||
{
|
||||
await _terminalView.ChangeKeyBindings(FlattenKeyBindings(keyBindings)).ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
|
||||
private async void OnKeyboardCommandReceived(object sender, Command e)
|
||||
{
|
||||
if (e == Command.Copy)
|
||||
@@ -300,7 +330,7 @@ namespace FluentTerminal.App.ViewModels
|
||||
var content = await _clipboardService.GetText().ConfigureAwait(true);
|
||||
if (content != null)
|
||||
{
|
||||
await _terminalView.Write(content).ConfigureAwait(true);
|
||||
await _trayProcessCommunicationService.WriteText(_terminalId, content).ConfigureAwait(true);
|
||||
}
|
||||
}
|
||||
else if (e == Command.Search)
|
||||
@@ -323,6 +353,14 @@ namespace FluentTerminal.App.ViewModels
|
||||
ShowResizeOverlay = false;
|
||||
}
|
||||
|
||||
private void OnTerminalExited(object sender, int e)
|
||||
{
|
||||
if (e == _terminalId)
|
||||
{
|
||||
_applicationView.RunOnDispatcherThread(() => Closed?.Invoke(this, EventArgs.Empty));
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnTerminalOptionsChanged(object sender, TerminalOptions e)
|
||||
{
|
||||
await _applicationView.RunOnDispatcherThread(async () =>
|
||||
@@ -347,55 +385,25 @@ namespace FluentTerminal.App.ViewModels
|
||||
Title = e;
|
||||
}
|
||||
|
||||
private IEnumerable<KeyBinding> FlattenKeyBindings(IDictionary<Command, ICollection<KeyBinding>> keyBindings)
|
||||
private void SelectTabTheme(string name)
|
||||
{
|
||||
return keyBindings.Values.SelectMany(k => k);
|
||||
TabTheme = TabThemes.FirstOrDefault(t => t.Name == name);
|
||||
}
|
||||
|
||||
private Task FindNext()
|
||||
private async Task TryClose()
|
||||
{
|
||||
return _terminalView.FindNext(SearchText);
|
||||
}
|
||||
|
||||
private Task FindPrevious()
|
||||
{
|
||||
return _terminalView.FindPrevious(SearchText);
|
||||
}
|
||||
|
||||
private void CloseSearchPanel()
|
||||
{
|
||||
SearchText = string.Empty;
|
||||
ShowSearchPanel = false;
|
||||
_terminalView.FocusTerminal();
|
||||
}
|
||||
|
||||
private const int FirstDynamicPort = 49151;
|
||||
|
||||
public static int? GetAvailablePort()
|
||||
{
|
||||
var usedPorts = new List<int>();
|
||||
|
||||
var properties = IPGlobalProperties.GetIPGlobalProperties();
|
||||
|
||||
var connections = properties.GetActiveTcpConnections();
|
||||
usedPorts.AddRange(connections.Where(c => c.LocalEndPoint.Port >= FirstDynamicPort).Select(c => c.LocalEndPoint.Port));
|
||||
|
||||
var endPoints = properties.GetActiveTcpListeners();
|
||||
usedPorts.AddRange(endPoints.Where(e => e.Port >= FirstDynamicPort).Select(e => e.Port));
|
||||
|
||||
endPoints = properties.GetActiveUdpListeners();
|
||||
usedPorts.AddRange(endPoints.Where(e => e.Port >= FirstDynamicPort).Select(e => e.Port));
|
||||
|
||||
usedPorts.Sort();
|
||||
|
||||
for (var i = FirstDynamicPort; i < UInt16.MaxValue; i++)
|
||||
if (ApplicationSettings.ConfirmClosingTabs)
|
||||
{
|
||||
if (!usedPorts.Contains(i))
|
||||
var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to close this tab?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(true);
|
||||
|
||||
if (result == DialogButton.Cancel)
|
||||
{
|
||||
return i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
await _trayProcessCommunicationService.CloseTerminal(_terminalId).ConfigureAwait(true);
|
||||
Closed?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using FluentTerminal.App.ViewModels.Infrastructure;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FluentTerminal.App.ViewModels.Utilities
|
||||
{
|
||||
public static class TaskUtilities
|
||||
{
|
||||
#pragma warning disable RECS0165 // Asynchronous methods should return a Task instead of void
|
||||
public static async void FireAndForgetSafeAsync(this Task task, IErrorHandler handler = null)
|
||||
#pragma warning restore RECS0165 // Asynchronous methods should return a Task instead of void
|
||||
{
|
||||
try
|
||||
{
|
||||
await task;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
handler?.HandleError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
@@ -11,9 +12,24 @@ namespace FluentTerminal.App.Adapters
|
||||
{
|
||||
private readonly AppServiceConnection _appServiceConnection;
|
||||
|
||||
public event EventHandler<IDictionary<string, string>> MessageReceived;
|
||||
|
||||
public AppServiceConnectionAdapter(AppServiceConnection appServiceConnection)
|
||||
{
|
||||
_appServiceConnection = appServiceConnection;
|
||||
_appServiceConnection.RequestReceived += OnRequestReceived;
|
||||
}
|
||||
|
||||
private void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
|
||||
{
|
||||
var messageType = (string)args.Request.Message[MessageKeys.Type];
|
||||
var messageContent = (string)args.Request.Message[MessageKeys.Content];
|
||||
|
||||
MessageReceived?.Invoke(this, new Dictionary<string, string>
|
||||
{
|
||||
[MessageKeys.Type] = messageType,
|
||||
[MessageKeys.Content] = messageContent
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<IDictionary<string, string>> SendMessageAsync(IDictionary<string, string> message)
|
||||
@@ -39,4 +55,4 @@ namespace FluentTerminal.App.Adapters
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,5 +64,4 @@ namespace FluentTerminal.App.Adapters
|
||||
deferral.Complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.App.Services;
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace FluentTerminal.App.Adapters
|
||||
@@ -39,4 +39,4 @@ namespace FluentTerminal.App.Adapters
|
||||
_dispatcherTimer.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,10 @@
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Styles\Custom.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<LinearGradientBrush x:Key="MissingColorSelectionBrush" StartPoint="0,0" EndPoint="1,1">
|
||||
<GradientStop Offset="0" Color="Black" />
|
||||
<GradientStop Offset="1.0" Color="White" />
|
||||
</LinearGradientBrush>
|
||||
<converters:IntToVisibilityConverter
|
||||
x:Key="OneToVisibleConverter"
|
||||
Else="Collapsed"
|
||||
@@ -21,6 +25,7 @@
|
||||
<converters:NegateConverter x:Key="NegateConverter" />
|
||||
<converters:FalseToVisibleConverter x:Key="FalseToVisibleConverter" />
|
||||
<converters:TrueToVisibleConverter x:Key="TrueToVisibleConverter" />
|
||||
<converters:TabColorFallbackConverter x:Key="TabColorFallbackConverter" />
|
||||
<converters:IntToVisibilityConverter
|
||||
x:Key="ZeroToCollapsedConverter"
|
||||
Else="Visible"
|
||||
@@ -29,6 +34,9 @@
|
||||
<converters:IntToExtendedVirtualKeyConverter x:Key="IntToExtendedVirtualKeyConverter" />
|
||||
<converters:BackgroundToApplicationThemeConverter x:Key="BackgroundToApplicationThemeConverter" />
|
||||
<converters:StringToColorConverter x:Key="StringToColorConverter" />
|
||||
<converters:EnumValueToVisibiltyConverter x:Key="EnumValueToVisibiltyConverter" />
|
||||
<converters:TabThemeSelectedConverter x:Key="TabThemeSelectedConverter" />
|
||||
<converters:ColorResourceKeyFallbackConverter x:Key="ColorResourceKeyFallbackConverter" />
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
</Application>
|
||||
@@ -2,6 +2,7 @@
|
||||
using FluentTerminal.App.Adapters;
|
||||
using FluentTerminal.App.Dialogs;
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.App.Services.Adapters;
|
||||
using FluentTerminal.App.Services.Dialogs;
|
||||
using FluentTerminal.App.Services.Implementation;
|
||||
using FluentTerminal.App.ViewModels;
|
||||
@@ -29,10 +30,6 @@ namespace FluentTerminal.App
|
||||
{
|
||||
public sealed partial class App : Application
|
||||
{
|
||||
public const string ThemesContainerName = "Themes";
|
||||
public const string KeyBindingsContainerName = "KeyBindings";
|
||||
public const string ShellProfilesContainerName = "ShellProfiles";
|
||||
|
||||
public TaskCompletionSource<int> _trayReady = new TaskCompletionSource<int>();
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ITrayProcessCommunicationService _trayProcessCommunicationService;
|
||||
@@ -55,9 +52,9 @@ namespace FluentTerminal.App
|
||||
{
|
||||
LocalSettings = new ApplicationDataContainerAdapter(ApplicationData.Current.LocalSettings),
|
||||
RoamingSettings = new ApplicationDataContainerAdapter(ApplicationData.Current.RoamingSettings),
|
||||
KeyBindings = new ApplicationDataContainerAdapter(ApplicationData.Current.RoamingSettings.CreateContainer(KeyBindingsContainerName, ApplicationDataCreateDisposition.Always)),
|
||||
ShellProfiles = new ApplicationDataContainerAdapter(ApplicationData.Current.LocalSettings.CreateContainer(ShellProfilesContainerName, ApplicationDataCreateDisposition.Always)),
|
||||
Themes = new ApplicationDataContainerAdapter(ApplicationData.Current.RoamingSettings.CreateContainer(ThemesContainerName, ApplicationDataCreateDisposition.Always))
|
||||
KeyBindings = new ApplicationDataContainerAdapter(ApplicationData.Current.RoamingSettings.CreateContainer(Constants.KeyBindingsContainerName, ApplicationDataCreateDisposition.Always)),
|
||||
ShellProfiles = new ApplicationDataContainerAdapter(ApplicationData.Current.LocalSettings.CreateContainer(Constants.ShellProfilesContainerName, ApplicationDataCreateDisposition.Always)),
|
||||
Themes = new ApplicationDataContainerAdapter(ApplicationData.Current.RoamingSettings.CreateContainer(Constants.ThemesContainerName, ApplicationDataCreateDisposition.Always))
|
||||
};
|
||||
|
||||
var builder = new ContainerBuilder();
|
||||
@@ -79,6 +76,7 @@ namespace FluentTerminal.App
|
||||
builder.RegisterType<MessageDialogAdapter>().As<IMessageDialog>().InstancePerDependency();
|
||||
builder.RegisterType<ApplicationViewAdapter>().As<IApplicationView>().InstancePerDependency();
|
||||
builder.RegisterType<DispatcherTimerAdapter>().As<IDispatcherTimer>().InstancePerDependency();
|
||||
builder.RegisterType<StartupTaskService>().As<IStartupTaskService>().SingleInstance();
|
||||
builder.RegisterInstance(applicationDataContainers);
|
||||
|
||||
_container = builder.Build();
|
||||
@@ -296,10 +294,10 @@ namespace FluentTerminal.App
|
||||
|
||||
private async Task StartSystemTray()
|
||||
{
|
||||
var launch = FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync().AsTask();
|
||||
var launch = FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("AppLaunchedParameterGroup").AsTask();
|
||||
var clearCache = WebView.ClearTemporaryWebDataAsync().AsTask();
|
||||
await Task.WhenAll(launch, clearCache, _trayReady.Task).ConfigureAwait(true);
|
||||
await _trayProcessCommunicationService.Initialize(_appServiceConnection).ConfigureAwait(true);
|
||||
_trayProcessCommunicationService.Initialize(_appServiceConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -14,7 +14,8 @@ namespace FluentTerminal.App.Converters
|
||||
if (value is string colorString)
|
||||
{
|
||||
color = colorString.ToColor();
|
||||
} else if (value is Color)
|
||||
}
|
||||
else if (value is Color)
|
||||
{
|
||||
color = (Color)value;
|
||||
}
|
||||
@@ -32,4 +33,4 @@ namespace FluentTerminal.App.Converters
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Microsoft.Toolkit.Uwp.Helpers;
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
||||
namespace FluentTerminal.App.Converters
|
||||
{
|
||||
public class ColorResourceKeyFallbackConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return Application.Current.Resources[(string)parameter];
|
||||
}
|
||||
else if (value is string hex)
|
||||
{
|
||||
var color = hex.ToColor();
|
||||
return new SolidColorBrush(color);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace FluentTerminal.App.Converters
|
||||
{
|
||||
public class EnumValueToVisibiltyConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value.GetType().IsEnum && Enum.TryParse(value.GetType(), parameter.ToString(), true, out object result))
|
||||
{
|
||||
return Equals(value, result) ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,4 +24,4 @@ namespace FluentTerminal.App.Converters
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,4 +21,4 @@ namespace FluentTerminal.App.Converters
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,4 +19,4 @@ namespace FluentTerminal.App.Converters
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ namespace FluentTerminal.App.Converters
|
||||
{
|
||||
return colorString.FromString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -25,4 +26,4 @@ namespace FluentTerminal.App.Converters
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using FluentTerminal.Models;
|
||||
using FluentTerminal.Models.Enums;
|
||||
using Microsoft.Toolkit.Uwp.Helpers;
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
||||
namespace FluentTerminal.App.Converters
|
||||
{
|
||||
public class TabColorFallbackConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is TabTheme theme && Enum.TryParse<TabThemeKey>((string)parameter, true, out TabThemeKey tabThemeKey))
|
||||
{
|
||||
switch (tabThemeKey)
|
||||
{
|
||||
case TabThemeKey.Background:
|
||||
return GetBrush(tabThemeKey, theme.Color, theme.BackgroundOpacity);
|
||||
case TabThemeKey.BackgroundPointerOver:
|
||||
return GetBrush(tabThemeKey, theme.Color, theme.BackgroundPointerOverOpacity);
|
||||
case TabThemeKey.BackgroundPressed:
|
||||
return GetBrush(tabThemeKey, theme.Color, theme.BackgroundPressedOpacity);
|
||||
case TabThemeKey.BackgroundSelected:
|
||||
return GetBrush(tabThemeKey, theme.Color, theme.BackgroundSelectedOpacity);
|
||||
case TabThemeKey.BackgroundSelectedPointerOver:
|
||||
return GetBrush(tabThemeKey, theme.Color, theme.BackgroundSelectedPointerOverOpacity);
|
||||
case TabThemeKey.BackgroundSelectedPressed:
|
||||
return GetBrush(tabThemeKey, theme.Color, theme.BackgroundSelectedPressedOpacity);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private Brush GetBrush(TabThemeKey tabThemeKey, string color, double opacity)
|
||||
{
|
||||
if (double.IsNaN(opacity))
|
||||
{
|
||||
return (Brush)Application.Current.Resources[GetFallbackRessourceKey(tabThemeKey)];
|
||||
}
|
||||
else
|
||||
{
|
||||
return CreateBrush(color, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
private Brush CreateBrush(string hex, double opacity)
|
||||
{
|
||||
var color = hex.ToColor();
|
||||
return new SolidColorBrush(color)
|
||||
{
|
||||
Opacity = opacity
|
||||
};
|
||||
}
|
||||
|
||||
private string GetFallbackRessourceKey(TabThemeKey tabThemeKey)
|
||||
{
|
||||
switch (tabThemeKey)
|
||||
{
|
||||
case TabThemeKey.Background:
|
||||
return "SystemControlTransparentBrush";
|
||||
case TabThemeKey.BackgroundPointerOver:
|
||||
return "SystemControlHighlightListLowBrush";
|
||||
case TabThemeKey.BackgroundPressed:
|
||||
return "SystemControlHighlightListMediumBrush";
|
||||
case TabThemeKey.BackgroundSelected:
|
||||
return "SystemControlHighlightListAccentLowBrush";
|
||||
case TabThemeKey.BackgroundSelectedPointerOver:
|
||||
return "SystemControlHighlightListAccentMediumBrush";
|
||||
case TabThemeKey.BackgroundSelectedPressed:
|
||||
return "SystemControlHighlightListAccentHighBrush";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using FluentTerminal.Models;
|
||||
using System;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace FluentTerminal.App.Converters
|
||||
{
|
||||
public class TabThemeSelectedConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is TabTheme theme && parameter is string name)
|
||||
{
|
||||
return theme.Name == name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,24 +8,24 @@ namespace FluentTerminal.App.Converters
|
||||
{
|
||||
internal class TerminalViewModelToViewConverter : IValueConverter
|
||||
{
|
||||
private readonly Dictionary<int, TerminalView> _viewDictionary;
|
||||
private readonly Dictionary<TerminalViewModel, TerminalView> _viewDictionary;
|
||||
|
||||
public TerminalViewModelToViewConverter()
|
||||
{
|
||||
_viewDictionary = new Dictionary<int, TerminalView>();
|
||||
_viewDictionary = new Dictionary<TerminalViewModel, TerminalView>();
|
||||
}
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is TerminalViewModel terminal)
|
||||
{
|
||||
if (_viewDictionary.TryGetValue(terminal.Id, out TerminalView view))
|
||||
if (_viewDictionary.TryGetValue(terminal, out TerminalView view))
|
||||
{
|
||||
return view;
|
||||
}
|
||||
|
||||
var newView = new TerminalView(terminal);
|
||||
_viewDictionary.Add(terminal.Id, newView);
|
||||
_viewDictionary.Add(terminal, newView);
|
||||
return newView;
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -24,4 +24,4 @@ namespace FluentTerminal.App.Converters
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,4 +76,4 @@
|
||||
PreviewKeyDown="OnResetButtonPreviewKeyDown" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
</ContentDialog>
|
||||
@@ -1,13 +1,13 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using FluentTerminal.App.Services.Dialogs;
|
||||
using FluentTerminal.App.Services.Dialogs;
|
||||
using FluentTerminal.Models;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using System;
|
||||
|
||||
namespace FluentTerminal.App.Dialogs
|
||||
{
|
||||
@@ -92,16 +92,20 @@ namespace FluentTerminal.App.Dialogs
|
||||
case VirtualKey.Control:
|
||||
Ctrl = true;
|
||||
break;
|
||||
|
||||
case VirtualKey.Shift:
|
||||
Shift = true;
|
||||
break;
|
||||
|
||||
case VirtualKey.Menu:
|
||||
Alt = true;
|
||||
break;
|
||||
|
||||
case VirtualKey.LeftWindows:
|
||||
case VirtualKey.RightWindows:
|
||||
Meta = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
Key = (int)e.Key;
|
||||
break;
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{x:Bind Profiles}"
|
||||
SelectedItem="{x:Bind SelectedProfile, Mode=TwoWay}" />
|
||||
</ContentDialog>
|
||||
</ContentDialog>
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.App.Services;
|
||||
using FluentTerminal.App.Services.Dialogs;
|
||||
using FluentTerminal.App.Utilities;
|
||||
using FluentTerminal.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -35,4 +35,4 @@ namespace FluentTerminal.App.Dialogs
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
||||
<AppInstallerUpdateFrequency>1</AppInstallerUpdateFrequency>
|
||||
<AppInstallerCheckForUpdateFrequency>OnApplicationRun</AppInstallerCheckForUpdateFrequency>
|
||||
<AppxSymbolPackageEnabled>True</AppxSymbolPackageEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -103,7 +104,6 @@
|
||||
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Adapters\ApplicationDataContainerAdapter.cs" />
|
||||
<Compile Include="Adapters\ApplicationViewAdapter.cs" />
|
||||
<Compile Include="Adapters\AppServiceConnectionAdapter.cs" />
|
||||
<Compile Include="Adapters\DispatcherTimerAdapter.cs" />
|
||||
@@ -112,11 +112,15 @@
|
||||
</Compile>
|
||||
<Compile Include="Behaviors\MiddleClickBehavior.cs" />
|
||||
<Compile Include="Converters\BackgroundToApplicationThemeConverter.cs" />
|
||||
<Compile Include="Converters\ColorResourceKeyFallbackConverter.cs" />
|
||||
<Compile Include="Converters\TabColorFallbackConverter.cs" />
|
||||
<Compile Include="Converters\EnumValueToVisibiltyConverter.cs" />
|
||||
<Compile Include="Converters\FalseToVisibleConverter.cs" />
|
||||
<Compile Include="Converters\IntToExtendedVirtualKeyConverter.cs" />
|
||||
<Compile Include="Converters\IntToVisibilityConverter.cs" />
|
||||
<Compile Include="Converters\NegateConverter.cs" />
|
||||
<Compile Include="Converters\StringToColorConverter.cs" />
|
||||
<Compile Include="Converters\TabThemeSelectedConverter.cs" />
|
||||
<Compile Include="Converters\TerminalViewModelToViewConverter.cs" />
|
||||
<Compile Include="Converters\TrueToVisibleConverter.cs" />
|
||||
<Compile Include="Adapters\MessageDialogAdapter.cs" />
|
||||
@@ -125,6 +129,7 @@
|
||||
</Compile>
|
||||
<Compile Include="Services\ClipboardService.cs" />
|
||||
<Compile Include="Services\FileSystemService.cs" />
|
||||
<Compile Include="Services\StartupTaskService.cs" />
|
||||
<Compile Include="Services\SystemFontService.cs" />
|
||||
<Compile Include="Utilities\ColorExtensions.cs" />
|
||||
<Compile Include="Utilities\ContrastHelper.cs" />
|
||||
@@ -141,6 +146,9 @@
|
||||
<Compile Include="Views\SettingsPage.xaml.cs">
|
||||
<DependentUpon>SettingsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPages\MouseSettings.xaml.cs">
|
||||
<DependentUpon>MouseSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsPages\ThemeSettings.xaml.cs">
|
||||
<DependentUpon>ThemeSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -156,6 +164,11 @@
|
||||
<Compile Include="Views\SettingsPages\ShellProfileSettings.xaml.cs">
|
||||
<DependentUpon>ShellProfileSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\TabBar.xaml.cs">
|
||||
<DependentUpon>TabBar.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\TabBarBackgroundBindingHelper.cs" />
|
||||
<Compile Include="Views\TabThemeTemplateSelector.cs" />
|
||||
<Compile Include="Views\TerminalColorPicker.xaml.cs">
|
||||
<DependentUpon>TerminalColorPicker.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -169,13 +182,15 @@
|
||||
</AppxManifest>
|
||||
<Content Include="Assets\settingsicons.ttf" />
|
||||
<Content Include="Win32\Autofac.dll" />
|
||||
<Content Include="Win32\Fleck.dll" />
|
||||
<Content Include="Win32\FluentTerminal.App.Services.dll" />
|
||||
<Content Include="Win32\FluentTerminal.App.Services.pdb" />
|
||||
<Content Include="Win32\FluentTerminal.Models.dll" />
|
||||
<Content Include="Win32\FluentTerminal.Models.pdb" />
|
||||
<Content Include="Win32\FluentTerminal.SystemTray.exe" />
|
||||
<Content Include="Win32\FluentTerminal.SystemTray.pdb" />
|
||||
<Content Include="Win32\GlobalHotKey.dll" />
|
||||
<Content Include="Win32\Newtonsoft.Json.dll" />
|
||||
<Content Include="Win32\RestSharp.dll" />
|
||||
<Content Include="Win32\System.Data.Common.dll" />
|
||||
<Content Include="Win32\System.Diagnostics.StackTrace.dll" />
|
||||
<Content Include="Win32\System.Diagnostics.Tracing.dll" />
|
||||
@@ -279,6 +294,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPages\MouseSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsPages\ThemeSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -299,6 +318,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\TabBar.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\TerminalColorPicker.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<StoreAssociation xmlns="http://schemas.microsoft.com/appx/2010/storeassociation">
|
||||
<Publisher>CN=BDC72197-B634-438A-B863-16DCB7D90C85</Publisher>
|
||||
<NamespacePrefix>53621FSApps</NamespacePrefix>
|
||||
<PublisherDisplayName>FS Apps</PublisherDisplayName>
|
||||
<GeneratePackageHash>http://www.w3.org/2001/04/xmlenc#sha256</GeneratePackageHash>
|
||||
<SupportedLocales>
|
||||
<Language Code="af" InMinimumRequirementSet="false" />
|
||||
<Language Code="af-za" InMinimumRequirementSet="false" />
|
||||
<Language Code="am" InMinimumRequirementSet="false" />
|
||||
<Language Code="am-et" InMinimumRequirementSet="false" />
|
||||
<Language Code="ar" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-ae" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-bh" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-dz" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-eg" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-iq" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-jo" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-kw" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-lb" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-ly" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-ma" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-om" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-qa" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-sa" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-sy" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-tn" InMinimumRequirementSet="true" />
|
||||
<Language Code="ar-ye" InMinimumRequirementSet="true" />
|
||||
<Language Code="as" InMinimumRequirementSet="false" />
|
||||
<Language Code="as-in" InMinimumRequirementSet="false" />
|
||||
<Language Code="az" InMinimumRequirementSet="false" />
|
||||
<Language Code="az-arab" InMinimumRequirementSet="false" />
|
||||
<Language Code="az-arab-az" InMinimumRequirementSet="false" />
|
||||
<Language Code="az-cyrl" InMinimumRequirementSet="false" />
|
||||
<Language Code="az-cyrl-az" InMinimumRequirementSet="false" />
|
||||
<Language Code="az-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="az-latn-az" InMinimumRequirementSet="false" />
|
||||
<Language Code="be" InMinimumRequirementSet="false" />
|
||||
<Language Code="be-by" InMinimumRequirementSet="false" />
|
||||
<Language Code="bg" InMinimumRequirementSet="true" />
|
||||
<Language Code="bg-bg" InMinimumRequirementSet="true" />
|
||||
<Language Code="bn" InMinimumRequirementSet="false" />
|
||||
<Language Code="bn-bd" InMinimumRequirementSet="false" />
|
||||
<Language Code="bn-in" InMinimumRequirementSet="false" />
|
||||
<Language Code="bs" InMinimumRequirementSet="false" />
|
||||
<Language Code="bs-cyrl" InMinimumRequirementSet="false" />
|
||||
<Language Code="bs-cyrl-ba" InMinimumRequirementSet="false" />
|
||||
<Language Code="bs-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="bs-latn-ba" InMinimumRequirementSet="false" />
|
||||
<Language Code="ca" InMinimumRequirementSet="false" />
|
||||
<Language Code="ca-es" InMinimumRequirementSet="false" />
|
||||
<Language Code="ca-es-valencia" InMinimumRequirementSet="false" />
|
||||
<Language Code="chr-cher" InMinimumRequirementSet="false" />
|
||||
<Language Code="chr-cher-us" InMinimumRequirementSet="false" />
|
||||
<Language Code="chr-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="cs" InMinimumRequirementSet="true" />
|
||||
<Language Code="cs-cz" InMinimumRequirementSet="true" />
|
||||
<Language Code="cy" InMinimumRequirementSet="false" />
|
||||
<Language Code="cy-gb" InMinimumRequirementSet="false" />
|
||||
<Language Code="da" InMinimumRequirementSet="true" />
|
||||
<Language Code="da-dk" InMinimumRequirementSet="true" />
|
||||
<Language Code="de" InMinimumRequirementSet="true" />
|
||||
<Language Code="de-at" InMinimumRequirementSet="true" />
|
||||
<Language Code="de-ch" InMinimumRequirementSet="true" />
|
||||
<Language Code="de-de" InMinimumRequirementSet="true" />
|
||||
<Language Code="de-li" InMinimumRequirementSet="true" />
|
||||
<Language Code="de-lu" InMinimumRequirementSet="true" />
|
||||
<Language Code="el" InMinimumRequirementSet="true" />
|
||||
<Language Code="el-gr" InMinimumRequirementSet="true" />
|
||||
<Language Code="en" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-au" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-bz" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-ca" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-gb" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-hk" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-id" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-ie" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-in" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-jm" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-kz" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-mt" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-my" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-nz" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-ph" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-pk" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-sg" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-tt" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-us" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-vn" InMinimumRequirementSet="true" />
|
||||
<Language Code="en-za" InMinimumRequirementSet="true" />
|
||||
<Language Code="es" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-ar" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-bo" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-cl" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-co" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-cr" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-do" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-ec" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-es" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-gt" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-hn" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-mx" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-ni" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-pa" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-pe" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-pr" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-py" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-sv" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-us" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-uy" InMinimumRequirementSet="true" />
|
||||
<Language Code="es-ve" InMinimumRequirementSet="true" />
|
||||
<Language Code="et" InMinimumRequirementSet="true" />
|
||||
<Language Code="et-ee" InMinimumRequirementSet="true" />
|
||||
<Language Code="eu" InMinimumRequirementSet="false" />
|
||||
<Language Code="eu-es" InMinimumRequirementSet="false" />
|
||||
<Language Code="fa" InMinimumRequirementSet="false" />
|
||||
<Language Code="fa-ir" InMinimumRequirementSet="false" />
|
||||
<Language Code="fi" InMinimumRequirementSet="true" />
|
||||
<Language Code="fi-fi" InMinimumRequirementSet="true" />
|
||||
<Language Code="fil" InMinimumRequirementSet="false" />
|
||||
<Language Code="fil-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="fil-ph" InMinimumRequirementSet="false" />
|
||||
<Language Code="fr" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-015" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-be" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-ca" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-cd" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-ch" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-ci" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-cm" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-fr" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-ht" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-lu" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-ma" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-mc" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-ml" InMinimumRequirementSet="true" />
|
||||
<Language Code="fr-re" InMinimumRequirementSet="true" />
|
||||
<Language Code="frc" InMinimumRequirementSet="true" />
|
||||
<Language Code="frc-latn" InMinimumRequirementSet="true" />
|
||||
<Language Code="frp" InMinimumRequirementSet="true" />
|
||||
<Language Code="frp-latn" InMinimumRequirementSet="true" />
|
||||
<Language Code="ga" InMinimumRequirementSet="false" />
|
||||
<Language Code="ga-ie" InMinimumRequirementSet="false" />
|
||||
<Language Code="gd" InMinimumRequirementSet="false" />
|
||||
<Language Code="gd-gb" InMinimumRequirementSet="false" />
|
||||
<Language Code="gd-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="gl" InMinimumRequirementSet="false" />
|
||||
<Language Code="gl-es" InMinimumRequirementSet="false" />
|
||||
<Language Code="gu" InMinimumRequirementSet="false" />
|
||||
<Language Code="gu-in" InMinimumRequirementSet="false" />
|
||||
<Language Code="ha-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="ha-latn-ng" InMinimumRequirementSet="false" />
|
||||
<Language Code="he" InMinimumRequirementSet="true" />
|
||||
<Language Code="he-il" InMinimumRequirementSet="true" />
|
||||
<Language Code="hi" InMinimumRequirementSet="true" />
|
||||
<Language Code="hi-in" InMinimumRequirementSet="true" />
|
||||
<Language Code="hr" InMinimumRequirementSet="true" />
|
||||
<Language Code="hr-ba" InMinimumRequirementSet="true" />
|
||||
<Language Code="hr-hr" InMinimumRequirementSet="true" />
|
||||
<Language Code="hu" InMinimumRequirementSet="true" />
|
||||
<Language Code="hu-hu" InMinimumRequirementSet="true" />
|
||||
<Language Code="hy" InMinimumRequirementSet="false" />
|
||||
<Language Code="hy-am" InMinimumRequirementSet="false" />
|
||||
<Language Code="id" InMinimumRequirementSet="true" />
|
||||
<Language Code="id-id" InMinimumRequirementSet="true" />
|
||||
<Language Code="ig" InMinimumRequirementSet="false" />
|
||||
<Language Code="ig-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="ig-ng" InMinimumRequirementSet="false" />
|
||||
<Language Code="is" InMinimumRequirementSet="false" />
|
||||
<Language Code="is-is" InMinimumRequirementSet="false" />
|
||||
<Language Code="it" InMinimumRequirementSet="true" />
|
||||
<Language Code="it-ch" InMinimumRequirementSet="true" />
|
||||
<Language Code="it-it" InMinimumRequirementSet="true" />
|
||||
<Language Code="iu-cans" InMinimumRequirementSet="false" />
|
||||
<Language Code="iu-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="iu-latn-ca" InMinimumRequirementSet="false" />
|
||||
<Language Code="ja" InMinimumRequirementSet="true" />
|
||||
<Language Code="ja-jp" InMinimumRequirementSet="true" />
|
||||
<Language Code="ka" InMinimumRequirementSet="false" />
|
||||
<Language Code="ka-ge" InMinimumRequirementSet="false" />
|
||||
<Language Code="kk" InMinimumRequirementSet="false" />
|
||||
<Language Code="kk-kz" InMinimumRequirementSet="false" />
|
||||
<Language Code="km" InMinimumRequirementSet="false" />
|
||||
<Language Code="km-kh" InMinimumRequirementSet="false" />
|
||||
<Language Code="kn" InMinimumRequirementSet="false" />
|
||||
<Language Code="kn-in" InMinimumRequirementSet="false" />
|
||||
<Language Code="ko" InMinimumRequirementSet="true" />
|
||||
<Language Code="ko-kr" InMinimumRequirementSet="true" />
|
||||
<Language Code="kok" InMinimumRequirementSet="false" />
|
||||
<Language Code="kok-in" InMinimumRequirementSet="false" />
|
||||
<Language Code="ku-arab" InMinimumRequirementSet="false" />
|
||||
<Language Code="ku-arab-iq" InMinimumRequirementSet="false" />
|
||||
<Language Code="ky" InMinimumRequirementSet="false" />
|
||||
<Language Code="ky-cyrl" InMinimumRequirementSet="false" />
|
||||
<Language Code="ky-kg" InMinimumRequirementSet="false" />
|
||||
<Language Code="lb" InMinimumRequirementSet="false" />
|
||||
<Language Code="lb-lu" InMinimumRequirementSet="false" />
|
||||
<Language Code="lt" InMinimumRequirementSet="true" />
|
||||
<Language Code="lt-lt" InMinimumRequirementSet="true" />
|
||||
<Language Code="lv" InMinimumRequirementSet="true" />
|
||||
<Language Code="lv-lv" InMinimumRequirementSet="true" />
|
||||
<Language Code="mi" InMinimumRequirementSet="false" />
|
||||
<Language Code="mi-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="mi-nz" InMinimumRequirementSet="false" />
|
||||
<Language Code="mk" InMinimumRequirementSet="false" />
|
||||
<Language Code="mk-mk" InMinimumRequirementSet="false" />
|
||||
<Language Code="ml" InMinimumRequirementSet="false" />
|
||||
<Language Code="ml-in" InMinimumRequirementSet="false" />
|
||||
<Language Code="mn" InMinimumRequirementSet="false" />
|
||||
<Language Code="mn-cyrl" InMinimumRequirementSet="false" />
|
||||
<Language Code="mn-mn" InMinimumRequirementSet="false" />
|
||||
<Language Code="mn-mong" InMinimumRequirementSet="false" />
|
||||
<Language Code="mn-phag" InMinimumRequirementSet="false" />
|
||||
<Language Code="mr" InMinimumRequirementSet="false" />
|
||||
<Language Code="mr-in" InMinimumRequirementSet="false" />
|
||||
<Language Code="ms" InMinimumRequirementSet="false" />
|
||||
<Language Code="ms-bn" InMinimumRequirementSet="false" />
|
||||
<Language Code="ms-my" InMinimumRequirementSet="false" />
|
||||
<Language Code="mt" InMinimumRequirementSet="false" />
|
||||
<Language Code="mt-mt" InMinimumRequirementSet="false" />
|
||||
<Language Code="nb" InMinimumRequirementSet="true" />
|
||||
<Language Code="nb-no" InMinimumRequirementSet="true" />
|
||||
<Language Code="ne" InMinimumRequirementSet="false" />
|
||||
<Language Code="ne-np" InMinimumRequirementSet="false" />
|
||||
<Language Code="nl" InMinimumRequirementSet="true" />
|
||||
<Language Code="nl-be" InMinimumRequirementSet="true" />
|
||||
<Language Code="nl-nl" InMinimumRequirementSet="true" />
|
||||
<Language Code="nn" InMinimumRequirementSet="false" />
|
||||
<Language Code="nn-no" InMinimumRequirementSet="false" />
|
||||
<Language Code="no" InMinimumRequirementSet="true" />
|
||||
<Language Code="no-no" InMinimumRequirementSet="true" />
|
||||
<Language Code="nso" InMinimumRequirementSet="false" />
|
||||
<Language Code="nso-za" InMinimumRequirementSet="false" />
|
||||
<Language Code="or" InMinimumRequirementSet="false" />
|
||||
<Language Code="or-in" InMinimumRequirementSet="false" />
|
||||
<Language Code="pa" InMinimumRequirementSet="false" />
|
||||
<Language Code="pa-arab" InMinimumRequirementSet="false" />
|
||||
<Language Code="pa-arab-pk" InMinimumRequirementSet="false" />
|
||||
<Language Code="pa-deva" InMinimumRequirementSet="false" />
|
||||
<Language Code="pa-in" InMinimumRequirementSet="false" />
|
||||
<Language Code="pl" InMinimumRequirementSet="true" />
|
||||
<Language Code="pl-pl" InMinimumRequirementSet="true" />
|
||||
<Language Code="prs" InMinimumRequirementSet="false" />
|
||||
<Language Code="prs-af" InMinimumRequirementSet="false" />
|
||||
<Language Code="prs-arab" InMinimumRequirementSet="false" />
|
||||
<Language Code="pt" InMinimumRequirementSet="true" />
|
||||
<Language Code="pt-br" InMinimumRequirementSet="true" />
|
||||
<Language Code="pt-pt" InMinimumRequirementSet="true" />
|
||||
<Language Code="quc" InMinimumRequirementSet="false" />
|
||||
<Language Code="quc-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="qut" InMinimumRequirementSet="false" />
|
||||
<Language Code="qut-gt" InMinimumRequirementSet="false" />
|
||||
<Language Code="qut-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="quz" InMinimumRequirementSet="false" />
|
||||
<Language Code="quz-bo" InMinimumRequirementSet="false" />
|
||||
<Language Code="quz-ec" InMinimumRequirementSet="false" />
|
||||
<Language Code="quz-pe" InMinimumRequirementSet="false" />
|
||||
<Language Code="ro" InMinimumRequirementSet="true" />
|
||||
<Language Code="ro-ro" InMinimumRequirementSet="true" />
|
||||
<Language Code="ru" InMinimumRequirementSet="true" />
|
||||
<Language Code="ru-ru" InMinimumRequirementSet="true" />
|
||||
<Language Code="rw" InMinimumRequirementSet="false" />
|
||||
<Language Code="rw-rw" InMinimumRequirementSet="false" />
|
||||
<Language Code="sd-arab" InMinimumRequirementSet="false" />
|
||||
<Language Code="sd-arab-pk" InMinimumRequirementSet="false" />
|
||||
<Language Code="sd-deva" InMinimumRequirementSet="false" />
|
||||
<Language Code="si" InMinimumRequirementSet="false" />
|
||||
<Language Code="si-lk" InMinimumRequirementSet="false" />
|
||||
<Language Code="sk" InMinimumRequirementSet="true" />
|
||||
<Language Code="sk-sk" InMinimumRequirementSet="true" />
|
||||
<Language Code="sl" InMinimumRequirementSet="true" />
|
||||
<Language Code="sl-si" InMinimumRequirementSet="true" />
|
||||
<Language Code="sq" InMinimumRequirementSet="false" />
|
||||
<Language Code="sq-al" InMinimumRequirementSet="false" />
|
||||
<Language Code="sr" InMinimumRequirementSet="true" />
|
||||
<Language Code="sr-cyrl" InMinimumRequirementSet="false" />
|
||||
<Language Code="sr-cyrl-ba" InMinimumRequirementSet="false" />
|
||||
<Language Code="sr-cyrl-cs" InMinimumRequirementSet="false" />
|
||||
<Language Code="sr-cyrl-me" InMinimumRequirementSet="false" />
|
||||
<Language Code="sr-cyrl-rs" InMinimumRequirementSet="false" />
|
||||
<Language Code="sr-latn" InMinimumRequirementSet="true" />
|
||||
<Language Code="sr-latn-ba" InMinimumRequirementSet="true" />
|
||||
<Language Code="sr-latn-cs" InMinimumRequirementSet="true" />
|
||||
<Language Code="sr-latn-me" InMinimumRequirementSet="true" />
|
||||
<Language Code="sr-latn-rs" InMinimumRequirementSet="true" />
|
||||
<Language Code="sv" InMinimumRequirementSet="true" />
|
||||
<Language Code="sv-fi" InMinimumRequirementSet="true" />
|
||||
<Language Code="sv-se" InMinimumRequirementSet="true" />
|
||||
<Language Code="sw" InMinimumRequirementSet="false" />
|
||||
<Language Code="sw-ke" InMinimumRequirementSet="false" />
|
||||
<Language Code="ta" InMinimumRequirementSet="false" />
|
||||
<Language Code="ta-in" InMinimumRequirementSet="false" />
|
||||
<Language Code="te" InMinimumRequirementSet="false" />
|
||||
<Language Code="te-in" InMinimumRequirementSet="false" />
|
||||
<Language Code="tg-arab" InMinimumRequirementSet="false" />
|
||||
<Language Code="tg-cyrl" InMinimumRequirementSet="false" />
|
||||
<Language Code="tg-cyrl-tj" InMinimumRequirementSet="false" />
|
||||
<Language Code="tg-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="th" InMinimumRequirementSet="true" />
|
||||
<Language Code="th-th" InMinimumRequirementSet="true" />
|
||||
<Language Code="ti" InMinimumRequirementSet="false" />
|
||||
<Language Code="ti-et" InMinimumRequirementSet="false" />
|
||||
<Language Code="tk" InMinimumRequirementSet="false" />
|
||||
<Language Code="tk-cyrl" InMinimumRequirementSet="false" />
|
||||
<Language Code="tk-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="tk-tm" InMinimumRequirementSet="false" />
|
||||
<Language Code="tk-tr" InMinimumRequirementSet="false" />
|
||||
<Language Code="tn" InMinimumRequirementSet="false" />
|
||||
<Language Code="tn-bw" InMinimumRequirementSet="false" />
|
||||
<Language Code="tn-za" InMinimumRequirementSet="false" />
|
||||
<Language Code="tr" InMinimumRequirementSet="true" />
|
||||
<Language Code="tr-tr" InMinimumRequirementSet="true" />
|
||||
<Language Code="tt" InMinimumRequirementSet="false" />
|
||||
<Language Code="tt-arab" InMinimumRequirementSet="false" />
|
||||
<Language Code="tt-cyrl" InMinimumRequirementSet="false" />
|
||||
<Language Code="tt-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="tt-ru" InMinimumRequirementSet="false" />
|
||||
<Language Code="ug" InMinimumRequirementSet="false" />
|
||||
<Language Code="ug-arab" InMinimumRequirementSet="false" />
|
||||
<Language Code="ug-cn" InMinimumRequirementSet="false" />
|
||||
<Language Code="ug-cyrl" InMinimumRequirementSet="false" />
|
||||
<Language Code="ug-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="uk" InMinimumRequirementSet="true" />
|
||||
<Language Code="uk-ua" InMinimumRequirementSet="true" />
|
||||
<Language Code="ur" InMinimumRequirementSet="false" />
|
||||
<Language Code="ur-pk" InMinimumRequirementSet="false" />
|
||||
<Language Code="uz-cyrl" InMinimumRequirementSet="false" />
|
||||
<Language Code="uz-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="uz-latn-uz" InMinimumRequirementSet="false" />
|
||||
<Language Code="vi" InMinimumRequirementSet="false" />
|
||||
<Language Code="vi-vn" InMinimumRequirementSet="false" />
|
||||
<Language Code="wo" InMinimumRequirementSet="false" />
|
||||
<Language Code="wo-sn" InMinimumRequirementSet="false" />
|
||||
<Language Code="xh" InMinimumRequirementSet="false" />
|
||||
<Language Code="xh-za" InMinimumRequirementSet="false" />
|
||||
<Language Code="yo" InMinimumRequirementSet="false" />
|
||||
<Language Code="yo-latn" InMinimumRequirementSet="false" />
|
||||
<Language Code="yo-ng" InMinimumRequirementSet="false" />
|
||||
<Language Code="zh-cn" InMinimumRequirementSet="true" />
|
||||
<Language Code="zh-hans" InMinimumRequirementSet="true" />
|
||||
<Language Code="zh-hans-cn" InMinimumRequirementSet="true" />
|
||||
<Language Code="zh-hans-sg" InMinimumRequirementSet="true" />
|
||||
<Language Code="zh-hant" InMinimumRequirementSet="true" />
|
||||
<Language Code="zh-hant-hk" InMinimumRequirementSet="true" />
|
||||
<Language Code="zh-hant-mo" InMinimumRequirementSet="true" />
|
||||
<Language Code="zh-hant-tw" InMinimumRequirementSet="true" />
|
||||
<Language Code="zh-hk" InMinimumRequirementSet="true" />
|
||||
<Language Code="zh-tw" InMinimumRequirementSet="true" />
|
||||
<Language Code="zu" InMinimumRequirementSet="false" />
|
||||
<Language Code="zu-za" InMinimumRequirementSet="false" />
|
||||
</SupportedLocales>
|
||||
<ProductReservedInfo>
|
||||
<MainPackageIdentityName>53621FSApps.FluentTerminal</MainPackageIdentityName>
|
||||
<ReservedNames>
|
||||
<ReservedName>Fluent Terminal</ReservedName>
|
||||
</ReservedNames>
|
||||
</ProductReservedInfo>
|
||||
<AccountPackageIdentityNames />
|
||||
<PackageInfoList LandingUrl="https://appdev.microsoft.com:443/StorePortals/Developer/Catalog/ReleaseAnchor/f9c07088-9f3e-4312-ad5b-0f3b4aeb9b37" />
|
||||
</StoreAssociation>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10" IgnorableNamespaces="uap mp desktop rescap">
|
||||
<Identity Name="53621FSApps.FluentTerminal" Publisher="CN=BDC72197-B634-438A-B863-16DCB7D90C85" Version="0.1.11.0" />
|
||||
<Identity Name="53621FSApps.FluentTerminal" Publisher="CN=BDC72197-B634-438A-B863-16DCB7D90C85" Version="0.2.1.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="f7225014-f405-4342-ad2e-ebf6ac60ea2c" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>Fluent Terminal</DisplayName>
|
||||
@@ -26,12 +26,19 @@
|
||||
<uap:SplashScreen Image="Assets\AppIcons\SplashScreen.png" uap5:Optional="true" />
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
<desktop:Extension Category="windows.fullTrustProcess" Executable="Win32\FluentTerminal.SystemTray.exe" />
|
||||
<desktop:Extension Category="windows.fullTrustProcess" Executable="Win32\FluentTerminal.SystemTray.exe">
|
||||
<desktop:FullTrustProcess>
|
||||
<desktop:ParameterGroup GroupId="AppLaunchedParameterGroup" Parameters="appLaunched" />
|
||||
</desktop:FullTrustProcess>
|
||||
</desktop:Extension>
|
||||
<uap5:Extension Category="windows.appExecutionAlias" Executable="FluentTerminal.App.exe" EntryPoint="FluentTerminal.App.App">
|
||||
<uap5:AppExecutionAlias>
|
||||
<uap5:ExecutionAlias Alias="flute.exe" />
|
||||
</uap5:AppExecutionAlias>
|
||||
</uap5:Extension>
|
||||
<desktop:Extension Category="windows.startupTask" Executable="Win32\FluentTerminal.SystemTray.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<desktop:StartupTask TaskId="FluentTerminalStartupTask" Enabled="false" DisplayName="Fluent Terminal" />
|
||||
</desktop:Extension>
|
||||
<uap:Extension Category="windows.appService">
|
||||
<uap:AppService Name="FluentTerminalAppService" />
|
||||
</uap:Extension>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("FluentTerminal.App")]
|
||||
@@ -17,11 +16,11 @@ using System.Runtime.InteropServices;
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
Laufzeitdirektiven sind hier dokumentiert: https://go.microsoft.com/fwlink/?LinkID=391919
|
||||
|
||||
Vollständige Aktivierung der Reflektion von "App1.MyClass" und allen zugehörigen öffentlichen/privaten Membern:
|
||||
<Type Name="App1.MyClass" Dynamic="Required All"/>
|
||||
<Type Name="App1.MyClass" Dynamic="Required All" />
|
||||
|
||||
Aktivierung der dynamischen Erstellung der spezifischen Instanziierung von "AppClass<T>" über "System.Int32":
|
||||
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
|
||||
@@ -22,10 +22,7 @@
|
||||
Anwendungspaket. Die Sternchen sind keine Platzhalter.
|
||||
-->
|
||||
<Assembly Name="*Application*" Dynamic="Required All" />
|
||||
|
||||
|
||||
|
||||
<!-- Fügen Sie hier Ihre anwendungsspezifischen Laufzeitdirektiven ein. -->
|
||||
|
||||
|
||||
</Application>
|
||||
</Directives>
|
||||
@@ -13,7 +13,8 @@ namespace FluentTerminal.App.Services
|
||||
{
|
||||
return content.GetTextAsync().AsTask();
|
||||
}
|
||||
return null;
|
||||
// Otherwise return a new task that just sends an empty string.
|
||||
return Task.FromResult(string.Empty);
|
||||
}
|
||||
|
||||
public void SetText(string text)
|
||||
@@ -23,4 +24,4 @@ namespace FluentTerminal.App.Services
|
||||
Clipboard.SetContent(dataPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
@@ -59,4 +58,4 @@ namespace FluentTerminal.App.Services
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using FluentTerminal.Models.Enums;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel;
|
||||
|
||||
namespace FluentTerminal.App.Services
|
||||
{
|
||||
public class StartupTaskService : IStartupTaskService
|
||||
{
|
||||
public const string StartupTaskname = "FluentTerminalStartupTask";
|
||||
|
||||
public async Task<StartupTaskStatus> GetStatus()
|
||||
{
|
||||
var startupTask = await StartupTask.GetAsync(StartupTaskname);
|
||||
return ConvertState(startupTask.State);
|
||||
}
|
||||
|
||||
public async Task<StartupTaskStatus> EnableStartupTask()
|
||||
{
|
||||
var startupTask = await StartupTask.GetAsync(StartupTaskname);
|
||||
var newState = await startupTask.RequestEnableAsync();
|
||||
return ConvertState(newState);
|
||||
}
|
||||
|
||||
public async Task DisableStartupTask()
|
||||
{
|
||||
var startupTask = await StartupTask.GetAsync(StartupTaskname);
|
||||
startupTask.Disable();
|
||||
}
|
||||
|
||||
private StartupTaskStatus ConvertState(StartupTaskState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case StartupTaskState.Disabled:
|
||||
return StartupTaskStatus.Disabled;
|
||||
case StartupTaskState.DisabledByUser:
|
||||
return StartupTaskStatus.DisabledByUser;
|
||||
case StartupTaskState.Enabled:
|
||||
return StartupTaskStatus.Enabled;
|
||||
case StartupTaskState.DisabledByPolicy:
|
||||
return StartupTaskStatus.DisabledByPolicy;
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,4 +10,4 @@ namespace FluentTerminal.App.Services
|
||||
return CanvasTextFormat.GetSystemFontFamilies();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,70 @@
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="TitleBarRepeatButtonStyle" TargetType="RepeatButton">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<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="Width" Value="47" />
|
||||
<Setter Property="Height" Value="32" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="RepeatButton">
|
||||
<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}" />
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemListLowColor}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemListMediumColor}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ColorPreviewButtonStyle" TargetType="Button">
|
||||
<Setter Property="Width" Value="24" />
|
||||
<Setter Property="Height" Value="24" />
|
||||
@@ -95,5 +159,4 @@
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary>
|
||||
@@ -46,4 +46,4 @@ namespace FluentTerminal.App.Utilities
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ namespace FluentTerminal.App.Utilities
|
||||
titleBar.ButtonPressedBackgroundColor = GetColor("SystemListMediumColor", theme);
|
||||
}
|
||||
|
||||
private static Color? GetColor(string name, ElementTheme theme)
|
||||
public static Color? GetColor(string name, ElementTheme theme)
|
||||
{
|
||||
if (theme == ElementTheme.Light)
|
||||
{
|
||||
@@ -48,10 +48,13 @@ namespace FluentTerminal.App.Utilities
|
||||
{
|
||||
case "SystemBaseHighColor":
|
||||
return new Color { A = 0xFF, R = 0x00, G = 0x00, B = 0x00 };
|
||||
|
||||
case "SystemListLowColor":
|
||||
return new Color { A = 0x19, R = 0x00, G = 0x00, B = 0x00 };
|
||||
|
||||
case "SystemListMediumColor":
|
||||
return new Color { A = 0x33, R = 0x00, G = 0x00, B = 0x00 };
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@@ -62,14 +65,17 @@ namespace FluentTerminal.App.Utilities
|
||||
{
|
||||
case "SystemBaseHighColor":
|
||||
return new Color { A = 0xFF, R = 0xFF, G = 0xFF, B = 0xFF };
|
||||
|
||||
case "SystemListLowColor":
|
||||
return new Color { A = 0x19, R = 0xFF, G = 0xFF, B = 0xFF };
|
||||
|
||||
case "SystemListMediumColor":
|
||||
return new Color { A = 0x33, R = 0xFF, G = 0xFF, B = 0xFF };
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,4 +92,4 @@
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
@@ -2,13 +2,10 @@
|
||||
x:Class="FluentTerminal.App.Views.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:behaviors="using:FluentTerminal.App.Behaviors"
|
||||
xmlns:converters="using:FluentTerminal.App.Converters"
|
||||
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewmodels="using:FluentTerminal.App.ViewModels"
|
||||
xmlns:views="using:FluentTerminal.App.Views"
|
||||
RequestedTheme="{x:Bind ViewModel.Background, Mode=OneWay, Converter={StaticResource BackgroundToApplicationThemeConverter}}"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
@@ -25,113 +22,60 @@
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Rectangle x:Name="TitleBar" Fill="Transparent" />
|
||||
<Grid
|
||||
Grid.Row="0"
|
||||
x:Name="TitleBarContents"
|
||||
Height="{Binding CoreTitleBarHeight, Mode=OneWay}"
|
||||
Margin="{Binding CoreTitleBarPadding, Mode=OneWay}"
|
||||
SizeChanged="Grid_SizeChanged">
|
||||
Margin="{Binding CoreTitleBarPadding, Mode=OneWay}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button
|
||||
x:Name="Hamburger"
|
||||
Height="32"
|
||||
Style="{StaticResource TitleBarButtonStyle}">
|
||||
<Button.Content>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="" />
|
||||
</Viewbox>
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
Width="160"
|
||||
Command="{x:Bind ViewModel.AddTerminalCommand}"
|
||||
Text="New tab">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<SymbolIcon Symbol="Add" />
|
||||
</MenuFlyoutItem.Icon>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem
|
||||
Width="160"
|
||||
Command="{x:Bind ViewModel.ShowSettingsCommand}"
|
||||
Text="Settings">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<SymbolIcon Symbol="Setting" />
|
||||
</MenuFlyoutItem.Icon>
|
||||
</MenuFlyoutItem>
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Grid.Column="1"
|
||||
IsHitTestVisible="False"
|
||||
Style="{StaticResource WindowTitleTextBlockStyle}"
|
||||
Text="{x:Bind ViewModel.Title, Mode=OneWay}"
|
||||
Visibility="{x:Bind ViewModel.Terminals.Count, Mode=OneWay, Converter={StaticResource OneToVisibleConverter}}" />
|
||||
<ListView
|
||||
x:Name="Tabs"
|
||||
Grid.Column="0"
|
||||
AllowDrop="True"
|
||||
CanDragItems="True"
|
||||
CanReorderItems="True"
|
||||
ItemsSource="{x:Bind ViewModel.Terminals}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Auto"
|
||||
ScrollViewer.HorizontalScrollMode="Auto"
|
||||
Text="{x:Bind ViewModel.SelectedTerminal.Title, Mode=OneWay}"
|
||||
Visibility="{x:Bind ViewModel.ShowTabsOnTop, Mode=OneWay, Converter={StaticResource FalseToVisibleConverter}}" />
|
||||
<views:TabBar
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
AddCommand="{x:Bind ViewModel.AddTerminalCommand}"
|
||||
ItemsSource="{x:Bind ViewModel.Terminals, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind ViewModel.SelectedTerminal, Mode=TwoWay}"
|
||||
Visibility="{x:Bind ViewModel.Terminals.Count, Mode=OneWay, Converter={StaticResource OneToCollapsedConverter}}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="viewmodels:TerminalViewModel">
|
||||
<Grid
|
||||
Height="32"
|
||||
Margin="0"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Interactivity:Interaction.Behaviors>
|
||||
<behaviors:MiddleClickBehavior>
|
||||
<behaviors:MiddleClickBehavior.Actions>
|
||||
<core:InvokeCommandAction Command="{x:Bind CloseCommand}" />
|
||||
</behaviors:MiddleClickBehavior.Actions>
|
||||
</behaviors:MiddleClickBehavior>
|
||||
</Interactivity:Interaction.Behaviors>
|
||||
<Border
|
||||
Grid.ColumnSpan="3"
|
||||
Height="3"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="{ThemeResource SystemAccentColor}"
|
||||
Visibility="{x:Bind IsUnderlined, Mode=OneWay, Converter={StaticResource TrueToVisibleConverter}}" />
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="12,8,6,0"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Title, Mode=OneWay}" />
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Width="32"
|
||||
Command="{x:Bind CloseCommand}"
|
||||
Style="{StaticResource TitleBarButtonStyle}"
|
||||
ToolTipService.ToolTip="Close">
|
||||
<Viewbox Width="12" Height="12">
|
||||
<SymbolIcon Symbol="Cancel" />
|
||||
</Viewbox>
|
||||
</Button>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="MinWidth" Value="24" />
|
||||
<Setter Property="MinHeight" Value="32" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
||||
</Style>
|
||||
</ListView.ItemContainerStyle>
|
||||
<ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<ItemsStackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListView.ItemsPanel>
|
||||
</ListView>
|
||||
<StackPanel
|
||||
x:Name="TitleBarButtons"
|
||||
Grid.Column="2"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Command="{x:Bind ViewModel.AddTerminalCommand}"
|
||||
Style="{StaticResource TitleBarButtonStyle}"
|
||||
ToolTipService.ToolTip="New Tab">
|
||||
<Viewbox Width="12" Height="12">
|
||||
<SymbolIcon Symbol="Add" />
|
||||
</Viewbox>
|
||||
</Button>
|
||||
<Button
|
||||
HorizontalAlignment="Right"
|
||||
Command="{x:Bind ViewModel.ShowSettingsCommand}"
|
||||
Style="{StaticResource TitleBarButtonStyle}"
|
||||
ToolTipService.ToolTip="Settings">
|
||||
<Viewbox Width="12" Height="12">
|
||||
<SymbolIcon Symbol="Setting" />
|
||||
</Viewbox>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
Visibility="{x:Bind ViewModel.ShowTabsOnTop, Mode=OneWay}" />
|
||||
</Grid>
|
||||
<ContentControl
|
||||
x:Name="TerminalContainer"
|
||||
@@ -139,5 +83,12 @@
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Content="{x:Bind ViewModel.SelectedTerminal, Mode=OneWay, Converter={StaticResource TerminalViewModelToViewConverter}}" />
|
||||
<views:TabBar
|
||||
Grid.Row="2"
|
||||
HorizontalAlignment="Left"
|
||||
AddCommand="{x:Bind ViewModel.AddTerminalCommand}"
|
||||
ItemsSource="{x:Bind ViewModel.Terminals, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind ViewModel.SelectedTerminal, Mode=TwoWay}"
|
||||
Visibility="{x:Bind ViewModel.ShowTabsOnBottom, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -2,7 +2,6 @@
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using System.ComponentModel;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
@@ -84,7 +83,6 @@ namespace FluentTerminal.App.Views
|
||||
UpdateLayoutMetrics();
|
||||
}
|
||||
|
||||
|
||||
private void UpdateLayoutMetrics()
|
||||
{
|
||||
if (PropertyChanged != null)
|
||||
@@ -93,13 +91,5 @@ namespace FluentTerminal.App.Views
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(CoreTitleBarPadding)));
|
||||
}
|
||||
}
|
||||
|
||||
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (sender is Grid grid)
|
||||
{
|
||||
Tabs.MaxWidth = grid.ActualWidth - grid.ColumnDefinitions[2].ActualWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,14 @@
|
||||
ToolTipService.ToolTip="Keybindings" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
<NavigationViewItem Content="Mouse" Tag="mouse">
|
||||
<NavigationViewItem.Icon>
|
||||
<FontIcon
|
||||
FontFamily="/Assets/settingsicons.ttf#settingsicons"
|
||||
Glyph="g"
|
||||
ToolTipService.ToolTip="Keybindings" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
<NavigationViewItem Content="Themes" Tag="themes">
|
||||
<NavigationViewItem.Icon>
|
||||
<FontIcon
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using FluentTerminal.App.Utilities;
|
||||
using FluentTerminal.App.ViewModels;
|
||||
using FluentTerminal.App.Views.SettingsPages;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.Foundation;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.Core.Preview;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
using FluentTerminal.App.Utilities;
|
||||
|
||||
namespace FluentTerminal.App.Views
|
||||
{
|
||||
@@ -106,6 +103,10 @@ namespace FluentTerminal.App.Views
|
||||
case "keyBindings":
|
||||
ContentFrame.Navigate(typeof(KeyBindingSettings), ViewModel.KeyBindings);
|
||||
break;
|
||||
|
||||
case "mouse":
|
||||
ContentFrame.Navigate(typeof(MouseSettings), ViewModel.Mouse);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,23 +34,67 @@
|
||||
Label="Restore Defaults" />
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
<StackPanel Grid.Row="2" Margin="24,0,0,0">
|
||||
<TextBlock Margin="0,0,0,8" Text="Open new terminals as" />
|
||||
<RadioButton Content="Tabs" IsChecked="{x:Bind ViewModel.TabIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton
|
||||
Margin="0,0,0,24"
|
||||
Content="Windows"
|
||||
IsChecked="{x:Bind ViewModel.WindowIsSelected, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
Margin="0,0,0,24"
|
||||
Header="Underline selected tab"
|
||||
IsOn="{x:Bind ViewModel.UnderlineSelectedTab, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
Margin="0,0,0,24"
|
||||
Header="Ask before closing windows"
|
||||
IsOn="{x:Bind ViewModel.ConfirmClosingWindows, Mode=TwoWay}" />
|
||||
<ToggleSwitch Header="Ask before closing tabs" IsOn="{x:Bind ViewModel.ConfirmClosingTabs, Mode=TwoWay}" />
|
||||
|
||||
</StackPanel>
|
||||
<ScrollViewer Grid.Row="2" Margin="24,0,0,0">
|
||||
<StackPanel>
|
||||
<ToggleSwitch
|
||||
Header="Run on startup"
|
||||
IsEnabled="{x:Bind ViewModel.CanEnableStartupTask, Mode=OneWay}"
|
||||
IsOn="{x:Bind ViewModel.StartupTaskEnabled, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Foreground="Red"
|
||||
Text="{x:Bind ViewModel.StartupTaskErrorMessage, Mode=OneWay}"
|
||||
Visibility="{x:Bind ViewModel.CanEnableStartupTask, Mode=OneWay, Converter={StaticResource FalseToVisibleConverter}}" />
|
||||
<TextBlock Margin="0,24,0,8" Text="Open new terminals as" />
|
||||
<RadioButton
|
||||
Content="Tabs"
|
||||
GroupName="NewTerminalLocation"
|
||||
IsChecked="{x:Bind ViewModel.TabIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton
|
||||
Margin="0,0,0,24"
|
||||
Content="Windows"
|
||||
GroupName="NewTerminalLocation"
|
||||
IsChecked="{x:Bind ViewModel.WindowIsSelected, Mode=TwoWay}" />
|
||||
<TextBlock Margin="0,0,0,8" Text="Show tabs on" />
|
||||
<RadioButton
|
||||
Content="Top"
|
||||
GroupName="TabsPosition"
|
||||
IsChecked="{x:Bind ViewModel.TopIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton
|
||||
Margin="0,0,0,24"
|
||||
Content="Bottom"
|
||||
GroupName="TabsPosition"
|
||||
IsChecked="{x:Bind ViewModel.BottomIsSelected, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
Margin="0,0,0,24"
|
||||
Header="Always show tabs"
|
||||
IsOn="{x:Bind ViewModel.AlwaysShowTabs, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
Margin="0,0,0,24"
|
||||
Header="Underline selected tab"
|
||||
IsOn="{x:Bind ViewModel.UnderlineSelectedTab, Mode=TwoWay}" />
|
||||
<TextBlock Margin="0,0,0,8" Text="Color on inactive tabs" />
|
||||
<RadioButton
|
||||
Content="Background"
|
||||
GroupName="InactiveTabColorMode"
|
||||
IsChecked="{x:Bind ViewModel.BackgroundIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton
|
||||
Margin="0,0,0,24"
|
||||
Content="Underline"
|
||||
GroupName="InactiveTabColorMode"
|
||||
IsChecked="{x:Bind ViewModel.UnderlinedIsSelected, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
Margin="0,0,0,24"
|
||||
Header="Ask before closing windows"
|
||||
IsOn="{x:Bind ViewModel.ConfirmClosingWindows, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
Margin="0,0,0,24"
|
||||
Header="Ask before closing tabs"
|
||||
IsOn="{x:Bind ViewModel.ConfirmClosingTabs, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
Margin="0,0,0,24"
|
||||
Header="Show new output indicator on background tabs"
|
||||
IsOn="{x:Bind ViewModel.ShowNewOutputIndicator, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
||||
</Page>
|
||||
@@ -18,7 +18,8 @@ namespace FluentTerminal.App.Views.SettingsPages
|
||||
if (e.Parameter is GeneralPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
ViewModel.OnNavigatedTo();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,4 +52,4 @@
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
||||
</Page>
|
||||
@@ -35,4 +35,4 @@ namespace FluentTerminal.App.Views.SettingsPages
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<Page
|
||||
x:Class="FluentTerminal.App.Views.SettingsPages.MouseSettings"
|
||||
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"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<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="Mouse" />
|
||||
<CommandBar
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource SystemControlBackgroundAltHighBrush}"
|
||||
DefaultLabelPosition="Right">
|
||||
<AppBarButton
|
||||
Command="{x:Bind ViewModel.RestoreDefaultsCommand}"
|
||||
Icon="Undo"
|
||||
Label="Restore Defaults" />
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
<ScrollViewer Grid.Row="2" Margin="24,0,0,0">
|
||||
<StackPanel>
|
||||
<ToggleSwitch
|
||||
Margin="0,0,0,24"
|
||||
Header="Copy on select"
|
||||
IsOn="{x:Bind ViewModel.CopyOnSelect, Mode=TwoWay}" />
|
||||
<TextBlock Margin="0,0,0,8" Text="Middle button action" />
|
||||
<RadioButton
|
||||
Content="Nothing"
|
||||
GroupName="MiddleButton"
|
||||
IsChecked="{x:Bind ViewModel.MouseMiddleClickNoneIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton
|
||||
Content="Context menu"
|
||||
GroupName="MiddleButton"
|
||||
IsChecked="{x:Bind ViewModel.MouseMiddleClickContextMenuIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton
|
||||
Margin="0,0,0,24"
|
||||
Content="Paste"
|
||||
GroupName="MiddleButton"
|
||||
IsChecked="{x:Bind ViewModel.MouseMiddleClickPasteIsSelected, Mode=TwoWay}" />
|
||||
<TextBlock Margin="0,0,0,8" Text="Right button action" />
|
||||
<RadioButton
|
||||
Content="Nothing"
|
||||
GroupName="RightButton"
|
||||
IsChecked="{x:Bind ViewModel.MouseRightClickNoneIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton
|
||||
Content="Context menu"
|
||||
GroupName="RightButton"
|
||||
IsChecked="{x:Bind ViewModel.MouseRightClickContextMenuIsSelected, Mode=TwoWay}" />
|
||||
<RadioButton
|
||||
Margin="0,0,0,24"
|
||||
Content="Paste"
|
||||
GroupName="RightButton"
|
||||
IsChecked="{x:Bind ViewModel.MouseRightClickPasteIsSelected, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
||||
Loaded 100 of 180 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user