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