Skip to content

Commit 35d397e

Browse files
authored
Merge pull request #6 from devohmycode/0.3.0
Release 0.3.0
2 parents 5272f2b + 6cd8f4d commit 35d397e

14 files changed

Lines changed: 2716 additions & 13 deletions

‎ActionPanel.cs‎

Lines changed: 367 additions & 1 deletion
Large diffs are not rendered by default.

‎App.xaml.cs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ protected override void OnLaunched(LaunchActivatedEventArgs args)
1919
ReminderService.Initialize();
2020
_window = new MainWindow();
2121
_window.Activate();
22+
23+
if (AppSettings.LoadStartMinimized())
24+
{
25+
var appWindow = _window.AppWindow;
26+
appWindow.Hide();
27+
}
2228
}
2329

2430
public static void ApplyFontResource(string font)

‎AppSettings.cs‎

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,108 @@ public static void SaveNoteStyle(string style)
176176
MergeAndSaveSettings(new Dictionary<string, object> { ["noteStyle"] = style });
177177
}
178178

179+
// ── Startup ─────────────────────────────────────────────────
180+
181+
private const string StartupRegistryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
182+
private const string StartupRegistryName = "NoteUI";
183+
184+
public static bool LoadStartWithWindows()
185+
{
186+
try
187+
{
188+
using var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(StartupRegistryKey, false);
189+
return key?.GetValue(StartupRegistryName) is string;
190+
}
191+
catch { return false; }
192+
}
193+
194+
public static void SaveStartWithWindows(bool enabled)
195+
{
196+
try
197+
{
198+
using var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(StartupRegistryKey, true);
199+
if (key == null) return;
200+
if (enabled)
201+
{
202+
var exePath = Environment.ProcessPath ?? "";
203+
if (!string.IsNullOrEmpty(exePath))
204+
key.SetValue(StartupRegistryName, $"\"{exePath}\"");
205+
}
206+
else
207+
{
208+
key.DeleteValue(StartupRegistryName, false);
209+
}
210+
}
211+
catch { }
212+
}
213+
214+
public static bool LoadStartMinimized()
215+
{
216+
try
217+
{
218+
if (File.Exists(SettingsPath))
219+
{
220+
var json = File.ReadAllText(SettingsPath);
221+
var doc = JsonDocument.Parse(json);
222+
if (doc.RootElement.TryGetProperty("startMinimized", out var prop))
223+
return prop.GetBoolean();
224+
}
225+
}
226+
catch { }
227+
return false;
228+
}
229+
230+
public static void SaveStartMinimized(bool enabled)
231+
{
232+
MergeAndSaveSettings(new Dictionary<string, object> { ["startMinimized"] = enabled });
233+
}
234+
235+
// ── Compact cards ────────────────────────────────────────
236+
237+
public static bool LoadCompactCards()
238+
{
239+
try
240+
{
241+
if (File.Exists(SettingsPath))
242+
{
243+
var json = File.ReadAllText(SettingsPath);
244+
var doc = JsonDocument.Parse(json);
245+
if (doc.RootElement.TryGetProperty("compactCards", out var prop))
246+
return prop.GetBoolean();
247+
}
248+
}
249+
catch { }
250+
return false;
251+
}
252+
253+
public static void SaveCompactCards(bool enabled)
254+
{
255+
MergeAndSaveSettings(new Dictionary<string, object> { ["compactCards"] = enabled });
256+
}
257+
258+
// ── Sort preference ────────────────────────────────────────
259+
260+
public static string LoadSortPreference()
261+
{
262+
try
263+
{
264+
if (File.Exists(SettingsPath))
265+
{
266+
var json = File.ReadAllText(SettingsPath);
267+
var doc = JsonDocument.Parse(json);
268+
if (doc.RootElement.TryGetProperty("sortMode", out var prop))
269+
return prop.GetString() ?? "recent";
270+
}
271+
}
272+
catch { }
273+
return "recent";
274+
}
275+
276+
public static void SaveSortPreference(string mode)
277+
{
278+
MergeAndSaveSettings(new Dictionary<string, object> { ["sortMode"] = mode });
279+
}
280+
179281
// ── Slash commands ──────────────────────────────────────────
180282

181283
public static bool LoadSlashEnabled()

‎ClipboardMonitor.cs‎

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System.Runtime.InteropServices;
2+
using System.Text;
3+
using Microsoft.UI.Xaml;
4+
using WinRT.Interop;
5+
6+
namespace NoteUI;
7+
8+
internal sealed class ClipboardMonitor : IDisposable
9+
{
10+
private readonly IntPtr _ownHwnd;
11+
12+
public string? SourceExePath { get; private set; }
13+
public string? SourceTitle { get; private set; }
14+
15+
public ClipboardMonitor(Window window)
16+
{
17+
_ownHwnd = WindowNative.GetWindowHandle(window);
18+
Windows.ApplicationModel.DataTransfer.Clipboard.ContentChanged += OnContentChanged;
19+
}
20+
21+
private void OnContentChanged(object? sender, object e)
22+
{
23+
try
24+
{
25+
var fgHwnd = GetForegroundWindow();
26+
if (fgHwnd == IntPtr.Zero || fgHwnd == _ownHwnd) return;
27+
28+
GetWindowThreadProcessId(fgHwnd, out var pid);
29+
if (pid == 0) return;
30+
31+
SourceExePath = GetProcessPath(pid);
32+
33+
var sb = new StringBuilder(512);
34+
GetWindowText(fgHwnd, sb, sb.Capacity);
35+
SourceTitle = sb.ToString();
36+
}
37+
catch { }
38+
}
39+
40+
private static string? GetProcessPath(uint pid)
41+
{
42+
const uint PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
43+
var handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid);
44+
if (handle == IntPtr.Zero) return null;
45+
try
46+
{
47+
var sb = new StringBuilder(1024);
48+
int size = sb.Capacity;
49+
return QueryFullProcessImageName(handle, 0, sb, ref size) ? sb.ToString() : null;
50+
}
51+
finally
52+
{
53+
CloseHandle(handle);
54+
}
55+
}
56+
57+
public static string CleanTitle(string? title, string? exePath)
58+
{
59+
if (string.IsNullOrEmpty(title)) return "";
60+
61+
var processName = string.IsNullOrEmpty(exePath)
62+
? ""
63+
: Path.GetFileNameWithoutExtension(exePath).ToLowerInvariant();
64+
65+
if (processName is "chrome" or "msedge" or "firefox" or "brave" or "opera" or "vivaldi" or "arc")
66+
{
67+
string[] suffixes =
68+
[
69+
" - Google Chrome", " \u2014 Mozilla Firefox", " - Mozilla Firefox",
70+
" - Microsoft\u200B Edge", " - Microsoft Edge",
71+
" - Brave", " - Opera", " - Vivaldi", " - Arc"
72+
];
73+
foreach (var suffix in suffixes)
74+
{
75+
if (title.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
76+
return title[..^suffix.Length];
77+
}
78+
}
79+
80+
return title;
81+
}
82+
83+
public void Dispose()
84+
{
85+
Windows.ApplicationModel.DataTransfer.Clipboard.ContentChanged -= OnContentChanged;
86+
}
87+
88+
[DllImport("user32.dll")]
89+
private static extern IntPtr GetForegroundWindow();
90+
91+
[DllImport("user32.dll")]
92+
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
93+
94+
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
95+
private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int maxCount);
96+
97+
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
98+
private static extern bool QueryFullProcessImageName(IntPtr hProcess, int flags, StringBuilder buffer, ref int size);
99+
100+
[DllImport("kernel32.dll", SetLastError = true)]
101+
private static extern IntPtr OpenProcess(uint access, bool inheritHandle, uint processId);
102+
103+
[DllImport("kernel32.dll")]
104+
private static extern bool CloseHandle(IntPtr handle);
105+
}

‎HotkeyService.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ internal sealed class HotkeyService : IDisposable
1010
// Hotkey IDs
1111
public const int HOTKEY_SHOW = 1;
1212
public const int HOTKEY_NEW_NOTE = 2;
13+
public const int HOTKEY_PASTE_NOTE = 3;
1314

1415
[Flags]
1516
public enum Modifiers : uint
@@ -77,6 +78,7 @@ public static List<ShortcutEntry> GetDefaults() =>
7778
[
7879
new("show", Lang.T("shortcut_show"), Modifiers.Ctrl | Modifiers.Alt, 0x4E), // Ctrl+Alt+N
7980
new("new_note", Lang.T("shortcut_new_note"), Modifiers.Ctrl, 0x4E), // Ctrl+N
81+
new("paste_note", Lang.T("shortcut_paste_note"), Modifiers.Ctrl | Modifiers.Alt, 0x56), // Ctrl+Alt+V
8082
new("flyout_back", Lang.T("shortcut_flyout_back"), Modifiers.Ctrl, 0x50), // Ctrl+P
8183
];
8284

0 commit comments

Comments
 (0)