From 0155cfb8fc5938eca93bd45c124d7a1e15bbc5a0 Mon Sep 17 00:00:00 2001 From: Alexander Horner <33007665+alexhorner@users.noreply.github.com> Date: Mon, 9 Oct 2023 21:11:07 +0100 Subject: [PATCH] Add adjustable reconnects and settings revisions --- ntfysh_client/MainForm.cs | 54 ++++- .../Notifications/NotificationListener.cs | 46 +++-- ntfysh_client/SettingsDialog.Designer.cs | 192 +++++++++++------- ntfysh_client/SettingsDialog.cs | 12 ++ ntfysh_client/SettingsDialog.resx | 62 +++++- ntfysh_client/SettingsModel.cs | 3 + 6 files changed, 266 insertions(+), 103 deletions(-) diff --git a/ntfysh_client/MainForm.cs b/ntfysh_client/MainForm.cs index 469618c..cc2cdfa 100644 --- a/ntfysh_client/MainForm.cs +++ b/ntfysh_client/MainForm.cs @@ -92,15 +92,19 @@ namespace ntfysh_client //Do not subscribe on cancelled dialog if (result != DialogResult.OK) return; + + //Convert the reconnection values to ints + int reconnectAttempts = Convert.ToInt32(Math.Ceiling(Program.Settings.ReconnectAttempts)); + int reconnectAttemptDelay = Convert.ToInt32(Math.Ceiling(Program.Settings.ReconnectAttemptDelay)); //Subscribe if (dialog.UseWebsockets) { - _notificationListener.SubscribeToTopicUsingWebsocket(dialog.Unique, dialog.TopicId, dialog.ServerUrl, dialog.Username, dialog.Password); + _notificationListener.SubscribeToTopicUsingWebsocket(dialog.Unique, dialog.TopicId, dialog.ServerUrl, dialog.Username, dialog.Password, reconnectAttempts, reconnectAttemptDelay); } else { - _notificationListener.SubscribeToTopicUsingLongHttpJson(dialog.Unique, dialog.TopicId, dialog.ServerUrl, dialog.Username, dialog.Password); + _notificationListener.SubscribeToTopicUsingLongHttpJson(dialog.Unique, dialog.TopicId, dialog.ServerUrl, dialog.Username, dialog.Password, reconnectAttempts, reconnectAttemptDelay); } //Add to the user visible list @@ -129,6 +133,8 @@ namespace ntfysh_client //Load current settings into dialog dialog.Timeout = Program.Settings.Timeout; + dialog.ReconnectAttempts = Program.Settings.ReconnectAttempts; + dialog.ReconnectAttemptDelay = Program.Settings.ReconnectAttemptDelay; //Show dialog DialogResult result = dialog.ShowDialog(); @@ -138,6 +144,8 @@ namespace ntfysh_client //Read new settings from dialog Program.Settings.Timeout = dialog.Timeout; + Program.Settings.ReconnectAttempts = dialog.ReconnectAttempts; + Program.Settings.ReconnectAttemptDelay = dialog.ReconnectAttemptDelay; //Save new settings persistently SaveSettingsToFile(); @@ -259,6 +267,10 @@ namespace ntfysh_client return; } + //Convert the reconnection values to ints + int reconnectAttempts = Convert.ToInt32(Math.Ceiling(Program.Settings.ReconnectAttempts)); + int reconnectAttemptDelay = Convert.ToInt32(Math.Ceiling(Program.Settings.ReconnectAttemptDelay)); + //Load them in foreach (SubscribedTopic topic in topics) { @@ -268,12 +280,12 @@ namespace ntfysh_client { case "ws": case "wss": - _notificationListener.SubscribeToTopicUsingWebsocket($"{topic.TopicId}@{topic.ServerUrl}", topic.TopicId, topic.ServerUrl, topic.Username, topic.Password); + _notificationListener.SubscribeToTopicUsingWebsocket($"{topic.TopicId}@{topic.ServerUrl}", topic.TopicId, topic.ServerUrl, topic.Username, topic.Password, reconnectAttempts, reconnectAttemptDelay); break; case "http": case "https": - _notificationListener.SubscribeToTopicUsingLongHttpJson($"{topic.TopicId}@{topic.ServerUrl}", topic.TopicId, topic.ServerUrl, topic.Username, topic.Password); + _notificationListener.SubscribeToTopicUsingLongHttpJson($"{topic.TopicId}@{topic.ServerUrl}", topic.TopicId, topic.ServerUrl, topic.Username, topic.Password, reconnectAttempts, reconnectAttemptDelay); break; default: @@ -286,17 +298,34 @@ namespace ntfysh_client private SettingsModel GetDefaultSettings() => new() { - Timeout = 5 + Revision = 1, + Timeout = 5, + ReconnectAttempts = 10, + ReconnectAttemptDelay = 3 }; + + private void MergeSettingsRevisions(SettingsModel older, SettingsModel newer) + { + //Apply settings introduced in Revision 1 + if (older.Revision < 1) + { + older.ReconnectAttempts = newer.ReconnectAttempts; + older.ReconnectAttemptDelay = newer.ReconnectAttemptDelay; + } + + //Update the revision + older.Revision = newer.Revision; + } private void LoadSettings() { string settingsFilePath = GetSettingsFilePath(); + SettingsModel defaultSettings = GetDefaultSettings(); //Check if we have any settings file on disk to load. If we don't, initialise defaults if (!File.Exists(settingsFilePath)) { - Program.Settings = GetDefaultSettings(); + Program.Settings = defaultSettings; SaveSettingsToFile(); @@ -309,7 +338,7 @@ namespace ntfysh_client //Check if the file is empty. If it is, initialise default settings if (string.IsNullOrWhiteSpace(settingsSerialised)) { - Program.Settings = GetDefaultSettings(); + Program.Settings = defaultSettings; SaveSettingsToFile(); @@ -322,14 +351,21 @@ namespace ntfysh_client //Check if the deserialise succeeded. If it didn't, initialise default settings if (settings is null) { - Program.Settings = GetDefaultSettings(); + Program.Settings = defaultSettings; SaveSettingsToFile(); return; } - + Program.Settings = settings; + + //Check the settings revision. If it is older than the current latest revision, apply the settings defaults missing from previous revision + if (Program.Settings.Revision < defaultSettings.ReconnectAttempts) + { + MergeSettingsRevisions(Program.Settings, defaultSettings); + SaveSettingsToFile(); + } } private void MainForm_FormClosed(object sender, FormClosedEventArgs e) diff --git a/ntfysh_client/Notifications/NotificationListener.cs b/ntfysh_client/Notifications/NotificationListener.cs index f0acaa6..cf0e99c 100644 --- a/ntfysh_client/Notifications/NotificationListener.cs +++ b/ntfysh_client/Notifications/NotificationListener.cs @@ -31,16 +31,16 @@ namespace ntfysh_client.Notifications ServicePointManager.DefaultConnectionLimit = 100; } - private async Task ListenToTopicWithHttpLongJsonAsync(HttpRequestMessage message, CancellationToken cancellationToken, SubscribedTopic topic) + private async Task ListenToTopicWithHttpLongJsonAsync(HttpRequestMessage message, SubscribedTopic topic, int reconnectAttempts = 10, int reconnectAttemptDelay = 3, CancellationToken cancellationToken = default) { int connectionAttempts = 0; while (!cancellationToken.IsCancellationRequested) { //See if we have exceeded maximum attempts - if (connectionAttempts >= 10) + if (reconnectAttempts != 0 && connectionAttempts >= reconnectAttempts) { - //10 connection failures (1 initial + 9 reattempts)! Do not retry + // connection failures (1 initial + ( - 1) reattempts)! Do not retry OnConnectionMultiAttemptFailure?.Invoke(this, topic); return; } @@ -119,16 +119,16 @@ namespace ntfysh_client.Notifications } finally { - //We land here if we fail to connect or our connection gets closed (and if we are canceeling, but that gets ignored) + //We land here if we fail to connect or our connection gets closed (and if we are canceling, but that gets ignored) if (!cancellationToken.IsCancellationRequested) { //Not cancelling, legitimate connection failure or termination - if (connectionAttempts != 0) + if (reconnectAttempts == 0 || connectionAttempts != 0) { - //On our first reconnect attempt, try instantly. On consecutive, wait 3 seconds before each attempt - await Task.Delay(TimeSpan.FromSeconds(3), cancellationToken); + //On our first reconnect attempt, try instantly (unless we have infinite retries). On consecutive, wait seconds before each attempt + await Task.Delay(TimeSpan.FromSeconds(reconnectAttemptDelay), cancellationToken); } //Increment attempts @@ -140,16 +140,16 @@ namespace ntfysh_client.Notifications } } - private async Task ListenToTopicWithWebsocketAsync(Uri uri, string? credentials, CancellationToken cancellationToken, SubscribedTopic topic) + private async Task ListenToTopicWithWebsocketAsync(Uri uri, string? credentials, SubscribedTopic topic, int reconnectAttempts = 10, int reconnectAttemptDelay = 3, CancellationToken cancellationToken = default) { int connectionAttempts = 0; while (!cancellationToken.IsCancellationRequested) { //See if we have exceeded maximum attempts - if (connectionAttempts >= 10) + if (reconnectAttempts != 0 && connectionAttempts >= reconnectAttempts) { - //10 connection failures (1 initial + 9 reattempts)! Do not retry + // connection failures (1 initial + ( - 1) reattempts)! Do not retry OnConnectionMultiAttemptFailure?.Invoke(this, topic); return; } @@ -223,16 +223,16 @@ namespace ntfysh_client.Notifications } finally { - //We land here if we fail to connect or our connection gets closed (and if we are canceeling, but that gets ignored) + //We land here if we fail to connect or our connection gets closed (and if we are canceling, but that gets ignored) if (!cancellationToken.IsCancellationRequested) { //Not cancelling, legitimate connection failure or termination - if (connectionAttempts != 0) + if (reconnectAttempts == 0 || connectionAttempts != 0) { - //On our first reconnect attempt, try instantly. On consecutive, wait 3 seconds before each attempt - await Task.Delay(TimeSpan.FromSeconds(3), cancellationToken); + //On our first reconnect attempt, try instantly (unless we have infinite retries). On consecutive, wait seconds before each attempt + await Task.Delay(TimeSpan.FromSeconds(reconnectAttemptDelay), cancellationToken); } //Increment attempts @@ -261,13 +261,16 @@ namespace ntfysh_client.Notifications } } - public void SubscribeToTopicUsingLongHttpJson(string unique, string topicId, string serverUrl, string? username, string? password) + public void SubscribeToTopicUsingLongHttpJson(string unique, string topicId, string serverUrl, string? username, string? password, int reconnectAttempts, int reconnectAttemptDelay) { - if (SubscribedTopicsByUnique.ContainsKey(unique)) throw new InvalidOperationException("A topic with this unique already exists"); + if (SubscribedTopicsByUnique.ContainsKey(unique)) throw new ArgumentException("A topic with this unique already exists", nameof(unique)); if (string.IsNullOrWhiteSpace(username)) username = null; if (string.IsNullOrWhiteSpace(password)) password = null; + if (reconnectAttempts < 0) throw new ArgumentException("Reconnect attempts must be 0 or more", nameof(reconnectAttempts)); + if (reconnectAttemptDelay < 0) throw new ArgumentException("Reconnect attempt delay; must be 0 or more", nameof(reconnectAttemptDelay)); + HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, $"{serverUrl}/{HttpUtility.UrlEncode(topicId)}/json"); if (username is not null && password is not null) @@ -280,20 +283,23 @@ namespace ntfysh_client.Notifications SubscribedTopic newTopic = new(topicId, serverUrl, username, password); CancellationTokenSource listenCanceller = new(); - Task listenTask = ListenToTopicWithHttpLongJsonAsync(message, listenCanceller.Token, newTopic); + Task listenTask = ListenToTopicWithHttpLongJsonAsync(message, newTopic, reconnectAttempts, reconnectAttemptDelay, listenCanceller.Token); newTopic.SetAssociatedRunner(listenTask, listenCanceller); SubscribedTopicsByUnique.Add(unique, newTopic); } - public void SubscribeToTopicUsingWebsocket(string unique, string topicId, string serverUrl, string? username, string? password) + public void SubscribeToTopicUsingWebsocket(string unique, string topicId, string serverUrl, string? username, string? password, int reconnectAttempts, int reconnectAttemptDelay) { - if (SubscribedTopicsByUnique.ContainsKey(unique)) throw new InvalidOperationException("A topic with this unique already exists"); + if (SubscribedTopicsByUnique.ContainsKey(unique)) throw new ArgumentException("A topic with this unique already exists", nameof(unique)); if (string.IsNullOrWhiteSpace(username)) username = null; if (string.IsNullOrWhiteSpace(password)) password = null; + if (reconnectAttempts < 0) throw new ArgumentException("Reconnect attempts must be 0 or more", nameof(reconnectAttempts)); + if (reconnectAttemptDelay < 0) throw new ArgumentException("Reconnect attempt delay; must be 0 or more", nameof(reconnectAttemptDelay)); + SubscribedTopic newTopic = new(topicId, serverUrl, username, password); string? credentials = null; @@ -306,7 +312,7 @@ namespace ntfysh_client.Notifications } CancellationTokenSource listenCanceller = new(); - Task listenTask = ListenToTopicWithWebsocketAsync(new Uri($"{serverUrl}/{HttpUtility.UrlEncode(topicId)}/ws"), credentials, listenCanceller.Token, newTopic); + Task listenTask = ListenToTopicWithWebsocketAsync(new Uri($"{serverUrl}/{HttpUtility.UrlEncode(topicId)}/ws"), credentials, newTopic, reconnectAttempts, reconnectAttemptDelay, listenCanceller.Token); newTopic.SetAssociatedRunner(listenTask, listenCanceller); diff --git a/ntfysh_client/SettingsDialog.Designer.cs b/ntfysh_client/SettingsDialog.Designer.cs index c7eb2d5..8f240fe 100644 --- a/ntfysh_client/SettingsDialog.Designer.cs +++ b/ntfysh_client/SettingsDialog.Designer.cs @@ -29,101 +29,147 @@ namespace ntfysh_client /// 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(); + buttonPanel = new System.Windows.Forms.Panel(); + cancelButton = new System.Windows.Forms.Button(); + saveButton = new System.Windows.Forms.Button(); + timeoutLabel = new System.Windows.Forms.Label(); + timeout = new System.Windows.Forms.NumericUpDown(); + reconnectAttempts = new System.Windows.Forms.NumericUpDown(); + reconnectAttemptsLabel = new System.Windows.Forms.Label(); + reconnectAttemptDelay = new System.Windows.Forms.NumericUpDown(); + reconnectAttemptDelayLabel = new System.Windows.Forms.Label(); + buttonPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)timeout).BeginInit(); + ((System.ComponentModel.ISupportInitialize)reconnectAttempts).BeginInit(); + ((System.ComponentModel.ISupportInitialize)reconnectAttemptDelay).BeginInit(); + SuspendLayout(); // - // panel1 + // buttonPanel // - 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; + buttonPanel.BackColor = System.Drawing.SystemColors.Control; + buttonPanel.Controls.Add(cancelButton); + buttonPanel.Controls.Add(saveButton); + buttonPanel.Dock = System.Windows.Forms.DockStyle.Bottom; + buttonPanel.Location = new System.Drawing.Point(0, 150); + buttonPanel.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + buttonPanel.Name = "buttonPanel"; + buttonPanel.Size = new System.Drawing.Size(531, 51); + buttonPanel.TabIndex = 0; // // 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); + cancelButton.Location = new System.Drawing.Point(363, 16); + cancelButton.Name = "cancelButton"; + cancelButton.Size = new System.Drawing.Size(75, 23); + cancelButton.TabIndex = 2; + cancelButton.Text = "Cancel"; + cancelButton.UseVisualStyleBackColor = true; + cancelButton.Click += 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); + saveButton.Location = new System.Drawing.Point(444, 16); + saveButton.Name = "saveButton"; + saveButton.Size = new System.Drawing.Size(75, 23); + saveButton.TabIndex = 1; + saveButton.Text = "Save"; + saveButton.UseVisualStyleBackColor = true; + saveButton.Click += saveButton_Click; // - // label1 + // timeoutLabel // - 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):"; + timeoutLabel.AutoSize = true; + timeoutLabel.Location = new System.Drawing.Point(13, 9); + timeoutLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + timeoutLabel.Name = "timeoutLabel"; + timeoutLabel.Size = new System.Drawing.Size(488, 15); + timeoutLabel.TabIndex = 3; + timeoutLabel.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; + timeout.Location = new System.Drawing.Point(13, 28); + timeout.Maximum = new decimal(new int[] { -1981284353, -1966660860, 0, 0 }); + timeout.Name = "timeout"; + timeout.Size = new System.Drawing.Size(506, 23); + timeout.TabIndex = 4; + // + // reconnectAttempts + // + reconnectAttempts.Location = new System.Drawing.Point(12, 73); + reconnectAttempts.Maximum = new decimal(new int[] { -1981284353, -1966660860, 0, 0 }); + reconnectAttempts.Name = "reconnectAttempts"; + reconnectAttempts.Size = new System.Drawing.Size(506, 23); + reconnectAttempts.TabIndex = 6; + // + // reconnectAttemptsLabel + // + reconnectAttemptsLabel.AutoSize = true; + reconnectAttemptsLabel.Location = new System.Drawing.Point(12, 54); + reconnectAttemptsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + reconnectAttemptsLabel.Name = "reconnectAttemptsLabel"; + reconnectAttemptsLabel.Size = new System.Drawing.Size(198, 15); + reconnectAttemptsLabel.TabIndex = 5; + reconnectAttemptsLabel.Text = "Maximum reconnect retry attempts (requires restart):"; + // + // reconnectAttemptDelay + // + reconnectAttemptDelay.Location = new System.Drawing.Point(12, 118); + reconnectAttemptDelay.Maximum = new decimal(new int[] { -1981284353, -1966660860, 0, 0 }); + reconnectAttemptDelay.Name = "reconnectAttemptDelay"; + reconnectAttemptDelay.Size = new System.Drawing.Size(506, 23); + reconnectAttemptDelay.TabIndex = 8; + // + // reconnectAttemptDelayLabel + // + reconnectAttemptDelayLabel.AutoSize = true; + reconnectAttemptDelayLabel.Location = new System.Drawing.Point(12, 99); + reconnectAttemptDelayLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + reconnectAttemptDelayLabel.Name = "reconnectAttemptDelayLabel"; + reconnectAttemptDelayLabel.Size = new System.Drawing.Size(191, 15); + reconnectAttemptDelayLabel.TabIndex = 7; + reconnectAttemptDelayLabel.Text = "Delay between attempts (seconds, requires restart):"; // // 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(); - + AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + BackColor = System.Drawing.Color.White; + ClientSize = new System.Drawing.Size(531, 201); + Controls.Add(reconnectAttemptDelay); + Controls.Add(reconnectAttemptDelayLabel); + Controls.Add(reconnectAttempts); + Controls.Add(reconnectAttemptsLabel); + Controls.Add(timeout); + Controls.Add(timeoutLabel); + Controls.Add(buttonPanel); + FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + MaximizeBox = false; + MinimizeBox = false; + Name = "SettingsDialog"; + ShowIcon = false; + ShowInTaskbar = false; + StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + Text = "Settings"; + buttonPanel.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)timeout).EndInit(); + ((System.ComponentModel.ISupportInitialize)reconnectAttempts).EndInit(); + ((System.ComponentModel.ISupportInitialize)reconnectAttemptDelay).EndInit(); + ResumeLayout(false); + PerformLayout(); } #endregion - private System.Windows.Forms.Panel panel1; - private System.Windows.Forms.Label label1; + private System.Windows.Forms.Panel buttonPanel; + private System.Windows.Forms.Label timeoutLabel; private System.Windows.Forms.NumericUpDown timeout; private System.Windows.Forms.Button cancelButton; private System.Windows.Forms.Button saveButton; + private System.Windows.Forms.NumericUpDown reconnectAttempts; + private System.Windows.Forms.Label reconnectAttemptsLabel; + private System.Windows.Forms.NumericUpDown reconnectAttemptDelay; + private System.Windows.Forms.Label reconnectAttemptDelayLabel; } } \ No newline at end of file diff --git a/ntfysh_client/SettingsDialog.cs b/ntfysh_client/SettingsDialog.cs index a456fc7..6568d9d 100644 --- a/ntfysh_client/SettingsDialog.cs +++ b/ntfysh_client/SettingsDialog.cs @@ -11,6 +11,18 @@ namespace ntfysh_client set => timeout.Value = value; } + public decimal ReconnectAttempts + { + get => reconnectAttempts.Value; + set => reconnectAttempts.Value = value; + } + + public decimal ReconnectAttemptDelay + { + get => reconnectAttemptDelay.Value; + set => reconnectAttemptDelay.Value = value; + } + public SettingsDialog() { InitializeComponent(); diff --git a/ntfysh_client/SettingsDialog.resx b/ntfysh_client/SettingsDialog.resx index f298a7b..af32865 100644 --- a/ntfysh_client/SettingsDialog.resx +++ b/ntfysh_client/SettingsDialog.resx @@ -1,4 +1,64 @@ - + + + diff --git a/ntfysh_client/SettingsModel.cs b/ntfysh_client/SettingsModel.cs index f349748..ef67969 100644 --- a/ntfysh_client/SettingsModel.cs +++ b/ntfysh_client/SettingsModel.cs @@ -2,6 +2,9 @@ { public class SettingsModel { + public uint Revision { get; set; } public decimal Timeout { get; set; } + public decimal ReconnectAttempts { get; set; } + public decimal ReconnectAttemptDelay { get; set; } } } \ No newline at end of file -- 2.49.1