Skip to content

Commit

Permalink
This is my largest commit yet. Please forgive me.
Browse files Browse the repository at this point in the history
From this day on, all future commits in this repository will be of adequate size (I promise!) 👼

To be honest, I can't muster the energy to document each individual file change, so I'll make it brief:

- The application now has a context menu!
Just right click that juicy icon to see all the different possibilities!

- Settings
1) CUSTOM HOTKEY(s)!: You can now bind your own hotkey instead of using the default one I created in a jiffy (WIN+SHIFT+K).
2) Adjust discovery time (the time in milliseconds the app should search for Bluetooth devices)

- UI updated slightly

- Some other negligible functionality that nobody will notice

Also, I tried to clean the code base and implement some sweet tricks here and there... Personally, I ain't satisfied, but I'll keep working hard to reach omnipotence.

Thanks for joining my TED talk.
  • Loading branch information
Karsten committed Jun 11, 2022
1 parent 577b91f commit 8da302a
Show file tree
Hide file tree
Showing 59 changed files with 1,996 additions and 540 deletions.
79 changes: 14 additions & 65 deletions BTQuickie/App.xaml
Original file line number Diff line number Diff line change
@@ -1,72 +1,21 @@
<Application x:Class="BTQuickie.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:t="clr-namespace:System;assembly=mscorlib"
xmlns:converters="clr-namespace:BTQuickie.Converters"
Startup="OnStartup">

<Application.Resources>

<!-- Colors -->
<!-- Gray -->
<Brush x:Key="Gray50"> #F9FAFB</Brush>
<Brush x:Key="Gray100">#F3F4F6</Brush>
<Brush x:Key="Gray200">#E5E7EB</Brush>
<Brush x:Key="Gray300">#D1D5DB</Brush>
<Brush x:Key="Gray400">#9CA3AF</Brush>
<Brush x:Key="Gray500">#6B7280</Brush>
<Brush x:Key="Gray600">#4B5563</Brush>
<Brush x:Key="Gray700">#374151</Brush>
<Brush x:Key="Gray800">#1F2937</Brush>
<Brush x:Key="Gray900">#111827</Brush>
<!-- Emerald -->
<Brush x:Key="Emerald500">#10B981</Brush>

<!-- Sizes -->
<!-- Thickness -->
<Thickness x:Key="ThicknessXMicro">1</Thickness>
<Thickness x:Key="ThicknessMicro">5</Thickness>
<Thickness x:Key="ThicknessXSmall">10</Thickness>
<Thickness x:Key="ThicknessSmall">25</Thickness>
<Thickness x:Key="ThicknessMedium">50</Thickness>
<Thickness x:Key="ThicknessLarge">70</Thickness>

<!-- Font Size -->
<t:Double x:Key="FontSizeXSmall">8</t:Double>
<t:Double x:Key="FontSizeSmall">11</t:Double>
<t:Double x:Key="FontSizeMedium">14</t:Double>
<t:Double x:Key="FontSizeLarge">22</t:Double>
<t:Double x:Key="FontSizeXLarge">36</t:Double>

<!-- Strings -->
<t:String x:Key="UnknownDeviceString">Unknown Device</t:String>

<!-- Converters -->
<converters:VisibilityBooleanConverter x:Key="VisibilityBooleanConverter" />
<converters:InvertedVisibilityBooleanConverter x:Key="InvertedVisibilityBooleanConverter" />
<converters:StringToVisibilityConverter x:Key="StringToVisibilityConverter" />
<converters:EmptyStringToParameterConverter x:Key="EmptyStringToParameterConverter" />

<ImageSource x:Key="TrayIconSource">Resources/Icons/exported_small.ico</ImageSource>

<!-- Styles -->

<!-- Grid -->
<Style TargetType="Grid"
x:Key="MainGridStyle">
<Setter Property="Background"
Value="{StaticResource Gray700}" />
</Style>
<!-- Label -->
<Style TargetType="Label">
<Setter Property="Foreground"
Value="{StaticResource Gray200}" />
</Style>
<!-- Button -->
<Style TargetType="Button">
<Setter Property="Foreground"
Value="{StaticResource Gray200}" />
</Style>

<ResourceDictionary>

<!-- Merged Dictionaries-->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml"/>
<ResourceDictionary Source="Resources/Styles/Converters.xaml"/>
<ResourceDictionary Source="Resources/Styles/Styles.xaml"/>
<ResourceDictionary Source="Resources/Styles/Values.xaml"/>
</ResourceDictionary.MergedDictionaries>

<!-- Tray Icon -->
<ImageSource x:Key="TrayIconSource">Resources/Icons/exported_small.ico</ImageSource>

</ResourceDictionary>
</Application.Resources>
</Application>
52 changes: 41 additions & 11 deletions BTQuickie/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Windows;
using BTQuickie.Extensions;
using BTQuickie.Services.Settings;
using BTQuickie.ViewModels.Base;
using BTQuickie.Views;
using Microsoft.Extensions.DependencyInjection;

Expand All @@ -9,26 +11,54 @@ namespace BTQuickie
public partial class App
{
private readonly IServiceProvider serviceProvider;
private readonly IApplicationSettingsProvider applicationSettingsProvider;

public App()
{
this.serviceProvider = new ServiceCollection()
.ConfigureServices()
.ConfigureViews()
.ConfigureViewModels()
.BuildServiceProvider();
}

private void OnStartup(object sender, StartupEventArgs e)
{
MainWindow = this.serviceProvider.GetService<MainWindow>();
MainWindow?.EnsureRendered();
IServiceProvider serviceProvider = new ServiceCollection()
.ConfigureServices()
.ConfigureViewModels()
.ConfigureViews()
.BuildServiceProvider();

this.applicationSettingsProvider = serviceProvider.GetRequiredService<IApplicationSettingsProvider>();
this.serviceProvider = serviceProvider;
}

protected override void OnDeactivated(EventArgs e)
{
base.OnDeactivated(e);
MainWindow?.Hide();
this.applicationSettingsProvider.WriteUserSettings();
}

private void OnStartup(object sender, StartupEventArgs e)
{
this.applicationSettingsProvider.WriteUserSettings();
TaskbarIconView taskbarIconView = this.serviceProvider.GetRequiredService<TaskbarIconView>();
SettingsView settingsView = this.serviceProvider.GetRequiredService<SettingsView>();
MainWindow = this.serviceProvider.GetRequiredService<MainView>();
taskbarIconView.EnsureHandle();
settingsView.EnsureHandle();
MainWindow.EnsureHandle();

foreach (Window window in Current.Windows)
{
window.Activated += OnWindowActivated;
}
}

private static void OnWindowActivated(object? o, EventArgs e)
{
Window window = (Window) o!;
ViewModelBase viewModelBase = (ViewModelBase) window.DataContext;
viewModelBase.InitializeAsync();
}

protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
this.applicationSettingsProvider.WriteUserSettings();
}
}
}
11 changes: 7 additions & 4 deletions BTQuickie/BTQuickie.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,30 @@
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>Resources\Icons\exported_small.ico</ApplicationIcon>
<Company>KMRH47</Company>
<AssemblyVersion>0.4</AssemblyVersion>
<FileVersion>0.4</FileVersion>
<AssemblyVersion>0.5</AssemblyVersion>
<FileVersion>0.5</FileVersion>
<LangVersion>preview</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.0.0-preview3" />
<PackageReference Include="FontAwesome.WPF" Version="4.7.0.9" />
<PackageReference Include="H.NotifyIcon.Wpf" Version="2.0.46" />
<PackageReference Include="InTheHand.Net.Bluetooth" Version="4.0.29" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0-preview.3.22175.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0-preview.3.22175.4" />
<PackageReference Include="TrayIcon" Version="1.0.7.2" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Update="Resources\Localization\AppResources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>AppResources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Remove="Resources\Settings\appsettings.json" />
<EmbeddedResource Include="Resources\Settings\appsettings.json" />
</ItemGroup>

<ItemGroup>
Expand All @@ -44,4 +47,4 @@
<Resource Include="Resources\Icons\exported_small.ico" />
</ItemGroup>

</Project>
</Project>
56 changes: 29 additions & 27 deletions BTQuickie/Behaviors/GlobalHotkeyBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Threading;

namespace BTQuickie.Behaviors;

public class GlobalHotkeyBehavior
{
private const int HOTKEY_ID = 9000;
private static HwndSource? _windowHandleSource;
private static KeyBinding? _keyBinding;

private static KeyBinding _keyBinding = new();
private static Key _key;
private static ModifierKeys _modifierKeys;

[DllImport("User32.dll")]
private static extern bool RegisterHotKey(
IntPtr windowHandle,
Expand All @@ -25,7 +28,7 @@ private static extern bool RegisterHotKey(
private static extern bool UnregisterHotKey(
IntPtr windowHandle,
int hotkeyId);

public static readonly DependencyProperty RegisterProperty =
DependencyProperty.RegisterAttached(
"Register",
Expand Down Expand Up @@ -60,34 +63,28 @@ private static void RegisterPropertyChanged(DependencyObject dependencyObject, D
return;
}

bool oldValue = (bool) e.OldValue;
bool newValue = (bool) e.NewValue;

Window window = Application.Current.MainWindow!;

if (oldValue && !newValue)
{
UnregisterHotkey(window);
}
else if (newValue && !oldValue)
{
_keyBinding = keyBinding;
window.SourceInitialized += RegisterHotKey;
}
_keyBinding = keyBinding;
keyBinding.Changed += KeyBindingOnChanged;
KeyBindingOnChanged(keyBinding, EventArgs.Empty);
}

private static void RegisterHotKey(object? sender, EventArgs e)
private static void KeyBindingOnChanged(object? sender, EventArgs e)
{
if (sender is not Window window)
if (_key == _keyBinding.Key && _modifierKeys == _keyBinding.Modifiers)
{
return;
}

if (_keyBinding is null)
{
return;
}
_key = _keyBinding.Key;
_modifierKeys = _keyBinding.Modifiers;

Window window = Application.Current.MainWindow!;
OnUnregisterHotkey(window);
OnRegisterHotKey(window);
}

private static void OnRegisterHotKey(Window window)
{
WindowInteropHelper windowInteropHelper = new(window);
uint key = (uint) KeyInterop.VirtualKeyFromKey(_keyBinding.Key);
uint modifiers = (uint) _keyBinding.Modifiers;
Expand All @@ -102,15 +99,14 @@ private static void RegisterHotKey(object? sender, EventArgs e)
Debug.WriteLine($"Hotkey couldn't be registered...");
}
}
private static void UnregisterHotkey(Window window)

private static void OnUnregisterHotkey(Window window)
{
if (_windowHandleSource is null)
{
return;
}

_keyBinding = null;
_windowHandleSource.RemoveHook(WindowHandleHook);
WindowInteropHelper windowInteropHelper = new(window);
UnregisterHotKey(windowInteropHelper.Handle, HOTKEY_ID);
Expand All @@ -135,7 +131,13 @@ private static IntPtr WindowHandleHook(
return IntPtr.Zero;
}

_keyBinding?.Command?.Execute(_keyBinding.CommandParameter);
if (Keyboard.FocusedElement is not null)
{
return IntPtr.Zero;
}

_keyBinding.Command.Execute(_keyBinding.CommandParameter);

isHandled = true;

return IntPtr.Zero;
Expand Down
58 changes: 58 additions & 0 deletions BTQuickie/Behaviors/NumericTextBoxBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace BTQuickie.Behaviors;

public class NumericTextBoxBehavior
{
public static readonly DependencyProperty IsNumericInputProperty =
DependencyProperty.RegisterAttached(
"NumericInput",
typeof(bool),
typeof(NumericTextBoxBehavior),
new PropertyMetadata(false, IsNumericInputPropertyChanged));

public static bool GetIsNumericInput(Control control)
{
return (bool) control.GetValue(IsNumericInputProperty);
}

/// <summary>
/// Forces focus on this element when its parent window is shown.
/// </summary>
public static void SetIsNumericInput(Control control, bool value)
{
control.SetValue(IsNumericInputProperty, value);
}

private static void IsNumericInputPropertyChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs args)
{
if (dependencyObject is not TextBox textBox)
{
return;
}

if (args.NewValue is not true)
{
return;
}

textBox.PreviewTextInput += TextBoxOnPreviewTextInput;
}

private static void TextBoxOnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
string text = e.Text;

if (text.Length <= 0)
{
e.Handled = true;
return;
}

bool isNotDigit = !char.IsDigit(text[^1]);
e.Handled = isNotDigit;
}
}
Loading

0 comments on commit 8da302a

Please sign in to comment.