diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs
index 76ba271..be45706 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs
@@ -135,6 +135,7 @@
this.runAsAdministratorToolStripMenuItem,
this.globalSettingsToolStripMenuItem,
this.startTheEditorToolStripMenuItem,
+ this.webSocketManagerToolStripMenuItem,
this.openCopilotToolStripMenuItem});
this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
this.settingsToolStripMenuItem.Size = new System.Drawing.Size(62, 20);
@@ -174,9 +175,16 @@
this.startTheEditorToolStripMenuItem.Size = new System.Drawing.Size(196, 22);
this.startTheEditorToolStripMenuItem.Text = "Start the editor...";
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
- //
+ //
this.openCopilotToolStripMenuItem.Name = "openCopilotToolStripMenuItem";
this.openCopilotToolStripMenuItem.Size = new System.Drawing.Size(196, 22);
this.openCopilotToolStripMenuItem.Text = "Open the Copilot...";
@@ -291,6 +299,7 @@
private System.Windows.Forms.ToolStripMenuItem openCodeEditorToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem openLauncherToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem openCopilotToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem webSocketManagerToolStripMenuItem;
private System.Windows.Forms.SaveFileDialog saveFileDialog1;
private System.Windows.Forms.Button btnStartTheEditor;
private System.Windows.Forms.Button btnJoinTheCommunity;
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs
index f55da4b..e3ce7dd 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs
@@ -335,6 +335,11 @@ namespace WelsonJS.Launcher
Program.OpenWebBrowser(Program.GetAppConfig("CopilotUrl"));
}
+ private void webSocketManagerToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ (new WebSocketManagerForm()).Show();
+ }
+
private void btnJoinTheCommunity_Click(object sender, EventArgs e)
{
Program.OpenWebBrowser(Program.GetAppConfig("RepositoryUrl"));
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.Designer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.Designer.cs
new file mode 100644
index 0000000..df51939
--- /dev/null
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.Designer.cs
@@ -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
+ {
+ ///
+ /// 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.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;
+ }
+}
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.cs
new file mode 100644
index 0000000..ea3e65e
--- /dev/null
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.cs
@@ -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 _records;
+ private readonly string _dateTimeFormat;
+
+ public WebSocketManagerForm()
+ {
+ InitializeComponent();
+
+ _manager = new WebSocketManager();
+ _records = new ConcurrentDictionary();
+
+ 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;
+ }
+ }
+}
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.resx b/WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.resx
new file mode 100644
index 0000000..1510323
--- /dev/null
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/WebSocketManagerForm.resx
@@ -0,0 +1,15 @@
+
+
+
+ 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
+
+
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj b/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj
index 5bc8b61..c5a314f 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj
@@ -127,6 +127,12 @@
GlobalSettingsForm.cs
+
+ Form
+
+
+ WebSocketManagerForm.cs
+
@@ -147,6 +153,9 @@
GlobalSettingsForm.cs
+
+ WebSocketManagerForm.cs
+
SettingsSingleFileGenerator