├── .gitattributes ├── .github ├── PublishAllPlatforms.ps1 └── workflows │ ├── createrelease.yml │ └── dotnetcore.yml ├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── Installers └── MacOsX │ └── SQRL.app.zip ├── LICENSE ├── README.md ├── SQRLCommon ├── Assets │ └── Localization │ │ └── Flags │ │ ├── default_16.png │ │ ├── germany_16.png │ │ └── united_states_16.png ├── AvaloniaExtensions │ ├── CopyPasteTextBox.cs │ ├── EnumBooleanConverter.cs │ ├── LocalizationExtension.cs │ ├── MenuItemViewModel.cs │ ├── StringUppercaseConverter.cs │ └── WindowExtensions.cs ├── Models │ ├── CommonUtils.cs │ ├── GitHubHelper.cs │ ├── GithubReleases.cs │ ├── PathConf.cs │ └── SystemAndShellUtils.cs └── SQRLCommon.csproj ├── SQRLDotNetClient.sln ├── SQRLDotNetClientUI ├── App.xaml ├── App.xaml.cs ├── Assets │ ├── Fonts │ │ ├── SpaceMono-Bold.ttf │ │ ├── SpaceMono-BoldItalic.ttf │ │ ├── SpaceMono-Italic.ttf │ │ ├── SpaceMono-Regular.ttf │ │ ├── UbuntuMono-Bold.ttf │ │ └── UbuntuMono-Regular.ttf │ ├── Icons │ │ ├── MenuIcons │ │ │ ├── About_16x.png │ │ │ ├── AddUser_16x.png │ │ │ ├── CheckOut_16x.png │ │ │ ├── DeleteUser_16x.png │ │ │ ├── Exit_16x.png │ │ │ ├── Export_16x.png │ │ │ ├── IdentitySettings_16x.png │ │ │ ├── Import_16x.png │ │ │ ├── Key_16x.png │ │ │ ├── Localize_16x.png │ │ │ ├── NewFile_16x.png │ │ │ ├── Password_16x.png │ │ │ ├── Settings_16x.png │ │ │ ├── SwitchIdentity_16x.png │ │ │ ├── Uninstall_16x.png │ │ │ └── db_16x.png │ │ ├── error.png │ │ ├── ok.png │ │ ├── pdf_16.png │ │ ├── question.png │ │ └── warning.png │ ├── Linux_Installer.png │ ├── Localization │ │ └── localization.json │ ├── MacOsx_Error2.png │ ├── MacOsx_Installer.png │ ├── MacOsx_InstallerPrompt.png │ ├── Mac_AllowAnyways.png │ ├── Mac_Error1.png │ ├── Mac_SecurityAndPrivacy.png │ ├── NewIdentitySetup.gif │ ├── SQRL_InAction.gif │ ├── SQRL_icon_light_128.png │ ├── SQRL_icon_light_16.png │ ├── SQRL_icon_light_256.png │ ├── SQRL_icon_light_32.png │ ├── SQRL_icon_light_64.png │ ├── SQRL_icon_normal.svg │ ├── SQRL_icon_normal_128.png │ ├── SQRL_icon_normal_16.png │ ├── SQRL_icon_normal_256.png │ ├── SQRL_icon_normal_32.png │ ├── SQRL_icon_normal_64.png │ ├── VL.png │ ├── WinInstaller.png │ ├── WinInstallerPrompt.png │ ├── WinRunAnyways.png │ ├── avalonia-logo.ico │ ├── error.ico │ ├── sqrl_icon_normal_256.ico │ ├── sqrl_icon_normal_256_32_icon.ico │ └── sqrl_icon_normal_48_icon.ico ├── Behaviors │ └── FocusOnAttached.cs ├── DB │ ├── DBContext │ │ └── SQRLDBContext.cs │ ├── Migrations │ │ ├── 20200219133551_InitialCreate.Designer.cs │ │ ├── 20200219133551_InitialCreate.cs │ │ ├── 20200418165401_AddStartMinimized.Designer.cs │ │ ├── 20200418165401_AddStartMinimized.cs │ │ └── SQRLDBContextModelSnapshot.cs │ └── Models │ │ ├── Identity.cs │ │ └── UserData.cs ├── IPC │ └── IPCServer.cs ├── Models │ ├── AppSettings.cs │ ├── INotifyIcon.cs │ ├── ISystemEventNotifier.cs │ ├── IdentityManager.cs │ ├── PasswordStrengthMeter.cs │ ├── PdfHelper.cs │ ├── QuickPassManager.cs │ └── SystemEventArgs.cs ├── Platform │ ├── Implementation.cs │ ├── Linux │ │ ├── LinuxTrayIcon.cs │ │ ├── NotifyIcon.cs │ │ └── SystemEventNotifier.cs │ ├── OSX │ │ ├── AppDelegate.cs │ │ ├── NotifyIcon.cs │ │ └── SystemEventNotifier.cs │ └── Win │ │ ├── Interop │ │ ├── NativeWindow.cs │ │ └── UnmanagedMethods.cs │ │ ├── NotifyIcon.cs │ │ └── SystemEventNotifier.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── SQRLDotNetClientUI.csproj ├── ViewLocator.cs ├── ViewModels │ ├── AboutViewModel.cs │ ├── AppSettingsViewModel.cs │ ├── AskViewModel.cs │ ├── AuthenticationViewModel.cs │ ├── ChangePasswordViewModel.cs │ ├── ExportIdentityViewModel.cs │ ├── IdentitySettingsViewModel.cs │ ├── ImportIdentitySetupViewModel.cs │ ├── ImportIdentityViewModel.cs │ ├── InputSecretDialogViewModel.cs │ ├── MainMenuViewModel.cs │ ├── MainWindowViewModel.cs │ ├── MessageBoxViewModel.cs │ ├── NewIdentityVerifyViewModel.cs │ ├── NewIdentityViewModel.cs │ ├── ProgressDialogViewModel.cs │ ├── ReKeyViewModel.cs │ ├── SelectIdentityViewModel.cs │ └── ViewModelBase.cs ├── Views │ ├── AboutView.xaml │ ├── AboutView.xaml.cs │ ├── AppSettingsView.xaml │ ├── AppSettingsView.xaml.cs │ ├── AskView.xaml │ ├── AskView.xaml.cs │ ├── AuthenticationView.xaml │ ├── AuthenticationView.xaml.cs │ ├── ChangePasswordView.xaml │ ├── ChangePasswordView.xaml.cs │ ├── ExportIdentityView.xaml │ ├── ExportIdentityView.xaml.cs │ ├── IdentitySettingsView.xaml │ ├── IdentitySettingsView.xaml.cs │ ├── ImportIdentitySetupView.xaml │ ├── ImportIdentitySetupView.xaml.cs │ ├── ImportIdentityView.xaml │ ├── ImportIdentityView.xaml.cs │ ├── InputSecretDialogView.xaml │ ├── InputSecretDialogView.xaml.cs │ ├── MainMenuView.xaml │ ├── MainMenuView.xaml.cs │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── MessageBoxView.xaml │ ├── MessageBoxView.xaml.cs │ ├── NewIdentityVerifyView.xaml │ ├── NewIdentityVerifyView.xaml.cs │ ├── NewIdentityView.xaml │ ├── NewIdentityView.xaml.cs │ ├── NewPasswordWidget.xaml │ ├── NewPasswordWidget.xaml.cs │ ├── ProgressDialogView.xaml │ ├── ProgressDialogView.xaml.cs │ ├── ReKeyView.xaml │ ├── ReKeyView.xaml.cs │ ├── SelectIdentityView.xaml │ └── SelectIdentityView.xaml.cs └── nuget.config ├── SQRLPlatformAwareInstaller ├── App.xaml ├── App.xaml.cs ├── Assets │ ├── Fonts │ │ ├── SpaceMono-Bold.ttf │ │ ├── SpaceMono-BoldItalic.ttf │ │ ├── SpaceMono-Italic.ttf │ │ └── SpaceMono-Regular.ttf │ ├── Icons │ │ ├── alert-triangle.png │ │ └── alert-triangle.svg │ ├── Localization │ │ └── localization.json │ ├── SQRLPlatformAwareInstaller_linux.policy │ ├── SQRL_InAction.gif │ ├── SQRL_icon_light_128.png │ ├── SQRL_icon_light_16.png │ ├── SQRL_icon_light_256.png │ ├── SQRL_icon_light_32.png │ ├── SQRL_icon_light_64.png │ ├── SQRL_icon_normal.svg │ ├── SQRL_icon_normal_128.png │ ├── SQRL_icon_normal_16.png │ ├── SQRL_icon_normal_256.png │ ├── SQRL_icon_normal_32.png │ ├── SQRL_icon_normal_64.png │ ├── VL.png │ ├── avalonia-logo.ico │ ├── crown.png │ ├── key.png │ ├── linux.png │ ├── mac.png │ ├── sqrl_icon_normal_256.ico │ ├── sqrl_icon_normal_256_32_icon.ico │ ├── sqrl_icon_normal_48_icon.ico │ ├── unknown.png │ └── windows.png ├── Models │ ├── CommandLineArgs.cs │ ├── IInstaller.cs │ ├── Inventory.cs │ └── Uninstaller.cs ├── Platform │ ├── Implementation.cs │ ├── Linux │ │ └── Installer.cs │ ├── OSX │ │ └── Installer.cs │ └── Windows │ │ ├── Installer.cs │ │ ├── ShellLink.cs │ │ └── VcRedistHelper.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── SQRLPlatformAwareInstaller.csproj ├── Utils.cs ├── ViewLocator.cs ├── ViewModels │ ├── InstallationCompleteViewModel.cs │ ├── MainInstallViewModel.cs │ ├── MainWindowViewModel.cs │ ├── RootBailViewModel.cs │ ├── UninstallViewModel.cs │ ├── VersionSelectorViewModel.cs │ └── ViewModelBase.cs ├── Views │ ├── InstallationCompleteView.xaml │ ├── InstallationCompleteView.xaml.cs │ ├── MainInstallView.xaml │ ├── MainInstallView.xaml.cs │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── RootBailView.xaml │ ├── RootBailView.xaml.cs │ ├── UninstallView.xaml │ ├── UninstallView.xaml.cs │ ├── VersionSelectorView.xaml │ └── VersionSelectorView.xaml.cs ├── app.manifest └── nuget.config ├── SQRLUtilLibTest ├── SQRLCryptoTests.cs ├── SQRLIdentityTests.cs └── SQRLUtilLibTest.csproj ├── SQRLUtilsLib ├── Resources │ ├── CPS.html │ ├── SQRLClientDemo.gif │ └── sqrl_icon_normal_64.png ├── SQRL.cs ├── SQRLCPSServer.cs ├── SQRLIdentity.cs ├── SQRLIdentityOptions.cs ├── SQRLOptions.cs ├── SQRLServerResponse.cs └── SQRLUtilsLib.csproj └── Sodium.Core ├── CryptoHash.cs ├── DetachedBox.cs ├── Exceptions ├── AdditionalDataOutOfRangeException.cs ├── BytesOutOfRangeException.cs ├── KeyOutOfRangeException.cs ├── MacOutOfRangeException.cs ├── NonceOutOfRangeException.cs ├── PersonalOutOfRangeException.cs ├── SaltOutOfRangeException.cs ├── SeedOutOfRangeException.cs └── SignatureOutOfRangeException .cs ├── GenericHash.cs ├── GenericHashAlgorithm.cs ├── KeyPair.cs ├── OneTimeAuth.cs ├── PasswordHash.cs ├── PublicKeyAuth.cs ├── PublicKeyBox.cs ├── ScalarMult.cs ├── SealedPublicKeyBox.cs ├── SecretAead.cs ├── SecretAeadAes.cs ├── SecretAeadChaCha20Poly1305.cs ├── SecretAeadChaCha20Poly1305IETF.cs ├── SecretAeadXChaCha20Poly1305.cs ├── SecretBox.cs ├── SecretKeyAuth.cs ├── ShortHash.cs ├── Sodium.Core.ForSqrl.csproj ├── SodiumCore.cs ├── SodiumLibrary.cs ├── StreamEncryption.cs └── Utilities.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/workflows/createrelease.yml: -------------------------------------------------------------------------------- 1 | name: Create and Publish Release 2 | 3 | on: 4 | milestone: 5 | types: [closed] 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: windows-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v1 14 | - name: Setup .NET Core SDK 15 | uses: actions/setup-dotnet@v1.4.0 16 | with: 17 | # SDK version to use. Example: 2.2.104 18 | dotnet-version: 3.1.100 # optional 19 | - name: Create Releases Assets 20 | run: | 21 | powershell .github/releases.ps1 -token ${{secrets.TOKEN}} -milestone ${{ github.event.milestone.title }} -milestonedesc ${{ github.event.milestone.description }} 22 | -------------------------------------------------------------------------------- /.github/workflows/dotnetcore.yml: -------------------------------------------------------------------------------- 1 | name: Build & Test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Setup .NET Core SDK 13 | uses: actions/setup-dotnet@v1.4.0 14 | with: 15 | # SDK version to use. Example: 2.2.104 16 | dotnet-version: 3.1.100 # optional 17 | - name: Build with dotnet 18 | run: dotnet build --configuration Release 19 | - name: Test with dotnet 20 | run: dotnet test 21 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to find out which attributes exist for C# debugging 3 | // Use hover for the description of the existing attributes 4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (Client)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/SQRLDotNetClientUI/bin/Debug/netcoreapp3.1/SQRLDotNetClientUI.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/SQRLDotNetClientUI", 16 | // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console 17 | "console": "internalConsole", 18 | "stopAtEntry": false 19 | }, 20 | { 21 | "name": ".NET Core Launch (Installer)", 22 | "type": "coreclr", 23 | "request": "launch", 24 | "preLaunchTask": "build", 25 | // If you have changed target frameworks, make sure to update the program path. 26 | "program": "${workspaceFolder}/SQRLPlatformAwareInstaller/bin/Debug/netcoreapp3.1/SQRLPlatformAwareInstaller.dll", 27 | "args": [], 28 | "cwd": "${workspaceFolder}/SQRLPlatformAwareInstaller", 29 | // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console 30 | "console": "internalConsole", 31 | "stopAtEntry": false 32 | }, 33 | { 34 | "name": ".NET Core Attach", 35 | "type": "coreclr", 36 | "request": "attach", 37 | "processId": "${command:pickProcess}" 38 | } 39 | ] 40 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/SQRLDotNetClientUI/SQRLDotNetClientUI.csproj", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "publish", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "publish", 22 | "${workspaceFolder}/SQRLDotNetClientUI/SQRLDotNetClientUI.csproj", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "watch", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": [ 33 | "watch", 34 | "run", 35 | "${workspaceFolder}/SQRLDotNetClientUI/SQRLDotNetClientUI.csproj", 36 | "/property:GenerateFullPaths=true", 37 | "/consoleloggerparameters:NoSummary" 38 | ], 39 | "problemMatcher": "$msCompile" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /Installers/MacOsX/SQRL.app.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/Installers/MacOsX/SQRL.app.zip -------------------------------------------------------------------------------- /SQRLCommon/Assets/Localization/Flags/default_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLCommon/Assets/Localization/Flags/default_16.png -------------------------------------------------------------------------------- /SQRLCommon/Assets/Localization/Flags/germany_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLCommon/Assets/Localization/Flags/germany_16.png -------------------------------------------------------------------------------- /SQRLCommon/Assets/Localization/Flags/united_states_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLCommon/Assets/Localization/Flags/united_states_16.png -------------------------------------------------------------------------------- /SQRLCommon/AvaloniaExtensions/EnumBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Data.Converters; 2 | using System; 3 | 4 | 5 | namespace SQRLCommon.AvaloniaExtensions 6 | { 7 | public class EnumBooleanConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 10 | { 11 | string parameterString = parameter.ToString(); 12 | 13 | object parameterValue = Enum.Parse(value.GetType(), parameterString); 14 | 15 | return parameterValue.Equals(value); 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 19 | { 20 | string parameterString = parameter.ToString(); 21 | 22 | return Enum.Parse(targetType, parameterString); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SQRLCommon/AvaloniaExtensions/MenuItemViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Windows.Input; 5 | 6 | namespace SQRLCommon.AvaloniaExtensions 7 | { 8 | public class MenuItemViewModel 9 | { 10 | public string Header { get; set; } 11 | public ICommand Command { get; set; } 12 | public object CommandParameter { get; set; } 13 | public IList Items { get; set; } 14 | 15 | public override string ToString() 16 | { 17 | return Header; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SQRLCommon/AvaloniaExtensions/StringUppercaseConverter.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Data.Converters; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace SQRLCommon.AvaloniaExtensions 7 | { 8 | public class StringUppercaseConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 11 | { 12 | return value.ToString().ToUpper(); 13 | } 14 | 15 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 16 | { 17 | return value.ToString().ToLower(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SQRLCommon/AvaloniaExtensions/WindowExtensions.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using System; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace SQRLCommon.AvaloniaExtensions 6 | { 7 | /// 8 | /// Provides extension methods for the Avalonia Window class, mainly 9 | /// providing workarounds or bugfixes. 10 | /// 11 | public static class WindowExtensions 12 | { 13 | private static readonly bool IsWin32NT = Environment.OSVersion.Platform == PlatformID.Win32NT; 14 | 15 | [DllImport("user32.dll")] 16 | [return: MarshalAs(UnmanagedType.Bool)] 17 | private static extern bool SetForegroundWindow(IntPtr hWnd); 18 | 19 | /// 20 | /// Activates the window (brings it into the foreground). This is a bugfix 21 | /// for https://github.com/AvaloniaUI/Avalonia/issues/2975. 22 | /// 23 | /// 24 | public static void ActivateWorkaround(this Window window) 25 | { 26 | if (ReferenceEquals(window, null)) throw new ArgumentNullException(nameof(window)); 27 | 28 | // Call default Activate() anyway. 29 | window.Activate(); 30 | 31 | // Skip workaround for non-windows platforms. 32 | if (!IsWin32NT) return; 33 | 34 | var platformImpl = window.PlatformImpl; 35 | if (ReferenceEquals(platformImpl, null)) return; 36 | 37 | var platformHandle = platformImpl.Handle; 38 | if (ReferenceEquals(platformHandle, null)) return; 39 | 40 | var handle = platformHandle.Handle; 41 | if (IntPtr.Zero == handle) return; 42 | 43 | try 44 | { 45 | SetForegroundWindow(handle); 46 | } 47 | catch {} 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /SQRLCommon/SQRLCommon.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/App.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Fonts/SpaceMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Fonts/SpaceMono-Bold.ttf -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Fonts/SpaceMono-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Fonts/SpaceMono-BoldItalic.ttf -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Fonts/SpaceMono-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Fonts/SpaceMono-Italic.ttf -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Fonts/UbuntuMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Fonts/UbuntuMono-Bold.ttf -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Fonts/UbuntuMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Fonts/UbuntuMono-Regular.ttf -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/About_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/About_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/AddUser_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/AddUser_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/CheckOut_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/CheckOut_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/DeleteUser_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/DeleteUser_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/Exit_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/Exit_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/Export_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/Export_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/IdentitySettings_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/IdentitySettings_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/Import_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/Import_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/Key_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/Key_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/Localize_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/Localize_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/NewFile_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/NewFile_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/Password_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/Password_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/Settings_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/Settings_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/SwitchIdentity_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/SwitchIdentity_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/Uninstall_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/Uninstall_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/MenuIcons/db_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/MenuIcons/db_16x.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/error.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/ok.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/pdf_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/pdf_16.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/question.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Icons/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Icons/warning.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Linux_Installer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Linux_Installer.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/MacOsx_Error2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/MacOsx_Error2.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/MacOsx_Installer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/MacOsx_Installer.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/MacOsx_InstallerPrompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/MacOsx_InstallerPrompt.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Mac_AllowAnyways.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Mac_AllowAnyways.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Mac_Error1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Mac_Error1.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/Mac_SecurityAndPrivacy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/Mac_SecurityAndPrivacy.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/NewIdentitySetup.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/NewIdentitySetup.gif -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/SQRL_InAction.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/SQRL_InAction.gif -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/SQRL_icon_light_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/SQRL_icon_light_128.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/SQRL_icon_light_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/SQRL_icon_light_16.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/SQRL_icon_light_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/SQRL_icon_light_256.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/SQRL_icon_light_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/SQRL_icon_light_32.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/SQRL_icon_light_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/SQRL_icon_light_64.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/SQRL_icon_normal_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/SQRL_icon_normal_128.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/SQRL_icon_normal_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/SQRL_icon_normal_16.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/SQRL_icon_normal_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/SQRL_icon_normal_256.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/SQRL_icon_normal_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/SQRL_icon_normal_32.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/SQRL_icon_normal_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/SQRL_icon_normal_64.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/VL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/VL.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/WinInstaller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/WinInstaller.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/WinInstallerPrompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/WinInstallerPrompt.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/WinRunAnyways.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/WinRunAnyways.png -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/avalonia-logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/avalonia-logo.ico -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/error.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/error.ico -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/sqrl_icon_normal_256.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/sqrl_icon_normal_256.ico -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/sqrl_icon_normal_256_32_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/sqrl_icon_normal_256_32_icon.ico -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Assets/sqrl_icon_normal_48_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/919925300dc73db7600b16b051387575c2557304/SQRLDotNetClientUI/Assets/sqrl_icon_normal_48_icon.ico -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Behaviors/FocusOnAttached.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Threading; 3 | using Avalonia.Xaml.Interactivity; 4 | 5 | namespace SQRLDotNetClientUI.Behaviors 6 | { 7 | /// 8 | /// This behaviour can be set in XAML to give initial focus 9 | /// to a UI control. 10 | /// 11 | public class FocusOnAttached: Behavior 12 | { 13 | protected override void OnAttached() 14 | { 15 | base.OnAttached(); 16 | 17 | Dispatcher.UIThread.Post(() => 18 | { 19 | AssociatedObject.Focus(); 20 | }, DispatcherPriority.Layout); 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/DB/DBContext/SQRLDBContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Serilog; 3 | using SQRLCommon.Models; 4 | using SQRLDotNetClientUI.DB.Models; 5 | using System; 6 | using System.IO; 7 | 8 | namespace SQRLDotNetClientUI.DB.DBContext 9 | { 10 | public sealed class SQRLDBContext: DbContext 11 | { 12 | private static SQRLDBContext _instance; 13 | 14 | /// 15 | /// The constructor is private, use the property 16 | /// to get the singletion class instance. 17 | /// 18 | private SQRLDBContext():base() 19 | { 20 | 21 | } 22 | 23 | /// 24 | /// Allows us to dispose the singleton instance if needed to reload the DB File 25 | /// 26 | public static void DisposeDB() 27 | { 28 | _instance.Dispose(); 29 | _instance = null; 30 | } 31 | 32 | /// 33 | /// Gets the singleton SQRLDBContext instance. 34 | /// 35 | public static SQRLDBContext Instance 36 | { 37 | get 38 | { 39 | if (_instance == null) _instance = new SQRLDBContext(); 40 | return _instance; 41 | } 42 | } 43 | 44 | /// 45 | /// Used for saving user state like last loaded identity etc. 46 | /// 47 | public DbSet UserData { get; set; } 48 | 49 | /// 50 | /// The list of imported identities. 51 | /// 52 | public DbSet Identities { get; set; } 53 | 54 | protected override void OnConfiguring(DbContextOptionsBuilder options) 55 | { 56 | if (!Directory.Exists(PathConf.ClientDBPath)) 57 | { 58 | Log.Information("DB directory did not exist, creating"); 59 | Directory.CreateDirectory(PathConf.ClientDBPath); 60 | } 61 | 62 | 63 | options.UseSqlite($"Data Source={PathConf.FullClientDbPath}"); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/DB/Migrations/20200219133551_InitialCreate.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using SQRLDotNetClientUI.DB.DBContext; 8 | 9 | namespace SQRLDotNetClientUI.Migrations 10 | { 11 | [DbContext(typeof(SQRLDBContext))] 12 | [Migration("20200219133551_InitialCreate")] 13 | partial class InitialCreate 14 | { 15 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 16 | { 17 | #pragma warning disable 612, 618 18 | modelBuilder 19 | .HasAnnotation("ProductVersion", "3.1.1"); 20 | 21 | modelBuilder.Entity("SQRLDotNetClientUI.DB.Models.Identity", b => 22 | { 23 | b.Property("UniqueId") 24 | .HasColumnType("TEXT"); 25 | 26 | b.Property("DataBytes") 27 | .HasColumnType("BLOB"); 28 | 29 | b.Property("GenesisId") 30 | .HasColumnType("TEXT"); 31 | 32 | b.Property("Name") 33 | .HasColumnType("TEXT"); 34 | 35 | b.HasKey("UniqueId"); 36 | 37 | b.ToTable("Identities"); 38 | }); 39 | 40 | modelBuilder.Entity("SQRLDotNetClientUI.DB.Models.UserData", b => 41 | { 42 | b.Property("Id") 43 | .ValueGeneratedOnAdd() 44 | .HasColumnType("INTEGER"); 45 | 46 | b.Property("LastLoadedIdentity") 47 | .HasColumnType("TEXT"); 48 | 49 | b.HasKey("Id"); 50 | 51 | b.ToTable("UserData"); 52 | }); 53 | #pragma warning restore 612, 618 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/DB/Migrations/20200219133551_InitialCreate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace SQRLDotNetClientUI.Migrations 5 | { 6 | public partial class InitialCreate : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.CreateTable( 11 | name: "Identities", 12 | columns: table => new 13 | { 14 | UniqueId = table.Column(nullable: false), 15 | GenesisId = table.Column(nullable: true), 16 | Name = table.Column(nullable: true), 17 | DataBytes = table.Column(nullable: true) 18 | }, 19 | constraints: table => 20 | { 21 | table.PrimaryKey("PK_Identities", x => x.UniqueId); 22 | }); 23 | 24 | migrationBuilder.CreateTable( 25 | name: "UserData", 26 | columns: table => new 27 | { 28 | Id = table.Column(nullable: false) 29 | .Annotation("Sqlite:Autoincrement", true), 30 | LastLoadedIdentity = table.Column(nullable: true) 31 | }, 32 | constraints: table => 33 | { 34 | table.PrimaryKey("PK_UserData", x => x.Id); 35 | }); 36 | } 37 | 38 | protected override void Down(MigrationBuilder migrationBuilder) 39 | { 40 | migrationBuilder.DropTable( 41 | name: "Identities"); 42 | 43 | migrationBuilder.DropTable( 44 | name: "UserData"); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/DB/Migrations/20200418165401_AddStartMinimized.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using SQRLDotNetClientUI.DB.DBContext; 8 | 9 | namespace SQRLDotNetClientUI.Migrations 10 | { 11 | [DbContext(typeof(SQRLDBContext))] 12 | [Migration("20200418165401_AddStartMinimized")] 13 | partial class AddStartMinimized 14 | { 15 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 16 | { 17 | #pragma warning disable 612, 618 18 | modelBuilder 19 | .HasAnnotation("ProductVersion", "3.1.3"); 20 | 21 | modelBuilder.Entity("SQRLDotNetClientUI.DB.Models.Identity", b => 22 | { 23 | b.Property("UniqueId") 24 | .HasColumnType("TEXT"); 25 | 26 | b.Property("DataBytes") 27 | .HasColumnType("BLOB"); 28 | 29 | b.Property("GenesisId") 30 | .HasColumnType("TEXT"); 31 | 32 | b.Property("Name") 33 | .HasColumnType("TEXT"); 34 | 35 | b.HasKey("UniqueId"); 36 | 37 | b.ToTable("Identities"); 38 | }); 39 | 40 | modelBuilder.Entity("SQRLDotNetClientUI.DB.Models.UserData", b => 41 | { 42 | b.Property("Id") 43 | .ValueGeneratedOnAdd() 44 | .HasColumnType("INTEGER"); 45 | 46 | b.Property("LastLoadedIdentity") 47 | .HasColumnType("TEXT"); 48 | 49 | b.Property("StartMinimized") 50 | .HasColumnType("INTEGER"); 51 | 52 | b.HasKey("Id"); 53 | 54 | b.ToTable("UserData"); 55 | }); 56 | #pragma warning restore 612, 618 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/DB/Migrations/20200418165401_AddStartMinimized.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | namespace SQRLDotNetClientUI.Migrations 4 | { 5 | public partial class AddStartMinimized : Migration 6 | { 7 | protected override void Up(MigrationBuilder migrationBuilder) 8 | { 9 | migrationBuilder.AddColumn( 10 | name: "StartMinimized", 11 | table: "UserData", 12 | nullable: false, 13 | defaultValue: false); 14 | } 15 | 16 | protected override void Down(MigrationBuilder migrationBuilder) 17 | { 18 | migrationBuilder.DropColumn( 19 | name: "StartMinimized", 20 | table: "UserData"); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/DB/Migrations/SQRLDBContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 6 | using SQRLDotNetClientUI.DB.DBContext; 7 | 8 | namespace SQRLDotNetClientUI.Migrations 9 | { 10 | [DbContext(typeof(SQRLDBContext))] 11 | partial class SQRLDBContextModelSnapshot : ModelSnapshot 12 | { 13 | protected override void BuildModel(ModelBuilder modelBuilder) 14 | { 15 | #pragma warning disable 612, 618 16 | modelBuilder 17 | .HasAnnotation("ProductVersion", "3.1.3"); 18 | 19 | modelBuilder.Entity("SQRLDotNetClientUI.DB.Models.Identity", b => 20 | { 21 | b.Property("UniqueId") 22 | .HasColumnType("TEXT"); 23 | 24 | b.Property("DataBytes") 25 | .HasColumnType("BLOB"); 26 | 27 | b.Property("GenesisId") 28 | .HasColumnType("TEXT"); 29 | 30 | b.Property("Name") 31 | .HasColumnType("TEXT"); 32 | 33 | b.HasKey("UniqueId"); 34 | 35 | b.ToTable("Identities"); 36 | }); 37 | 38 | modelBuilder.Entity("SQRLDotNetClientUI.DB.Models.UserData", b => 39 | { 40 | b.Property("Id") 41 | .ValueGeneratedOnAdd() 42 | .HasColumnType("INTEGER"); 43 | 44 | b.Property("LastLoadedIdentity") 45 | .HasColumnType("TEXT"); 46 | 47 | b.Property("StartMinimized") 48 | .HasColumnType("INTEGER"); 49 | 50 | b.HasKey("Id"); 51 | 52 | b.ToTable("UserData"); 53 | }); 54 | #pragma warning restore 612, 618 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/DB/Models/Identity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Text; 5 | 6 | namespace SQRLDotNetClientUI.DB.Models 7 | { 8 | /// 9 | /// This is a database model representing a SQRL identity record. 10 | /// 11 | public class Identity 12 | { 13 | /// 14 | /// The unique identifier of the identity. 15 | /// 16 | [Key] 17 | public string UniqueId { get; set; } 18 | 19 | /// 20 | /// The genesis identifier of the identity. 21 | /// 22 | public string GenesisId { get; set; } 23 | 24 | /// 25 | /// The identity's name. 26 | /// 27 | public string Name { get; set; } 28 | 29 | /// 30 | /// The identity's raw data bytes. 31 | /// 32 | public byte[] DataBytes { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/DB/Models/UserData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace SQRLDotNetClientUI.DB.Models 6 | { 7 | /// 8 | /// Stores user information such as the last loaded identity, etc. 9 | /// 10 | public class UserData 11 | { 12 | /// 13 | /// The database record id for the UserData. 14 | /// 15 | public int Id { get; set; } 16 | 17 | /// 18 | /// The id of the last loaded identity. 19 | /// 20 | public string LastLoadedIdentity { get; set; } 21 | 22 | /// 23 | /// Gets or sets a value that determines if the app should start 24 | /// minimized to the tray icon. 25 | /// 26 | public bool StartMinimized { get; set; } = false; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Models/INotifyIcon.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using System; 3 | 4 | namespace SQRLDotNetClientUI.Models 5 | { 6 | /// 7 | /// Represents a taskbar notification area icon (aka "tray icon") on Windows, 8 | /// and similar task panel notification icons on Linux and Mac. 9 | /// 10 | /// Platform-specific implementations for this interface can be found in 11 | /// SQRLDotNetClientUI.Platform.XXX. 12 | /// 13 | /// 14 | public interface INotifyIcon 15 | { 16 | /// 17 | /// Gets or sets the icon for the notify icon. Either a file system path 18 | /// or a resm: manifest resource path can be specified. 19 | /// 20 | public string IconPath { get; set; } 21 | 22 | /// 23 | /// Gets or sets the tooltip text for the notify icon. 24 | /// 25 | public string ToolTipText { get; set; } 26 | 27 | /// 28 | /// Gets or sets the context- (right-click)-menu for the notify icon. 29 | /// 30 | public ContextMenu ContextMenu { get; set; } 31 | 32 | /// 33 | /// Gets or sets if the notify icon is visible in the 34 | /// taskbar notification area or not. 35 | /// 36 | public bool Visible { get; set; } 37 | 38 | /// 39 | /// Removes the notify icon from the taskbar notification area. 40 | /// 41 | public void Remove(); 42 | 43 | /// 44 | /// This event is raised when a user clicks on the notification icon. 45 | /// 46 | public event EventHandler Click; 47 | 48 | /// 49 | /// This event is raised when a user doubleclicks on the notification icon. 50 | /// 51 | public event EventHandler DoubleClick; 52 | 53 | /// 54 | /// This event is raised when a user right-clicks on the notification icon. 55 | /// 56 | public event EventHandler RightClick; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Models/ISystemEventNotifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SQRLDotNetClientUI.Models 4 | { 5 | /// 6 | /// Provides access to system events that are relevant to the 7 | /// clearing of QuickPass-related data from RAM, like entering 8 | /// an idle state, logging off or entering a sleep or hilbernation 9 | /// state. 10 | /// 11 | /// Platform-specific implementations for this interface can be found in 12 | /// SQRLDotNetClientUI.Platform.XXX. 13 | /// 14 | /// 15 | public interface ISystemEventNotifier 16 | { 17 | /// 18 | /// This event is fired when the system is in an idle state 19 | /// (no user input) for longer than the given time. 20 | /// 21 | public event EventHandler Idle; 22 | 23 | /// 24 | /// This event is fired when the screensaver starts running. 25 | /// 26 | public event EventHandler Screensaver; 27 | 28 | /// 29 | /// This event is fired when the system enters any sleep state 30 | /// like standby or hilbernate. 31 | /// 32 | public event EventHandler Standby; 33 | 34 | /// 35 | /// This event is fired when the user logg off the current session. 36 | /// 37 | public event EventHandler SessionLogoff; 38 | 39 | /// 40 | /// This event is fired when the user locks the current session. 41 | /// 42 | public event EventHandler SessionLock; 43 | 44 | /// 45 | /// This event is fired when the system is being shut down or restarted. 46 | /// 47 | public event EventHandler ShutdownOrRestart; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Models/SystemEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace SQRLDotNetClientUI.Models 6 | { 7 | /// 8 | /// Represents event args for system event notifications. 9 | /// 10 | public class SystemEventArgs : EventArgs 11 | { 12 | /// 13 | /// The description of the system event that triggered the notification. 14 | /// 15 | public string EventDescription; 16 | 17 | /// 18 | /// Creates a new SystemEventArgs instance. 19 | /// 20 | /// The description of the system event that triggered the notification. 21 | public SystemEventArgs(string eventDescription) 22 | { 23 | this.EventDescription = eventDescription; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Platform/Implementation.cs: -------------------------------------------------------------------------------- 1 | using Serilog; 2 | using SQRLDotNetClientUI.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using ToolBox.Bridge; 8 | 9 | namespace SQRLDotNetClientUI.Platform 10 | { 11 | /// 12 | /// Provides a central place for accessing platform-specific implementations. 13 | /// New platform-specific implementations should be registered here. 14 | /// 15 | public static class Implementation 16 | { 17 | private static IBridgeSystem _bridgeSystem { get; set; } = BridgeSystem.Bash; 18 | private static ShellConfigurator _shell { get; set; } = new ShellConfigurator(_bridgeSystem); 19 | 20 | /// 21 | /// Returns a Type that represents the platform-specific implementation for 22 | /// the given type , or null if no implementation 23 | /// exists for the current platform. 24 | /// 25 | /// The Type (mostly an interface type) to get a platform- 26 | /// specific implementation for. 27 | public static Type ForType() 28 | { 29 | if (typeof(T) == typeof(INotifyIcon)) 30 | { 31 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 32 | return typeof(Win.NotifyIcon); 33 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) 34 | { 35 | // On Linux, we only support a tray icon for Ubuntu, 36 | // sorry folks ¯\_(ツ)_/¯ 37 | var response = _shell.Term($"cat /etc/*-release", Output.Hidden); 38 | Log.Information($"Checking Linux distribution to see if we can use a tray icon"); 39 | Log.Information($"Output of \"cat / etc/*-release\" is:\r\n{response.stdout}"); 40 | if (!string.IsNullOrEmpty(response.stdout) && 41 | response.stdout.ToLower().Contains("ubuntu")) 42 | { 43 | return typeof(Linux.NotifyIcon); 44 | } 45 | return null; 46 | } 47 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) 48 | return typeof(OSX.NotifyIcon); 49 | else return null; 50 | } 51 | 52 | if (typeof(T) == typeof(ISystemEventNotifier)) 53 | { 54 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 55 | return typeof(Win.SystemEventNotifier); 56 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) 57 | return typeof(Linux.SystemEventNotifier); 58 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) 59 | return typeof(OSX.SystemEventNotifier); 60 | else return null; 61 | } 62 | 63 | throw new NotImplementedException( 64 | String.Format("No platform-specific implementations registered for type {0}!", 65 | typeof(T).ToString())); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Platform/Linux/LinuxTrayIcon.cs: -------------------------------------------------------------------------------- 1 | using Eto.Drawing; 2 | using Eto.Forms; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Linq; 7 | using Avalonia.Threading; 8 | namespace SQRLDotNetClientUI.Platform.Linux 9 | { 10 | /// 11 | /// This Implements a Linux GTK3 Tray Icon 12 | /// 13 | public class LinuxTrayIcon: Eto.Forms.Form 14 | { 15 | public TrayIndicator _tray; 16 | private bool _startup = true; 17 | 18 | //Everything has to be sent in on the constructor since things do not auto-refresh / update this is a limitation 19 | public LinuxTrayIcon(string TooTip, string IconPath, Avalonia.Controls.ContextMenu _menu) 20 | { 21 | Dispatcher.UIThread.Post(() => 22 | { 23 | var ctxMnu = new Eto.Forms.ContextMenu(); 24 | foreach (var x in _menu.Items.Cast()) 25 | { 26 | ButtonMenuItem bmi = new ButtonMenuItem(); 27 | bmi.Text = x.Header.ToString(); 28 | bmi.Command = new Command((s, e) => { Dispatcher.UIThread.Post(() => 29 | { 30 | x.Command.Execute(null); 31 | }); 32 | }); 33 | ctxMnu.Items.Add(bmi); 34 | } 35 | 36 | ClientSize = new Size(200, 200); 37 | _tray = new TrayIndicator 38 | { 39 | Image = Eto.Drawing.Icon.FromResource(IconPath.Replace("resm:","")), 40 | Menu = ctxMnu, 41 | Title = ToolTip 42 | }; 43 | 44 | _tray.Show(); 45 | _tray.Visible = true; 46 | }); 47 | } 48 | 49 | protected override void OnShown(EventArgs e) 50 | { 51 | if(_startup) 52 | { 53 | Visible=false; 54 | } 55 | } 56 | 57 | protected override void OnUnLoad(EventArgs e) 58 | { 59 | base.OnUnLoad(e); 60 | _tray.Hide(); 61 | } 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Platform/Linux/NotifyIcon.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Eto.Forms; 3 | using SQRLDotNetClientUI.Models; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using Avalonia.Threading; 10 | namespace SQRLDotNetClientUI.Platform.Linux 11 | { 12 | public class NotifyIcon : INotifyIcon 13 | { 14 | #pragma warning disable 67 15 | public event EventHandler Click; 16 | public event EventHandler DoubleClick; 17 | public event EventHandler RightClick; 18 | #pragma warning restore 67 19 | 20 | private LinuxTrayIcon lti; 21 | private LinuxTrayIcon ltiProp { get => lti; set { lti = value; } } 22 | 23 | private Task trayIconTask; 24 | private System.Threading.CancellationTokenSource canTok; 25 | /// 26 | /// Gets or sets the icon for the notify icon. Either a file system path 27 | /// or a resm: manifest resource path can be specified. 28 | /// 29 | private string _iconPath = ""; 30 | public string IconPath { get => _iconPath; set { _iconPath = value; UpdateMenu(); } } 31 | private string _toolTip = ""; 32 | 33 | /// 34 | /// Gets or sets the tooltip text for the notify icon. 35 | /// 36 | public string ToolTipText { get => _toolTip; set { _toolTip = value; UpdateMenu(); } } 37 | private Avalonia.Controls.ContextMenu _menu; 38 | /// 39 | /// Gets or sets the context menu for the notify icon. 40 | /// 41 | public Avalonia.Controls.ContextMenu ContextMenu 42 | { 43 | get => _menu; set 44 | { 45 | _menu = value; 46 | UpdateMenu(); 47 | } 48 | } 49 | 50 | /// 51 | /// Gets or sets if the notify icon is visible in the 52 | /// taskbar notification area or not. 53 | /// 54 | public bool Visible { get; set; } 55 | 56 | 57 | public void Remove() 58 | { 59 | Dispatcher.UIThread.Post(() => 60 | { 61 | lti._tray.Hide(); 62 | canTok.Cancel(); 63 | }); 64 | } 65 | 66 | private void UpdateMenu() 67 | { 68 | if (!string.IsNullOrEmpty(this.IconPath) && !string.IsNullOrEmpty(this.ToolTipText) && this.ContextMenu != null) 69 | { 70 | canTok = new System.Threading.CancellationTokenSource(); 71 | Dispatcher.UIThread.Post(() => 72 | { 73 | //Because of the way that Linux works this needs to run on its own Thread. 74 | trayIconTask = Task.Factory.StartNew(() => 75 | { 76 | new Eto.Forms.Application(Eto.Platform.Detect).Run(ltiProp = new LinuxTrayIcon(this.ToolTipText, this.IconPath, this.ContextMenu)); 77 | } 78 | , canTok.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.Default); 79 | }, DispatcherPriority.MaxValue); 80 | } 81 | 82 | 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Platform/Win/Interop/NativeWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace SQRLDotNetClientUI.Platform.Win.Interop 6 | { 7 | /// 8 | /// A native Win32 window encapsulation for receiving window messages. 9 | /// 10 | public class NativeWindow 11 | { 12 | private UnmanagedMethods.WndProc _wndProc; 13 | private string _className = "NativeHelperWindow" + Guid.NewGuid(); 14 | 15 | /// 16 | /// The window handle of the underlying native window. 17 | /// 18 | public IntPtr Handle { get; set; } 19 | 20 | /// 21 | /// Creates a new native (Win32) helper window for receiving window messages. 22 | /// 23 | public NativeWindow() 24 | { 25 | // We need to store the window proc as a field so that 26 | // it doesn't get garbage collected away. 27 | _wndProc = new UnmanagedMethods.WndProc(WndProc); 28 | 29 | UnmanagedMethods.WNDCLASSEX wndClassEx = new UnmanagedMethods.WNDCLASSEX 30 | { 31 | cbSize = Marshal.SizeOf(), 32 | lpfnWndProc = _wndProc, 33 | hInstance = UnmanagedMethods.GetModuleHandle(null), 34 | lpszClassName = _className 35 | }; 36 | 37 | ushort atom = UnmanagedMethods.RegisterClassEx(ref wndClassEx); 38 | 39 | if (atom == 0) 40 | { 41 | throw new Win32Exception(); 42 | } 43 | 44 | Handle = UnmanagedMethods.CreateWindowEx(0, atom, null, UnmanagedMethods.WS_POPUP, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); 45 | 46 | if (Handle == IntPtr.Zero) 47 | { 48 | throw new Win32Exception(); 49 | } 50 | } 51 | 52 | /// 53 | /// Destructs the object and destroys the native window. 54 | /// 55 | ~NativeWindow() 56 | { 57 | if (Handle != IntPtr.Zero) 58 | { 59 | UnmanagedMethods.PostMessage(this.Handle, (uint)UnmanagedMethods.WindowsMessage.WM_DESTROY, IntPtr.Zero, IntPtr.Zero); 60 | } 61 | } 62 | 63 | /// 64 | /// This function will receive all the system window messages relevant to our window. 65 | /// 66 | protected virtual IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) 67 | { 68 | switch (msg) 69 | { 70 | case (uint)UnmanagedMethods.WindowsMessage.WM_CLOSE: 71 | UnmanagedMethods.DestroyWindow(hWnd); 72 | break; 73 | case (uint)UnmanagedMethods.WindowsMessage.WM_DESTROY: 74 | UnmanagedMethods.PostQuitMessage(0); 75 | break; 76 | default: 77 | return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam); 78 | } 79 | return IntPtr.Zero; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "SQRLDotNetClientUI": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /SQRLDotNetClientUI/ViewLocator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia.Controls; 3 | using Avalonia.Controls.Templates; 4 | using SQRLDotNetClientUI.ViewModels; 5 | 6 | namespace SQRLDotNetClientUI 7 | { 8 | public class ViewLocator : IDataTemplate 9 | { 10 | public bool SupportsRecycling => false; 11 | 12 | public IControl Build(object data) 13 | { 14 | var name = data.GetType().FullName.Replace("ViewModel", "View"); 15 | var type = Type.GetType(name); 16 | 17 | if (type != null) 18 | { 19 | return (Control)Activator.CreateInstance(type); 20 | } 21 | else 22 | { 23 | return new TextBlock { Text = "Not Found: " + name }; 24 | } 25 | } 26 | 27 | public bool Match(object data) 28 | { 29 | return data is ViewModelBase; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /SQRLDotNetClientUI/ViewModels/AboutViewModel.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using Serilog; 3 | using SQRLCommon.Models; 4 | using System; 5 | using System.Diagnostics; 6 | using System.Reflection; 7 | 8 | namespace SQRLDotNetClientUI.ViewModels 9 | { 10 | /// 11 | /// A view model representing the app's "About" screen. 12 | /// 13 | public class AboutViewModel : ViewModelBase 14 | { 15 | private string _appVersion; 16 | private int _testingModeCounter = 0; 17 | 18 | /// 19 | /// Gets or sets the app's executable version. 20 | /// 21 | public string AppVersion 22 | { 23 | get => _appVersion; 24 | set => this.RaiseAndSetIfChanged(ref _appVersion, value); 25 | } 26 | 27 | /// 28 | /// Creates a new instance, sets the window title and performs 29 | /// a few initializations. 30 | /// 31 | public AboutViewModel() 32 | { 33 | var assemblyName = Assembly.GetExecutingAssembly().GetName(); 34 | 35 | this.Title = _loc.GetLocalizationValue("AboutWindowTitle") + " " + 36 | assemblyName.Name; 37 | 38 | this.AppVersion = _loc.GetLocalizationValue("VersionLabel") + ": " + 39 | assemblyName.Version.ToString(); 40 | } 41 | 42 | /// 43 | /// Navigates back to the app's main screen. 44 | /// 45 | public void Back() 46 | { 47 | Log.Information("Leaving about screen"); 48 | 49 | ((MainWindowViewModel)_mainWindow.DataContext).Content = 50 | ((MainWindowViewModel)_mainWindow.DataContext).PriorContent; 51 | } 52 | 53 | /// 54 | /// Starts a browser window with a link to the repo on Github. 55 | /// 56 | public void ShowRepository() 57 | { 58 | Process p = new Process(); 59 | p.StartInfo.UseShellExecute = true; 60 | p.StartInfo.FileName = @"https://github.com/sqrldev/SQRLDotNetClient"; 61 | p.Start(); 62 | } 63 | 64 | /// 65 | /// Starts a browser window with a link to the repo on Github. 66 | /// 67 | public void ShowLicense() 68 | { 69 | Process p = new Process(); 70 | p.StartInfo.UseShellExecute = true; 71 | p.StartInfo.FileName = @"https://raw.githubusercontent.com/sqrldev/SQRLDotNetClient/master/LICENSE"; 72 | p.Start(); 73 | } 74 | 75 | /// 76 | /// Enables testing mode when clicking on the version label 5 times. 77 | /// 78 | public void EnableTestingMode() 79 | { 80 | _testingModeCounter++; 81 | if (_testingModeCounter == 5) 82 | { 83 | Environment.SetEnvironmentVariable(GithubHelper.TestModeEnvVar, "true"); 84 | Log.Information("Testing mode enabled"); 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/ViewModels/AppSettingsViewModel.cs: -------------------------------------------------------------------------------- 1 | using Serilog; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace SQRLDotNetClientUI.ViewModels 7 | { 8 | /// 9 | /// A view model representing the "app settings" screen. 10 | /// 11 | class AppSettingsViewModel : ViewModelBase 12 | { 13 | /// 14 | /// Gets or sets a value that determines if the app should start 15 | /// minimized to the tray icon. 16 | /// 17 | public bool StartMinimized 18 | { 19 | get { return _appSettings.StartMinimized; } 20 | set { _appSettings.StartMinimized = value; } 21 | } 22 | 23 | /// 24 | /// Creates a new instance and performs some initialization tasks. 25 | /// 26 | public AppSettingsViewModel() 27 | { 28 | this.Title = _loc.GetLocalizationValue("AppSettingsTitle"); 29 | } 30 | 31 | /// 32 | /// Returns back to the previous screen without changing or saving 33 | /// any settings. 34 | /// 35 | public void Cancel() 36 | { 37 | Log.Information("Cancelling out of app settings screen"); 38 | 39 | // Discard any pending changes 40 | _appSettings.Reload(); 41 | 42 | ((MainWindowViewModel)_mainWindow.DataContext).Content = 43 | ((MainWindowViewModel)_mainWindow.DataContext).PriorContent; 44 | } 45 | 46 | /// 47 | /// Saves the settings set by the user. 48 | /// 49 | public void Save() 50 | { 51 | Log.Information("Saving app settings"); 52 | 53 | _appSettings.Save(); 54 | 55 | ((MainWindowViewModel)_mainWindow.DataContext).Content = 56 | ((MainWindowViewModel)_mainWindow.DataContext).PriorContent; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/ViewModels/InputSecretDialogViewModel.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using SQRLDotNetClientUI.Views; 3 | using System.Collections.Concurrent; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace SQRLDotNetClientUI.ViewModels 8 | { 9 | /// 10 | /// A view model for the app's screen to enter a user secret 11 | /// (password or rescue code). 12 | /// 13 | public class InputSecretDialogViewModel: ViewModelBase 14 | { 15 | private AutoResetEvent _dialogClosed = null; 16 | private string _secret = ""; 17 | 18 | /// 19 | /// Gets or sets the type of secret that the user should be asked to enter. 20 | /// 21 | public SecretType SecretType { get; set; } 22 | 23 | /// 24 | /// Gets or sets the actual secret entered by the user. 25 | /// 26 | public string Secret { 27 | get => _secret; 28 | set => this.RaiseAndSetIfChanged(ref _secret, value); 29 | } 30 | 31 | /// 32 | /// Gets or sets the view model that the Input Secret Dialog was called from and 33 | /// that should be shown again when the dialog gets closed. 34 | /// 35 | public ViewModelBase Parent { get; set; } 36 | 37 | /// 38 | /// Creates a new InputSecretDialogViewModel instance, specifying the 39 | /// type of secret that the user should be asked to enter within . 40 | /// 41 | /// The type of secret that the user should be asked to enter. 42 | public InputSecretDialogViewModel(SecretType secretType=SecretType.Password) 43 | { 44 | this.SecretType = secretType; 45 | _dialogClosed = new AutoResetEvent(false); 46 | } 47 | 48 | /// 49 | /// This event handler gets called when the dialog's "OK" button is clicked. 50 | /// 51 | public void Ok() 52 | { 53 | ((MainWindowViewModel)_mainWindow.DataContext).Content = Parent; 54 | _dialogClosed.Set(); 55 | } 56 | 57 | /// 58 | /// This method sets the current view to the Input Secret Dialog then waits for the 59 | /// "OK" button to be clicked before returning. 60 | /// 61 | /// The view model that the Input Secret Dialog was called from 62 | /// and that should be shown again when the dialog gets closed. 63 | /// An optional title for the dialog window. 64 | public async Task ShowDialog(ViewModelBase parent, string title = "") 65 | { 66 | this.Parent = parent; 67 | this.Title = string.IsNullOrEmpty(title) ? parent.Title : title; 68 | 69 | ((MainWindowViewModel)_mainWindow.DataContext).Content = this; 70 | 71 | return await Task.Run(() => 72 | { 73 | _dialogClosed.WaitOne(); 74 | return true; 75 | }); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/ViewModels/MainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using SQRLDotNetClientUI.Views; 3 | 4 | namespace SQRLDotNetClientUI.ViewModels 5 | { 6 | /// 7 | /// A view model representing the main application window. 8 | /// 9 | public class MainWindowViewModel : ViewModelBase 10 | { 11 | MainMenuViewModel _mainMenu; 12 | ViewModelBase _content; 13 | ViewModelBase _priorContent; 14 | 15 | /// 16 | /// Gets or sets the view model representing the app's main screen. 17 | /// 18 | public MainMenuViewModel MainMenu 19 | { 20 | get => _mainMenu; 21 | set { this.RaiseAndSetIfChanged(ref _mainMenu, value); } 22 | } 23 | 24 | /// 25 | /// Gets or sets the view model of the corresponding view that will 26 | /// be displayed within the app's main window. 27 | /// 28 | public ViewModelBase Content 29 | { 30 | get => _content; 31 | set 32 | { 33 | // Don't want PriorContent to be messed up because of the progress indicator 34 | // or message boxes so we aren't counting those 35 | if (Content != null && 36 | Content != PriorContent && 37 | Content.GetType() != typeof(ProgressDialogViewModel) && 38 | Content.GetType() != typeof(MessageBoxViewModel) && 39 | value.GetType() != typeof(ProgressDialogViewModel) && 40 | value.GetType() != typeof(MessageBoxViewModel)) 41 | { 42 | PriorContent = Content; 43 | } 44 | 45 | this.RaiseAndSetIfChanged(ref _content, value); 46 | } 47 | } 48 | 49 | /// 50 | /// Gets or sets the view model of the corresponding view that was 51 | /// previously displayed within the app's main window. 52 | /// 53 | public ViewModelBase PriorContent 54 | { 55 | get => _priorContent; 56 | set => this.RaiseAndSetIfChanged(ref _priorContent, value); 57 | } 58 | 59 | /// 60 | /// Creates a new MainWindowViewModel instance and performs some 61 | /// initialization tasks. 62 | /// 63 | public MainWindowViewModel() 64 | { 65 | var mainMnu = new MainMenuViewModel(); 66 | if (mainMnu != null && mainMnu.AuthVM != null) 67 | Content = mainMnu.AuthVM; 68 | else 69 | Content = mainMnu; 70 | 71 | MainMenu = mainMnu; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/ViewModels/SelectIdentityViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace SQRLDotNetClientUI.ViewModels 5 | { 6 | /// 7 | /// Represents a view model for the SelectIdentityView screen. 8 | /// 9 | public class SelectIdentityViewModel : ViewModelBase 10 | { 11 | private AutoResetEvent _identitySelected = null; 12 | private ViewModelBase _parent = null; 13 | 14 | public SelectIdentityViewModel() 15 | { 16 | _identitySelected = new AutoResetEvent(false); 17 | } 18 | 19 | /// 20 | /// Handles the event of an identity being selected. 21 | /// 22 | public void OnIdentitySelected(string identityUniqueId) 23 | { 24 | _identityManager.SetCurrentIdentity(identityUniqueId); 25 | 26 | // Signal the auto reset event that we're done 27 | _identitySelected.Set(); 28 | } 29 | 30 | public async void ShowDialog(ViewModelBase Parent) 31 | { 32 | this._parent = Parent; 33 | 34 | // Set the content of the main window to the select identity screen 35 | ((MainWindowViewModel)_mainWindow.DataContext).Content = this; 36 | 37 | // Wait for an identity to get selected 38 | await Task.Run(() => _identitySelected.WaitOne()); 39 | 40 | // Set the content of the main window back to where it was before 41 | ((MainWindowViewModel)_mainWindow.DataContext).Content = _parent; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using ReactiveUI; 3 | using SQRLCommon.AvaloniaExtensions; 4 | using SQRLDotNetClientUI.Models; 5 | using SQRLDotNetClientUI.Views; 6 | 7 | namespace SQRLDotNetClientUI.ViewModels 8 | { 9 | /// 10 | /// A base class for all of the app's view models. 11 | /// 12 | public class ViewModelBase : ReactiveObject 13 | { 14 | private string title = ""; 15 | 16 | /// 17 | /// The singleton AppSettings instance representing the 18 | /// app's general settings. 19 | /// 20 | protected AppSettings _appSettings = AppSettings.Instance; 21 | 22 | /// 23 | /// The singleton IdentityManager instance. 24 | /// 25 | protected IdentityManager _identityManager = IdentityManager.Instance; 26 | 27 | /// 28 | /// The app's main window. 29 | /// 30 | protected MainWindow _mainWindow = AvaloniaLocator.Current.GetService(); 31 | 32 | /// 33 | /// An Avalonia extension providing localization/translation 34 | /// services for the app. 35 | /// 36 | protected LocalizationExtension _loc = (App.Current as App).Localization; 37 | 38 | /// 39 | /// The window title of the screen represented by the view model. 40 | /// 41 | public string Title 42 | { 43 | get => this.title; 44 | set { this.RaiseAndSetIfChanged(ref title, value); } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Views/AboutView.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 38 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Views/AskView.xaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | 5 | namespace SQRLDotNetClientUI.Views 6 | { 7 | public class AskView : UserControl 8 | { 9 | public AskView() 10 | { 11 | this.InitializeComponent(); 12 | 13 | } 14 | 15 | private void InitializeComponent() 16 | { 17 | AvaloniaXamlLoader.Load(this); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Views/AuthenticationView.xaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | using SQRLCommon.AvaloniaExtensions; 5 | using SQRLDotNetClientUI.ViewModels; 6 | 7 | namespace SQRLDotNetClientUI.Views 8 | { 9 | public class AuthenticationView : UserControl 10 | { 11 | private CopyPasteTextBox _txtPassword = null; 12 | private CopyPasteTextBox _txtAltID = null; 13 | 14 | public AuthenticationView() 15 | { 16 | this.InitializeComponent(); 17 | _txtPassword = this.FindControl("txtPassword"); 18 | _txtAltID = this.FindControl("txtAltID"); 19 | this.GotFocus += AuthenticationView_GotFocus; 20 | } 21 | 22 | private void InitializeComponent() 23 | { 24 | AvaloniaXamlLoader.Load(this); 25 | } 26 | 27 | private void AuthenticationView_GotFocus(object sender, Avalonia.Input.GotFocusEventArgs e) 28 | { 29 | if (e?.Source is Button) 30 | { 31 | if (((Button)e.Source).Name == "btnIdentitySelector") 32 | { 33 | _txtPassword.Focus(); 34 | e.Handled = true; 35 | } 36 | 37 | if (((Button)e.Source).Name == "btnAdvancedFunctions") 38 | { 39 | _txtAltID.Focus(); 40 | e.Handled = true; 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SQRLDotNetClientUI/Views/ChangePasswordView.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 31 | 32 | 33 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | 50 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 |