Merge pull request #1 from Stone-Red-Code/develop

Develop
This commit is contained in:
Stone_Red
2025-01-22 21:41:35 +01:00
committed by GitHub
7 changed files with 262 additions and 32 deletions
@@ -1,9 +1,12 @@
using System.ComponentModel; using CommunityToolkit.Mvvm.Input;
using SharpHook.Native;
using System.Reflection; using System.Reflection;
namespace InvLock.DataContexts; namespace InvLock.DataContexts;
internal class MainWindowDataContext : INotifyPropertyChanged internal partial class MainWindowDataContext(Func<LockWindow?> lockWindowAccessor)
{ {
#if DEBUG #if DEBUG
public string Title => $"{App.AppName} - Dev {AppVersion}"; public string Title => $"{App.AppName} - Dev {AppVersion}";
@@ -19,4 +22,40 @@ internal class MainWindowDataContext : INotifyPropertyChanged
public string AppVersion => Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "Unknown"; public string AppVersion => Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "Unknown";
public Settings Settings { get; } = Settings.Load(); public Settings Settings { get; } = Settings.Load();
[RelayCommand]
public async Task RecordLockShortcut()
{
LockWindow? lockWindow = lockWindowAccessor();
if (lockWindow is null)
{
return;
}
HashSet<KeyCode>? lockShortcut = await lockWindow.RecordShortcut();
if (lockShortcut is not null)
{
Settings.LockShortcut = lockShortcut;
}
}
[RelayCommand]
public async Task RecordUnlockShortcut()
{
LockWindow? lockWindow = lockWindowAccessor();
if (lockWindow is null)
{
return;
}
HashSet<KeyCode>? unlockShortcut = await lockWindow.RecordShortcut();
if (unlockShortcut is not null)
{
Settings.UnlockShortcut = unlockShortcut;
}
}
} }
+1
View File
@@ -15,6 +15,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="CuteUtils" Version="1.0.0" /> <PackageReference Include="CuteUtils" Version="1.0.0" />
<PackageReference Include="SharpHook" Version="5.3.8" /> <PackageReference Include="SharpHook" Version="5.3.8" />
<PackageReference Include="WPF-UI" Version="3.0.5" /> <PackageReference Include="WPF-UI" Version="3.0.5" />
+3 -1
View File
@@ -17,5 +17,7 @@
ShowInTaskbar="False" ShowInTaskbar="False"
Title="MainWindow" Height="Auto" Width="Auto"> Title="MainWindow" Height="Auto" Width="Auto">
<controls:OutlinedTextBlock x:Name="textBlock" Text="Lock Screen Active" Bold="True" Stroke="Red" Opacity="0" Fill="Black" StrokeThickness="1" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="50" Font="Segoe UI" /> <Viewbox Stretch="Uniform" StretchDirection="DownOnly">
<controls:OutlinedTextBlock x:Name="textBlock" Text="Lock Screen Active" Bold="True" Stroke="Red" Opacity="0" Fill="Black" StrokeThickness="1" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="50" Font="Segoe UI" />
</Viewbox>
</Window> </Window>
+90 -12
View File
@@ -3,6 +3,7 @@
using SharpHook; using SharpHook;
using SharpHook.Native; using SharpHook.Native;
using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Interop; using System.Windows.Interop;
using System.Windows.Media; using System.Windows.Media;
@@ -59,6 +60,59 @@ public partial class LockWindow : Window
_ = Task.Run(hook.Run); _ = Task.Run(hook.Run);
} }
public async Task<HashSet<KeyCode>?> RecordShortcut()
{
HashSet<KeyCode> keys = [];
hook.KeyPressed -= Hook_KeyPressed;
hook.KeyPressed += Record;
textBlock.Text = "Press a key combination to record a shortcut";
textBlock.Stroke = Brushes.White;
textBlock.Opacity = 1;
// Wait for the user to press the enter key
await Task.Run(async () =>
{
while (!keys.Contains(KeyCode.VcEnter) && !keys.Contains(KeyCode.VcEscape))
{
await Task.Delay(100);
}
});
hook.KeyPressed -= Record;
hook.KeyPressed += Hook_KeyPressed;
textBlock.Opacity = 0;
if (keys.Contains(KeyCode.VcEscape) || keys.Count <= 1)
{
textBlock.Text = "Shortcut Recording Cancelled";
textBlock.Stroke = (Brush)FindResource("PaletteRedBrush");
Animation();
return null;
}
textBlock.Text = "Shortcut Recorded";
textBlock.Stroke = (Brush)FindResource("PaletteGreenBrush");
Animation();
_ = keys.Remove(KeyCode.VcEnter);
return keys;
void Record(object? sender, KeyboardHookEventArgs e)
{
e.SuppressEvent = true;
_ = keys.Add(e.Data.KeyCode);
Debug.WriteLine(string.Join(" + ", keys.Select(key => key.ToString())));
_ = Dispatcher.Invoke(() => textBlock.Text = string.Join(" + ", keys.Select(key => key.ToString()[2..]))
+ Environment.NewLine
+ "Press ENTER to save or ESCAPE to cancel");
}
}
private void ActivateLockScreen() private void ActivateLockScreen()
{ {
if (settings.HideWindows) if (settings.HideWindows)
@@ -82,8 +136,31 @@ public partial class LockWindow : Window
private void DeactivateLockScreen() private void DeactivateLockScreen()
{ {
isOpen = false; if (settings.UseWindowsLockScreen)
Dispatcher.Invoke(Close); {
isOpen = false;
Dispatcher.Invoke(Close);
}
else
{
Dispatcher.Invoke(() =>
{
suppressInput = false;
if (settings.HideWindows)
{
RestoreWindows();
}
isOpen = true;
textBlock.Text = settings.UnlockText;
textBlock.Stroke = (Brush)FindResource("PaletteGreenBrush");
Animation();
});
}
} }
private void Hook_KeyPressed(object? sender, KeyboardHookEventArgs e) private void Hook_KeyPressed(object? sender, KeyboardHookEventArgs e)
@@ -97,16 +174,13 @@ public partial class LockWindow : Window
} }
_ = pressedKeys[e.Data.KeyCode] = DateTime.UtcNow; _ = pressedKeys[e.Data.KeyCode] = DateTime.UtcNow;
if (pressedKeys.ContainsKey(KeyCode.VcL) && pressedKeys.ContainsKey(KeyCode.VcLeftShift) && pressedKeys.ContainsKey(KeyCode.VcLeftControl) && pressedKeys.Count == 3) if (pressedKeys.All(kvp => settings.UnlockShortcut.Contains(kvp.Key)) && suppressInput && pressedKeys.Count == settings.UnlockShortcut.Count)
{ {
if (suppressInput) DeactivateLockScreen();
{ }
DeactivateLockScreen(); else if (pressedKeys.All(kvp => settings.LockShortcut.Contains(kvp.Key)) && !suppressInput && pressedKeys.Count == settings.LockShortcut.Count)
} {
else ActivateLockScreen();
{
ActivateLockScreen();
}
} }
e.SuppressEvent = suppressInput; e.SuppressEvent = suppressInput;
@@ -171,7 +245,11 @@ public partial class LockWindow : Window
private void Animation() private void Animation()
{ {
Storyboard storyboard = new Storyboard(); Storyboard storyboard = new Storyboard
{
FillBehavior = FillBehavior.Stop
};
TimeSpan duration = TimeSpan.FromMilliseconds(500); TimeSpan duration = TimeSpan.FromMilliseconds(500);
DoubleAnimation fadeInAnimation = new DoubleAnimation() DoubleAnimation fadeInAnimation = new DoubleAnimation()
+44 -12
View File
@@ -56,10 +56,6 @@
It is designed to be lightweight and easy to use. It is designed to be lightweight and easy to use.
<LineBreak /> <LineBreak />
If you have any issues or feature requests, please report them on GitHub. If you have any issues or feature requests, please report them on GitHub.
<LineBreak />
<LineBreak />
To lock and unlock your screen, press
<ui:TextBlock Foreground="{DynamicResource AccentTextFillColorPrimaryBrush}">WIN + SHIFT + L</ui:TextBlock>
</ui:TextBlock> </ui:TextBlock>
<ui:TextBlock Margin="0,0,0,8" FontTypography="BodyStrong" Text="Appearance &amp; behavior" /> <ui:TextBlock Margin="0,0,0,8" FontTypography="BodyStrong" Text="Appearance &amp; behavior" />
@@ -76,7 +72,7 @@
</ui:HyperlinkButton> </ui:HyperlinkButton>
</Grid> </Grid>
</ui:CardControl.Header> </ui:CardControl.Header>
<ComboBox Grid.Column="1" MinWidth="200" SelectedIndex="0"> <ComboBox Grid.Column="1" MinWidth="200" SelectedIndex="0" SelectedValue="{Binding Settings.Theme}" SelectedValuePath="Content">
<ComboBoxItem Content="Windows default" /> <ComboBoxItem Content="Windows default" />
<ComboBoxItem Content="Light" /> <ComboBoxItem Content="Light" />
<ComboBoxItem Content="Dark" /> <ComboBoxItem Content="Dark" />
@@ -90,6 +86,13 @@
<ui:ToggleSwitch Grid.Column="1" IsChecked="{Binding Settings.HideWindows}" OffContent="Off" OnContent="On" /> <ui:ToggleSwitch Grid.Column="1" IsChecked="{Binding Settings.HideWindows}" OffContent="Off" OnContent="On" />
</ui:CardControl> </ui:CardControl>
<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=WindowShield24}" Height="75">
<ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Use windows lock screen to unlock" />
</ui:CardControl.Header>
<ui:ToggleSwitch Grid.Column="1" IsChecked="{Binding Settings.UseWindowsLockScreen}" OffContent="Off" OnContent="On" />
</ui:CardControl>
<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockClosed24}" Height="75"> <ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockClosed24}" Height="75">
<ui:CardControl.Header> <ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Lock text" /> <ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Lock text" />
@@ -97,6 +100,13 @@
<ui:TextBox Grid.Column="1" MinWidth="200" Text="{Binding Settings.LockText, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Type your lock text here" /> <ui:TextBox Grid.Column="1" MinWidth="200" Text="{Binding Settings.LockText, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Type your lock text here" />
</ui:CardControl> </ui:CardControl>
<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockClosed24}" Height="75">
<ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Lock shortcut" />
</ui:CardControl.Header>
<ui:Button Grid.Column="1" Command="{Binding RecordLockShortcutCommand}" MinWidth="200" Icon="{ui:SymbolIcon Symbol=Edit24}" Content="{Binding Settings.LockShortcutText}" />
</ui:CardControl>
<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockOpen24}" Height="75"> <ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockOpen24}" Height="75">
<ui:CardControl.Header> <ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Unlock text" /> <ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Unlock text" />
@@ -104,6 +114,13 @@
<ui:TextBox Grid.Column="1" MinWidth="200" Text="{Binding Settings.UnlockText, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Type your unlock text here" /> <ui:TextBox Grid.Column="1" MinWidth="200" Text="{Binding Settings.UnlockText, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Type your unlock text here" />
</ui:CardControl> </ui:CardControl>
<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockOpen24}" Height="75">
<ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Unlock shortcut" />
</ui:CardControl.Header>
<ui:Button Grid.Column="1" Command="{Binding RecordUnlockShortcutCommand}" MinWidth="200" Icon="{ui:SymbolIcon Symbol=Edit24}" Content="{Binding Settings.UnlockShortcutText}" />
</ui:CardControl>
<ui:TextBlock Margin="0,24,0,8" FontTypography="BodyStrong" Text="About" /> <ui:TextBlock Margin="0,24,0,8" FontTypography="BodyStrong" Text="About" />
<ui:CardExpander ContentPadding="0"> <ui:CardExpander ContentPadding="0">
<ui:CardExpander.Header> <ui:CardExpander.Header>
@@ -129,7 +146,26 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Report an issue or request a feature" /> <TextBlock Grid.Column="0" Text="Report an issue or request a feature" />
<ui:SymbolIcon Grid.Column="1" Symbol="Link24" /> <StackPanel Grid.Column="1" Orientation="Horizontal">
<ui:SymbolIcon Margin="0 0 6 0" Symbol="Link24" />
<TextBlock Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="https://github.com/Stone-Red-Code/InvLock/issues" />
</StackPanel>
</Grid>
</ui:Anchor>
<Separator />
<ui:Anchor Margin="0" Padding="16" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Background="Transparent" CornerRadius="0" BorderThickness="0" NavigateUri="https://github.com/Stone-Red-Code/InvLock">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="GitHub" />
<StackPanel Grid.Column="1" Orientation="Horizontal">
<ui:SymbolIcon Margin="0 0 6 0" Symbol="Link24" />
<TextBlock Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="https://github.com/Stone-Red-Code/InvLock" />
</StackPanel>
</Grid> </Grid>
</ui:Anchor> </ui:Anchor>
@@ -140,13 +176,9 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Clone repository" /> <TextBlock Grid.Column="0" Text="Version" />
<TextBlock Grid.Column="1" Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="git clone https://github.com/Stone-Red-Code/InvLock" /> <TextBlock Grid.Column="1" Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="{Binding AppVersion}" />
</Grid> </Grid>
<Separator />
<TextBlock Margin="16" Text="{Binding AppVersion, StringFormat='Version {0}'}" />
</StackPanel> </StackPanel>
</ui:CardExpander> </ui:CardExpander>
</StackPanel> </StackPanel>
+2 -1
View File
@@ -12,12 +12,13 @@ namespace InvLock;
/// </summary> /// </summary>
public partial class MainWindow : FluentWindow public partial class MainWindow : FluentWindow
{ {
private readonly MainWindowDataContext mainWindowDataContext = new MainWindowDataContext(); private readonly MainWindowDataContext mainWindowDataContext;
private LockWindow? lockWindow; private LockWindow? lockWindow;
private bool blockWindowClosing = true; private bool blockWindowClosing = true;
public MainWindow() public MainWindow()
{ {
mainWindowDataContext = new MainWindowDataContext(() => lockWindow);
DataContext = mainWindowDataContext; DataContext = mainWindowDataContext;
InitializeComponent(); InitializeComponent();
+81 -4
View File
@@ -1,7 +1,12 @@
using System.ComponentModel; using SharpHook.Native;
using System.ComponentModel;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization;
using Wpf.Ui.Appearance;
namespace InvLock; namespace InvLock;
@@ -10,8 +15,12 @@ public class Settings : INotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
private static readonly string settingsPath = Path.Combine(App.ApplicationDataPath, "settings.json"); private static readonly string settingsPath = Path.Combine(App.ApplicationDataPath, "settings.json");
private bool useWindowsLockScreen = true;
private bool hideWindows = false; private bool hideWindows = false;
private string lockText = "Lock Screen Active"; private string lockText = "Lock Screen Active";
private string theme = "Windows default";
private HashSet<KeyCode> lockShortcut = [KeyCode.VcLeftControl, KeyCode.VcLeftShift, KeyCode.VcL];
private HashSet<KeyCode> unlockShortcut = [KeyCode.VcLeftControl, KeyCode.VcLeftShift, KeyCode.VcL];
private string unlockText = "Lock Screen Inactive"; private string unlockText = "Lock Screen Inactive";
@@ -25,6 +34,16 @@ public class Settings : INotifyPropertyChanged
} }
} }
public bool UseWindowsLockScreen
{
get => useWindowsLockScreen;
set
{
useWindowsLockScreen = value;
OnPropertyChanged();
}
}
public string LockText public string LockText
{ {
get => lockText; get => lockText;
@@ -35,6 +54,20 @@ public class Settings : INotifyPropertyChanged
} }
} }
public HashSet<KeyCode> LockShortcut
{
get => lockShortcut;
set
{
lockShortcut = value;
OnPropertyChanged();
OnPropertyChanged(nameof(LockShortcutText));
}
}
[JsonIgnore]
public string LockShortcutText => string.Join(" + ", LockShortcut.Select(key => key.ToString()[2..]));
public string UnlockText public string UnlockText
{ {
get => unlockText; get => unlockText;
@@ -45,14 +78,58 @@ public class Settings : INotifyPropertyChanged
} }
} }
public HashSet<KeyCode> UnlockShortcut
{
get => unlockShortcut;
set
{
unlockShortcut = value;
OnPropertyChanged();
OnPropertyChanged(nameof(UnlockShortcutText));
}
}
[JsonIgnore]
public string UnlockShortcutText => string.Join(" + ", UnlockShortcut.Select(key => key.ToString()[2..]));
public string Theme
{
get => theme;
set
{
theme = value;
if (value == "Windows default")
{
ApplicationThemeManager.ApplySystemTheme();
}
else if (value == "Light")
{
ApplicationThemeManager.Apply(ApplicationTheme.Light);
}
else if (value == "Dark")
{
ApplicationThemeManager.Apply(ApplicationTheme.Dark);
}
OnPropertyChanged();
}
}
public static Settings Load() public static Settings Load()
{ {
if (File.Exists(settingsPath)) if (File.Exists(settingsPath))
{ {
string json = File.ReadAllText(settingsPath); try
return JsonSerializer.Deserialize<Settings>(json) ?? new Settings(); {
string json = File.ReadAllText(settingsPath);
return JsonSerializer.Deserialize<Settings>(json) ?? new Settings();
}
catch (JsonException)
{
return new Settings();
}
} }
return new Settings(); return new Settings();
} }