Skip to content

Commit

Permalink
Merge pull request #9 from flyingpie/features/settings
Browse files Browse the repository at this point in the history
Settings
  • Loading branch information
flyingpie authored Aug 17, 2020
2 parents 05e2eab + 947aac0 commit 2360831
Show file tree
Hide file tree
Showing 8 changed files with 369 additions and 21 deletions.
73 changes: 64 additions & 9 deletions build.cake
Original file line number Diff line number Diff line change
@@ -1,19 +1,74 @@
#tool "nuget:?package=vswhere&version=2.6.7"
#tool "nuget:?package=ILRepack&version=2.0.18"

var configuration = Argument("configuration", "Release");
var output = Argument("output", "artifacts");
var version = Argument("version", "v0.4");

var sln = "windows-terminal-quake.sln";
var bin = "./windows-terminal-quake/bin";

Task("Default").Does(() =>
{
NuGetRestore(sln);
Task("Clean")
.Does(() =>
{
CleanDirectory(output);
});

Task("Build")
.IsDependentOn("Clean")
.Does(() =>
{
MSBuild(sln, new MSBuildSettings
{
Configuration = "Release",
Restore = true,
ToolPath = GetFiles(VSWhereLatest() + "/**/MSBuild.exe").FirstOrDefault()
});
});

MSBuild(sln, new MSBuildSettings
Task("Artifact.Regular")
.IsDependentOn("Build")
.Does(() =>
{
Configuration = "Release",
Restore = true,
ToolPath = GetFiles(VSWhereLatest() + "/**/MSBuild.exe").FirstOrDefault()
var art = output + "/Artifact.Regular";
CopyDirectory(bin, art);
DeleteFiles(art + "/*.config");
DeleteFiles(art + "/*.pdb");
});
});

RunTarget("Default");
Task("Artifact.SingleExe")
.IsDependentOn("Build")
.Does(() =>
{
var deps = GetFiles(bin + "/*.dll");
var art = output + "/Artifact.SingleExe";
System.IO.Directory.CreateDirectory(art);
ILRepack(
art + "/windows-terminal-quake.exe", // Output file
bin + "/windows-terminal-quake.exe", // Primary assembly
deps, // Assembly paths
new ILRepackSettings()
);
CopyFile(bin + "/windows-terminal-quake.json", art + "/windows-terminal-quake.json");
DeleteFile(art + "/windows-terminal-quake.exe.config");
});

Task("Artifact.SingleExe.Zip")
.IsDependentOn("Artifact.SingleExe")
.Does(() =>
{
var art = output + "/Artifact.SingleExe.Zip";
System.IO.Directory.CreateDirectory(art);
Zip(output + "/Artifact.SingleExe", art + $"/windows-terminal-quake-{version}-{DateTimeOffset.UtcNow:yyyy-MM-dd_HHmm}.zip");
});

Task("Default")
.IsDependentOn("Artifact.Regular")
.IsDependentOn("Artifact.SingleExe")
.IsDependentOn("Artifact.SingleExe.Zip")
.Does(() => {});

RunTarget("Default");
27 changes: 27 additions & 0 deletions windows-terminal-quake/Logging.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Serilog;
using System;
using System.IO;

namespace WindowsTerminalQuake
{
public static class Logging
{
public static void Configure()
{
var here = Path.GetDirectoryName(new Uri(typeof(Logging).Assembly.Location).AbsolutePath);

Log.Logger = new LoggerConfiguration()
.MinimumLevel.Is(Serilog.Events.LogEventLevel.Information)
.WriteTo.File(
path: Path.Combine(here, "logs/.txt"),
fileSizeLimitBytes: 10_000_000,
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 3
)
.CreateLogger()
;

Log.Information("Windows Terminal Quake started");
}
}
}
6 changes: 5 additions & 1 deletion windows-terminal-quake/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class Program

public static void Main(string[] args)
{
Logging.Configure();

_trayIcon = new TrayIcon((s, a) => Close());

try
Expand Down Expand Up @@ -40,7 +42,9 @@ public static void Main(string[] args)
};
_toggler = new Toggler(process);

_trayIcon.Notify(ToolTipIcon.Info, $"Windows Terminal Quake is running, press CTRL+~ or CTRL+Q to toggle.");
var hks = string.Join(" or ", Settings.Instance.Hotkeys.Select(hk => $"{hk.Modifiers}+{hk.Key}"));

_trayIcon.Notify(ToolTipIcon.Info, $"Windows Terminal Quake is running, press {hks} to toggle.");
}
catch (Exception ex)
{
Expand Down
132 changes: 132 additions & 0 deletions windows-terminal-quake/Settings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using Newtonsoft.Json;
using Polly;
using Polly.Retry;
using Serilog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using WindowsTerminalQuake.Native;
using WindowsTerminalQuake.UI;

namespace WindowsTerminalQuake
{
public class Settings
{
public static readonly string[] PathsToSettings = new[]
{
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "windows-terminal-quake.json"),
Path.Combine(Path.GetDirectoryName(new Uri(typeof(Settings).Assembly.Location).AbsolutePath), "windows-terminal-quake.json"),
};

public static SettingsDto Instance { get; private set; } = new SettingsDto() // Defaults
{
Hotkeys = new List<Hotkey>()
{
new Hotkey() { Modifiers = KeyModifiers.Control, Key = Keys.Oemtilde },
new Hotkey() { Modifiers = KeyModifiers.Control, Key = Keys.Q }
},
Notifications = true,
ToggleDurationMs = 250,
VerticalScreenCoverage = 100
};

private static readonly List<Action<SettingsDto>> _listeners = new List<Action<SettingsDto>>();

public static void Get(Action<SettingsDto> action)
{
_listeners.Add(action);

action(Instance);
}

#region Loading & Reloading

private static readonly RetryPolicy Retry = Policy
.Handle<Exception>()
.WaitAndRetry(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1) })
;

private static readonly List<FileSystemWatcher> _fsWatchers;

static Settings()
{
_fsWatchers = PathsToSettings
.Select(path =>
{
Log.Information($"Watching settings file '{path}' for changes");
var fsWatcher = new FileSystemWatcher(Path.GetDirectoryName(path), Path.GetFileName(path));
fsWatcher.Changed += (s, a) =>
{
Log.Information($"Settings file '{a.FullPath}' changed");
Reload(true);
};
fsWatcher.EnableRaisingEvents = true;
return fsWatcher;
})
.ToList()
;

Application.ApplicationExit += (s, a) => _fsWatchers.ForEach(w => w.Dispose());

Reload(false);
}

public static void Reload(bool notify)
{
Retry.Execute(() =>
{
Log.Information("Reloading settings");
foreach (var pathToSettings in PathsToSettings)
{
if (!File.Exists(pathToSettings))
{
Log.Warning($"Settings file at '{pathToSettings}' does not exist");
continue;
}
Log.Information($"Found settings file at '{pathToSettings}'");
try
{
Instance = JsonConvert.DeserializeObject<SettingsDto>(File.ReadAllText(pathToSettings));
Log.Information($"Loaded settings from '{pathToSettings}'");
if (notify) TrayIcon.Instance.Notify(ToolTipIcon.Info, $"Loaded settings from '{pathToSettings}'");
break;
}
catch (Exception ex)
{
Log.Error($"Could not load settings from file '{pathToSettings}': {ex.Message}", ex);
}
}
_listeners.ForEach(l => l(Instance));
});
}

#endregion Loading & Reloading
}

public class SettingsDto
{
public List<Hotkey> Hotkeys { get; set; }

public bool Notifications { get; set; }

public int VerticalScreenCoverage { get; set; }

public int ToggleDurationMs { get; set; }
}

public class Hotkey
{
public KeyModifiers Modifiers { get; set; }

public Keys Key { get; set; }
}
}
40 changes: 31 additions & 9 deletions windows-terminal-quake/Toggler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using Serilog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -11,6 +13,8 @@ public class Toggler : IDisposable
{
private Process _process;

private readonly List<int> _registeredHotKeys = new List<int>();

public Toggler(Process process)
{
_process = process;
Expand All @@ -23,28 +27,41 @@ public Toggler(Process process)
var isOpen = rect.Top >= GetScreenWithCursor().Bounds.Y;
User32.ShowWindow(_process.MainWindowHandle, NCmdShow.MAXIMIZE);

var stepCount = 10;
// Register hotkeys
Settings.Get(s =>
{
_registeredHotKeys.ForEach(hk => HotKeyManager.UnregisterHotKey(hk));
_registeredHotKeys.Clear();
HotKeyManager.RegisterHotKey(Keys.Oemtilde, KeyModifiers.Control);
HotKeyManager.RegisterHotKey(Keys.Q, KeyModifiers.Control);
s.Hotkeys.ForEach(hk =>
{
Log.Information($"Registering hot key {hk.Modifiers} + {hk.Key}");
var reg = HotKeyManager.RegisterHotKey(hk.Key, hk.Modifiers);
_registeredHotKeys.Add(reg);
});
});

HotKeyManager.HotKeyPressed += (s, a) =>
{
var stepCount = (int)Math.Max(Math.Ceiling(Settings.Instance.ToggleDurationMs / 25f), 1f);
var stepDelayMs = Settings.Instance.ToggleDurationMs / stepCount;
if (isOpen)
{
isOpen = false;
Console.WriteLine("Close");
Log.Information("Close");
User32.ShowWindow(_process.MainWindowHandle, NCmdShow.RESTORE);
User32.SetForegroundWindow(_process.MainWindowHandle);
var bounds = GetScreenWithCursor().Bounds;
bounds.Height = (int)Math.Ceiling((bounds.Height / 100f) * Settings.Instance.VerticalScreenCoverage);
for (int i = stepCount - 1; i >= 0; i--)
{
User32.MoveWindow(_process.MainWindowHandle, bounds.X, bounds.Y + (-bounds.Height + (bounds.Height / stepCount * i)), bounds.Width, bounds.Height, true);
Task.Delay(1).GetAwaiter().GetResult();
Task.Delay(TimeSpan.FromMilliseconds(stepDelayMs)).GetAwaiter().GetResult();
}
// Minimize, so the last window gets focus
Expand All @@ -56,20 +73,25 @@ public Toggler(Process process)
else
{
isOpen = true;
Console.WriteLine("Open");
Log.Information("Open");
User32.ShowWindow(_process.MainWindowHandle, NCmdShow.RESTORE);
User32.SetForegroundWindow(_process.MainWindowHandle);
var bounds = GetScreenWithCursor().Bounds;
bounds.Height = (int)Math.Ceiling((bounds.Height / 100f) * Settings.Instance.VerticalScreenCoverage);
for (int i = 1; i <= stepCount; i++)
{
User32.MoveWindow(_process.MainWindowHandle, bounds.X, bounds.Y + (-bounds.Height + (bounds.Height / stepCount * i)), bounds.Width, bounds.Height, true);
Task.Delay(1).GetAwaiter().GetResult();
Task.Delay(TimeSpan.FromMilliseconds(stepDelayMs)).GetAwaiter().GetResult();
}
if (Settings.Instance.VerticalScreenCoverage == 100)
{
User32.ShowWindow(_process.MainWindowHandle, NCmdShow.MAXIMIZE);
}
User32.ShowWindow(_process.MainWindowHandle, NCmdShow.MAXIMIZE);
}
};
}
Expand Down
9 changes: 8 additions & 1 deletion windows-terminal-quake/UI/TrayIcon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ namespace WindowsTerminalQuake.UI
{
public class TrayIcon : IDisposable
{
public static TrayIcon Instance { get; private set; }

private NotifyIcon _notificationIcon;

public TrayIcon(Action<object, EventArgs> exitHandler)
{
Instance = this;

var waiter = new TaskCompletionSource<bool>();

var notifyThread = new Thread(delegate ()
Expand Down Expand Up @@ -56,7 +60,10 @@ public void Dispose()

public void Notify(ToolTipIcon type, string message)
{
_notificationIcon.ShowBalloonTip(3, $"Windows Terminal", message, type);
if (Settings.Instance.Notifications)
{
_notificationIcon.ShowBalloonTip(3, $"Windows Terminal", message, type);
}
}

private static Icon CreateIcon()
Expand Down
Loading

0 comments on commit 2360831

Please sign in to comment.