diff --git a/ntfysh_client/MainForm.Designer.cs b/ntfysh_client/MainForm.Designer.cs index 83e8285..7961c23 100644 --- a/ntfysh_client/MainForm.Designer.cs +++ b/ntfysh_client/MainForm.Designer.cs @@ -46,6 +46,7 @@ namespace ntfysh_client this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.label1 = new System.Windows.Forms.Label(); + this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.trayContextMenu.SuspendLayout(); this.menuStrip1.SuspendLayout(); this.SuspendLayout(); @@ -138,7 +139,8 @@ namespace ntfysh_client // fileToolStripMenuItem // this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.exitToolStripMenuItem1}); + this.exitToolStripMenuItem1, + this.settingsToolStripMenuItem}); this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); this.fileToolStripMenuItem.Text = "File"; @@ -147,7 +149,7 @@ namespace ntfysh_client // this.exitToolStripMenuItem1.Image = ((System.Drawing.Image)(resources.GetObject("exitToolStripMenuItem1.Image"))); this.exitToolStripMenuItem1.Name = "exitToolStripMenuItem1"; - this.exitToolStripMenuItem1.Size = new System.Drawing.Size(93, 22); + this.exitToolStripMenuItem1.Size = new System.Drawing.Size(180, 22); this.exitToolStripMenuItem1.Text = "Exit"; this.exitToolStripMenuItem1.Click += new System.EventHandler(this.exitToolStripMenuItem1_Click); // @@ -192,6 +194,14 @@ namespace ntfysh_client this.label1.TabIndex = 1; this.label1.Text = "Subscribed Notification Topics:"; // + // settingsToolStripMenuItem + // + this.settingsToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("settingsToolStripMenuItem.Image"))); + this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; + this.settingsToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.settingsToolStripMenuItem.Text = "Settings"; + this.settingsToolStripMenuItem.Click += new System.EventHandler(this.settingsToolStripMenuItem_Click); + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); @@ -240,6 +250,7 @@ namespace ntfysh_client private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem ntfyshWebsiteToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem; } } diff --git a/ntfysh_client/MainForm.cs b/ntfysh_client/MainForm.cs index ce77083..469618c 100644 --- a/ntfysh_client/MainForm.cs +++ b/ntfysh_client/MainForm.cs @@ -28,8 +28,12 @@ namespace ntfysh_client InitializeComponent(); } - private void MainForm_Load(object sender, EventArgs e) => LoadTopics(); - + private void MainForm_Load(object sender, EventArgs e) + { + LoadSettings(); + LoadTopics(); + } + protected override void SetVisibleCore(bool value) { if (_startInTray) @@ -66,7 +70,7 @@ namespace ntfysh_client string finalTitle = string.IsNullOrWhiteSpace(e.Title) ? $"{e.Sender.TopicId}@{e.Sender.ServerUrl}" : e.Title; - notifyIcon.ShowBalloonTip(5000, finalTitle, e.Message, priorityIcon); + notifyIcon.ShowBalloonTip((int)TimeSpan.FromSeconds((double)Program.Settings.Timeout).TotalMilliseconds, finalTitle, e.Message, priorityIcon); } private void OnConnectionMultiAttemptFailure(NotificationListener sender, SubscribedTopic topic) @@ -118,6 +122,26 @@ namespace ntfysh_client SaveTopicsToFile(); } + + private void settingsToolStripMenuItem_Click(object sender, EventArgs e) + { + using SettingsDialog dialog = new(); + + //Load current settings into dialog + dialog.Timeout = Program.Settings.Timeout; + + //Show dialog + DialogResult result = dialog.ShowDialog(); + + //Do not save on cancelled dialog + if (result != DialogResult.OK) return; + + //Read new settings from dialog + Program.Settings.Timeout = dialog.Timeout; + + //Save new settings persistently + SaveSettingsToFile(); + } private void notificationTopics_SelectedValueChanged(object sender, EventArgs e) { @@ -132,11 +156,6 @@ namespace ntfysh_client if (clickedItemIndex == -1) notificationTopics.ClearSelected(); } - private void button1_Click(object sender, EventArgs e) - { - Visible = false; - } - private void notifyIcon_Click(object sender, EventArgs e) { MouseEventArgs mouseEv = (MouseEventArgs)e; @@ -171,6 +190,19 @@ namespace ntfysh_client File.WriteAllText(GetTopicsFilePath(), topicsSerialised); } + + private string GetSettingsFilePath() + { + string binaryDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? throw new InvalidOperationException("Unable to determine path for application"); + return Path.Combine(binaryDirectory ?? throw new InvalidOperationException("Unable to determine path for settings file"), "settings.json"); + } + + private void SaveSettingsToFile() + { + string settingsSerialised = JsonConvert.SerializeObject(Program.Settings, Formatting.Indented); + + File.WriteAllText(GetSettingsFilePath(), settingsSerialised); + } private void LoadTopics() { @@ -252,6 +284,54 @@ namespace ntfysh_client } } + private SettingsModel GetDefaultSettings() => new() + { + Timeout = 5 + }; + + private void LoadSettings() + { + string settingsFilePath = GetSettingsFilePath(); + + //Check if we have any settings file on disk to load. If we don't, initialise defaults + if (!File.Exists(settingsFilePath)) + { + Program.Settings = GetDefaultSettings(); + + SaveSettingsToFile(); + + return; + } + + //We have a settings file. Load it! + string settingsSerialised = File.ReadAllText(settingsFilePath); + + //Check if the file is empty. If it is, initialise default settings + if (string.IsNullOrWhiteSpace(settingsSerialised)) + { + Program.Settings = GetDefaultSettings(); + + SaveSettingsToFile(); + + return; + } + + //Deserialise the settings + SettingsModel? settings = JsonConvert.DeserializeObject(settingsSerialised); + + //Check if the deserialise succeeded. If it didn't, initialise default settings + if (settings is null) + { + Program.Settings = GetDefaultSettings(); + + SaveSettingsToFile(); + + return; + } + + Program.Settings = settings; + } + private void MainForm_FormClosed(object sender, FormClosedEventArgs e) { notifyIcon.Dispose(); diff --git a/ntfysh_client/MainForm.resx b/ntfysh_client/MainForm.resx index 85f0136..ceabbf2 100644 --- a/ntfysh_client/MainForm.resx +++ b/ntfysh_client/MainForm.resx @@ -67,7 +67,7 @@ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA69AAAOvQFH+5CtAAAAiklE + JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA68AAAOvAGVvHJJAAAAiklE QVQ4T8WPQQqAIBBFvUOrXIhu3dcZOkqtu5R1ia4SdRDrxyyGGKmBIOGBDL6nmk9WCGE9yUpW0q9Ads7V GuCQ/kHAe79joAEO6dcLFmttpQEO6c+Bvpm2oZ0zwB4zVQBiF8cIsMdMDPCb+G2vA/wgP/z6C6WAhBgo fUFCDGi4BxIGShLpvy5jDoPes/0oNG3VAAAAAElFTkSuQmCC @@ -76,7 +76,7 @@ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA69AAAOvQFH+5CtAAAAgUlE + JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA68AAAOvAGVvHJJAAAAgUlE QVQ4T2OgGjjOLq4AZeIFWNWBBI9yib06zC3uABXCCkDyIHVYDTnMI2pzhEvs5VFucSeoEAo4wiNii08e DHAZQshwFICumCTNMADyK1gTl2gJiCYUNlgBSDPQ1v8gGipEPKDIBRSFAa6oIsoQQvGM1xCqpESsglgA seroBRgYAOoOWBJbfVcRAAAAAElFTkSuQmCC @@ -267,16 +267,28 @@ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA69AAAOvQFH+5CtAAAAgUlE + JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA68AAAOvAGVvHJJAAAAgUlE QVQ4T2OgGjjOLq4AZeIFWNWBBI9yib06zC3uABXCCkDyIHVYDTnMI2pzhEvs5VFucSeoEAo4wiNii08e DHAZQshwFICumCTNMADyK1gTl2gJiCYUNlgBSDPQ1v8gGipEPKDIBRSFAa6oIsoQQvGM1xCqpESsglgA seroBRgYAOoOWBJbfVcRAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 + JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA7CAAAOwgEVKEqAAAABT0lE + QVQ4T7WTzU3DUBCEXQICcSAYx5bdgKkDEuggF37aIJwJVBBfsCsAux+iII6hgvCNM5GV8HeBlUa73tnZ + fe9lE/ybJUlyC5bG2OmfLY7jK1CGYbiLr/v9/kigQeNcqRqXbxrEJXgBBYJX/DviPE3TY8Xk5vgpmIHP + TUhWKoii6AA/RPygWFBMbmCuAKVlnVG0AzHDnzH1iPheJ/HkiXLEp/rWdSxbGckxRTVYeNoEPFF4mGVZ + CC9uYm4BamksbxssIUe6r46pKRKaDjx97uvkqpXGdNdA5G8NNOSrBmPQcDS9fHsFvms1sVjcnTn9Io00 + lq8Mcv2I5xK5yVxQrBwnOCF+o/G+ZZ1BaEkKHRM/0DTFgicPzWkXKss6I7lepClT20XyfXPFzmkHdMpr + yzYN8gJUvV5vD/9M4fYqP34r3jZEetj1n+nG6b+2IPgAzHGHcFUSC1YAAAAASUVORK5CYII= iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA69AAAOvQFH+5CtAAABDElE + JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA68AAAOvAGVvHJJAAABDElE QVQ4T91RO3bCQAzUy3uhChdJnTVlCj5FcMsZsF1jmy4XycPrzl6fBLgEXMFp4srRiF0wcaBP5j0VI2m0 4zH9EwSq8gPP7ELPNFxtpxrbn9vVPkSsykOkqvHi2QxsWwAevhQTzG8eCb1yD7Glv2I5MlM+sLX0GqEq 6+jVPFl6QZz7lOgdJVnzuMq/sEepbsGln2YnR3AAm0IcIE71geJsTO9mcOWAOa3zicxxxGWApXMGabaH @@ -287,7 +299,7 @@ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 - JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA69AAAOvQFH+5CtAAAAwUlE + JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA68AAAOvAGVvHJJAAAAwUlE QVQ4T2OgClBUVHwAxP9JxA+g2sEG/JeTk5MkBYP0QLVTwQAFBYXHIAFSMEgPVDvYBfulpKSEScEgPVDt dDIA6OTNQHX/YXysBjAxMcUxMjKuBrGB9DIgPxqmARhwOUBD3sD4WA0QERGRBHLvCwoKygLpm6KiohIw DVBNz5HY2L0AtHkOEE8F4okgvoyMjDSSJsIGsLOzuwKFfnBycppJS0vLAJ39BUQTbQA6RnYBMkY3YAVI diff --git a/ntfysh_client/Program.cs b/ntfysh_client/Program.cs index 5942747..9880e89 100644 --- a/ntfysh_client/Program.cs +++ b/ntfysh_client/Program.cs @@ -11,7 +11,8 @@ namespace ntfysh_client static class Program { private static readonly NotificationListener NotificationListener = new(); - + public static SettingsModel Settings { get; set; } = null!; + /// /// The main entry point for the application. /// diff --git a/ntfysh_client/SettingsDialog.Designer.cs b/ntfysh_client/SettingsDialog.Designer.cs new file mode 100644 index 0000000..c7eb2d5 --- /dev/null +++ b/ntfysh_client/SettingsDialog.Designer.cs @@ -0,0 +1,129 @@ + +namespace ntfysh_client +{ + partial class SettingsDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.panel1 = new System.Windows.Forms.Panel(); + this.cancelButton = new System.Windows.Forms.Button(); + this.saveButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.timeout = new System.Windows.Forms.NumericUpDown(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.timeout)).BeginInit(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.BackColor = System.Drawing.SystemColors.Control; + this.panel1.Controls.Add(this.cancelButton); + this.panel1.Controls.Add(this.saveButton); + this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.panel1.Location = new System.Drawing.Point(0, 61); + this.panel1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(531, 51); + this.panel1.TabIndex = 9; + // + // cancelButton + // + this.cancelButton.Location = new System.Drawing.Point(363, 16); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(75, 23); + this.cancelButton.TabIndex = 1; + this.cancelButton.Text = "Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // saveButton + // + this.saveButton.Location = new System.Drawing.Point(444, 16); + this.saveButton.Name = "saveButton"; + this.saveButton.Size = new System.Drawing.Size(75, 23); + this.saveButton.TabIndex = 0; + this.saveButton.Text = "Save"; + this.saveButton.UseVisualStyleBackColor = true; + this.saveButton.Click += new System.EventHandler(this.saveButton_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(13, 9); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(488, 15); + this.label1.TabIndex = 11; + this.label1.Text = "Notification Toast Timeout (seconds, may be ignored by OS based on accessibility " + + "settings):"; + // + // timeout + // + this.timeout.Location = new System.Drawing.Point(13, 27); + this.timeout.Maximum = new decimal(new int[] { + -1981284353, + -1966660860, + 0, + 0}); + this.timeout.Name = "timeout"; + this.timeout.Size = new System.Drawing.Size(506, 23); + this.timeout.TabIndex = 12; + // + // SettingsDialog + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.White; + this.ClientSize = new System.Drawing.Size(531, 112); + this.Controls.Add(this.timeout); + this.Controls.Add(this.label1); + this.Controls.Add(this.panel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SettingsDialog"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Settings"; + this.panel1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.timeout)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.NumericUpDown timeout; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button saveButton; + } +} \ No newline at end of file diff --git a/ntfysh_client/SettingsDialog.cs b/ntfysh_client/SettingsDialog.cs new file mode 100644 index 0000000..a456fc7 --- /dev/null +++ b/ntfysh_client/SettingsDialog.cs @@ -0,0 +1,29 @@ +using System; +using System.Windows.Forms; + +namespace ntfysh_client +{ + public partial class SettingsDialog : Form + { + public decimal Timeout + { + get => timeout.Value; + set => timeout.Value = value; + } + + public SettingsDialog() + { + InitializeComponent(); + } + + private void saveButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + } + + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + } + } +} diff --git a/ntfysh_client/SettingsDialog.resx b/ntfysh_client/SettingsDialog.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/ntfysh_client/SettingsDialog.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ntfysh_client/SettingsModel.cs b/ntfysh_client/SettingsModel.cs new file mode 100644 index 0000000..f349748 --- /dev/null +++ b/ntfysh_client/SettingsModel.cs @@ -0,0 +1,7 @@ +namespace ntfysh_client +{ + public class SettingsModel + { + public decimal Timeout { get; set; } + } +} \ No newline at end of file