diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index d407957c..2728b3d0 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -717,6 +717,12 @@ namespace Shadowsocks.Controller Configuration.Save(_config); } + public void SaveOnlineConfigSource(IEnumerable vs) + { + _config.onlineConfigSource = vs.ToList(); + SaveConfig(_config); + } + #endregion } } diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 3ac1748f..f73e2102 100644 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -57,13 +57,13 @@ namespace Shadowsocks.View private MenuItem VerboseLoggingToggleItem; private MenuItem ShowPluginOutputToggleItem; private MenuItem WriteI18NFileItem; + private MenuItem onlineConfigItem; private ConfigForm configForm; private ProxyForm proxyForm; private LogForm logForm; private HotkeySettingsForm hotkeySettingsForm; - - + private OnlineConfigForm onlineConfigForm; // color definition for icon color transformation private readonly Color colorMaskBlue = Color.FromArgb(255, 25, 125, 191); @@ -118,37 +118,6 @@ namespace Shadowsocks.View } } - private void controller_TrafficChanged(object sender, EventArgs e) - { - if (icon == null) - return; - - Icon newIcon; - - bool hasInbound = controller.trafficPerSecondQueue.Last().inboundIncreasement > 0; - bool hasOutbound = controller.trafficPerSecondQueue.Last().outboundIncreasement > 0; - - if (hasInbound && hasOutbound) - newIcon = icon_both; - else if (hasInbound) - newIcon = icon_in; - else if (hasOutbound) - newIcon = icon_out; - else - newIcon = icon; - - if (newIcon != this.previousIcon) - { - this.previousIcon = newIcon; - _notifyIcon.Icon = newIcon; - } - } - - void controller_Errored(object sender, System.IO.ErrorEventArgs e) - { - MessageBox.Show(e.GetException().ToString(), I18N.GetString("Shadowsocks Error: {0}", e.GetException().Message)); - } - #region Tray Icon private void UpdateTrayIconAndNotifyText() @@ -269,8 +238,6 @@ namespace Shadowsocks.View icon_both = Icon.FromHandle(ViewUtils.ResizeBitmap(ViewUtils.AddBitmapOverlay(iconBitmap, Resources.ss32In, Resources.ss32Out), size.Width, size.Height).GetHicon()); } - - #endregion #region MenuItems and MenuGroups @@ -314,6 +281,7 @@ namespace Shadowsocks.View this.editOnlinePACItem = CreateMenuItem("Edit Online PAC URL...", new EventHandler(this.UpdateOnlinePACURLItem_Click)), }), this.proxyItem = CreateMenuItem("Forward Proxy...", new EventHandler(this.proxyItem_Click)), + this.onlineConfigItem = CreateMenuItem("Online Config...", new EventHandler(this.OnlineConfig_Click)), new MenuItem("-"), this.AutoStartupItem = CreateMenuItem("Start on Boot", new EventHandler(this.AutoStartupItem_Click)), this.ProtocolHandlerItem = CreateMenuItem("Associate ss:// Links", new EventHandler(this.ProtocolHandlerItem_Click)), @@ -340,99 +308,41 @@ namespace Shadowsocks.View #endregion - private void controller_ConfigChanged(object sender, EventArgs e) - { - LoadCurrentConfiguration(); - UpdateTrayIconAndNotifyText(); - } - - private void controller_EnableStatusChanged(object sender, EventArgs e) - { - disableItem.Checked = !controller.GetConfigurationCopy().enabled; - } - - void controller_ShareOverLANStatusChanged(object sender, EventArgs e) - { - ShareOverLANItem.Checked = controller.GetConfigurationCopy().shareOverLan; - } - - void controller_VerboseLoggingStatusChanged(object sender, EventArgs e) - { - VerboseLoggingToggleItem.Checked = controller.GetConfigurationCopy().isVerboseLogging; - } - - void controller_ShowPluginOutputChanged(object sender, EventArgs e) - { - ShowPluginOutputToggleItem.Checked = controller.GetConfigurationCopy().showPluginOutput; - } - - void controller_EnableGlobalChanged(object sender, EventArgs e) - { - globalModeItem.Checked = controller.GetConfigurationCopy().global; - PACModeItem.Checked = !globalModeItem.Checked; - } - - void controller_FileReadyToOpen(object sender, ShadowsocksController.PathEventArgs e) + private void controller_TrafficChanged(object sender, EventArgs e) { - string argument = @"/select, " + e.Path; - - Process.Start("explorer.exe", argument); - } + if (icon == null) + return; - void ShowBalloonTip(string title, string content, ToolTipIcon icon, int timeout) - { - _notifyIcon.BalloonTipTitle = title; - _notifyIcon.BalloonTipText = content; - _notifyIcon.BalloonTipIcon = icon; - _notifyIcon.ShowBalloonTip(timeout); - } + Icon newIcon; - void controller_UpdatePACFromGeositeError(object sender, System.IO.ErrorEventArgs e) - { - ShowBalloonTip(I18N.GetString("Failed to update PAC file"), e.GetException().Message, ToolTipIcon.Error, 5000); - logger.LogUsefulException(e.GetException()); - } + bool hasInbound = controller.trafficPerSecondQueue.Last().inboundIncreasement > 0; + bool hasOutbound = controller.trafficPerSecondQueue.Last().outboundIncreasement > 0; - void controller_UpdatePACFromGeositeCompleted(object sender, GeositeResultEventArgs e) - { - string result = e.Success - ? I18N.GetString("PAC updated") - : I18N.GetString("No updates found. Please report to Geosite if you have problems with it."); - ShowBalloonTip(I18N.GetString("Shadowsocks"), result, ToolTipIcon.Info, 1000); - } + if (hasInbound && hasOutbound) + newIcon = icon_both; + else if (hasInbound) + newIcon = icon_in; + else if (hasOutbound) + newIcon = icon_out; + else + newIcon = icon; - void updateChecker_CheckUpdateCompleted(object sender, EventArgs e) - { - if (updateChecker.NewVersionFound) - { - ShowBalloonTip(I18N.GetString("Shadowsocks {0} Update Found", updateChecker.LatestVersionNumber + updateChecker.LatestVersionSuffix), I18N.GetString("Click here to update"), ToolTipIcon.Info, 5000); - } - else if (!_isStartupChecking) + if (newIcon != this.previousIcon) { - ShowBalloonTip(I18N.GetString("Shadowsocks"), I18N.GetString("No update is available"), ToolTipIcon.Info, 5000); + this.previousIcon = newIcon; + _notifyIcon.Icon = newIcon; } - _isStartupChecking = false; } - void notifyIcon1_BalloonTipClicked(object sender, EventArgs e) + void controller_Errored(object sender, System.IO.ErrorEventArgs e) { - if (updateChecker.NewVersionFound) - { - updateChecker.NewVersionFound = false; /* Reset the flag */ - if (File.Exists(updateChecker.LatestVersionLocalName)) - { - string argument = "/select, \"" + updateChecker.LatestVersionLocalName + "\""; - Process.Start("explorer.exe", argument); - } - } + MessageBox.Show(e.GetException().ToString(), I18N.GetString("Shadowsocks Error: {0}", e.GetException().Message)); } - private void _notifyIcon_BalloonTipClosed(object sender, EventArgs e) + private void controller_ConfigChanged(object sender, EventArgs e) { - if (updateChecker.NewVersionFound) - { - updateChecker.NewVersionFound = false; /* Reset the flag */ - } + LoadCurrentConfiguration(); + UpdateTrayIconAndNotifyText(); } private void LoadCurrentConfiguration() @@ -452,48 +362,7 @@ namespace Shadowsocks.View UpdateUpdateMenu(); } - private void UpdateServersMenu() - { - var items = ServersItem.MenuItems; - while (items[0] != SeperatorItem) - { - items.RemoveAt(0); - } - int strategyCount = 0; - foreach (var strategy in controller.GetStrategies()) - { - MenuItem item = new MenuItem(strategy.Name); - item.Tag = strategy.ID; - item.Click += AStrategyItem_Click; - items.Add(strategyCount, item); - strategyCount++; - } - - // user wants a seperator item between strategy and servers menugroup - items.Add(strategyCount++, new MenuItem("-")); - - int serverCount = 0; - Configuration configuration = controller.GetConfigurationCopy(); - foreach (var server in configuration.configs) - { - if (Configuration.ChecksServer(server)) - { - MenuItem item = new MenuItem(server.ToString()); - item.Tag = configuration.configs.FindIndex(s => s == server); - item.Click += AServerItem_Click; - items.Add(strategyCount + serverCount, item); - serverCount++; - } - } - - foreach (MenuItem item in items) - { - if (item.Tag != null && (item.Tag.ToString() == configuration.index.ToString() || item.Tag.ToString() == configuration.strategy)) - { - item.Checked = true; - } - } - } + #region Forms private void ShowConfigForm() { @@ -555,6 +424,22 @@ namespace Shadowsocks.View } } + private void ShowOnlineConfigForm() + { + + if (onlineConfigForm != null) + { + onlineConfigForm.Activate(); + } + else + { + onlineConfigForm = new OnlineConfigForm(controller); + onlineConfigForm.Show(); + onlineConfigForm.Activate(); + onlineConfigForm.FormClosed += onlineConfigForm_FormClosed; + } + } + void logForm_FormClosed(object sender, FormClosedEventArgs e) { logForm.Dispose(); @@ -594,29 +479,44 @@ namespace Shadowsocks.View Utils.ReleaseMemory(true); } - private void Config_Click(object sender, EventArgs e) + void onlineConfigForm_FormClosed(object sender, FormClosedEventArgs e) { - ShowConfigForm(); + onlineConfigForm.Dispose(); + onlineConfigForm = null; + Utils.ReleaseMemory(true); } - private void Quit_Click(object sender, EventArgs e) + #endregion + + #region Misc + + void ShowBalloonTip(string title, string content, ToolTipIcon icon, int timeout) { - controller.Stop(); - _notifyIcon.Visible = false; - Application.Exit(); + _notifyIcon.BalloonTipTitle = title; + _notifyIcon.BalloonTipText = content; + _notifyIcon.BalloonTipIcon = icon; + _notifyIcon.ShowBalloonTip(timeout); } - private void CheckUpdateForFirstRun() + void notifyIcon1_BalloonTipClicked(object sender, EventArgs e) { - Configuration config = controller.GetConfigurationCopy(); - if (config.isDefault) return; - _isStartupChecking = true; - updateChecker.CheckUpdate(config, 3000); + if (updateChecker.NewVersionFound) + { + updateChecker.NewVersionFound = false; /* Reset the flag */ + if (File.Exists(updateChecker.LatestVersionLocalName)) + { + string argument = "/select, \"" + updateChecker.LatestVersionLocalName + "\""; + Process.Start("explorer.exe", argument); + } + } } - private void AboutItem_Click(object sender, EventArgs e) + private void _notifyIcon_BalloonTipClosed(object sender, EventArgs e) { - Process.Start("https://github.com/shadowsocks/shadowsocks-windows"); + if (updateChecker.NewVersionFound) + { + updateChecker.NewVersionFound = false; /* Reset the flag */ + } } private void notifyIcon1_Click(object sender, MouseEventArgs e) @@ -636,6 +536,85 @@ namespace Shadowsocks.View } } + private void CheckUpdateForFirstRun() + { + Configuration config = controller.GetConfigurationCopy(); + if (config.isDefault) return; + _isStartupChecking = true; + updateChecker.CheckUpdate(config, 3000); + } + + public void ShowLogForm_HotKey() + { + ShowLogForm(); + } + + #endregion + + #region Main menu + + void controller_ShareOverLANStatusChanged(object sender, EventArgs e) + { + ShareOverLANItem.Checked = controller.GetConfigurationCopy().shareOverLan; + } + + private void proxyItem_Click(object sender, EventArgs e) + { + ShowProxyForm(); + } + + private void OnlineConfig_Click(object sender, EventArgs e) + { + ShowOnlineConfigForm(); + } + + private void hotKeyItem_Click(object sender, EventArgs e) + { + ShowHotKeySettingsForm(); + } + + private void ShareOverLANItem_Click(object sender, EventArgs e) + { + ShareOverLANItem.Checked = !ShareOverLANItem.Checked; + controller.ToggleShareOverLAN(ShareOverLANItem.Checked); + } + + private void AutoStartupItem_Click(object sender, EventArgs e) + { + AutoStartupItem.Checked = !AutoStartupItem.Checked; + if (!AutoStartup.Set(AutoStartupItem.Checked)) + { + MessageBox.Show(I18N.GetString("Failed to update registry")); + } + LoadCurrentConfiguration(); + } + + private void ProtocolHandlerItem_Click(object sender, EventArgs e) + { + ProtocolHandlerItem.Checked = !ProtocolHandlerItem.Checked; + if (!ProtocolHandler.Set(ProtocolHandlerItem.Checked)) + { + MessageBox.Show(I18N.GetString("Failed to update registry")); + } + LoadCurrentConfiguration(); + } + + private void Quit_Click(object sender, EventArgs e) + { + controller.Stop(); + _notifyIcon.Visible = false; + Application.Exit(); + } + + #endregion + + #region System proxy + + private void controller_EnableStatusChanged(object sender, EventArgs e) + { + disableItem.Checked = !controller.GetConfigurationCopy().enabled; + } + private void EnableItem_Click(object sender, EventArgs e) { controller.ToggleEnable(false); @@ -643,6 +622,12 @@ namespace Shadowsocks.View UpdateSystemProxyItemsEnabledStatus(config); } + void controller_EnableGlobalChanged(object sender, EventArgs e) + { + globalModeItem.Checked = controller.GetConfigurationCopy().global; + PACModeItem.Checked = !globalModeItem.Checked; + } + private void UpdateSystemProxyItemsEnabledStatus(Configuration config) { disableItem.Checked = !config.enabled; @@ -674,25 +659,51 @@ namespace Shadowsocks.View UpdateSystemProxyItemsEnabledStatus(config); } - private void ShareOverLANItem_Click(object sender, EventArgs e) - { - ShareOverLANItem.Checked = !ShareOverLANItem.Checked; - controller.ToggleShareOverLAN(ShareOverLANItem.Checked); - } + #endregion - private void EditPACFileItem_Click(object sender, EventArgs e) - { - controller.TouchPACFile(); - } + #region Server - private async void UpdatePACFromGeositeItem_Click(object sender, EventArgs e) + private void UpdateServersMenu() { - await GeositeUpdater.UpdatePACFromGeosite(); - } + var items = ServersItem.MenuItems; + while (items[0] != SeperatorItem) + { + items.RemoveAt(0); + } + int strategyCount = 0; + foreach (var strategy in controller.GetStrategies()) + { + MenuItem item = new MenuItem(strategy.Name); + item.Tag = strategy.ID; + item.Click += AStrategyItem_Click; + items.Add(strategyCount, item); + strategyCount++; + } - private void EditUserRuleFileForGeositeItem_Click(object sender, EventArgs e) - { - controller.TouchUserRuleFile(); + // user wants a seperator item between strategy and servers menugroup + items.Add(strategyCount++, new MenuItem("-")); + + int serverCount = 0; + Configuration configuration = controller.GetConfigurationCopy(); + foreach (var server in configuration.configs) + { + if (Configuration.ChecksServer(server)) + { + MenuItem item = new MenuItem(server.ToString()); + item.Tag = configuration.configs.FindIndex(s => s == server); + item.Click += AServerItem_Click; + items.Add(strategyCount + serverCount, item); + serverCount++; + } + } + + foreach (MenuItem item in items) + { + if (item.Tag != null && (item.Tag.ToString() == configuration.index.ToString() || item.Tag.ToString() == configuration.strategy)) + { + item.Checked = true; + } + } } private void AServerItem_Click(object sender, EventArgs e) @@ -707,21 +718,19 @@ namespace Shadowsocks.View controller.SelectStrategy((string)item.Tag); } - private void VerboseLoggingToggleItem_Click(object sender, EventArgs e) + private void Config_Click(object sender, EventArgs e) { - VerboseLoggingToggleItem.Checked = !VerboseLoggingToggleItem.Checked; - controller.ToggleVerboseLogging(VerboseLoggingToggleItem.Checked); + ShowConfigForm(); } - private void ShowPluginOutputToggleItem_Click(object sender, EventArgs e) + void splash_FormClosed(object sender, FormClosedEventArgs e) { - ShowPluginOutputToggleItem.Checked = !ShowPluginOutputToggleItem.Checked; - controller.ToggleShowPluginOutput(ShowPluginOutputToggleItem.Checked); + ShowConfigForm(); } - private void WriteI18NFileItem_Click(object sender, EventArgs e) + void openURLFromQRCode(object sender, FormClosedEventArgs e) { - File.WriteAllText(I18N.I18N_FILE, Resources.i18n_csv, Encoding.UTF8); + Process.Start(_urlToOpen); } private void StatisticsConfigItem_Click(object sender, EventArgs e) @@ -830,34 +839,9 @@ namespace Shadowsocks.View } } - void splash_FormClosed(object sender, FormClosedEventArgs e) - { - ShowConfigForm(); - } - - void openURLFromQRCode(object sender, FormClosedEventArgs e) - { - Process.Start(_urlToOpen); - } + #endregion - private void AutoStartupItem_Click(object sender, EventArgs e) - { - AutoStartupItem.Checked = !AutoStartupItem.Checked; - if (!AutoStartup.Set(AutoStartupItem.Checked)) - { - MessageBox.Show(I18N.GetString("Failed to update registry")); - } - LoadCurrentConfiguration(); - } - private void ProtocolHandlerItem_Click(object sender, EventArgs e) - { - ProtocolHandlerItem.Checked = !ProtocolHandlerItem.Checked; - if (!ProtocolHandler.Set(ProtocolHandlerItem.Checked)) - { - MessageBox.Show(I18N.GetString("Failed to update registry")); - } - LoadCurrentConfiguration(); - } + #region PAC private void LocalPACItem_Click(object sender, EventArgs e) { @@ -930,6 +914,94 @@ namespace Shadowsocks.View } } + private void EditPACFileItem_Click(object sender, EventArgs e) + { + controller.TouchPACFile(); + } + + private async void UpdatePACFromGeositeItem_Click(object sender, EventArgs e) + { + await GeositeUpdater.UpdatePACFromGeosite(); + } + + private void EditUserRuleFileForGeositeItem_Click(object sender, EventArgs e) + { + controller.TouchUserRuleFile(); + } + + void controller_FileReadyToOpen(object sender, ShadowsocksController.PathEventArgs e) + { + string argument = @"/select, " + e.Path; + + Process.Start("explorer.exe", argument); + } + + void controller_UpdatePACFromGeositeError(object sender, System.IO.ErrorEventArgs e) + { + ShowBalloonTip(I18N.GetString("Failed to update PAC file"), e.GetException().Message, ToolTipIcon.Error, 5000); + logger.LogUsefulException(e.GetException()); + } + + void controller_UpdatePACFromGeositeCompleted(object sender, GeositeResultEventArgs e) + { + string result = e.Success + ? I18N.GetString("PAC updated") + : I18N.GetString("No updates found. Please report to Geosite if you have problems with it."); + ShowBalloonTip(I18N.GetString("Shadowsocks"), result, ToolTipIcon.Info, 1000); + } + + #endregion + + #region Help + + void controller_VerboseLoggingStatusChanged(object sender, EventArgs e) + { + VerboseLoggingToggleItem.Checked = controller.GetConfigurationCopy().isVerboseLogging; + } + + void controller_ShowPluginOutputChanged(object sender, EventArgs e) + { + ShowPluginOutputToggleItem.Checked = controller.GetConfigurationCopy().showPluginOutput; + } + + private void VerboseLoggingToggleItem_Click(object sender, EventArgs e) + { + VerboseLoggingToggleItem.Checked = !VerboseLoggingToggleItem.Checked; + controller.ToggleVerboseLogging(VerboseLoggingToggleItem.Checked); + } + + private void ShowLogItem_Click(object sender, EventArgs e) + { + ShowLogForm(); + } + + private void ShowPluginOutputToggleItem_Click(object sender, EventArgs e) + { + ShowPluginOutputToggleItem.Checked = !ShowPluginOutputToggleItem.Checked; + controller.ToggleShowPluginOutput(ShowPluginOutputToggleItem.Checked); + } + + private void WriteI18NFileItem_Click(object sender, EventArgs e) + { + File.WriteAllText(I18N.I18N_FILE, Resources.i18n_csv, Encoding.UTF8); + } + + #endregion + + #region Update + + void updateChecker_CheckUpdateCompleted(object sender, EventArgs e) + { + if (updateChecker.NewVersionFound) + { + ShowBalloonTip(I18N.GetString("Shadowsocks {0} Update Found", updateChecker.LatestVersionNumber + updateChecker.LatestVersionSuffix), I18N.GetString("Click here to update"), ToolTipIcon.Info, 5000); + } + else if (!_isStartupChecking) + { + ShowBalloonTip(I18N.GetString("Shadowsocks"), I18N.GetString("No update is available"), ToolTipIcon.Info, 5000); + } + _isStartupChecking = false; + } private void UpdateUpdateMenu() { @@ -957,24 +1029,11 @@ namespace Shadowsocks.View updateChecker.CheckUpdate(controller.GetConfigurationCopy()); } - private void proxyItem_Click(object sender, EventArgs e) - { - ShowProxyForm(); - } - - private void hotKeyItem_Click(object sender, EventArgs e) - { - ShowHotKeySettingsForm(); - } - - private void ShowLogItem_Click(object sender, EventArgs e) + private void AboutItem_Click(object sender, EventArgs e) { - ShowLogForm(); + Process.Start("https://github.com/shadowsocks/shadowsocks-windows"); } - public void ShowLogForm_HotKey() - { - ShowLogForm(); - } + #endregion } } diff --git a/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs b/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs new file mode 100644 index 00000000..f80e5ba6 --- /dev/null +++ b/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs @@ -0,0 +1,207 @@ +namespace Shadowsocks.View +{ + partial class OnlineConfigForm + { + /// + /// 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.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.UrlListBox = new System.Windows.Forms.ListBox(); + this.label1 = new System.Windows.Forms.Label(); + this.UrlTextBox = new System.Windows.Forms.TextBox(); + this.UpdateButton = new System.Windows.Forms.Button(); + this.AddButton = new System.Windows.Forms.Button(); + this.DeleteButton = new System.Windows.Forms.Button(); + this.UpdateAllButton = new System.Windows.Forms.Button(); + this.OkButton = new System.Windows.Forms.Button(); + this.CancelButton = new System.Windows.Forms.Button(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel1.Controls.Add(this.UrlListBox, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.label1, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.UrlTextBox, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.UpdateButton, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.AddButton, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.DeleteButton, 2, 2); + this.tableLayoutPanel1.Controls.Add(this.OkButton, 1, 3); + this.tableLayoutPanel1.Controls.Add(this.UpdateAllButton, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.CancelButton, 2, 3); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 4; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(488, 465); + this.tableLayoutPanel1.TabIndex = 0; + // + // UrlListBox + // + this.tableLayoutPanel1.SetColumnSpan(this.UrlListBox, 3); + this.UrlListBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.UrlListBox.FormattingEnabled = true; + this.UrlListBox.ItemHeight = 15; + this.UrlListBox.Location = new System.Drawing.Point(3, 3); + this.UrlListBox.Name = "UrlListBox"; + this.UrlListBox.Size = new System.Drawing.Size(482, 344); + this.UrlListBox.TabIndex = 0; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Dock = System.Windows.Forms.DockStyle.Fill; + this.label1.Location = new System.Drawing.Point(3, 350); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(156, 31); + this.label1.TabIndex = 1; + this.label1.Text = "Online config URL"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // UrlTextBox + // + this.tableLayoutPanel1.SetColumnSpan(this.UrlTextBox, 2); + this.UrlTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.UrlTextBox.Location = new System.Drawing.Point(165, 353); + this.UrlTextBox.Name = "UrlTextBox"; + this.UrlTextBox.Size = new System.Drawing.Size(320, 25); + this.UrlTextBox.TabIndex = 2; + // + // UpdateButton + // + this.UpdateButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.UpdateButton.Location = new System.Drawing.Point(20, 386); + this.UpdateButton.Margin = new System.Windows.Forms.Padding(20, 5, 20, 5); + this.UpdateButton.MaximumSize = new System.Drawing.Size(0, 32); + this.UpdateButton.MinimumSize = new System.Drawing.Size(0, 32); + this.UpdateButton.Name = "UpdateButton"; + this.UpdateButton.Size = new System.Drawing.Size(122, 32); + this.UpdateButton.TabIndex = 3; + this.UpdateButton.Text = "Update"; + this.UpdateButton.UseVisualStyleBackColor = true; + // + // AddButton + // + this.AddButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.AddButton.Location = new System.Drawing.Point(182, 386); + this.AddButton.Margin = new System.Windows.Forms.Padding(20, 5, 20, 5); + this.AddButton.MaximumSize = new System.Drawing.Size(0, 32); + this.AddButton.MinimumSize = new System.Drawing.Size(0, 32); + this.AddButton.Name = "AddButton"; + this.AddButton.Size = new System.Drawing.Size(122, 32); + this.AddButton.TabIndex = 4; + this.AddButton.Text = "Add"; + this.AddButton.UseVisualStyleBackColor = true; + this.AddButton.Click += new System.EventHandler(this.AddButton_Click); + // + // DeleteButton + // + this.DeleteButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.DeleteButton.Location = new System.Drawing.Point(344, 386); + this.DeleteButton.Margin = new System.Windows.Forms.Padding(20, 5, 20, 5); + this.DeleteButton.MaximumSize = new System.Drawing.Size(0, 32); + this.DeleteButton.MinimumSize = new System.Drawing.Size(0, 32); + this.DeleteButton.Name = "DeleteButton"; + this.DeleteButton.Size = new System.Drawing.Size(124, 32); + this.DeleteButton.TabIndex = 5; + this.DeleteButton.Text = "Delete"; + this.DeleteButton.UseVisualStyleBackColor = true; + // + // UpdateAllButton + // + this.UpdateAllButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.UpdateAllButton.Location = new System.Drawing.Point(20, 428); + this.UpdateAllButton.Margin = new System.Windows.Forms.Padding(20, 5, 20, 5); + this.UpdateAllButton.MaximumSize = new System.Drawing.Size(0, 32); + this.UpdateAllButton.MinimumSize = new System.Drawing.Size(0, 32); + this.UpdateAllButton.Name = "UpdateAllButton"; + this.UpdateAllButton.Size = new System.Drawing.Size(122, 32); + this.UpdateAllButton.TabIndex = 6; + this.UpdateAllButton.Text = "Update all"; + this.UpdateAllButton.UseVisualStyleBackColor = true; + // + // OkButton + // + this.OkButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.OkButton.Location = new System.Drawing.Point(182, 428); + this.OkButton.Margin = new System.Windows.Forms.Padding(20, 5, 20, 5); + this.OkButton.MaximumSize = new System.Drawing.Size(0, 32); + this.OkButton.MinimumSize = new System.Drawing.Size(0, 32); + this.OkButton.Name = "OkButton"; + this.OkButton.Size = new System.Drawing.Size(122, 32); + this.OkButton.TabIndex = 7; + this.OkButton.Text = "OK"; + this.OkButton.UseVisualStyleBackColor = true; + // + // CancelButton + // + this.CancelButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.CancelButton.Location = new System.Drawing.Point(344, 428); + this.CancelButton.Margin = new System.Windows.Forms.Padding(20, 5, 20, 5); + this.CancelButton.MaximumSize = new System.Drawing.Size(0, 32); + this.CancelButton.MinimumSize = new System.Drawing.Size(0, 32); + this.CancelButton.Name = "CancelButton"; + this.CancelButton.Size = new System.Drawing.Size(124, 32); + this.CancelButton.TabIndex = 8; + this.CancelButton.Text = "Cancel"; + this.CancelButton.UseVisualStyleBackColor = true; + // + // OnlineConfigForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(488, 465); + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "OnlineConfigForm"; + this.Text = "OnlineConfigForm"; + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.ListBox UrlListBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox UrlTextBox; + private System.Windows.Forms.Button UpdateButton; + private System.Windows.Forms.Button AddButton; + private System.Windows.Forms.Button DeleteButton; + private System.Windows.Forms.Button OkButton; + private System.Windows.Forms.Button UpdateAllButton; + private System.Windows.Forms.Button CancelButton; + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/View/OnlineConfigForm.cs b/shadowsocks-csharp/View/OnlineConfigForm.cs new file mode 100644 index 00000000..782ef65e --- /dev/null +++ b/shadowsocks-csharp/View/OnlineConfigForm.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Shadowsocks.Controller; +using Shadowsocks.Model; + +namespace Shadowsocks.View +{ + public partial class OnlineConfigForm : Form + { + private ShadowsocksController controller; + private Configuration config; + + private const string DefaultPrefix = "http://www.baidu.com/"; + + public OnlineConfigForm(ShadowsocksController controller) + { + this.controller = controller; + InitializeComponent(); + LoadConfig(); + } + + private void LoadConfig() + { + config = controller.GetConfigurationCopy(); + var idx = UrlListBox.SelectedIndex; + UrlListBox.Items.Clear(); + + foreach (var item in config.onlineConfigSource) + { + UrlListBox.Items.Add(item); + } + + if (idx >= UrlListBox.Items.Count) idx = 0; + UrlListBox.SelectedIndex = idx; + } + + private bool ValidateUrl() + { + try + { + var scheme = new Uri(UrlTextBox.Text).Scheme; + if (scheme != "http" && scheme != "https") return false; + } + catch + { + return false; + } + return true; + } + + private bool Commit() + { + if (!ValidateUrl()) return false; + + UrlListBox.Items[UrlListBox.SelectedIndex] = UrlTextBox.Text; + controller.SaveOnlineConfigSource(UrlListBox.Items.OfType().Where(s=>!string.IsNullOrWhiteSpace(s))); + LoadConfig(); + return true; + } + + private void AddButton_Click(object sender, EventArgs e) + { + Commit(); + UrlListBox.Items.Add(""); + UrlTextBox.Text = DefaultPrefix; + UrlListBox.SelectedIndex = UrlListBox.Items.Count - 1; + } + } +} diff --git a/shadowsocks-csharp/View/OnlineConfigForm.resx b/shadowsocks-csharp/View/OnlineConfigForm.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/shadowsocks-csharp/View/OnlineConfigForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index c71ab472..a8d99a26 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -273,6 +273,12 @@ LogForm.cs + + Form + + + OnlineConfigForm.cs + Form @@ -312,6 +318,9 @@ LogForm.cs + + OnlineConfigForm.cs + ProxyForm.cs