From 7b67c03270ec0c664f77ff5a5c8c962d0fc01e6b Mon Sep 17 00:00:00 2001
From: minster586 <43217359+minster586@users.noreply.github.com>
Date: Thu, 3 Sep 2026 00:20:33 -0400
Subject: [PATCH] Added in Windows toast notifications
---
RadioDJViewer/Main.cs | 345 ++++++++++++++++++
RadioDJViewer/ProfileStorage.cs | 1 +
RadioDJViewer/Program.cs | 13 +-
RadioDJViewer/Properties/AssemblyInfo.cs | 4 +-
.../radiodj-restapi-template.Designer.cs | 90 +++--
RadioDJViewer/radiodj-restapi-template.cs | 4 +-
6 files changed, 426 insertions(+), 31 deletions(-)
diff --git a/RadioDJViewer/Main.cs b/RadioDJViewer/Main.cs
index 8143543..86d74d6 100644
--- a/RadioDJViewer/Main.cs
+++ b/RadioDJViewer/Main.cs
@@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -12,6 +14,10 @@ using System.Threading;
using System.IO;
using System.Resources;
using System.Globalization;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Security;
namespace RadioDJViewer
{
@@ -294,6 +300,28 @@ namespace RadioDJViewer
{
_currentTrackKey = newKey;
ShowTemporaryStatus("Song Change Detected", 2000);
+ bool toastEnabled = IsToastEnabledForActiveProfile();
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[Toast] Track changed. Enabled={toastEnabled}, Profile={loadedProfile?.Name ?? "(null)"}");
+#endif
+ if (toastEnabled)
+ {
+ try
+ {
+ string outputImagePath = GetProfileOutputImagePath();
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[Toast] Trigger with title='{marqueeTextTitle}', artist='{marqueeTextArtist}', imagePath='{outputImagePath}'");
+#endif
+ ShowTrackChangeToast(marqueeTextTitle, marqueeTextArtist, outputImagePath);
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[Toast] Trigger error: {ex}");
+ MessageBox.Show($"Toast trigger failed: {ex.Message}", "Toast Debug", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+#endif
+ }
+ }
}
}
catch { }
@@ -443,6 +471,7 @@ namespace RadioDJViewer
{
var resized = new Bitmap(fallbackImg, pictureBox1.Size);
pictureBox1.Image = resized;
+ currentSongImagePath = defaultImagePath;
// Save fallback image to output folder as PNG
if (!string.IsNullOrEmpty(outputFolderPath) && !string.IsNullOrEmpty(outputImageName))
{
@@ -453,6 +482,7 @@ namespace RadioDJViewer
else
{
pictureBox1.Image = null;
+ currentSongImagePath = defaultImagePath;
}
return;
}
@@ -462,6 +492,7 @@ namespace RadioDJViewer
{
var resized = new Bitmap(img, pictureBox1.Size);
pictureBox1.Image = resized;
+ currentSongImagePath = imagePath;
// Save to output folder as PNG
if (!string.IsNullOrEmpty(outputFolderPath) && !string.IsNullOrEmpty(outputImageName))
{
@@ -478,6 +509,7 @@ namespace RadioDJViewer
{
var resized = new Bitmap(fallbackImg, pictureBox1.Size);
pictureBox1.Image = resized;
+ currentSongImagePath = defaultImagePath;
if (!string.IsNullOrEmpty(outputFolderPath) && !string.IsNullOrEmpty(outputImageName))
{
string destPath = Path.Combine(outputFolderPath, Path.ChangeExtension(outputImageName, ".png"));
@@ -487,6 +519,7 @@ namespace RadioDJViewer
else
{
pictureBox1.Image = null;
+ currentSongImagePath = defaultImagePath;
}
}
}
@@ -970,5 +1003,317 @@ namespace RadioDJViewer
int secs = seconds % 60;
return $"{minutes}:{secs:D2}";
}
+
+ private bool IsToastEnabledForActiveProfile()
+ {
+ return loadedProfile != null && loadedProfile.ToastNotificationsEnabled;
+ }
+
+ private string GetProfileOutputImagePath()
+ {
+ if (string.IsNullOrWhiteSpace(outputFolderPath) || string.IsNullOrWhiteSpace(loadedProfile?.OutputImageName))
+ return string.Empty;
+
+ try
+ {
+ string imageName = Path.ChangeExtension(loadedProfile.OutputImageName, ".png");
+ string fullPath = Path.GetFullPath(Path.Combine(outputFolderPath, imageName));
+ return fullPath;
+ }
+ catch
+ {
+ return string.Empty;
+ }
+ }
+
+ private void ShowTrackChangeToast(string title, string artist, string outputImagePath)
+ {
+ string safeTitle = string.IsNullOrWhiteSpace(title) ? "No title" : title;
+ string safeArtist = string.IsNullOrWhiteSpace(artist) ? "No artist" : artist;
+ DateTime now = DateTime.Now;
+ string attribution = $"Date: {now:MM/dd/yyyy} | Time: {now:hh:mm tt}";
+ try
+ {
+ ToastNotificationService.ShowTrackChangeToast(safeTitle, safeArtist, attribution, outputImagePath);
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[Toast] ShowTrackChangeToast failed: {ex}");
+ MessageBox.Show($"Toast display failed: {ex.Message}", "Toast Debug", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+#endif
+ }
+ }
+ }
+
+ internal static class ToastNotificationService
+ {
+ private const string AppId = "RadioDJViewer.App";
+ private static bool _initialized;
+
+ public static void ShowTrackChangeToast(string trackTitle, string artistName, string attributionLine, string outputImagePath)
+ {
+ try
+ {
+ EnsureInitialized();
+ string toastXml = BuildToastXml(trackTitle, artistName, attributionLine, outputImagePath);
+
+ var xmlDocumentType = Type.GetType("Windows.Data.Xml.Dom.XmlDocument, Windows, ContentType=WindowsRuntime");
+ var toastType = Type.GetType("Windows.UI.Notifications.ToastNotification, Windows, ContentType=WindowsRuntime");
+ var managerType = Type.GetType("Windows.UI.Notifications.ToastNotificationManager, Windows, ContentType=WindowsRuntime");
+ if (xmlDocumentType == null || toastType == null || managerType == null)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[Toast] Windows Runtime toast types are unavailable.");
+#endif
+ return;
+ }
+
+ object xmlDocument = Activator.CreateInstance(xmlDocumentType);
+ MethodInfo loadXmlMethod = xmlDocumentType.GetMethod(
+ "LoadXml",
+ BindingFlags.Public | BindingFlags.Instance,
+ null,
+ new[] { typeof(string) },
+ null);
+ if (loadXmlMethod == null)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[Toast] LoadXml(string) method not found.");
+#endif
+ return;
+ }
+ loadXmlMethod.Invoke(xmlDocument, new object[] { toastXml });
+
+ object toast = Activator.CreateInstance(toastType, new[] { xmlDocument });
+
+ MethodInfo createNotifierMethod = managerType.GetMethod(
+ "CreateToastNotifier",
+ BindingFlags.Public | BindingFlags.Static,
+ null,
+ new[] { typeof(string) },
+ null);
+ if (createNotifierMethod == null)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[Toast] CreateToastNotifier(string) method not found.");
+#endif
+ return;
+ }
+
+ object notifier = createNotifierMethod.Invoke(null, new object[] { AppId });
+ if (notifier == null)
+ return;
+
+ MethodInfo showMethod = notifier.GetType().GetMethod(
+ "Show",
+ BindingFlags.Public | BindingFlags.Instance,
+ null,
+ new[] { toastType },
+ null);
+ if (showMethod == null)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[Toast] Show(ToastNotification) method not found.");
+#endif
+ return;
+ }
+
+ showMethod.Invoke(notifier, new[] { toast });
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[Toast] Toast shown for AppId='{AppId}'.");
+#endif
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[Toast] Service error: {ex}");
+ MessageBox.Show($"Toast service error: {ex.Message}", "Toast Debug", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+#endif
+ }
+ }
+
+ private static void EnsureInitialized()
+ {
+ if (_initialized)
+ return;
+
+ DesktopToastRegistrar.EnsureStartMenuShortcut(AppId);
+ _initialized = true;
+ }
+
+ private static string BuildToastXml(string trackTitle, string artistName, string attributionLine, string outputImagePath)
+ {
+ string safeTitle = SecurityElement.Escape(string.IsNullOrWhiteSpace(trackTitle) ? "No title" : trackTitle);
+ string safeArtist = SecurityElement.Escape(string.IsNullOrWhiteSpace(artistName) ? "No artist" : artistName);
+ string safeAttribution = SecurityElement.Escape(attributionLine ?? string.Empty);
+
+ string imageUri = string.Empty;
+ if (!string.IsNullOrWhiteSpace(outputImagePath))
+ {
+ try
+ {
+ string fullPath = Path.GetFullPath(outputImagePath);
+ if (File.Exists(fullPath))
+ {
+ var localUri = new Uri(fullPath);
+ imageUri = localUri.AbsoluteUri;
+ }
+#if DEBUG
+ else
+ {
+ System.Diagnostics.Debug.WriteLine($"[Toast] Output image file missing: '{fullPath}'");
+ }
+#endif
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[Toast] Invalid output image path '{outputImagePath}': {ex.Message}");
+#endif
+ }
+ }
+
+ string safeImage = SecurityElement.Escape(imageUri);
+ string imageNode = string.IsNullOrWhiteSpace(safeImage)
+ ? string.Empty
+ : $"";
+
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[Toast] Image URI used: '{imageUri}'");
+#endif
+ return $"{imageNode}{safeTitle}{safeArtist}{safeAttribution}";
+ }
+ }
+
+ internal static class DesktopToastRegistrar
+ {
+ [ComImport]
+ [Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ [ComImport]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ [Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cch, out WIN32_FIND_DATAW pfd, uint fFlags);
+ void GetIDList(out IntPtr ppidl);
+ void SetIDList(IntPtr pidl);
+ void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cch);
+ void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cch);
+ void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cch);
+ void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ void GetHotkey(out short pwHotkey);
+ void SetHotkey(short wHotkey);
+ void GetShowCmd(out int piShowCmd);
+ void SetShowCmd(int iShowCmd);
+ void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cch, out int piIcon);
+ void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);
+ void Resolve(IntPtr hwnd, uint fFlags);
+ void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
+ public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
+ public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ [ComImport]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ [Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount(out uint cProps);
+ uint GetAt(uint iProp, out PROPERTYKEY pkey);
+ uint GetValue(ref PROPERTYKEY key, out PROPVARIANT pv);
+ uint SetValue(ref PROPERTYKEY key, ref PROPVARIANT pv);
+ uint Commit();
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PROPERTYKEY
+ {
+ public Guid fmtid;
+ public uint pid;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ private struct PROPVARIANT
+ {
+ [FieldOffset(0)]
+ public ushort vt;
+ [FieldOffset(8)]
+ public IntPtr pointerValue;
+
+ public static PROPVARIANT FromString(string value)
+ {
+ var pv = new PROPVARIANT();
+ pv.vt = 31;
+ pv.pointerValue = Marshal.StringToCoTaskMemUni(value);
+ return pv;
+ }
+ }
+
+ private static PROPERTYKEY PKEY_AppUserModel_ID = new PROPERTYKEY
+ {
+ fmtid = new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"),
+ pid = 5
+ };
+
+ public static void EnsureStartMenuShortcut(string appId)
+ {
+ try
+ {
+ string shortcutPath = Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.StartMenu),
+ "Programs",
+ "RadioDJ Viewer.lnk");
+
+ string exePath = Assembly.GetEntryAssembly()?.Location ?? Application.ExecutablePath;
+ string workDir = Path.GetDirectoryName(exePath) ?? AppDomain.CurrentDomain.BaseDirectory;
+ string iconPath = Path.Combine(workDir, "icon.ico");
+ if (!File.Exists(iconPath))
+ iconPath = exePath;
+
+ var shellLink = (IShellLinkW)new CShellLink();
+ shellLink.SetPath(exePath);
+ shellLink.SetWorkingDirectory(workDir);
+ shellLink.SetIconLocation(iconPath, 0);
+
+ var propertyStore = (IPropertyStore)shellLink;
+ var value = PROPVARIANT.FromString(appId);
+ propertyStore.SetValue(ref PKEY_AppUserModel_ID, ref value);
+ propertyStore.Commit();
+
+ ((IPersistFile)shellLink).Save(shortcutPath, true);
+ Marshal.FreeCoTaskMem(value.pointerValue);
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[Toast] Shortcut registered: '{shortcutPath}', AppId='{appId}'");
+#endif
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[Toast] Shortcut registration error: {ex}");
+ MessageBox.Show($"Toast registration failed: {ex.Message}", "Toast Debug", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+#endif
+ }
+ }
}
}
diff --git a/RadioDJViewer/ProfileStorage.cs b/RadioDJViewer/ProfileStorage.cs
index 6759bf1..76100b5 100644
--- a/RadioDJViewer/ProfileStorage.cs
+++ b/RadioDJViewer/ProfileStorage.cs
@@ -25,6 +25,7 @@ namespace RadioDJViewer
public int WebServerPort { get; set; }
// Clock visibility setting
public bool ClockVisibilityEnabled { get; set; }
+ public bool ToastNotificationsEnabled { get; set; }
}
public static class ProfileStorage
diff --git a/RadioDJViewer/Program.cs b/RadioDJViewer/Program.cs
index 9c30b33..b2acc4b 100644
--- a/RadioDJViewer/Program.cs
+++ b/RadioDJViewer/Program.cs
@@ -1,19 +1,26 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
+using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace RadioDJViewer
{
internal static class Program
{
+ [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
+ private static extern int SetCurrentProcessExplicitAppUserModelID(string AppID);
+
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
+ try
+ {
+ SetCurrentProcessExplicitAppUserModelID("RadioDJViewer.App");
+ }
+ catch { }
+
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Main());
diff --git a/RadioDJViewer/Properties/AssemblyInfo.cs b/RadioDJViewer/Properties/AssemblyInfo.cs
index 35b4986..58f9411 100644
--- a/RadioDJViewer/Properties/AssemblyInfo.cs
+++ b/RadioDJViewer/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
-[assembly: AssemblyVersion("1.10.0")]
-[assembly: AssemblyFileVersion("1.10.0")]
+[assembly: AssemblyVersion("1.14.0")]
+[assembly: AssemblyFileVersion("1.14.0")]
diff --git a/RadioDJViewer/radiodj-restapi-template.Designer.cs b/RadioDJViewer/radiodj-restapi-template.Designer.cs
index 18e98e0..820e436 100644
--- a/RadioDJViewer/radiodj-restapi-template.Designer.cs
+++ b/RadioDJViewer/radiodj-restapi-template.Designer.cs
@@ -56,7 +56,12 @@
this.label7 = new System.Windows.Forms.Label();
this.textBox7 = new System.Windows.Forms.TextBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.toast_box_group_box = new System.Windows.Forms.GroupBox();
+ this.toast_check_box_enable = new System.Windows.Forms.CheckBox();
+ this.toast_label = new System.Windows.Forms.Label();
this.web_server_settings_groupbox = new System.Windows.Forms.GroupBox();
+ this.clock_visibility_checkBox = new System.Windows.Forms.CheckBox();
+ this.clock_label = new System.Windows.Forms.Label();
this.web_server_port_textbox = new System.Windows.Forms.TextBox();
this.web_server_port_label = new System.Windows.Forms.Label();
this.web_server_label = new System.Windows.Forms.Label();
@@ -69,11 +74,10 @@
this.label9 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.label12 = new System.Windows.Forms.Label();
- this.clock_label = new System.Windows.Forms.Label();
- this.clock_visibility_checkBox = new System.Windows.Forms.CheckBox();
this.groupBox1.SuspendLayout();
this.groupBox3.SuspendLayout();
this.groupBox2.SuspendLayout();
+ this.toast_box_group_box.SuspendLayout();
this.web_server_settings_groupbox.SuspendLayout();
this.SuspendLayout();
//
@@ -106,7 +110,7 @@
//
// ok_button_master
//
- this.ok_button_master.Location = new System.Drawing.Point(65, 694);
+ this.ok_button_master.Location = new System.Drawing.Point(54, 729);
this.ok_button_master.Name = "ok_button_master";
this.ok_button_master.Size = new System.Drawing.Size(157, 23);
this.ok_button_master.TabIndex = 1;
@@ -115,7 +119,7 @@
//
// button2
//
- this.button2.Location = new System.Drawing.Point(305, 694);
+ this.button2.Location = new System.Drawing.Point(302, 729);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(157, 23);
this.button2.TabIndex = 2;
@@ -304,6 +308,7 @@
//
// groupBox2
//
+ this.groupBox2.Controls.Add(this.toast_box_group_box);
this.groupBox2.Controls.Add(this.web_server_settings_groupbox);
this.groupBox2.Controls.Add(this.label13);
this.groupBox2.Controls.Add(this.comboBoxScrollSpeed);
@@ -331,11 +336,41 @@
this.groupBox2.Controls.Add(this.comboBox1);
this.groupBox2.Location = new System.Drawing.Point(12, 100);
this.groupBox2.Name = "groupBox2";
- this.groupBox2.Size = new System.Drawing.Size(519, 575);
+ this.groupBox2.Size = new System.Drawing.Size(519, 623);
this.groupBox2.TabIndex = 3;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Profiles";
//
+ // toast_box_group_box
+ //
+ this.toast_box_group_box.Controls.Add(this.toast_check_box_enable);
+ this.toast_box_group_box.Controls.Add(this.toast_label);
+ this.toast_box_group_box.Location = new System.Drawing.Point(133, 575);
+ this.toast_box_group_box.Name = "toast_box_group_box";
+ this.toast_box_group_box.Size = new System.Drawing.Size(248, 42);
+ this.toast_box_group_box.TabIndex = 4;
+ this.toast_box_group_box.TabStop = false;
+ this.toast_box_group_box.Text = "Windows Toast";
+ //
+ // toast_check_box_enable
+ //
+ this.toast_check_box_enable.AutoSize = true;
+ this.toast_check_box_enable.Location = new System.Drawing.Point(130, 17);
+ this.toast_check_box_enable.Name = "toast_check_box_enable";
+ this.toast_check_box_enable.Size = new System.Drawing.Size(59, 17);
+ this.toast_check_box_enable.TabIndex = 1;
+ this.toast_check_box_enable.Text = "Enable";
+ this.toast_check_box_enable.UseVisualStyleBackColor = true;
+ //
+ // toast_label
+ //
+ this.toast_label.AutoSize = true;
+ this.toast_label.Location = new System.Drawing.Point(40, 20);
+ this.toast_label.Name = "toast_label";
+ this.toast_label.Size = new System.Drawing.Size(73, 13);
+ this.toast_label.TabIndex = 0;
+ this.toast_label.Text = "Toast Control:";
+ //
// web_server_settings_groupbox
//
this.web_server_settings_groupbox.Controls.Add(this.clock_visibility_checkBox);
@@ -351,6 +386,25 @@
this.web_server_settings_groupbox.TabStop = false;
this.web_server_settings_groupbox.Text = "Web Server Settings";
//
+ // clock_visibility_checkBox
+ //
+ this.clock_visibility_checkBox.AutoSize = true;
+ this.clock_visibility_checkBox.Location = new System.Drawing.Point(119, 55);
+ this.clock_visibility_checkBox.Name = "clock_visibility_checkBox";
+ this.clock_visibility_checkBox.Size = new System.Drawing.Size(65, 17);
+ this.clock_visibility_checkBox.TabIndex = 38;
+ this.clock_visibility_checkBox.Text = "Enabled";
+ this.clock_visibility_checkBox.UseVisualStyleBackColor = true;
+ //
+ // clock_label
+ //
+ this.clock_label.AutoSize = true;
+ this.clock_label.Location = new System.Drawing.Point(44, 56);
+ this.clock_label.Name = "clock_label";
+ this.clock_label.Size = new System.Drawing.Size(76, 13);
+ this.clock_label.TabIndex = 37;
+ this.clock_label.Text = "Clock Visibility:";
+ //
// web_server_port_textbox
//
this.web_server_port_textbox.Location = new System.Drawing.Point(246, 19);
@@ -459,30 +513,11 @@
this.label12.TabIndex = 27;
this.label12.Text = "Separating character format";
//
- // clock_label
- //
- this.clock_label.AutoSize = true;
- this.clock_label.Location = new System.Drawing.Point(44, 56);
- this.clock_label.Name = "clock_label";
- this.clock_label.Size = new System.Drawing.Size(76, 13);
- this.clock_label.TabIndex = 37;
- this.clock_label.Text = "Clock Visibility:";
- //
- // clock_visibility_checkBox
- //
- this.clock_visibility_checkBox.AutoSize = true;
- this.clock_visibility_checkBox.Location = new System.Drawing.Point(119, 55);
- this.clock_visibility_checkBox.Name = "clock_visibility_checkBox";
- this.clock_visibility_checkBox.Size = new System.Drawing.Size(65, 17);
- this.clock_visibility_checkBox.TabIndex = 38;
- this.clock_visibility_checkBox.Text = "Enabled";
- this.clock_visibility_checkBox.UseVisualStyleBackColor = true;
- //
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(572, 729);
+ this.ClientSize = new System.Drawing.Size(553, 764);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.button2);
this.Controls.Add(this.ok_button_master);
@@ -496,6 +531,8 @@
this.groupBox3.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
+ this.toast_box_group_box.ResumeLayout(false);
+ this.toast_box_group_box.PerformLayout();
this.web_server_settings_groupbox.ResumeLayout(false);
this.web_server_settings_groupbox.PerformLayout();
this.ResumeLayout(false);
@@ -548,5 +585,8 @@
private System.Windows.Forms.Label web_server_port_label;
private System.Windows.Forms.CheckBox clock_visibility_checkBox;
private System.Windows.Forms.Label clock_label;
+ private System.Windows.Forms.GroupBox toast_box_group_box;
+ private System.Windows.Forms.CheckBox toast_check_box_enable;
+ private System.Windows.Forms.Label toast_label;
}
}
\ No newline at end of file
diff --git a/RadioDJViewer/radiodj-restapi-template.cs b/RadioDJViewer/radiodj-restapi-template.cs
index f9e4e2e..f0b12f9 100644
--- a/RadioDJViewer/radiodj-restapi-template.cs
+++ b/RadioDJViewer/radiodj-restapi-template.cs
@@ -85,6 +85,7 @@ namespace RadioDJViewer
web_server_port_textbox.Text = (profile.WebServerPort > 0 ? profile.WebServerPort : 8080).ToString();
// Clock visibility setting
clock_visibility_checkBox.Checked = profile.ClockVisibilityEnabled;
+ toast_check_box_enable.Checked = profile.ToastNotificationsEnabled;
}
catch { }
}
@@ -143,7 +144,8 @@ namespace RadioDJViewer
WebServerEnabled = web_server_checkbox.Checked,
WebServerPort = int.TryParse(web_server_port_textbox.Text, out int wp) ? wp : 8080,
// Clock visibility setting
- ClockVisibilityEnabled = clock_visibility_checkBox.Checked
+ ClockVisibilityEnabled = clock_visibility_checkBox.Checked,
+ ToastNotificationsEnabled = toast_check_box_enable.Checked
};
ProfileStorage.SaveProfile(profile);
// Refresh profile list