Skip to content

Commit b7eaaac

Browse files
Merge pull request #1 from Stone-Red-Code/develop
Develop
2 parents a499107 + 24149da commit b7eaaac

File tree

7 files changed

+262
-32
lines changed

7 files changed

+262
-32
lines changed

src/InvLock/DataContexts/MainWindowDataContext.cs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
using System.ComponentModel;
1+
using CommunityToolkit.Mvvm.Input;
2+
3+
using SharpHook.Native;
4+
25
using System.Reflection;
36

47
namespace InvLock.DataContexts;
58

6-
internal class MainWindowDataContext : INotifyPropertyChanged
9+
internal partial class MainWindowDataContext(Func<LockWindow?> lockWindowAccessor)
710
{
811
#if DEBUG
912
public string Title => $"{App.AppName} - Dev {AppVersion}";
@@ -19,4 +22,40 @@ internal class MainWindowDataContext : INotifyPropertyChanged
1922
public string AppVersion => Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "Unknown";
2023

2124
public Settings Settings { get; } = Settings.Load();
25+
26+
[RelayCommand]
27+
public async Task RecordLockShortcut()
28+
{
29+
LockWindow? lockWindow = lockWindowAccessor();
30+
31+
if (lockWindow is null)
32+
{
33+
return;
34+
}
35+
36+
HashSet<KeyCode>? lockShortcut = await lockWindow.RecordShortcut();
37+
38+
if (lockShortcut is not null)
39+
{
40+
Settings.LockShortcut = lockShortcut;
41+
}
42+
}
43+
44+
[RelayCommand]
45+
public async Task RecordUnlockShortcut()
46+
{
47+
LockWindow? lockWindow = lockWindowAccessor();
48+
49+
if (lockWindow is null)
50+
{
51+
return;
52+
}
53+
54+
HashSet<KeyCode>? unlockShortcut = await lockWindow.RecordShortcut();
55+
56+
if (unlockShortcut is not null)
57+
{
58+
Settings.UnlockShortcut = unlockShortcut;
59+
}
60+
}
2261
}

src/InvLock/InvLock.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
</ItemGroup>
1616

1717
<ItemGroup>
18+
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
1819
<PackageReference Include="CuteUtils" Version="1.0.0" />
1920
<PackageReference Include="SharpHook" Version="5.3.8" />
2021
<PackageReference Include="WPF-UI" Version="3.0.5" />

src/InvLock/LockWindow.xaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@
1717
ShowInTaskbar="False"
1818
Title="MainWindow" Height="Auto" Width="Auto">
1919

20-
<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" />
20+
<Viewbox Stretch="Uniform" StretchDirection="DownOnly">
21+
<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" />
22+
</Viewbox>
2123
</Window>

src/InvLock/LockWindow.xaml.cs

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using SharpHook;
44
using SharpHook.Native;
55

6+
using System.Diagnostics;
67
using System.Windows;
78
using System.Windows.Interop;
89
using System.Windows.Media;
@@ -59,6 +60,59 @@ public LockWindow(Settings settings)
5960
_ = Task.Run(hook.Run);
6061
}
6162

63+
public async Task<HashSet<KeyCode>?> RecordShortcut()
64+
{
65+
HashSet<KeyCode> keys = [];
66+
67+
hook.KeyPressed -= Hook_KeyPressed;
68+
hook.KeyPressed += Record;
69+
70+
textBlock.Text = "Press a key combination to record a shortcut";
71+
textBlock.Stroke = Brushes.White;
72+
textBlock.Opacity = 1;
73+
74+
// Wait for the user to press the enter key
75+
await Task.Run(async () =>
76+
{
77+
while (!keys.Contains(KeyCode.VcEnter) && !keys.Contains(KeyCode.VcEscape))
78+
{
79+
await Task.Delay(100);
80+
}
81+
});
82+
83+
hook.KeyPressed -= Record;
84+
hook.KeyPressed += Hook_KeyPressed;
85+
86+
textBlock.Opacity = 0;
87+
88+
if (keys.Contains(KeyCode.VcEscape) || keys.Count <= 1)
89+
{
90+
textBlock.Text = "Shortcut Recording Cancelled";
91+
textBlock.Stroke = (Brush)FindResource("PaletteRedBrush");
92+
Animation();
93+
94+
return null;
95+
}
96+
97+
textBlock.Text = "Shortcut Recorded";
98+
textBlock.Stroke = (Brush)FindResource("PaletteGreenBrush");
99+
Animation();
100+
101+
_ = keys.Remove(KeyCode.VcEnter);
102+
103+
return keys;
104+
105+
void Record(object? sender, KeyboardHookEventArgs e)
106+
{
107+
e.SuppressEvent = true;
108+
_ = keys.Add(e.Data.KeyCode);
109+
Debug.WriteLine(string.Join(" + ", keys.Select(key => key.ToString())));
110+
_ = Dispatcher.Invoke(() => textBlock.Text = string.Join(" + ", keys.Select(key => key.ToString()[2..]))
111+
+ Environment.NewLine
112+
+ "Press ENTER to save or ESCAPE to cancel");
113+
}
114+
}
115+
62116
private void ActivateLockScreen()
63117
{
64118
if (settings.HideWindows)
@@ -82,8 +136,31 @@ private void ActivateLockScreen()
82136

83137
private void DeactivateLockScreen()
84138
{
85-
isOpen = false;
86-
Dispatcher.Invoke(Close);
139+
if (settings.UseWindowsLockScreen)
140+
{
141+
isOpen = false;
142+
143+
Dispatcher.Invoke(Close);
144+
}
145+
else
146+
{
147+
Dispatcher.Invoke(() =>
148+
{
149+
suppressInput = false;
150+
151+
if (settings.HideWindows)
152+
{
153+
RestoreWindows();
154+
}
155+
156+
isOpen = true;
157+
158+
textBlock.Text = settings.UnlockText;
159+
textBlock.Stroke = (Brush)FindResource("PaletteGreenBrush");
160+
161+
Animation();
162+
});
163+
}
87164
}
88165

89166
private void Hook_KeyPressed(object? sender, KeyboardHookEventArgs e)
@@ -97,16 +174,13 @@ private void Hook_KeyPressed(object? sender, KeyboardHookEventArgs e)
97174
}
98175
_ = pressedKeys[e.Data.KeyCode] = DateTime.UtcNow;
99176

100-
if (pressedKeys.ContainsKey(KeyCode.VcL) && pressedKeys.ContainsKey(KeyCode.VcLeftShift) && pressedKeys.ContainsKey(KeyCode.VcLeftControl) && pressedKeys.Count == 3)
177+
if (pressedKeys.All(kvp => settings.UnlockShortcut.Contains(kvp.Key)) && suppressInput && pressedKeys.Count == settings.UnlockShortcut.Count)
101178
{
102-
if (suppressInput)
103-
{
104-
DeactivateLockScreen();
105-
}
106-
else
107-
{
108-
ActivateLockScreen();
109-
}
179+
DeactivateLockScreen();
180+
}
181+
else if (pressedKeys.All(kvp => settings.LockShortcut.Contains(kvp.Key)) && !suppressInput && pressedKeys.Count == settings.LockShortcut.Count)
182+
{
183+
ActivateLockScreen();
110184
}
111185

112186
e.SuppressEvent = suppressInput;
@@ -171,7 +245,11 @@ private void RestoreWindows()
171245

172246
private void Animation()
173247
{
174-
Storyboard storyboard = new Storyboard();
248+
Storyboard storyboard = new Storyboard
249+
{
250+
FillBehavior = FillBehavior.Stop
251+
};
252+
175253
TimeSpan duration = TimeSpan.FromMilliseconds(500);
176254

177255
DoubleAnimation fadeInAnimation = new DoubleAnimation()

src/InvLock/MainWindow.xaml

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,6 @@
5656
It is designed to be lightweight and easy to use.
5757
<LineBreak />
5858
If you have any issues or feature requests, please report them on GitHub.
59-
<LineBreak />
60-
<LineBreak />
61-
To lock and unlock your screen, press
62-
<ui:TextBlock Foreground="{DynamicResource AccentTextFillColorPrimaryBrush}">WIN + SHIFT + L</ui:TextBlock>
6359
</ui:TextBlock>
6460

6561
<ui:TextBlock Margin="0,0,0,8" FontTypography="BodyStrong" Text="Appearance &amp; behavior" />
@@ -76,7 +72,7 @@
7672
</ui:HyperlinkButton>
7773
</Grid>
7874
</ui:CardControl.Header>
79-
<ComboBox Grid.Column="1" MinWidth="200" SelectedIndex="0">
75+
<ComboBox Grid.Column="1" MinWidth="200" SelectedIndex="0" SelectedValue="{Binding Settings.Theme}" SelectedValuePath="Content">
8076
<ComboBoxItem Content="Windows default" />
8177
<ComboBoxItem Content="Light" />
8278
<ComboBoxItem Content="Dark" />
@@ -90,20 +86,41 @@
9086
<ui:ToggleSwitch Grid.Column="1" IsChecked="{Binding Settings.HideWindows}" OffContent="Off" OnContent="On" />
9187
</ui:CardControl>
9288

89+
<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=WindowShield24}" Height="75">
90+
<ui:CardControl.Header>
91+
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Use windows lock screen to unlock" />
92+
</ui:CardControl.Header>
93+
<ui:ToggleSwitch Grid.Column="1" IsChecked="{Binding Settings.UseWindowsLockScreen}" OffContent="Off" OnContent="On" />
94+
</ui:CardControl>
95+
9396
<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockClosed24}" Height="75">
9497
<ui:CardControl.Header>
9598
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Lock text" />
9699
</ui:CardControl.Header>
97100
<ui:TextBox Grid.Column="1" MinWidth="200" Text="{Binding Settings.LockText, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Type your lock text here" />
98101
</ui:CardControl>
99102

103+
<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockClosed24}" Height="75">
104+
<ui:CardControl.Header>
105+
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Lock shortcut" />
106+
</ui:CardControl.Header>
107+
<ui:Button Grid.Column="1" Command="{Binding RecordLockShortcutCommand}" MinWidth="200" Icon="{ui:SymbolIcon Symbol=Edit24}" Content="{Binding Settings.LockShortcutText}" />
108+
</ui:CardControl>
109+
100110
<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockOpen24}" Height="75">
101111
<ui:CardControl.Header>
102112
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Unlock text" />
103113
</ui:CardControl.Header>
104114
<ui:TextBox Grid.Column="1" MinWidth="200" Text="{Binding Settings.UnlockText, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Type your unlock text here" />
105115
</ui:CardControl>
106116

117+
<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockOpen24}" Height="75">
118+
<ui:CardControl.Header>
119+
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Unlock shortcut" />
120+
</ui:CardControl.Header>
121+
<ui:Button Grid.Column="1" Command="{Binding RecordUnlockShortcutCommand}" MinWidth="200" Icon="{ui:SymbolIcon Symbol=Edit24}" Content="{Binding Settings.UnlockShortcutText}" />
122+
</ui:CardControl>
123+
107124
<ui:TextBlock Margin="0,24,0,8" FontTypography="BodyStrong" Text="About" />
108125
<ui:CardExpander ContentPadding="0">
109126
<ui:CardExpander.Header>
@@ -129,7 +146,26 @@
129146
<ColumnDefinition Width="Auto" />
130147
</Grid.ColumnDefinitions>
131148
<TextBlock Grid.Column="0" Text="Report an issue or request a feature" />
132-
<ui:SymbolIcon Grid.Column="1" Symbol="Link24" />
149+
<StackPanel Grid.Column="1" Orientation="Horizontal">
150+
<ui:SymbolIcon Margin="0 0 6 0" Symbol="Link24" />
151+
<TextBlock Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="https://github.com/Stone-Red-Code/InvLock/issues" />
152+
</StackPanel>
153+
</Grid>
154+
</ui:Anchor>
155+
156+
<Separator />
157+
158+
<ui:Anchor Margin="0" Padding="16" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Background="Transparent" CornerRadius="0" BorderThickness="0" NavigateUri="https://github.com/Stone-Red-Code/InvLock">
159+
<Grid>
160+
<Grid.ColumnDefinitions>
161+
<ColumnDefinition Width="*" />
162+
<ColumnDefinition Width="Auto" />
163+
</Grid.ColumnDefinitions>
164+
<TextBlock Grid.Column="0" Text="GitHub" />
165+
<StackPanel Grid.Column="1" Orientation="Horizontal">
166+
<ui:SymbolIcon Margin="0 0 6 0" Symbol="Link24" />
167+
<TextBlock Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="https://github.com/Stone-Red-Code/InvLock" />
168+
</StackPanel>
133169
</Grid>
134170
</ui:Anchor>
135171

@@ -140,13 +176,9 @@
140176
<ColumnDefinition Width="*" />
141177
<ColumnDefinition Width="Auto" />
142178
</Grid.ColumnDefinitions>
143-
<TextBlock Grid.Column="0" Text="Clone repository" />
144-
<TextBlock Grid.Column="1" Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="git clone https://github.com/Stone-Red-Code/InvLock" />
179+
<TextBlock Grid.Column="0" Text="Version" />
180+
<TextBlock Grid.Column="1" Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="{Binding AppVersion}" />
145181
</Grid>
146-
147-
<Separator />
148-
149-
<TextBlock Margin="16" Text="{Binding AppVersion, StringFormat='Version {0}'}" />
150182
</StackPanel>
151183
</ui:CardExpander>
152184
</StackPanel>

src/InvLock/MainWindow.xaml.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ namespace InvLock;
1212
/// </summary>
1313
public partial class MainWindow : FluentWindow
1414
{
15-
private readonly MainWindowDataContext mainWindowDataContext = new MainWindowDataContext();
15+
private readonly MainWindowDataContext mainWindowDataContext;
1616
private LockWindow? lockWindow;
1717
private bool blockWindowClosing = true;
1818

1919
public MainWindow()
2020
{
21+
mainWindowDataContext = new MainWindowDataContext(() => lockWindow);
2122
DataContext = mainWindowDataContext;
2223

2324
InitializeComponent();

0 commit comments

Comments
 (0)