mirror of
https://github.com/gnh1201/welsonjs.git
synced 2025-11-27 18:11:20 +00:00
Add WinForms interface for WebSocket management
This commit is contained in:
parent
83b8e453f0
commit
cfcfaf3e1f
|
|
@ -135,6 +135,7 @@
|
||||||
this.runAsAdministratorToolStripMenuItem,
|
this.runAsAdministratorToolStripMenuItem,
|
||||||
this.globalSettingsToolStripMenuItem,
|
this.globalSettingsToolStripMenuItem,
|
||||||
this.startTheEditorToolStripMenuItem,
|
this.startTheEditorToolStripMenuItem,
|
||||||
|
this.webSocketManagerToolStripMenuItem,
|
||||||
this.openCopilotToolStripMenuItem});
|
this.openCopilotToolStripMenuItem});
|
||||||
this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
|
this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
|
||||||
this.settingsToolStripMenuItem.Size = new System.Drawing.Size(62, 20);
|
this.settingsToolStripMenuItem.Size = new System.Drawing.Size(62, 20);
|
||||||
|
|
@ -175,6 +176,13 @@
|
||||||
this.startTheEditorToolStripMenuItem.Text = "Start the editor...";
|
this.startTheEditorToolStripMenuItem.Text = "Start the editor...";
|
||||||
this.startTheEditorToolStripMenuItem.Click += new System.EventHandler(this.startCodeEditorToolStripMenuItem_Click);
|
this.startTheEditorToolStripMenuItem.Click += new System.EventHandler(this.startCodeEditorToolStripMenuItem_Click);
|
||||||
//
|
//
|
||||||
|
// webSocketManagerToolStripMenuItem
|
||||||
|
//
|
||||||
|
this.webSocketManagerToolStripMenuItem.Name = "webSocketManagerToolStripMenuItem";
|
||||||
|
this.webSocketManagerToolStripMenuItem.Size = new System.Drawing.Size(196, 22);
|
||||||
|
this.webSocketManagerToolStripMenuItem.Text = "WebSocket manager...";
|
||||||
|
this.webSocketManagerToolStripMenuItem.Click += new System.EventHandler(this.webSocketManagerToolStripMenuItem_Click);
|
||||||
|
//
|
||||||
// openCopilotToolStripMenuItem
|
// openCopilotToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.openCopilotToolStripMenuItem.Name = "openCopilotToolStripMenuItem";
|
this.openCopilotToolStripMenuItem.Name = "openCopilotToolStripMenuItem";
|
||||||
|
|
@ -291,6 +299,7 @@
|
||||||
private System.Windows.Forms.ToolStripMenuItem openCodeEditorToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem openCodeEditorToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem openLauncherToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem openLauncherToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem openCopilotToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem openCopilotToolStripMenuItem;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem webSocketManagerToolStripMenuItem;
|
||||||
private System.Windows.Forms.SaveFileDialog saveFileDialog1;
|
private System.Windows.Forms.SaveFileDialog saveFileDialog1;
|
||||||
private System.Windows.Forms.Button btnStartTheEditor;
|
private System.Windows.Forms.Button btnStartTheEditor;
|
||||||
private System.Windows.Forms.Button btnJoinTheCommunity;
|
private System.Windows.Forms.Button btnJoinTheCommunity;
|
||||||
|
|
|
||||||
|
|
@ -335,6 +335,11 @@ namespace WelsonJS.Launcher
|
||||||
Program.OpenWebBrowser(Program.GetAppConfig("CopilotUrl"));
|
Program.OpenWebBrowser(Program.GetAppConfig("CopilotUrl"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void webSocketManagerToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
(new WebSocketManagerForm()).Show();
|
||||||
|
}
|
||||||
|
|
||||||
private void btnJoinTheCommunity_Click(object sender, EventArgs e)
|
private void btnJoinTheCommunity_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Program.OpenWebBrowser(Program.GetAppConfig("RepositoryUrl"));
|
Program.OpenWebBrowser(Program.GetAppConfig("RepositoryUrl"));
|
||||||
|
|
|
||||||
278
WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.Designer.cs
generated
Normal file
278
WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,278 @@
|
||||||
|
// WebSocketManagerForm.Designer.cs
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// SPDX-FileCopyrightText: 2025 Catswords OSS and WelsonJS Contributors
|
||||||
|
// https://github.com/gnh1201/welsonjs
|
||||||
|
//
|
||||||
|
namespace WelsonJS.Launcher
|
||||||
|
{
|
||||||
|
partial class WebSocketManagerForm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.lvConnections = new System.Windows.Forms.ListView();
|
||||||
|
this.chHost = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||||
|
this.chPort = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||||
|
this.chPath = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||||
|
this.chStatus = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||||
|
this.chUpdated = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||||
|
this.btnRefresh = new System.Windows.Forms.Button();
|
||||||
|
this.gbNewConnection = new System.Windows.Forms.GroupBox();
|
||||||
|
this.btnConnect = new System.Windows.Forms.Button();
|
||||||
|
this.txtPath = new System.Windows.Forms.TextBox();
|
||||||
|
this.lblPath = new System.Windows.Forms.Label();
|
||||||
|
this.nudPort = new System.Windows.Forms.NumericUpDown();
|
||||||
|
this.lblPort = new System.Windows.Forms.Label();
|
||||||
|
this.txtHost = new System.Windows.Forms.TextBox();
|
||||||
|
this.lblHost = new System.Windows.Forms.Label();
|
||||||
|
this.btnDisconnect = new System.Windows.Forms.Button();
|
||||||
|
this.btnClose = new System.Windows.Forms.Button();
|
||||||
|
this.statusTimer = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.gbNewConnection.SuspendLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.nudPort)).BeginInit();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// lvConnections
|
||||||
|
//
|
||||||
|
this.lvConnections.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||||
|
this.chHost,
|
||||||
|
this.chPort,
|
||||||
|
this.chPath,
|
||||||
|
this.chStatus,
|
||||||
|
this.chUpdated});
|
||||||
|
this.lvConnections.FullRowSelect = true;
|
||||||
|
this.lvConnections.HideSelection = false;
|
||||||
|
this.lvConnections.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.lvConnections.MultiSelect = false;
|
||||||
|
this.lvConnections.Name = "lvConnections";
|
||||||
|
this.lvConnections.Size = new System.Drawing.Size(601, 188);
|
||||||
|
this.lvConnections.TabIndex = 0;
|
||||||
|
this.lvConnections.UseCompatibleStateImageBehavior = false;
|
||||||
|
this.lvConnections.View = System.Windows.Forms.View.Details;
|
||||||
|
this.lvConnections.SelectedIndexChanged += new System.EventHandler(this.lvConnections_SelectedIndexChanged);
|
||||||
|
//
|
||||||
|
// chHost
|
||||||
|
//
|
||||||
|
this.chHost.Text = "Host";
|
||||||
|
this.chHost.Width = 150;
|
||||||
|
//
|
||||||
|
// chPort
|
||||||
|
//
|
||||||
|
this.chPort.Text = "Port";
|
||||||
|
this.chPort.Width = 80;
|
||||||
|
//
|
||||||
|
// chPath
|
||||||
|
//
|
||||||
|
this.chPath.Text = "Path";
|
||||||
|
this.chPath.Width = 150;
|
||||||
|
//
|
||||||
|
// chStatus
|
||||||
|
//
|
||||||
|
this.chStatus.Text = "Status";
|
||||||
|
this.chStatus.Width = 120;
|
||||||
|
//
|
||||||
|
// chUpdated
|
||||||
|
//
|
||||||
|
this.chUpdated.Text = "Last Updated";
|
||||||
|
this.chUpdated.Width = 180;
|
||||||
|
//
|
||||||
|
// btnRefresh
|
||||||
|
//
|
||||||
|
this.btnRefresh.Location = new System.Drawing.Point(518, 206);
|
||||||
|
this.btnRefresh.Name = "btnRefresh";
|
||||||
|
this.btnRefresh.Size = new System.Drawing.Size(95, 23);
|
||||||
|
this.btnRefresh.TabIndex = 1;
|
||||||
|
this.btnRefresh.Text = "Refresh";
|
||||||
|
this.btnRefresh.UseVisualStyleBackColor = true;
|
||||||
|
this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
|
||||||
|
//
|
||||||
|
// gbNewConnection
|
||||||
|
//
|
||||||
|
this.gbNewConnection.Controls.Add(this.btnConnect);
|
||||||
|
this.gbNewConnection.Controls.Add(this.txtPath);
|
||||||
|
this.gbNewConnection.Controls.Add(this.lblPath);
|
||||||
|
this.gbNewConnection.Controls.Add(this.nudPort);
|
||||||
|
this.gbNewConnection.Controls.Add(this.lblPort);
|
||||||
|
this.gbNewConnection.Controls.Add(this.txtHost);
|
||||||
|
this.gbNewConnection.Controls.Add(this.lblHost);
|
||||||
|
this.gbNewConnection.Location = new System.Drawing.Point(12, 235);
|
||||||
|
this.gbNewConnection.Name = "gbNewConnection";
|
||||||
|
this.gbNewConnection.Size = new System.Drawing.Size(601, 100);
|
||||||
|
this.gbNewConnection.TabIndex = 2;
|
||||||
|
this.gbNewConnection.TabStop = false;
|
||||||
|
this.gbNewConnection.Text = "New connection";
|
||||||
|
//
|
||||||
|
// btnConnect
|
||||||
|
//
|
||||||
|
this.btnConnect.Location = new System.Drawing.Point(470, 56);
|
||||||
|
this.btnConnect.Name = "btnConnect";
|
||||||
|
this.btnConnect.Size = new System.Drawing.Size(112, 27);
|
||||||
|
this.btnConnect.TabIndex = 6;
|
||||||
|
this.btnConnect.Text = "Connect";
|
||||||
|
this.btnConnect.UseVisualStyleBackColor = true;
|
||||||
|
this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
|
||||||
|
//
|
||||||
|
// txtPath
|
||||||
|
//
|
||||||
|
this.txtPath.Location = new System.Drawing.Point(70, 60);
|
||||||
|
this.txtPath.Name = "txtPath";
|
||||||
|
this.txtPath.Size = new System.Drawing.Size(318, 21);
|
||||||
|
this.txtPath.TabIndex = 5;
|
||||||
|
this.txtPath.TextChanged += new System.EventHandler(this.ConnectionInputChanged);
|
||||||
|
//
|
||||||
|
// lblPath
|
||||||
|
//
|
||||||
|
this.lblPath.AutoSize = true;
|
||||||
|
this.lblPath.Location = new System.Drawing.Point(15, 63);
|
||||||
|
this.lblPath.Name = "lblPath";
|
||||||
|
this.lblPath.Size = new System.Drawing.Size(31, 12);
|
||||||
|
this.lblPath.TabIndex = 4;
|
||||||
|
this.lblPath.Text = "Path";
|
||||||
|
//
|
||||||
|
// nudPort
|
||||||
|
//
|
||||||
|
this.nudPort.Location = new System.Drawing.Point(308, 26);
|
||||||
|
this.nudPort.Maximum = new decimal(new int[] {
|
||||||
|
65535,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.nudPort.Minimum = new decimal(new int[] {
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.nudPort.Name = "nudPort";
|
||||||
|
this.nudPort.Size = new System.Drawing.Size(80, 21);
|
||||||
|
this.nudPort.TabIndex = 3;
|
||||||
|
this.nudPort.Value = new decimal(new int[] {
|
||||||
|
80,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.nudPort.ValueChanged += new System.EventHandler(this.ConnectionInputChanged);
|
||||||
|
//
|
||||||
|
// lblPort
|
||||||
|
//
|
||||||
|
this.lblPort.AutoSize = true;
|
||||||
|
this.lblPort.Location = new System.Drawing.Point(268, 29);
|
||||||
|
this.lblPort.Name = "lblPort";
|
||||||
|
this.lblPort.Size = new System.Drawing.Size(29, 12);
|
||||||
|
this.lblPort.TabIndex = 2;
|
||||||
|
this.lblPort.Text = "Port";
|
||||||
|
//
|
||||||
|
// txtHost
|
||||||
|
//
|
||||||
|
this.txtHost.Location = new System.Drawing.Point(70, 26);
|
||||||
|
this.txtHost.Name = "txtHost";
|
||||||
|
this.txtHost.Size = new System.Drawing.Size(180, 21);
|
||||||
|
this.txtHost.TabIndex = 1;
|
||||||
|
this.txtHost.TextChanged += new System.EventHandler(this.ConnectionInputChanged);
|
||||||
|
//
|
||||||
|
// lblHost
|
||||||
|
//
|
||||||
|
this.lblHost.AutoSize = true;
|
||||||
|
this.lblHost.Location = new System.Drawing.Point(15, 29);
|
||||||
|
this.lblHost.Name = "lblHost";
|
||||||
|
this.lblHost.Size = new System.Drawing.Size(31, 12);
|
||||||
|
this.lblHost.TabIndex = 0;
|
||||||
|
this.lblHost.Text = "Host";
|
||||||
|
//
|
||||||
|
// btnDisconnect
|
||||||
|
//
|
||||||
|
this.btnDisconnect.Location = new System.Drawing.Point(12, 341);
|
||||||
|
this.btnDisconnect.Name = "btnDisconnect";
|
||||||
|
this.btnDisconnect.Size = new System.Drawing.Size(126, 27);
|
||||||
|
this.btnDisconnect.TabIndex = 3;
|
||||||
|
this.btnDisconnect.Text = "Disconnect";
|
||||||
|
this.btnDisconnect.UseVisualStyleBackColor = true;
|
||||||
|
this.btnDisconnect.Click += new System.EventHandler(this.btnDisconnect_Click);
|
||||||
|
//
|
||||||
|
// btnClose
|
||||||
|
//
|
||||||
|
this.btnClose.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||||
|
this.btnClose.Location = new System.Drawing.Point(487, 341);
|
||||||
|
this.btnClose.Name = "btnClose";
|
||||||
|
this.btnClose.Size = new System.Drawing.Size(126, 27);
|
||||||
|
this.btnClose.TabIndex = 4;
|
||||||
|
this.btnClose.Text = "Close";
|
||||||
|
this.btnClose.UseVisualStyleBackColor = true;
|
||||||
|
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
|
||||||
|
//
|
||||||
|
// statusTimer
|
||||||
|
//
|
||||||
|
this.statusTimer.Interval = 2000;
|
||||||
|
this.statusTimer.Tick += new System.EventHandler(this.statusTimer_Tick);
|
||||||
|
//
|
||||||
|
// WebSocketManagerForm
|
||||||
|
//
|
||||||
|
this.AcceptButton = this.btnConnect;
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.CancelButton = this.btnClose;
|
||||||
|
this.ClientSize = new System.Drawing.Size(625, 380);
|
||||||
|
this.Controls.Add(this.btnClose);
|
||||||
|
this.Controls.Add(this.btnDisconnect);
|
||||||
|
this.Controls.Add(this.gbNewConnection);
|
||||||
|
this.Controls.Add(this.btnRefresh);
|
||||||
|
this.Controls.Add(this.lvConnections);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.Name = "WebSocketManagerForm";
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.Text = "WebSocket Manager";
|
||||||
|
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.WebSocketManagerForm_FormClosed);
|
||||||
|
this.Load += new System.EventHandler(this.WebSocketManagerForm_Load);
|
||||||
|
this.gbNewConnection.ResumeLayout(false);
|
||||||
|
this.gbNewConnection.PerformLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.nudPort)).EndInit();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.ListView lvConnections;
|
||||||
|
private System.Windows.Forms.ColumnHeader chHost;
|
||||||
|
private System.Windows.Forms.ColumnHeader chPort;
|
||||||
|
private System.Windows.Forms.ColumnHeader chPath;
|
||||||
|
private System.Windows.Forms.ColumnHeader chStatus;
|
||||||
|
private System.Windows.Forms.ColumnHeader chUpdated;
|
||||||
|
private System.Windows.Forms.Button btnRefresh;
|
||||||
|
private System.Windows.Forms.GroupBox gbNewConnection;
|
||||||
|
private System.Windows.Forms.Button btnConnect;
|
||||||
|
private System.Windows.Forms.TextBox txtPath;
|
||||||
|
private System.Windows.Forms.Label lblPath;
|
||||||
|
private System.Windows.Forms.NumericUpDown nudPort;
|
||||||
|
private System.Windows.Forms.Label lblPort;
|
||||||
|
private System.Windows.Forms.TextBox txtHost;
|
||||||
|
private System.Windows.Forms.Label lblHost;
|
||||||
|
private System.Windows.Forms.Button btnDisconnect;
|
||||||
|
private System.Windows.Forms.Button btnClose;
|
||||||
|
private System.Windows.Forms.Timer statusTimer;
|
||||||
|
}
|
||||||
|
}
|
||||||
288
WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.cs
Normal file
288
WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.cs
Normal file
|
|
@ -0,0 +1,288 @@
|
||||||
|
// WebSocketManagerForm.cs
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// SPDX-FileCopyrightText: 2025 Catswords OSS and WelsonJS Contributors
|
||||||
|
// https://github.com/gnh1201/welsonjs
|
||||||
|
//
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace WelsonJS.Launcher
|
||||||
|
{
|
||||||
|
public partial class WebSocketManagerForm : Form
|
||||||
|
{
|
||||||
|
private sealed class ConnectionInfo
|
||||||
|
{
|
||||||
|
public string Host;
|
||||||
|
public int Port;
|
||||||
|
public string Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class ConnectionRecord
|
||||||
|
{
|
||||||
|
public ConnectionInfo Info;
|
||||||
|
public ClientWebSocket Socket;
|
||||||
|
public string LastStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly WebSocketManager _manager;
|
||||||
|
private readonly ConcurrentDictionary<string, ConnectionRecord> _records;
|
||||||
|
private readonly string _dateTimeFormat;
|
||||||
|
|
||||||
|
public WebSocketManagerForm()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
_manager = new WebSocketManager();
|
||||||
|
_records = new ConcurrentDictionary<string, ConnectionRecord>();
|
||||||
|
|
||||||
|
string format = Program.GetAppConfig("DateTimeFormat");
|
||||||
|
if (string.IsNullOrWhiteSpace(format))
|
||||||
|
{
|
||||||
|
format = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
}
|
||||||
|
|
||||||
|
_dateTimeFormat = format;
|
||||||
|
btnConnect.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WebSocketManagerForm_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
statusTimer.Start();
|
||||||
|
UpdateButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WebSocketManagerForm_FormClosed(object sender, FormClosedEventArgs e)
|
||||||
|
{
|
||||||
|
statusTimer.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConnectionInputChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
btnConnect.Enabled = !string.IsNullOrWhiteSpace(txtHost.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void btnConnect_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
string host = txtHost.Text.Trim();
|
||||||
|
string path = NormalizePath(txtPath.Text);
|
||||||
|
int port = (int)nudPort.Value;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(host))
|
||||||
|
{
|
||||||
|
MessageBox.Show("Host is required.", "WebSocket Manager", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
txtHost.Focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
btnConnect.Enabled = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ConnectionInfo info = new ConnectionInfo
|
||||||
|
{
|
||||||
|
Host = host,
|
||||||
|
Port = port,
|
||||||
|
Path = path
|
||||||
|
};
|
||||||
|
|
||||||
|
ClientWebSocket socket = await _manager.GetOrCreateAsync(info.Host, info.Port, info.Path);
|
||||||
|
|
||||||
|
string key = BuildKey(info.Host, info.Port, info.Path);
|
||||||
|
ConnectionRecord record = _records.GetOrAdd(key, k => new ConnectionRecord { Info = info });
|
||||||
|
record.Info = info;
|
||||||
|
record.Socket = socket;
|
||||||
|
record.LastStatus = socket.State.ToString();
|
||||||
|
|
||||||
|
AddOrUpdateListViewItem(record, record.LastStatus);
|
||||||
|
RefreshStatuses();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Failed to connect: " + ex.Message, "WebSocket Manager", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
btnConnect.Enabled = !string.IsNullOrWhiteSpace(txtHost.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnDisconnect_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
ConnectionRecord record = GetSelectedRecord();
|
||||||
|
if (record == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_manager.Remove(record.Info.Host, record.Info.Port, record.Info.Path);
|
||||||
|
|
||||||
|
if (record.Socket != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
record.Socket.Dispose();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore dispose errors from socket
|
||||||
|
}
|
||||||
|
record.Socket = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
record.LastStatus = "Closed";
|
||||||
|
AddOrUpdateListViewItem(record, record.LastStatus);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Failed to disconnect: " + ex.Message, "WebSocket Manager", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnRefresh_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
RefreshStatuses();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnClose_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void statusTimer_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
RefreshStatuses();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lvConnections_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
UpdateButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateButtons()
|
||||||
|
{
|
||||||
|
btnDisconnect.Enabled = lvConnections.SelectedItems.Count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshStatuses()
|
||||||
|
{
|
||||||
|
foreach (ListViewItem item in lvConnections.Items)
|
||||||
|
{
|
||||||
|
ConnectionRecord record = item.Tag as ConnectionRecord;
|
||||||
|
if (record == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string status = record.LastStatus ?? "Unknown";
|
||||||
|
if (record.Socket != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
status = record.Socket.State.ToString();
|
||||||
|
record.LastStatus = status;
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
record.Socket = null;
|
||||||
|
status = "Disposed";
|
||||||
|
record.LastStatus = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.SubItems.Count >= 5)
|
||||||
|
{
|
||||||
|
item.SubItems[3].Text = status;
|
||||||
|
item.SubItems[4].Text = DateTime.Now.ToString(_dateTimeFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddOrUpdateListViewItem(ConnectionRecord record, string status)
|
||||||
|
{
|
||||||
|
string key = BuildKey(record.Info.Host, record.Info.Port, record.Info.Path);
|
||||||
|
string formattedPath = FormatPath(record.Info.Path);
|
||||||
|
string timestamp = DateTime.Now.ToString(_dateTimeFormat);
|
||||||
|
|
||||||
|
ListViewItem item;
|
||||||
|
if (lvConnections.Items.ContainsKey(key))
|
||||||
|
{
|
||||||
|
item = lvConnections.Items[key];
|
||||||
|
item.SubItems[0].Text = record.Info.Host;
|
||||||
|
item.SubItems[1].Text = record.Info.Port.ToString();
|
||||||
|
item.SubItems[2].Text = formattedPath;
|
||||||
|
item.SubItems[3].Text = status;
|
||||||
|
item.SubItems[4].Text = timestamp;
|
||||||
|
item.Tag = record;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item = new ListViewItem(new string[]
|
||||||
|
{
|
||||||
|
record.Info.Host,
|
||||||
|
record.Info.Port.ToString(),
|
||||||
|
formattedPath,
|
||||||
|
status,
|
||||||
|
timestamp
|
||||||
|
});
|
||||||
|
item.Name = key;
|
||||||
|
item.Tag = record;
|
||||||
|
lvConnections.Items.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConnectionRecord GetSelectedRecord()
|
||||||
|
{
|
||||||
|
if (lvConnections.SelectedItems.Count == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lvConnections.SelectedItems[0].Tag as ConnectionRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string NormalizePath(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
string trimmed = path.Trim();
|
||||||
|
while (trimmed.StartsWith("/", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
trimmed = trimmed.Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatPath(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.StartsWith("/", StringComparison.Ordinal) ? path : "/" + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildKey(string host, int port, string path)
|
||||||
|
{
|
||||||
|
if (host == null)
|
||||||
|
{
|
||||||
|
host = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path == null)
|
||||||
|
{
|
||||||
|
path = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return host.ToLowerInvariant() + ":" + port + "/" + path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.resx
Normal file
15
WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.resx
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
|
|
@ -127,6 +127,12 @@
|
||||||
<Compile Include="GlobalSettingsForm.Designer.cs">
|
<Compile Include="GlobalSettingsForm.Designer.cs">
|
||||||
<DependentUpon>GlobalSettingsForm.cs</DependentUpon>
|
<DependentUpon>GlobalSettingsForm.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="WebSocketManagerForm.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="WebSocketManagerForm.Designer.cs">
|
||||||
|
<DependentUpon>WebSocketManagerForm.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="ResourceServer.cs" />
|
<Compile Include="ResourceServer.cs" />
|
||||||
<Compile Include="TraceLogger.cs" />
|
<Compile Include="TraceLogger.cs" />
|
||||||
<Compile Include="WebSocketManager.cs" />
|
<Compile Include="WebSocketManager.cs" />
|
||||||
|
|
@ -147,6 +153,9 @@
|
||||||
<EmbeddedResource Include="GlobalSettingsForm.resx">
|
<EmbeddedResource Include="GlobalSettingsForm.resx">
|
||||||
<DependentUpon>GlobalSettingsForm.cs</DependentUpon>
|
<DependentUpon>GlobalSettingsForm.cs</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="WebSocketManagerForm.resx">
|
||||||
|
<DependentUpon>WebSocketManagerForm.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
<None Include="app.config" />
|
<None Include="app.config" />
|
||||||
<None Include="Properties\Settings.settings">
|
<None Include="Properties\Settings.settings">
|
||||||
<Generator>SettingsSingleFileGenerator</Generator>
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user