diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..299c44b --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,36 @@ +name: Deploy to GitHub Releases + +on: + push: + branches: + - main + + workflow_dispatch: + +jobs: + deploy-to-github-releases: + runs-on: windows-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Get next version + uses: reecetech/version-increment@2024.4.3 + id: version + with: + scheme: calver + + - name: Install .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 10.0.x + + - name: Publish Application + run: dotnet publish WorkIndicator.csproj -c Release -o publish + + - name: Create Velopack Release + run: | + dotnet tool install -g vpk + vpk download github --repoUrl https://github.com/ckaczor/WorkIndicator + vpk pack -u WorkIndicator -v ${{ steps.version.outputs.version }} -p publish --packTitle "Work Indicator" --shortcuts StartMenuRoot --framework net10.0-x64-desktop + vpk upload github --repoUrl https://github.com/ckaczor/WorkIndicator --publish --releaseName "${{ steps.version.outputs.version }}" --tag v${{ steps.version.outputs.version }} --token ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3e352b1..8a30d25 100644 --- a/.gitignore +++ b/.gitignore @@ -1,34 +1,84 @@ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore # User-specific files +*.rsuser *.suo *.user +*.userosscache *.sln.docstates -# Build results +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs +# Mono auto generated files +mono_crash.* + +# Build results [Dd]ebug/ +[Dd]ebugPublic/ [Rr]elease/ +[Rr]eleases/ x64/ -build/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ [Bb]in/ [Oo]bj/ +[Ll]og/ +[Ll]ogs/ -# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets -!packages/*/build/ +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio *_i.c *_p.c +*_h.h *.ilk *.meta *.obj +*.iobj *.pch *.pdb +*.ipdb *.pgc *.pgd *.rsp @@ -38,26 +88,41 @@ build/ *.tlh *.tmp *.tmp_proj +*_wpftmp.csproj *.log +*.tlog *.vspscc *.vssscc .builds *.pidb -*.log +*.svclog *.scc +# Chutzpah Test files +_Chutzpah* + # Visual C++ cache files ipch/ *.aps *.ncb +*.opendb *.opensdf *.sdf *.cachefile +*.VC.db +*.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ # Guidance Automation Toolkit *.gpState @@ -65,6 +130,7 @@ ipch/ # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper +*.DotSettings.user # TeamCity is a build add-in _TeamCity* @@ -72,9 +138,30 @@ _TeamCity* # DotCover is a Code Coverage Tool *.dotCover +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + # NCrunch -*.ncrunch* +_NCrunch_* .*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ # Installshield output folder [Ee]xpress/ @@ -93,65 +180,219 @@ DocProject/Help/html publish/ # Publish Web Output -*.Publish.xml +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj -# NuGet Packages Directory -packages/ +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ -# Windows Azure Build Output -csx +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ *.build.csdef -# Windows Store app package directory +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ # Others -sql/ -*.Cache ClientBin/ -[Ss]tyle[Cc]op.* ~$* *~ *.dbmdl -*.[Pp]ublish.xml +*.dbproj.schemaview +*.jfm *.pfx *.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ # RIA/Silverlight projects Generated_Code/ -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak # SQL Server files -App_Data/*.mdf -App_Data/*.ldf +*.mdf +*.ldf +*.ndf +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl -#LightSwitch generated files -GeneratedArtifacts/ -_Pvt_Extensions/ -ModelManifest.xml +# Microsoft Fakes +FakesAssemblies/ -# ========================= -# Windows detritus -# ========================= +# GhostDoc plugin setting file +*.GhostDoc.xml -# Windows image file caches -Thumbs.db -ehthumbs.db +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ -# Folder config file -Desktop.ini +# Visual Studio 6 build log +*.plg -# Recycle Bin used on file shares -$RECYCLE.BIN/ +# Visual Studio 6 workspace options file +*.opt -# Mac desktop service store files -.DS_Store +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw -.vs/ \ No newline at end of file +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml diff --git a/App.config b/App.config new file mode 100644 index 0000000..b4ff76f --- /dev/null +++ b/App.config @@ -0,0 +1,27 @@ + + + + +
+ + + + + + + + + + + + True + + + True + + + Working + + + + \ No newline at end of file diff --git a/App.xaml b/App.xaml index 6e76e0f..d571574 100644 --- a/App.xaml +++ b/App.xaml @@ -1,8 +1,8 @@  - + \ No newline at end of file diff --git a/App.xaml.cs b/App.xaml.cs index 34192a9..40af218 100644 --- a/App.xaml.cs +++ b/App.xaml.cs @@ -1,114 +1,29 @@ -using Common.Helpers; -using Common.IO; -using Common.Wpf.Extensions; -using Squirrel; -using System; -using System.Reflection; -using System.Threading.Tasks; +using ChrisKaczor.Wpf.Application; +using System.Diagnostics; using System.Windows; -using System.Windows.Threading; using Settings = WorkIndicator.Properties.Settings; -namespace WorkIndicator +namespace WorkIndicator; + +public partial class App { - public partial class App + protected override void OnStartup(StartupEventArgs e) { - private IDisposable _isolationHandle; + base.OnStartup(e); - public static string UpdateUrl = "https://github.com/ckaczor/WorkIndicator"; + Current.SetStartWithWindows(!Debugger.IsAttached && Settings.Default.AutoStart); - private Dispatcher _dispatcher; - private InterprocessMessageListener _commandLineListener; + NotificationIcon.Initialize(); - [STAThread] - public static void Main(string[] args) - { - SquirrelAwareApp.HandleEvents(onAppUpdate: version => Common.Settings.Extensions.RestoreSettings()); - - var application = new App(); - application.InitializeComponent(); - application.Run(); - } - - protected override void OnStartup(StartupEventArgs e) - { - base.OnStartup(e); - - _dispatcher = Dispatcher.CurrentDispatcher; - - // Create an isolation handle to see if we are already running - _isolationHandle = ApplicationIsolation.GetIsolationHandle(); - - // If there is another copy then pass it the command line and exit - if (_isolationHandle == null) - { - try - { - InterprocessMessageSender.SendMessage(Environment.CommandLine); - } - catch { } - - Shutdown(); - return; - } - - // Initialize the command line listener - _commandLineListener = new InterprocessMessageListener(Assembly.GetEntryAssembly().GetName().Name); - _commandLineListener.MessageReceived += HandleCommandLine; - - // Initialize the tray icon - TrayIcon.Initialize(); - - Task.Factory.StartNew(CheckUpdate).ContinueWith(task => StartApplication(task.Result.Result)); - } - - private void StartApplication(bool updateRequired) - { - if (updateRequired) - return; - - Task.Factory.StartNew(() => - { - // Set automatic start into the registry - Current.SetStartWithWindows(Settings.Default.StartWithWindows); - - // Initialize the light controller - LightController.Initialize(); - }); - } - - private void HandleCommandLine(object sender, InterprocessMessageListener.InterprocessMessageEventArgs e) - { - - } - - private async Task CheckUpdate() - { - return await UpdateCheck.CheckUpdate(HandleUpdateStatus); - } - - private void HandleUpdateStatus(UpdateCheck.UpdateStatus status, string message) - { - if (status != UpdateCheck.UpdateStatus.Installing) - return; - - _dispatcher.Invoke(() => TrayIcon.ShowUpdateMessage(message)); - - TrayIcon.Dispose(); - } - - protected override void OnExit(ExitEventArgs e) - { - // Get rid of the light controller - LightController.Dispose(); - - // Get rid of the tray icon - TrayIcon.Dispose(); - - // Get rid of the isolation handle - _isolationHandle?.Dispose(); - - base.OnExit(e); - } + LightController.Initialize(); } -} + + protected override void OnExit(ExitEventArgs e) + { + LightController.Dispose(); + + NotificationIcon.Dispose(); + + base.OnExit(e); + } +} \ No newline at end of file diff --git a/AudioWatcher.cs b/AudioWatcher.cs index 2a1337b..447716f 100644 --- a/AudioWatcher.cs +++ b/AudioWatcher.cs @@ -1,91 +1,21 @@ -using CSCore.CoreAudioAPI; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; +namespace WorkIndicator; -namespace WorkIndicator +internal static class AudioWatcher { - public static class AudioWatcher + public delegate void MicrophoneInUseChangedDelegate(bool microphoneInUse); + + public static event MicrophoneInUseChangedDelegate MicrophoneInUseChanged; + + public static void Start() { - public delegate void MicrophoneInUseChangedDelegate(bool microphoneInUse); - - private static ManualResetEvent _manualResetEvent; - - private static readonly Dictionary ActiveSessions = new Dictionary(); - - public static event MicrophoneInUseChangedDelegate MicrophoneInUseChanged; - - public static void Start() - { - _manualResetEvent = new ManualResetEvent(false); - - var thread = new Thread(delegate () - { - var deviceEnumerator = new MMDeviceEnumerator(); - - foreach (var device in deviceEnumerator.EnumAudioEndpoints(DataFlow.Capture, DeviceState.Active)) - { - var sessionManager = AudioSessionManager2.FromMMDevice(device); - - var sessionEnumerator = sessionManager.GetSessionEnumerator(); - - sessionManager.SessionCreated += (sessionSender, sessionCreatedEventArgs) => HandleDeviceSession(device, sessionCreatedEventArgs.NewSession); - - foreach (var audioSessionControl in sessionEnumerator) - { - HandleDeviceSession(device, audioSessionControl); - } - } - - _manualResetEvent.WaitOne(); - }); - - thread.SetApartmentState(ApartmentState.MTA); - thread.Start(); - } - - private static void HandleDeviceSession(MMDevice device, AudioSessionControl audioSessionControl) - { - var deviceId = device.DeviceID + audioSessionControl.GroupingParam; - - if (!ActiveSessions.ContainsKey(deviceId)) - ActiveSessions[deviceId] = 0; - - HandleAudioStateChanged(deviceId, audioSessionControl.SessionState); - - audioSessionControl.StateChanged += (sender, sessionStateChangedEventArgs) => - HandleAudioStateChanged(deviceId, sessionStateChangedEventArgs.NewState); - } - - public static void Stop() - { - _manualResetEvent?.Set(); - } - - private static void HandleAudioStateChanged(string deviceId, AudioSessionState newState) - { - switch (newState) - { - case AudioSessionState.AudioSessionStateActive: - ActiveSessions[deviceId]++; - break; - case AudioSessionState.AudioSessionStateInactive: - if (ActiveSessions[deviceId] > 0) - ActiveSessions[deviceId]--; - break; - case AudioSessionState.AudioSessionStateExpired: - break; - default: - throw new ArgumentOutOfRangeException(); - } - - MicrophoneInUseChanged?.Invoke(MicrophoneInUse()); - } - - public static bool MicrophoneInUse() - { - return ActiveSessions.Any(a => a.Value > 0); - } } -} + + public static void Stop() + { + } + + public static bool MicrophoneInUse() + { + return false; + } +} \ No newline at end of file diff --git a/Delcom/DeviceManagement.cs b/Delcom/DeviceManagement.cs index 39bcc45..08b0bc7 100644 --- a/Delcom/DeviceManagement.cs +++ b/Delcom/DeviceManagement.cs @@ -4,7 +4,7 @@ using System.Windows.Forms; namespace WorkIndicator.Delcom { - sealed internal partial class DeviceManagement + internal sealed partial class DeviceManagement { /// /// Compares two device path names. Used to find out if the device name diff --git a/Delcom/StoplightIndicator.cs b/Delcom/StoplightIndicator.cs index aafe777..fa72683 100644 --- a/Delcom/StoplightIndicator.cs +++ b/Delcom/StoplightIndicator.cs @@ -1,5 +1,4 @@ -using Common.Extensions; -using System; +using System; using System.Diagnostics; namespace WorkIndicator.Delcom @@ -20,29 +19,24 @@ namespace WorkIndicator.Delcom Blink } - private readonly Delcom _delcom; - private LightState _green = LightState.Off; private LightState _yellow = LightState.Off; private LightState _red = LightState.Off; public StoplightIndicator() { - _delcom = new Delcom(); - _delcom.Open(); + Device = new Delcom(); + Device.Open(); SetLights(_red, _yellow, _green); } public void Dispose() { - _delcom.Close(); + Device.Close(); } - public Delcom Device - { - get { return _delcom; } - } + public Delcom Device { get; } public void GetLights(out LightState red, out LightState yellow, out LightState green) { @@ -65,7 +59,7 @@ namespace WorkIndicator.Delcom return _green; default: - throw new ArgumentOutOfRangeException("light"); + throw new ArgumentOutOfRangeException(nameof(light)); } } @@ -86,7 +80,7 @@ namespace WorkIndicator.Delcom port1 = port1.SetBitValue((int) Light.Yellow, yellow == LightState.Off); port1 = port1.SetBitValue((int) Light.Red, red == LightState.Off); - _delcom.WritePorts(0, port1); + Device.WritePorts(0, port1); var blinkEnable = 0; var blinkDisable = 0; @@ -106,7 +100,7 @@ namespace WorkIndicator.Delcom else blinkDisable = blinkDisable.SetBitValue((int) Light.Green, true); - _delcom.WriteBlink(blinkDisable, blinkEnable); + Device.WriteBlink(blinkDisable, blinkEnable); } public void SetLight(Light light, LightState state) @@ -130,7 +124,7 @@ namespace WorkIndicator.Delcom break; default: - throw new ArgumentOutOfRangeException("light"); + throw new ArgumentOutOfRangeException(nameof(light)); } SetLights(red, yellow, green); diff --git a/Extensions.cs b/Extensions.cs new file mode 100644 index 0000000..672ebed --- /dev/null +++ b/Extensions.cs @@ -0,0 +1,17 @@ +namespace WorkIndicator; + +public static class Extensions +{ + extension(int i) + { + public int SetBitValue(int bit, bool value) + { + if (value) + i |= 1 << bit; + else + i &= ~(1 << bit); + + return i; + } + } +} \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md index de8cb70..924aa2d 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Chris Kaczor +Copyright (c) 2026 Chris Kaczor Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/LightController.cs b/LightController.cs index f49c7d0..cab8a3f 100644 --- a/LightController.cs +++ b/LightController.cs @@ -15,20 +15,40 @@ namespace WorkIndicator public static class LightController { private static StoplightIndicator _stoplightIndicator; + private static UsbService _usbService; private static bool _initialized; private static Status _status = Status.Auto; public static void Initialize() { + _usbService = new UsbService(); + _usbService.DevicesChanged += DevicesChanged; + _stoplightIndicator = new StoplightIndicator(); _stoplightIndicator.SetLight(StoplightIndicator.Light.Yellow, StoplightIndicator.LightState.On); + Properties.Settings.Default.PropertyChanged += HandleSettingChange; + AudioWatcher.MicrophoneInUseChanged += AudioWatcher_MicrophoneInUseChanged; AudioWatcher.Start(); _initialized = true; } + private static void HandleSettingChange(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(Properties.Settings.Default.DefaultStatus)) + UpdateLights(); + } + + private static void DevicesChanged() + { + _stoplightIndicator?.Dispose(); + _stoplightIndicator = new StoplightIndicator(); + + UpdateLights(); + } + private static void AudioWatcher_MicrophoneInUseChanged(bool microphoneInUse) { UpdateLights(); @@ -44,6 +64,8 @@ namespace WorkIndicator _stoplightIndicator.SetLights(StoplightIndicator.LightState.Off, StoplightIndicator.LightState.Off, StoplightIndicator.LightState.Off); _stoplightIndicator.Dispose(); + _usbService.Dispose(); + _initialized = false; } @@ -63,36 +85,36 @@ namespace WorkIndicator var yellow = StoplightIndicator.LightState.Off; var green = StoplightIndicator.LightState.Off; - if (_status == Status.Auto) + var status = _status; + + if (status == Status.Auto) { if (AudioWatcher.MicrophoneInUse()) { - red = StoplightIndicator.LightState.On; + status = Status.OnPhone; } else { - yellow = StoplightIndicator.LightState.On; + status = (Status) Enum.Parse(typeof(Status), Properties.Settings.Default.DefaultStatus); } } - else + + switch (status) { - switch (_status) - { - case Status.Free: - green = StoplightIndicator.LightState.On; - break; - case Status.Working: - yellow = StoplightIndicator.LightState.On; - break; - case Status.OnPhone: - red = StoplightIndicator.LightState.On; - break; - case Status.Talking: - red = StoplightIndicator.LightState.Blink; - break; - default: - throw new ArgumentOutOfRangeException(); - } + case Status.Free: + green = StoplightIndicator.LightState.On; + break; + case Status.Working: + yellow = StoplightIndicator.LightState.On; + break; + case Status.OnPhone: + red = StoplightIndicator.LightState.On; + break; + case Status.Talking: + red = StoplightIndicator.LightState.Blink; + break; + default: + throw new ArgumentOutOfRangeException(); } _stoplightIndicator.SetLights(red, yellow, green); diff --git a/NotificationIcon.cs b/NotificationIcon.cs new file mode 100644 index 0000000..e0845e1 --- /dev/null +++ b/NotificationIcon.cs @@ -0,0 +1,107 @@ +using ChrisKaczor.Wpf.Windows; +using H.NotifyIcon; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using WorkIndicator.Properties; +using WorkIndicator.SettingsWindow; + +namespace WorkIndicator; + +internal static class NotificationIcon +{ + private static TaskbarIcon _notificationIcon; + private static readonly Dictionary StatusMenuItems = new(); + + public static void Initialize() + { + // Create the notification icon + _notificationIcon = new TaskbarIcon { Icon = Resources.ApplicationIcon }; + + // Set up the menu + var contextMenu = new ContextMenu(); + contextMenu.Opened += HandleContextMenuOpening; + + AddStatusMenuItem(contextMenu, Resources.StatusAuto, Status.Auto); + AddStatusMenuItem(contextMenu, Resources.StatusFree, Status.Free); + AddStatusMenuItem(contextMenu, Resources.StatusWorking, Status.Working); + AddStatusMenuItem(contextMenu, Resources.StatusOnPhone, Status.OnPhone); + AddStatusMenuItem(contextMenu, Resources.StatusTalking, Status.Talking); + + contextMenu.Items.Add(new Separator()); + + var menuItem = new MenuItem + { + Header = Resources.NotificationIconContextMenuSettings + }; + menuItem.Click += ShowSettings; + contextMenu.Items.Add(menuItem); + + contextMenu.Items.Add(new Separator()); + + menuItem = new MenuItem + { + Header = Resources.NotificationIconContextMenuExit + }; + menuItem.Click += HandleContextMenuExitClick; + contextMenu.Items.Add(menuItem); + + // Set the menu into the icon + _notificationIcon.ContextMenu = contextMenu; + + // Show the icon + _notificationIcon.ForceCreate(false); + } + + private static void ShowSettings(object sender, RoutedEventArgs e) + { + var categoryPanels = new List + { + new GeneralSettingsPanel(), + new UpdateSettingsPanel(), + new AboutSettingsPanel() + }; + + var settingsWindow = new CategoryWindow(categoryPanels, Resources.SettingsTitle, Resources.CloseButtonText); + + settingsWindow.ShowDialog(); + } + + private static void HandleContextMenuOpening(object sender, RoutedEventArgs e) + { + foreach (var menuItem in StatusMenuItems) + { + menuItem.Value.IsChecked = menuItem.Key == LightController.Status; + } + } + + private static void HandleContextMenuExitClick(object sender, System.EventArgs e) + { + Application.Current.Shutdown(); + } + + public static void Dispose() + { + // Get rid of the icon + _notificationIcon?.Dispose(); + _notificationIcon = null; + } + + public static void ShowBalloonTip(string text, H.NotifyIcon.Core.NotificationIcon icon) + { + _notificationIcon.ShowNotification(Resources.ApplicationName, text, icon); + } + + private static void AddStatusMenuItem(ContextMenu contextMenu, string text, Status status) + { + var menuItem = new MenuItem + { + Header = text, + IsCheckable = true, + IsChecked = status == LightController.Status + }; + menuItem.Click += (_, _) => LightController.Status = status; + contextMenu.Items.Add(menuItem); + StatusMenuItems[status] = menuItem; + } +} \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..12ea478 --- /dev/null +++ b/Program.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.Logging; +using Serilog; +using System; +using Velopack; + +namespace WorkIndicator; + +internal static class Program +{ + [STAThread] + public static void Main(string[] args) + { + Log.Logger = new LoggerConfiguration().WriteTo.File("log.txt").CreateLogger(); + + Log.Logger.Information("Start"); + + var loggerFactory = new LoggerFactory().AddSerilog(Log.Logger); + + VelopackApp.Build().Run(loggerFactory.CreateLogger("Install")); + + var app = new App(); + app.InitializeComponent(); + app.Run(); + + Log.Logger.Information("End"); + } +} \ No newline at end of file diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 16dbe6f..5a0314e 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -1,21 +1,59 @@ using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Versioning; using System.Windows; +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. [assembly: AssemblyTitle("WorkIndicator")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Chris Kaczor")] +[assembly: AssemblyCompany("")] [assembly: AssemblyProduct("WorkIndicator")] -[assembly: AssemblyCopyright("Copyright © Chris Kaczor 2012")] +[assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] +[assembly: SupportedOSPlatform("windows7.0")] +[assembly: NeutralResourcesLanguage("en-US")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] - -[assembly: AssemblyMetadata("SquirrelAwareVersion", "1")] \ No newline at end of file diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs index 77b8ca0..9942909 100644 --- a/Properties/Resources.Designer.cs +++ b/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace WorkIndicator.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { @@ -60,33 +60,6 @@ namespace WorkIndicator.Properties { } } - /// - /// Looks up a localized string similar to Version: {0}. - /// - public static string About_Version { - get { - return ResourceManager.GetString("About_Version", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Add. - /// - public static string AddWindowPattern { - get { - return ResourceManager.GetString("AddWindowPattern", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Add Window Pattern. - /// - public static string AddWindowPattern_ToolTip { - get { - return ResourceManager.GetString("AddWindowPattern_ToolTip", resourceCulture); - } - } - /// /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). /// @@ -107,11 +80,11 @@ namespace WorkIndicator.Properties { } /// - /// Looks up a localized string similar to Auto. + /// Looks up a localized string similar to Free. /// - public static string Auto { + public static string B { get { - return ResourceManager.GetString("Auto", resourceCulture); + return ResourceManager.GetString("B", resourceCulture); } } @@ -143,47 +116,38 @@ namespace WorkIndicator.Properties { } /// - /// Looks up a localized string similar to Enabled. + /// Looks up a localized string similar to Check _Now. /// - public static string ColumnHeader_Enabled { + public static string checkVersionNowButton { get { - return ResourceManager.GetString("ColumnHeader_Enabled", resourceCulture); + return ResourceManager.GetString("checkVersionNowButton", resourceCulture); } } /// - /// Looks up a localized string similar to Name. + /// Looks up a localized string similar to _Check for a new version on startup. /// - public static string ColumnHeader_Name { + public static string checkVersionOnStartupCheckBox { get { - return ResourceManager.GetString("ColumnHeader_Name", resourceCulture); + return ResourceManager.GetString("checkVersionOnStartupCheckBox", resourceCulture); } } /// - /// Looks up a localized string similar to Pattern. + /// Looks up a localized string similar to Close. /// - public static string ColumnHeader_Pattern { + public static string CloseButtonText { get { - return ResourceManager.GetString("ColumnHeader_Pattern", resourceCulture); + return ResourceManager.GetString("CloseButtonText", resourceCulture); } } /// - /// Looks up a localized string similar to Delete. + /// Looks up a localized string similar to Default status:. /// - public static string DeleteWindowPattern { + public static string DefaultStatusLabel { get { - return ResourceManager.GetString("DeleteWindowPattern", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Delete Window Pattern. - /// - public static string DeleteWindowPattern_ToolTip { - get { - return ResourceManager.GetString("DeleteWindowPattern_ToolTip", resourceCulture); + return ResourceManager.GetString("DefaultStatusLabel", resourceCulture); } } @@ -196,33 +160,6 @@ namespace WorkIndicator.Properties { } } - /// - /// Looks up a localized string similar to Edit. - /// - public static string EditWindowPattern { - get { - return ResourceManager.GetString("EditWindowPattern", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Edit Window Pattern. - /// - public static string EditWindowPattern_ToolTip { - get { - return ResourceManager.GetString("EditWindowPattern_ToolTip", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Free. - /// - public static string Free { - get { - return ResourceManager.GetString("Free", resourceCulture); - } - } - /// /// Looks up a localized string similar to Installing update.... /// @@ -242,11 +179,20 @@ namespace WorkIndicator.Properties { } /// - /// Looks up a localized string similar to No update found. + /// Looks up a localized string similar to Exit. /// - public static string NoUpdate { + public static string NotificationIconContextMenuExit { get { - return ResourceManager.GetString("NoUpdate", resourceCulture); + return ResourceManager.GetString("NotificationIconContextMenuExit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Settings. + /// + public static string NotificationIconContextMenuSettings { + get { + return ResourceManager.GetString("NotificationIconContextMenuSettings", resourceCulture); } } @@ -259,184 +205,133 @@ namespace WorkIndicator.Properties { } } - /// - /// Looks up a localized string similar to On Phone. - /// - public static string OnPhone { - get { - return ResourceManager.GetString("OnPhone", resourceCulture); - } - } - /// /// Looks up a localized string similar to About. /// - public static string OptionCategory_About { + public static string optionCategoryAbout { get { - return ResourceManager.GetString("OptionCategory_About", resourceCulture); + return ResourceManager.GetString("optionCategoryAbout", resourceCulture); } } /// /// Looks up a localized string similar to General. /// - public static string OptionCategory_General { + public static string optionCategoryGeneral { get { - return ResourceManager.GetString("OptionCategory_General", resourceCulture); + return ResourceManager.GetString("optionCategoryGeneral", resourceCulture); } } /// - /// Looks up a localized string similar to Window Patterns. + /// Looks up a localized string similar to Update. /// - public static string OptionCategory_WindowPatterns { + public static string optionCategoryUpdate { get { - return ResourceManager.GetString("OptionCategory_WindowPatterns", resourceCulture); + return ResourceManager.GetString("optionCategoryUpdate", resourceCulture); } } /// - /// Looks up a localized string similar to Cancel. + /// Looks up a localized string similar to Settings. /// - public static string OptionsWindow_CancelButton { + public static string SettingsTitle { get { - return ResourceManager.GetString("OptionsWindow_CancelButton", resourceCulture); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). - /// - public static System.Drawing.Icon OptionsWindow_Icon { - get { - object obj = ResourceManager.GetObject("OptionsWindow_Icon", resourceCulture); - return ((System.Drawing.Icon)(obj)); - } - } - - /// - /// Looks up a localized string similar to OK. - /// - public static string OptionsWindow_OkayButton { - get { - return ResourceManager.GetString("OptionsWindow_OkayButton", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Options. - /// - public static string OptionsWindow_Title { - get { - return ResourceManager.GetString("OptionsWindow_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Restarting application.... - /// - public static string RestartingAfterUpdate { - get { - return ResourceManager.GetString("RestartingAfterUpdate", resourceCulture); + return ResourceManager.GetString("SettingsTitle", resourceCulture); } } /// /// Looks up a localized string similar to _Start when Windows starts. /// - public static string StartWithWindows { + public static string startWithWindowsCheckBox { get { - return ResourceManager.GetString("StartWithWindows", resourceCulture); + return ResourceManager.GetString("startWithWindowsCheckBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Auto. + /// + public static string StatusAuto { + get { + return ResourceManager.GetString("StatusAuto", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Free. + /// + public static string StatusFree { + get { + return ResourceManager.GetString("StatusFree", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to On Phone. + /// + public static string StatusOnPhone { + get { + return ResourceManager.GetString("StatusOnPhone", resourceCulture); } } /// /// Looks up a localized string similar to Talking. /// - public static string Talking { + public static string StatusTalking { get { - return ResourceManager.GetString("Talking", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Exit. - /// - public static string TrayIconContextMenuExit { - get { - return ResourceManager.GetString("TrayIconContextMenuExit", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Options.... - /// - public static string TrayIconContextMenuSettings { - get { - return ResourceManager.GetString("TrayIconContextMenuSettings", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Updating application.... - /// - public static string Updating { - get { - return ResourceManager.GetString("Updating", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to _Enabled:. - /// - public static string WindowPatternEnabledLabel { - get { - return ResourceManager.GetString("WindowPatternEnabledLabel", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to _Name:. - /// - public static string WindowPatternNameLabel { - get { - return ResourceManager.GetString("WindowPatternNameLabel", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to _Pattern:. - /// - public static string WindowPatternPatternLabel { - get { - return ResourceManager.GetString("WindowPatternPatternLabel", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Add Window Pattern. - /// - public static string WindowPatternWindowAdd { - get { - return ResourceManager.GetString("WindowPatternWindowAdd", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Edit Window Pattern. - /// - public static string WindowPatternWindowEdit { - get { - return ResourceManager.GetString("WindowPatternWindowEdit", resourceCulture); + return ResourceManager.GetString("StatusTalking", resourceCulture); } } /// /// Looks up a localized string similar to Working. /// - public static string Working { + public static string StatusWorking { get { - return ResourceManager.GetString("Working", resourceCulture); + return ResourceManager.GetString("StatusWorking", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are already running the most recent version. + /// + ///No updates are available at this time.. + /// + public static string UpdateCheckCurrent { + get { + return ResourceManager.GetString("UpdateCheckCurrent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Version {0} is now available. + /// + ///Would you like to download and install it now?. + /// + public static string UpdateCheckNewVersion { + get { + return ResourceManager.GetString("UpdateCheckNewVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} Update. + /// + public static string UpdateCheckTitle { + get { + return ResourceManager.GetString("UpdateCheckTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Version {0}. + /// + public static string Version { + get { + return ResourceManager.GetString("Version", resourceCulture); } } } diff --git a/Properties/Resources.resx b/Properties/Resources.resx index 1263abc..3617650 100644 --- a/Properties/Resources.resx +++ b/Properties/Resources.resx @@ -117,108 +117,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Version: {0} - - - Add - - - Add Window Pattern - - ..\Resources\ApplicationIcon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\Application.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a Work Indicator - - Auto - - - Cancel - - - Enabled - - - Name - - - Pattern - - - Delete - - - Delete Window Pattern - - - Edit - - - Edit Window Pattern - - - Free - - - OK - - - On Phone - - + About - - General + + _Check for Update - - Window Patterns - - - Cancel - - - ..\Resources\ApplicationIcon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - OK - - - Options - - + _Start when Windows starts - - Talking + + General - - Exit + + Settings - - Options... + + Close - - _Enabled: + + Version {0} - - _Name: + + Update - - _Pattern: + + _Check for a new version on startup - - Add Window Pattern + + Check _Now - - Edit Window Pattern + + {0} Update - - Working + + You are already running the most recent version. + +No updates are available at this time. + + + Version {0} is now available. + +Would you like to download and install it now? + + + Loading... Checking for update... @@ -226,22 +176,40 @@ Downloading update... - - No update found - - - Updating application... - - - Restarting application... - Installing update... - - Loading... + + OK - - _Check for Update + + Cancel + + + Exit + + + Free + + + Working + + + On Phone + + + Talking + + + Settings + + + Free + + + Auto + + + Default status: \ No newline at end of file diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs index adff8ca..77ca8fa 100644 --- a/Properties/Settings.Designer.cs +++ b/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace WorkIndicator.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "18.9.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -25,43 +25,49 @@ namespace WorkIndicator.Properties { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool StartWithWindows { + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string WindowSettings { get { - return ((bool)(this["StartWithWindows"])); + return ((string)(this["WindowSettings"])); } set { - this["StartWithWindows"] = value; - } - } - - [global::System.Configuration.ApplicationScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("00:00:10")] - public global::System.TimeSpan RetryInterval { - get { - return ((global::System.TimeSpan)(this["RetryInterval"])); - } - } - - [global::System.Configuration.ApplicationScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("00:00:00.5000000")] - public global::System.TimeSpan UpdateInterval { - get { - return ((global::System.TimeSpan)(this["UpdateInterval"])); + this["WindowSettings"] = value; } } [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] - public string WindowPatterns { + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool AutoStart { get { - return ((string)(this["WindowPatterns"])); + return ((bool)(this["AutoStart"])); } set { - this["WindowPatterns"] = value; + this["AutoStart"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool CheckVersionAtStartup { + get { + return ((bool)(this["CheckVersionAtStartup"])); + } + set { + this["CheckVersionAtStartup"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Working")] + public string DefaultStatus { + get { + return ((string)(this["DefaultStatus"])); + } + set { + this["DefaultStatus"] = value; } } } diff --git a/Properties/Settings.settings b/Properties/Settings.settings index 7cd4587..74a8ad2 100644 --- a/Properties/Settings.settings +++ b/Properties/Settings.settings @@ -2,17 +2,17 @@ - + + + + True - - 00:00:10 + + True - - 00:00:00.5000000 - - - + + Working \ No newline at end of file diff --git a/README.md b/README.md index e8e4a51..91afc13 100644 --- a/README.md +++ b/README.md @@ -1,11 +1 @@ -# WorkIndicator - -Controls a [Delcom Green/Yellow/Red Indicator](https://www.delcomproducts.com/productdetails.asp?PartNumber=907241) to show work status (free, working, on phone, talking) either manually or by automatically detecting a window title. - -## Authors - -* **Chris Kaczor** - *Initial work* - https://github.com/ckaczor - https://chriskaczor.com - -## License - -This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details. +# WorkIndicator \ No newline at end of file diff --git a/Resources/Application.ico b/Resources/Application.ico new file mode 100644 index 0000000..9c706cf Binary files /dev/null and b/Resources/Application.ico differ diff --git a/SettingsWindow/AboutSettingsPanel.xaml b/SettingsWindow/AboutSettingsPanel.xaml new file mode 100644 index 0000000..a09370b --- /dev/null +++ b/SettingsWindow/AboutSettingsPanel.xaml @@ -0,0 +1,21 @@ + + + + + + + + + \ No newline at end of file diff --git a/SettingsWindow/AboutSettingsPanel.xaml.cs b/SettingsWindow/AboutSettingsPanel.xaml.cs new file mode 100644 index 0000000..79f2b84 --- /dev/null +++ b/SettingsWindow/AboutSettingsPanel.xaml.cs @@ -0,0 +1,12 @@ +namespace WorkIndicator.SettingsWindow +{ + public partial class AboutSettingsPanel + { + public AboutSettingsPanel() + { + InitializeComponent(); + } + + public override string CategoryName => Properties.Resources.optionCategoryAbout; + } +} \ No newline at end of file diff --git a/SettingsWindow/GeneralSettingsPanel.xaml b/SettingsWindow/GeneralSettingsPanel.xaml new file mode 100644 index 0000000..ba455d1 --- /dev/null +++ b/SettingsWindow/GeneralSettingsPanel.xaml @@ -0,0 +1,33 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/SettingsWindow/GeneralSettingsPanel.xaml.cs b/SettingsWindow/GeneralSettingsPanel.xaml.cs new file mode 100644 index 0000000..b9851ac --- /dev/null +++ b/SettingsWindow/GeneralSettingsPanel.xaml.cs @@ -0,0 +1,36 @@ +using ChrisKaczor.Wpf.Application; +using System.Windows; +using WorkIndicator.Properties; + +namespace WorkIndicator.SettingsWindow; + +public partial class GeneralSettingsPanel +{ + public GeneralSettingsPanel() + { + InitializeComponent(); + } + + public override string CategoryName => Properties.Resources.optionCategoryGeneral; + + public override void LoadPanel(Window parentWindow) + { + base.LoadPanel(parentWindow); + + MarkLoaded(); + } + + private void OnSaveSettings(object sender, RoutedEventArgs e) + { + SaveSettings(); + } + + private void SaveSettings() + { + if (!HasLoaded) return; + + Settings.Default.Save(); + + Application.Current.SetStartWithWindows(Settings.Default.AutoStart); + } +} \ No newline at end of file diff --git a/SettingsWindow/UpdateSettingsPanel.xaml b/SettingsWindow/UpdateSettingsPanel.xaml new file mode 100644 index 0000000..335133d --- /dev/null +++ b/SettingsWindow/UpdateSettingsPanel.xaml @@ -0,0 +1,22 @@ + + + +