diff --git a/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs b/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs index 4dd92a3f..40c64bdc 100644 --- a/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs +++ b/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs @@ -35,8 +35,6 @@ namespace Shadowsocks.Controller private static readonly string DATABASE_PATH = Utils.GetTempPath("dlc.dat"); - private static HttpClientHandler httpClientHandler; - private static HttpClient httpClient; private static readonly string GEOSITE_URL = "https://github.com/v2fly/domain-list-community/raw/release/dlc.dat"; private static readonly string GEOSITE_SHA256SUM_URL = "https://github.com/v2fly/domain-list-community/raw/release/dlc.dat.sha256sum"; private static byte[] geositeDB; @@ -82,7 +80,8 @@ namespace Shadowsocks.Controller SHA256 mySHA256 = SHA256.Create(); var config = Program.MainController.GetCurrentConfiguration(); bool blacklist = config.geositePreferDirect; - + var httpClient = Program.MainController.GetHttpClient(); + if (!string.IsNullOrWhiteSpace(config.geositeUrl)) { logger.Info("Found custom Geosite URL in config file"); @@ -90,22 +89,6 @@ namespace Shadowsocks.Controller } logger.Info($"Checking Geosite from {geositeUrl}"); - // use System.Net.Http.HttpClient to download GeoSite db. - // NASTY workaround: new HttpClient every update - // because we can't change proxy on existing socketsHttpHandler instance - httpClientHandler = new HttpClientHandler(); - httpClient = new HttpClient(httpClientHandler); - if (!string.IsNullOrWhiteSpace(config.userAgentString)) - httpClient.DefaultRequestHeaders.Add("User-Agent", config.userAgentString); - if (config.enabled) - { - httpClientHandler.Proxy = new WebProxy( - config.isIPv6Enabled - ? $"[{IPAddress.IPv6Loopback}]" - : IPAddress.Loopback.ToString(), - config.localPort); - } - try { // download checksum first @@ -154,19 +137,6 @@ namespace Shadowsocks.Controller { Error?.Invoke(null, new ErrorEventArgs(ex)); } - finally - { - if (httpClientHandler != null) - { - httpClientHandler.Dispose(); - httpClientHandler = null; - } - if (httpClient != null) - { - httpClient.Dispose(); - httpClient = null; - } - } } /// diff --git a/shadowsocks-csharp/Controller/Service/OnlineConfigResolver.cs b/shadowsocks-csharp/Controller/Service/OnlineConfigResolver.cs index 457e2ab7..31059b73 100644 --- a/shadowsocks-csharp/Controller/Service/OnlineConfigResolver.cs +++ b/shadowsocks-csharp/Controller/Service/OnlineConfigResolver.cs @@ -11,28 +11,15 @@ namespace Shadowsocks.Controller.Service { public class OnlineConfigResolver { - public static async Task> GetOnline(string url, string userAgentString, IWebProxy proxy = null) + public static async Task> GetOnline(string url) { - var httpClientHandler = new HttpClientHandler() - { - Proxy = proxy - }; - var httpClient = new HttpClient(httpClientHandler) - { - Timeout = TimeSpan.FromSeconds(15) - }; - if (!string.IsNullOrWhiteSpace(userAgentString)) - httpClient.DefaultRequestHeaders.Add("User-Agent", userAgentString); - + var httpClient = Program.MainController.GetHttpClient(); string server_json = await httpClient.GetStringAsync(url); - var servers = server_json.GetServers(); - foreach (var server in servers) { server.group = url; } - return servers.ToList(); } } diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index f971c5a2..c7141a6b 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -191,7 +191,7 @@ namespace Shadowsocks.Controller public DateTime lastActivity; private readonly ShadowsocksController _controller; - private readonly ProxyConfig _config; + private readonly ForwardProxyConfig _config; private readonly Socket _connection; private IEncryptor _encryptor; @@ -665,10 +665,10 @@ namespace Shadowsocks.Controller { switch (_config.proxyType) { - case ProxyConfig.PROXY_SOCKS5: + case ForwardProxyConfig.PROXY_SOCKS5: remote = new Socks5Proxy(); break; - case ProxyConfig.PROXY_HTTP: + case ForwardProxyConfig.PROXY_HTTP: remote = new HttpProxy(); break; default: diff --git a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs index c31e49e1..92ed276b 100644 --- a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs @@ -1,254 +1,174 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.IO; using System.Net; +using System.Net.Http; using System.Text.RegularExpressions; - +using System.Threading.Tasks; +using System.Windows; using Newtonsoft.Json.Linq; using NLog; +using Shadowsocks.Localization; using Shadowsocks.Model; using Shadowsocks.Util; +using Shadowsocks.Views; namespace Shadowsocks.Controller { public class UpdateChecker { - private static Logger logger = LogManager.GetCurrentClassLogger(); + private readonly Logger logger; + private readonly HttpClient httpClient; + // https://developer.github.com/v3/repos/releases/ private const string UpdateURL = "https://api.github.com/repos/shadowsocks/shadowsocks-windows/releases"; - private const string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36"; - private Configuration config; - public bool NewVersionFound; - public string LatestVersionNumber; - public string LatestVersionSuffix; - public string LatestVersionName; - public string LatestVersionURL; - public string LatestVersionLocalName; - public event EventHandler CheckUpdateCompleted; + private Configuration _config; + private Window versionUpdatePromptWindow; + private JToken _releaseObject; - public const string Version = "4.2.1.0"; - - private class CheckUpdateTimer : System.Timers.Timer - { - public Configuration config; + public string NewReleaseVersion { get; private set; } + public string NewReleaseZipFilename { get; private set; } - public CheckUpdateTimer(int p) : base(p) - { - } - } + public event EventHandler CheckUpdateCompleted; - public void CheckUpdate(Configuration config, int delay) - { - CheckUpdateTimer timer = new CheckUpdateTimer(delay); - timer.AutoReset = false; - timer.Elapsed += Timer_Elapsed; - timer.config = config; - timer.Enabled = true; - } + public const string Version = "4.2.1.0"; + private readonly Version _version; - private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + public UpdateChecker() { - CheckUpdateTimer timer = (CheckUpdateTimer)sender; - Configuration config = timer.config; - timer.Elapsed -= Timer_Elapsed; - timer.Enabled = false; - timer.Dispose(); - CheckUpdate(config); + logger = LogManager.GetCurrentClassLogger(); + httpClient = Program.MainController.GetHttpClient(); + _version = new Version(Version); + _config = Program.MainController.GetCurrentConfiguration(); } - public void CheckUpdate(Configuration config) + /// + /// Checks for updates and asks the user if updates are found. + /// + /// A delay in milliseconds before checking. + /// + public async Task CheckForVersionUpdate(int millisecondsDelay = 0) { - this.config = config; - + // delay + logger.Info($"Waiting for {millisecondsDelay}ms before checking for version update."); + await Task.Delay(millisecondsDelay); + // start + logger.Info($"Checking for version update."); try { - logger.Info("Checking updates..."); - WebClient http = CreateWebClient(); - http.DownloadStringCompleted += http_DownloadStringCompleted; - http.DownloadStringAsync(new Uri(UpdateURL)); - } - catch (Exception ex) - { - logger.LogUsefulException(ex); - } - } - - private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) - { - try - { - string response = e.Result; - - JArray result = JArray.Parse(response); - - List asserts = new List(); - if (result != null) + // list releases via API + var releasesListJsonString = await httpClient.GetStringAsync(UpdateURL); + // parse + var releasesJArray = JArray.Parse(releasesListJsonString); + foreach (var releaseObject in releasesJArray) { - foreach (JObject release in result) + var releaseTagName = (string)releaseObject["tag_name"]; + var releaseVersion = new Version(releaseTagName); + if (releaseTagName == _config.skippedUpdateVersion) // finished checking + break; + if (releaseVersion.CompareTo(_version) > 0 && + (!(bool)releaseObject["prerelease"] || _config.checkPreRelease && (bool)releaseObject["prerelease"])) // selected { - var isPreRelease = (bool)release["prerelease"]; - if (isPreRelease && !config.checkPreRelease) - { - continue; - } - foreach (JObject asset in (JArray)release["assets"]) - { - Asset ass = Asset.ParseAsset(asset); - if (ass != null) - { - ass.prerelease = isPreRelease; - if (ass.IsNewVersion(Version, config.checkPreRelease)) - { - asserts.Add(ass); - } - } - } - } - } - if (asserts.Count != 0) - { - SortByVersions(asserts); - Asset asset = asserts[asserts.Count - 1]; - NewVersionFound = true; - LatestVersionURL = asset.browser_download_url; - LatestVersionNumber = asset.version; - LatestVersionName = asset.name; - LatestVersionSuffix = asset.suffix == null ? "" : $"-{asset.suffix}"; - - startDownload(); - } - else - { - logger.Info("No update is available"); - if (CheckUpdateCompleted != null) - { - CheckUpdateCompleted(this, new EventArgs()); + logger.Info($"Found new version {releaseTagName}."); + _releaseObject = releaseObject; + NewReleaseVersion = releaseTagName; + AskToUpdate(releaseObject); + return; } } + logger.Info($"No new versions found."); + CheckUpdateCompleted?.Invoke(this, new EventArgs()); } - catch (Exception ex) + catch (Exception e) { - logger.LogUsefulException(ex); + logger.LogUsefulException(e); } } - private void startDownload() + /// + /// Opens a window to show the update's information. + /// + /// The update release object. + private void AskToUpdate(JToken releaseObject) { - try + if (versionUpdatePromptWindow == null) { - LatestVersionLocalName = Utils.GetTempPath(LatestVersionName); - WebClient http = CreateWebClient(); - http.DownloadFileCompleted += Http_DownloadFileCompleted; - http.DownloadFileAsync(new Uri(LatestVersionURL), LatestVersionLocalName); - } - catch (Exception ex) - { - logger.LogUsefulException(ex); + versionUpdatePromptWindow = new Window() + { + Title = LocalizationProvider.GetLocalizedValue("VersionUpdate"), + Height = 480, + Width = 640, + MinHeight = 480, + MinWidth = 640, + Content = new VersionUpdatePromptView(releaseObject) + }; + versionUpdatePromptWindow.Closed += VersionUpdatePromptWindow_Closed; + versionUpdatePromptWindow.Show(); } + versionUpdatePromptWindow.Activate(); } - private void Http_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) + private void VersionUpdatePromptWindow_Closed(object sender, EventArgs e) + { + versionUpdatePromptWindow = null; + } + + /// + /// Downloads the selected update and notifies the user. + /// + /// + public async Task DoUpdate() { try { - if (e.Error != null) + var assets = (JArray)_releaseObject["assets"]; + // download all assets + foreach (JObject asset in assets) { - logger.LogUsefulException(e.Error); - return; - } - logger.Info($"New version {LatestVersionNumber}{LatestVersionSuffix} found: {LatestVersionLocalName}"); - if (CheckUpdateCompleted != null) - { - CheckUpdateCompleted(this, new EventArgs()); + var filename = (string)asset["name"]; + var browser_download_url = (string)asset["browser_download_url"]; + var response = await httpClient.GetAsync(browser_download_url); + using (var downloadedFileStream = File.Create(Utils.GetTempPath(filename))) + await response.Content.CopyToAsync(downloadedFileStream); + logger.Info($"Downloaded {filename}."); + // store .zip filename + if (filename.EndsWith(".zip")) + NewReleaseZipFilename = filename; } + logger.Info("Finished downloading."); + // notify user + CloseVersionUpdatePromptWindow(); + Process.Start("explorer.exe", $"/select, \"{Utils.GetTempPath(NewReleaseZipFilename)}\""); } - catch (Exception ex) + catch (Exception e) { - logger.LogUsefulException(ex); + logger.LogUsefulException(e); } } - private WebClient CreateWebClient() + /// + /// Saves the skipped update version. + /// + public void SkipUpdate() { - WebClient http = new WebClient(); - http.Headers.Add("User-Agent", UserAgent); - http.Proxy = new WebProxy(config.LocalHost, config.localPort); - return http; + var version = (string)_releaseObject["tag_name"] ?? ""; + _config.skippedUpdateVersion = version; + Program.MainController.SaveSkippedUpdateVerion(version); + logger.Info($"The update {version} has been skipped and will be ignored next time."); + CloseVersionUpdatePromptWindow(); } - private void SortByVersions(List asserts) + /// + /// Closes the update prompt window. + /// + public void CloseVersionUpdatePromptWindow() { - asserts.Sort(); - } - - public class Asset : IComparable - { - public bool prerelease; - public string name; - public string version; - public string browser_download_url; - public string suffix; - - public static Asset ParseAsset(JObject assertJObject) - { - var name = (string)assertJObject["name"]; - Match match = Regex.Match(name, @"^Shadowsocks-(?\d+(?:\.\d+)*)(?:|-(?.+))\.\w+$", - RegexOptions.IgnoreCase); - if (match.Success) - { - string version = match.Groups["version"].Value; - - var asset = new Asset - { - browser_download_url = (string)assertJObject["browser_download_url"], - name = name, - version = version - }; - - if (match.Groups["suffix"].Success) - { - asset.suffix = match.Groups["suffix"].Value; - } - - return asset; - } - - return null; - } - - public bool IsNewVersion(string currentVersion, bool checkPreRelease) - { - if (prerelease && !checkPreRelease) - { - return false; - } - if (version == null) - { - return false; - } - var cmp = CompareVersion(version, currentVersion); - return cmp > 0; - } - - public static int CompareVersion(string l, string r) - { - var ls = l.Split('.'); - var rs = r.Split('.'); - for (int i = 0; i < Math.Max(ls.Length, rs.Length); i++) - { - int lp = (i < ls.Length) ? int.Parse(ls[i]) : 0; - int rp = (i < rs.Length) ? int.Parse(rs[i]) : 0; - if (lp != rp) - { - return lp - rp; - } - } - return 0; - } - - public int CompareTo(Asset other) + if (versionUpdatePromptWindow != null) { - return CompareVersion(version, other.version); + versionUpdatePromptWindow.Close(); + versionUpdatePromptWindow = null; } } } diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 61d5458b..d1491cbd 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; +using System.Net.Http; using System.Net.Sockets; using System.Text; using System.Threading; @@ -20,7 +21,8 @@ namespace Shadowsocks.Controller { public class ShadowsocksController { - private static Logger logger = LogManager.GetCurrentClassLogger(); + private readonly Logger logger; + private readonly HttpClient httpClient; // controller: // handle user actions @@ -91,6 +93,8 @@ namespace Shadowsocks.Controller public ShadowsocksController() { + logger = LogManager.GetCurrentClassLogger(); + httpClient = new HttpClient(); _config = Configuration.Load(); Configuration.Process(ref _config); StatisticsConfiguration = StatisticsStrategyConfiguration.Load(); @@ -168,6 +172,19 @@ namespace Shadowsocks.Controller NLogConfig.LoadConfiguration(); + // set User-Agent for httpClient + try + { + if (!string.IsNullOrWhiteSpace(_config.userAgentString)) + httpClient.DefaultRequestHeaders.Add("User-Agent", _config.userAgentString); + } + catch + { + // reset userAgent to default and reapply + Configuration.ResetUserAgent(_config); + httpClient.DefaultRequestHeaders.Add("User-Agent", _config.userAgentString); + } + StatisticsConfiguration = StatisticsStrategyConfiguration.Load(); privoxyRunner = privoxyRunner ?? new PrivoxyRunner(); @@ -250,6 +267,7 @@ namespace Shadowsocks.Controller Errored?.Invoke(this, new ErrorEventArgs(e)); } + public HttpClient GetHttpClient() => httpClient; public Server GetCurrentServer() => _config.GetCurrentServer(); public Configuration GetCurrentConfiguration() => _config; @@ -310,7 +328,7 @@ namespace Shadowsocks.Controller EnableGlobalChanged?.Invoke(this, new EventArgs()); } - public void SaveProxy(ProxyConfig proxyConfig) + public void SaveProxy(ForwardProxyConfig proxyConfig) { _config.proxy = proxyConfig; SaveConfig(_config); @@ -478,6 +496,12 @@ namespace Shadowsocks.Controller ConfigChanged?.Invoke(this, new EventArgs()); } + public void SaveSkippedUpdateVerion(string version) + { + _config.skippedUpdateVersion = version; + Configuration.Save(_config); + } + public void SaveLogViewerConfig(LogViewerConfig newConfig) { _config.logViewer = newConfig; @@ -497,7 +521,7 @@ namespace Shadowsocks.Controller #endregion - #region Statistic + #region Statistics public void SelectStrategy(string strategyID) { @@ -672,7 +696,7 @@ namespace Shadowsocks.Controller public async Task UpdateOnlineConfigInternal(string url) { - var onlineServer = await OnlineConfigResolver.GetOnline(url, _config.userAgentString, _config.WebProxy); + var onlineServer = await OnlineConfigResolver.GetOnline(url); _config.configs = Configuration.SortByOnlineConfig( _config.configs .Where(c => c.group != url) @@ -699,10 +723,10 @@ namespace Shadowsocks.Controller return true; } - public async Task UpdateAllOnlineConfig() + public async Task> UpdateAllOnlineConfig() { var selected = GetCurrentServer(); - int failCount = 0; + var failedUrls = new List(); foreach (var url in _config.onlineConfigSource) { try @@ -712,18 +736,18 @@ namespace Shadowsocks.Controller catch (Exception e) { logger.LogUsefulException(e); - failCount++; + failedUrls.Add(url); } } _config.index = _config.configs.IndexOf(selected); SaveConfig(_config); - return failCount; + return failedUrls; } - public void SaveOnlineConfigSource(IEnumerable vs) + public void SaveOnlineConfigSource(List sources) { - _config.onlineConfigSource = vs.ToList(); + _config.onlineConfigSource = sources; SaveConfig(_config); } diff --git a/shadowsocks-csharp/Data/i18n.csv b/shadowsocks-csharp/Data/i18n.csv index f2836232..61664367 100644 --- a/shadowsocks-csharp/Data/i18n.csv +++ b/shadowsocks-csharp/Data/i18n.csv @@ -81,13 +81,6 @@ Move D&own,Ниже,下移(&O),下移 (&O),下に移動 (&O),아래로 (&O),Desc deprecated,Устаревшее,不推荐,不推薦,非推奨,더 이상 사용되지 않음,Obsolète "Encryption method {0} not exist, will replace with {1}",,加密方法{0}不存在,将使用{1}代替,,暗号化方式{0}が存在しません,{1}に置換します,{0} 암호화 방식이 존재하지 않으므로 {1}로 대체될 것입니다.,"Méthode de chiffrement {0} n'existe pas, sera remplacée par {1}" ,,,,,, -# Online Config Form,,,,,, -,,,,,, -Online config,,在线配置,線上配置,,, -Online config URL,,在线配置链接,線上配置鏈接,,, -&Update,,更新,更新,,, -U&pdate All,,全部更新,全部更新,,, -,,,,,, #Statistics Config,,,,,, ,,,,,, Enable Statistics,Включить сбор статистики,启用统计,,統計を有効にする,통계 활성화,Activer statistiques @@ -118,18 +111,6 @@ Chart Mode,График,图表模式,,図表モード,차트 모드,Mode graphiq 24h,24ч,24小时,,24時間,24시간,24h all,За все время,全部,,すべて,전체,tout ,,,,,, -# Proxy Form,,,,,, -,,,,,, -Edit Proxy,Редактирование прокси,代理设置,編輯 Proxy,プロキシの編集,프록시 수정,Modifier le proxy -Use Proxy,Использовать прокси,使用代理,使用 Proxy,プロキシを使用する,프록시 사용,Utiliser un proxy -Proxy Type,Тип прокси,代理类型,Proxy 類型,プロキシタイプ,프록시 종류,Type de proxy -Proxy Addr,Адрес прокси,代理地址,Proxy 位址,プロキシアドレス,프록시 주소,Adresse de proxy -Proxy Port,Порт прокси,代理端口,Proxy 連接埠,プロキシポート,프록시 포트,Port de proxy -"If server has a plugin, proxy will not be used","Если сервер использует плагины, прокси НЕ будет использоваться",若服务器含有插件,代理将不被使用,若伺服器含有外掛程式,Proxy 將不被使用,サーバーにプラグインがある場合、プロキシは使用されません,서버에 플러그인이 설치 되어 있는 경우 프록시를 사용할 수 없습니다.,"Si le serveur a un plugin, le proxy ne sera pas utilisé" -Use Auth,Требуется авторизация,使用认证,使用認證,認証を使用する,서버 인증 사용,Utiliser l'authentification -User Name,Пользователь,用户名,認證用戶,ユーザ名,사용자 이름,Nom d'utilisateur -Auth Pwd,Пароль,认证密码,認證口令,パスワード,비밀번호,Mot de passe d'authentification -,,,,,, # Log Form,,,,,, ,,,,,, &File,Файл,文件(&F),檔案 (&F),ファイル (&F),파일 (&F),Fichier @@ -155,17 +136,6 @@ Edit Online PAC URL,Изменение URL удаленного PAC,编辑在线 Edit Online PAC URL...,Редактировать URL удаленного PAC…,编辑在线 PAC 网址...,編輯線上 PAC 網址...,オンライン PAC URL の編集...,온라인 프록시 자동 구성 URL 수정…,Modifier l'URL du PAC en ligne ... Please input PAC Url,Введите URL адрес для PAC-файла,请输入 PAC 网址,請輸入 PAC 網址,PAC URLを入力して下さい,프록시 자동 구성 URL을 입력하세요,Veuillez saisir l'URL PAC ,,,,,, -# HotkeySettings Form,,,,,, -,,,,,, -Switch system proxy,ВКЛ/ВЫКЛ системный прокси-сервер,切换系统代理状态,切換系統 Proxy 狀態,システム プロキシの状態を切り替える,시스템 프록시 전환,Changer l'état de proxy système -Switch system proxy mode,Переключение режима прокси-сервера,切换系统代理模式,切換系統 Proxy 模式,プロキシモードを切り替える,시스템 프록시 모드 전환,Changer le mode de proxy système -Allow Clients from LAN,Общий доступ к подключению,切换局域网共享,切換區域網路共用,LAN からのアクセスの許可を切り替える,LAN으로부터 클라이언트 허용,Autoriser les clients du LAN -Show Logs...,Просмотр журналов,显示日志,顯示記錄檔,ログの表示,로그 보기…,Afficher les journaux -Switch to previous server,Переключить на пред. сервер,切换上个服务器,切換上一個伺服器,前のサーバーに切り替える,이전 서버로 전환,Passer au serveur précédent -Switch to next server,Переключить на след. сервер,切换下个服务器,切換下一個伺服器,次のサーバーに切り替える,다음 서버로 전환,Passer au serveur suivant -Reg All,Применить все,注册全部快捷键,註冊所有快速鍵,全部登録する,모두 등록,Enregistrer tout -Reg Hotkeys At Startup,Применять при запуске программы,启动时注册快捷键,啟動時註冊快速鍵,起動時にホットキーを登録する,시스템 시작 시 단축키 등록,Enregistrer tout au démarrage -,,,,,, # Messages,,,,,, ,,,,,, Shadowsocks Error: {0},Ошибка Shadowsocks: {0},Shadowsocks 错误: {0},Shadowsocks 錯誤: {0},Shadowsocks エラー: {0},Shadowsocks 오류: {0},Erreur shadowsocks: {0} @@ -178,9 +148,7 @@ Server IP can not be blank,IP-адрес сервера не может быть Password can not be blank,Пароль не может быть пустым,密码不能为空,密碼不能為空,パスワードが指定されていません。,비밀번호는 비어있으면 안됩니다.,Le mot de passe ne peut pas être vide Port out of range,Порт выходит за допустимый диапазон,端口超出范围,連接埠號碼超出範圍,ポート番号は範囲外です。,올바른 포트 범위가 아닙니다.,Port hors de portée Port can't be 8123,Адрес порта 8123 не может быть использован,端口不能为 8123,連接埠號碼不能為 8123,8123 番以外のポート番号を指定して下さい。,8123번 포트는 사용할 수 없습니다.,Le port ne peut pas être 8123 -Shadowsocks {0} Update Found,Обнаружена новая версия Shadowsocks: {0},Shadowsocks {0} 更新,Shadowsocks {0} 更新,Shadowsocks バージョン {0} は利用できます。,Shadowsocks {0} 업데이트가 있습니다.,Shadowsocks {0} Mise à jour trouvée No update is available,Обновлений не обнаружено,没有可用的更新,沒有可用的更新,お使いのバージョンは最新です。,사용 가능한 업데이트가 없습니다.,Aucune mise à jour n'est disponible -Click here to update,Нажмите сюда для обновления,点击这里升级,點按此處升級,クリックしてアップデートします。,여기를 클릭하여 업데이트,Cliquez ici pour mettre à jour Shadowsocks is here,Shadowsocks находится здесь,Shadowsocks 在这里,Shadowsocks 在這裡,Shadowsocks はここです。,Shadowsocks는 여기에 있습니다,Veuillez trouver Shadowsocks ici You can turn on/off Shadowsocks in the context menu,Вы можете управлять Shadowsocks из контекстного меню,可以在右键菜单中开关 Shadowsocks,可以在右鍵選項單中開關 Shadowsocks,コンテキストメニューを使って、Shadowsocks を有効または無効にすることができます。,프로그램 메뉴에서 Shadowsocks를 끄고 켤 수 있습니다.,Vous pouvez activer / désactiver Shadowsocks dans le menu contextuel System Proxy Enabled,Системный прокси включен,系统代理已启用,系統 Proxy 已啟用,システム プロキシが有効です。,시스템 프록시가 활성화되었습니다.,Proxy système activé @@ -219,5 +187,3 @@ Whether to discard unconfigured servers,Внесенные изменения б ,,,,タイムアウト値のフォーマットが無効なため、オートセーブできません。変更を破棄しますか,, "Error occured when process proxy setting, do you want reset current setting and retry?",Произошла ошибка при обработке настроек. Хотите сбросить текущие настройки и попробовать снова?,处理代理设置时发生错误,是否重置当前代理设置并重试?,,プロキシ設定の処理にエラーが発生しました、現在のプロキシ設定をリセットし、再試行してもいいですか,프록시 설정을 처리하는데에 오류가 발생했습니다. 현재 설정을 폐기하고 다시 시도하시겠습니까?,Une erreur s'est produite lors du processus de configuration du proxy. Voulez-vous réinitialiser le paramètre actuel et réessayer? "Unrecoverable proxy setting error occured, see log for detail","Произошла серьезная ошибка, подробности можно узнать в журналах",发生不可恢复的代理设置错误,查看日志以取得详情,,プロキシ設定に回復不能なエラーが発生しました、ログで詳細をご確認ください,복구 불가능한 프록시 설정 오류가 발생했습니다. 자세한 정보는 로그를 참조하세요.,"Une erreur de paramètre de proxy irrécupérable s'est produite, consultez le journal pour plus de détails" -Auth user can not be blank,Пользователь не может быть пустым,认证用户不能为空,認證用戶不能為空,認証ユーザが指定されていません。,인증 정보의 사용자 이름은 비어있을 수 없습니다.,L'utilisateur d'authentification ne peut pas être vide -Auth pwd can not be blank,Пароль не может быть пустым,认证密码不能为空,認證口令不能為空,認証パスワードが指定されていません。,인증 정보의 비밀번호는 비어있을 수 없습니다.,Le mot de passe d'authentification ne peut pas être vide diff --git a/shadowsocks-csharp/FodyWeavers.xml b/shadowsocks-csharp/FodyWeavers.xml index a5ec775c..39c0beec 100644 --- a/shadowsocks-csharp/FodyWeavers.xml +++ b/shadowsocks-csharp/FodyWeavers.xml @@ -2,4 +2,5 @@ + \ No newline at end of file diff --git a/shadowsocks-csharp/FodyWeavers.xsd b/shadowsocks-csharp/FodyWeavers.xsd index a96b3592..91102829 100644 --- a/shadowsocks-csharp/FodyWeavers.xsd +++ b/shadowsocks-csharp/FodyWeavers.xsd @@ -4,6 +4,7 @@ + diff --git a/shadowsocks-csharp/Localization/LocalizationProvider.cs b/shadowsocks-csharp/Localization/LocalizationProvider.cs new file mode 100644 index 00000000..0677bce1 --- /dev/null +++ b/shadowsocks-csharp/Localization/LocalizationProvider.cs @@ -0,0 +1,13 @@ +using System.Reflection; +using WPFLocalizeExtension.Extensions; + +namespace Shadowsocks.Localization +{ + public static class LocalizationProvider + { + public static T GetLocalizedValue(string key) + { + return LocExtension.GetLocalizedValue(Assembly.GetCallingAssembly().GetName().Name + ":Strings:" + key); + } + } +} diff --git a/shadowsocks-csharp/Localization/Strings.Designer.cs b/shadowsocks-csharp/Localization/Strings.Designer.cs new file mode 100644 index 00000000..4534a9cf --- /dev/null +++ b/shadowsocks-csharp/Localization/Strings.Designer.cs @@ -0,0 +1,432 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Shadowsocks.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Shadowsocks.Localization.Strings", typeof(Strings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to _Add. + /// + internal static string addButton_Content { + get { + return ResourceManager.GetString("addButton_Content", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Address. + /// + internal static string Address { + get { + return ResourceManager.GetString("Address", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Allow clients from LAN. + /// + internal static string AllowClientsFromLAN { + get { + return ResourceManager.GetString("AllowClientsFromLAN", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to _Cancel. + /// + internal static string cancelButton_Content { + get { + return ResourceManager.GetString("cancelButton_Content", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to _Copy. + /// + internal static string Copy { + get { + return ResourceManager.GetString("Copy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to _Copy link. + /// + internal static string copyLinkButton_Content { + get { + return ResourceManager.GetString("copyLinkButton_Content", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Credentials (optional). + /// + internal static string CredentialsOptional { + get { + return ResourceManager.GetString("CredentialsOptional", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Details. + /// + internal static string Details { + get { + return ResourceManager.GetString("Details", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Forward Proxy. + /// + internal static string ForwardProxy { + get { + return ResourceManager.GetString("ForwardProxy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hotkeys. + /// + internal static string Hotkeys { + get { + return ResourceManager.GetString("Hotkeys", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to HTTP. + /// + internal static string HTTP { + get { + return ResourceManager.GetString("HTTP", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No proxy. + /// + internal static string NoProxy { + get { + return ResourceManager.GetString("NoProxy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to _Not now. + /// + internal static string notNowButton_Content { + get { + return ResourceManager.GetString("notNowButton_Content", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to _OK. + /// + internal static string okButton_Content { + get { + return ResourceManager.GetString("okButton_Content", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Online Configuration Delivery. + /// + internal static string OnlineConfigDelivery { + get { + return ResourceManager.GetString("OnlineConfigDelivery", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open logs window. + /// + internal static string OpenLogsWindow { + get { + return ResourceManager.GetString("OpenLogsWindow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password. + /// + internal static string Password { + get { + return ResourceManager.GetString("Password", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Port. + /// + internal static string Port { + get { + return ResourceManager.GetString("Port", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to _Register all. + /// + internal static string registerAllButton_Content { + get { + return ResourceManager.GetString("registerAllButton_Content", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Register hotkeys at startup. + /// + internal static string RegisterHotkeysAtStartup { + get { + return ResourceManager.GetString("RegisterHotkeysAtStartup", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remove. + /// + internal static string removeButton_Content { + get { + return ResourceManager.GetString("removeButton_Content", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to _Save. + /// + internal static string saveButton_Content { + get { + return ResourceManager.GetString("saveButton_Content", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Server Sharing. + /// + internal static string ServerSharing { + get { + return ResourceManager.GetString("ServerSharing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The following sources failed to update:\n\n. + /// + internal static string sip008UpdateAllFailure { + get { + return ResourceManager.GetString("sip008UpdateAllFailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Successfully updated all sources!. + /// + internal static string sip008UpdateAllSuccess { + get { + return ResourceManager.GetString("sip008UpdateAllSuccess", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update failed. See the logs for more information.. + /// + internal static string sip008UpdateFailure { + get { + return ResourceManager.GetString("sip008UpdateFailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Successfully updated the selected source!. + /// + internal static string sip008UpdateSuccess { + get { + return ResourceManager.GetString("sip008UpdateSuccess", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to _Skip version. + /// + internal static string skipVersionButton_Content { + get { + return ResourceManager.GetString("skipVersionButton_Content", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SOCKS5. + /// + internal static string SOCKS5 { + get { + return ResourceManager.GetString("SOCKS5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Switch to next server. + /// + internal static string SwitchToNextServer { + get { + return ResourceManager.GetString("SwitchToNextServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Switch to previous server. + /// + internal static string SwitchToPreviousServer { + get { + return ResourceManager.GetString("SwitchToPreviousServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Timeout. + /// + internal static string Timeout { + get { + return ResourceManager.GetString("Timeout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Toggle proxy mode. + /// + internal static string ToggleProxyMode { + get { + return ResourceManager.GetString("ToggleProxyMode", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Toggle system proxy. + /// + internal static string ToggleSystemProxy { + get { + return ResourceManager.GetString("ToggleSystemProxy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type. + /// + internal static string Type { + get { + return ResourceManager.GetString("Type", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update all. + /// + internal static string updateAllButton_Content { + get { + return ResourceManager.GetString("updateAllButton_Content", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to _Update. + /// + internal static string updateButton_Content { + get { + return ResourceManager.GetString("updateButton_Content", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please read the release notes carefully. Then decide whether to update.. + /// + internal static string updatePromptBody { + get { + return ResourceManager.GetString("updatePromptBody", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An update is available.. + /// + internal static string updatePromptTitle { + get { + return ResourceManager.GetString("updatePromptTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Username. + /// + internal static string Username { + get { + return ResourceManager.GetString("Username", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to VersionUpdate. + /// + internal static string VersionUpdate { + get { + return ResourceManager.GetString("VersionUpdate", resourceCulture); + } + } + } +} diff --git a/shadowsocks-csharp/View/ProxyForm.resx b/shadowsocks-csharp/Localization/Strings.fr.resx similarity index 73% rename from shadowsocks-csharp/View/ProxyForm.resx rename to shadowsocks-csharp/Localization/Strings.fr.resx index 29dcb1b3..be01a273 100644 --- a/shadowsocks-csharp/View/ProxyForm.resx +++ b/shadowsocks-csharp/Localization/Strings.fr.resx @@ -1,120 +1,183 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Mot de passe + + + Port + + + Type + + + adresse + + + Délai d'attente + + + Annuler + + + OK + + + Changer l'état de proxy système + + + Changer le mode de proxy système + + + Autoriser les clients du LAN + + + Afficher les journaux + + + Passer au serveur précédent + + + Passer au serveur suivant + + + Enregistrer tout + + + Enregistrer tout au démarrage + + + Ajouter + + + sauter la version + + + Copier le lien + + + retirer + + + mise à jour + + + copie + \ No newline at end of file diff --git a/shadowsocks-csharp/View/HotkeySettingsForm.resx b/shadowsocks-csharp/Localization/Strings.ja.resx similarity index 58% rename from shadowsocks-csharp/View/HotkeySettingsForm.resx rename to shadowsocks-csharp/Localization/Strings.ja.resx index 5813f883..4d8f997d 100644 --- a/shadowsocks-csharp/View/HotkeySettingsForm.resx +++ b/shadowsocks-csharp/Localization/Strings.ja.resx @@ -1,183 +1,180 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 - - - False - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + パスワード + + + タイプ + + + アドレス + + + ポート + + + タイムアウト + + + キャンセル + + + OK + + + システム プロキシの状態を切り替える + + + プロキシモードを切り替える + + + LAN からのアクセスの許可を切り替える + + + ログの表示 + + + 前のサーバーに切り替える + + + 次のサーバーに切り替える + + + 全部登録する + + + 起動時にホットキーを登録する + + + 新規 + + + バージョンをスキップ + + + リンクをコピーする + + + 更新 + + + コピー + \ No newline at end of file diff --git a/shadowsocks-csharp/View/OnlineConfigForm.resx b/shadowsocks-csharp/Localization/Strings.ko.resx similarity index 74% rename from shadowsocks-csharp/View/OnlineConfigForm.resx rename to shadowsocks-csharp/Localization/Strings.ko.resx index 1af7de15..16df3925 100644 --- a/shadowsocks-csharp/View/OnlineConfigForm.resx +++ b/shadowsocks-csharp/Localization/Strings.ko.resx @@ -117,4 +117,64 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 비밀번호 + + + 유형 + + + 주소 + + + 포트 + + + 시간 초과 + + + 취소 + + + 확인 + + + 시스템 프록시 전환 + + + 시스템 프록시 모드 전환 + + + LAN으로부터 클라이언트 허용 + + + 로그 보기… + + + 이전 서버로 전환 + + + 다음 서버로 전환 + + + 모두 등록 + + + 시스템 시작 시 단축키 등록 + + + 추가 + + + 버전 건너 뛰기 + + + 링크 복사 + + + 새롭게 함 + + + + \ No newline at end of file diff --git a/shadowsocks-csharp/Localization/Strings.resx b/shadowsocks-csharp/Localization/Strings.resx new file mode 100644 index 00000000..17d6e307 --- /dev/null +++ b/shadowsocks-csharp/Localization/Strings.resx @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Type + + + No proxy + + + SOCKS5 + + + HTTP + + + Details + + + Address + + + Port + + + Timeout + + + Credentials (optional) + + + Username + + + Password + + + _Save + + + _Cancel + + + _OK + + + Toggle system proxy + + + Toggle proxy mode + + + Allow clients from LAN + + + Open logs window + + + Switch to previous server + + + Switch to next server + + + Register hotkeys at startup + + + _Register all + + + _Update + + + Update all + + + _Copy link + + + Remove + + + _Add + + + An update is available. + + + Please read the release notes carefully. Then decide whether to update. + + + _Skip version + + + _Not now + + + _Copy + + + Forward Proxy + + + Server Sharing + + + Hotkeys + + + Online Configuration Delivery + + + VersionUpdate + + + Successfully updated the selected source! + + + Update failed. See the logs for more information. + + + Successfully updated all sources! + + + The following sources failed to update:\n\n + + \ No newline at end of file diff --git a/shadowsocks-csharp/Localization/Strings.ru.resx b/shadowsocks-csharp/Localization/Strings.ru.resx new file mode 100644 index 00000000..7c0ceb3d --- /dev/null +++ b/shadowsocks-csharp/Localization/Strings.ru.resx @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/Localization/Strings.zh-Hans.resx b/shadowsocks-csharp/Localization/Strings.zh-Hans.resx new file mode 100644 index 00000000..9ca554ed --- /dev/null +++ b/shadowsocks-csharp/Localization/Strings.zh-Hans.resx @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 不使用代理 + + + 类型 + + + 认证 (可选) + + + 详细设置 + + + 地址 + + + 保存 + + + 取消 + + + 用户名 + + + 密码 + + + 端口 + + + 超时 + + + 确定 + + + 全部注册 + + + 切换系统代理 + + + 切换代理模式 + + + 允许内网客户端连接 + + + 打开日志窗口 + + + 切换到上一个服务器 + + + 切换到下一个服务器 + + + 启动时注册快捷键 + + + 更新 + + + 全部更新 + + + 复制链接 + + + 移除 + + + 添加 + + + 跳过版本 + + + 暂不更新 + + + 发现可用更新 + + + 请仔细阅读发布信息,然后决定是否更新。 + + + 复制 + + + 前置代理 + + + 在线配置下发 + + + 热键 + + + 服务器分享 + + + 版本更新 + + + 成功更新选定来源! + + + 更新失败,请查看日志获取更多信息。 + + + 成功更新所有来源! + + + 下列来源更新失败:\n\n + + \ No newline at end of file diff --git a/shadowsocks-csharp/Localization/Strings.zh-Hant.resx b/shadowsocks-csharp/Localization/Strings.zh-Hant.resx new file mode 100644 index 00000000..91610dc5 --- /dev/null +++ b/shadowsocks-csharp/Localization/Strings.zh-Hant.resx @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 密碼 + + + Port + + + 類型 + + + 位址 + + + 逾時 + + + 取消 + + + 確定 + + + 切換系統 Proxy 狀態 + + + 切換系統 Proxy 模式 + + + 切換區域網路共用 + + + 顯示記錄檔 + + + 切換上一個伺服器 + + + 切換下一個伺服器 + + + 註冊所有快速鍵 + + + 啟動時註冊快速鍵 + + + 更新 + + + 全部更新 + + + 新增 + + + 跳過版本 + + + 暫不更新 + + + 發現可用更新 + + + 複製鏈接 + + + 複製 + + \ No newline at end of file diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index 9de8049b..322dca5e 100644 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -40,6 +40,7 @@ namespace Shadowsocks.Model public bool availabilityStatistics; public bool autoCheckUpdate; public bool checkPreRelease; + public string skippedUpdateVersion; // skip the update with this version number public bool isVerboseLogging; // hidden options @@ -53,7 +54,7 @@ namespace Shadowsocks.Model //public NLogConfig.LogLevel logLevel; public LogViewerConfig logViewer; - public ProxyConfig proxy; + public ForwardProxyConfig proxy; public HotkeyConfig hotkey; [JsonIgnore] @@ -78,6 +79,7 @@ namespace Shadowsocks.Model availabilityStatistics = false; autoCheckUpdate = false; checkPreRelease = false; + skippedUpdateVersion = ""; isVerboseLogging = false; // hidden options @@ -97,7 +99,7 @@ namespace Shadowsocks.Model userAgent = "ShadowsocksWindows/$version"; logViewer = new LogViewerConfig(); - proxy = new ProxyConfig(); + proxy = new ForwardProxyConfig(); hotkey = new HotkeyConfig(); firstRunOnNewVersion = false; @@ -193,7 +195,9 @@ namespace Shadowsocks.Model ResetGeositeProxiedGroup(ref config.geositeProxiedGroups); // Mark the first run of a new version. - if (UpdateChecker.Asset.CompareVersion(UpdateChecker.Version, config.version ?? "0") > 0) + var appVersion = new Version(UpdateChecker.Version); + var configVersion = new Version(config.version); + if (appVersion.CompareTo(configVersion) > 0) { config.firstRunOnNewVersion = true; } @@ -316,6 +320,12 @@ namespace Shadowsocks.Model geositeProxiedGroups.Add("geolocation-!cn"); } + public static void ResetUserAgent(Configuration config) + { + config.userAgent = "ShadowsocksWindows/$version"; + config.userAgentString = config.userAgent.Replace("$version", config.version); + } + public static Server AddDefaultServerOrServer(Configuration config, Server server = null, int? index = null) { if (config?.configs != null) @@ -368,17 +378,5 @@ namespace Shadowsocks.Model throw new ArgumentException( I18N.GetString("Timeout is invalid, it should not exceed {0}", maxTimeout)); } - - public static void CheckProxyAuthUser(string user) - { - if (string.IsNullOrEmpty(user)) - throw new ArgumentException(I18N.GetString("Auth user can not be blank")); - } - - public static void CheckProxyAuthPwd(string pwd) - { - if (string.IsNullOrEmpty(pwd)) - throw new ArgumentException(I18N.GetString("Auth pwd can not be blank")); - } } } diff --git a/shadowsocks-csharp/Model/ProxyConfig.cs b/shadowsocks-csharp/Model/ForwardProxyConfig.cs similarity index 90% rename from shadowsocks-csharp/Model/ProxyConfig.cs rename to shadowsocks-csharp/Model/ForwardProxyConfig.cs index da60b622..7a1d4ec5 100644 --- a/shadowsocks-csharp/Model/ProxyConfig.cs +++ b/shadowsocks-csharp/Model/ForwardProxyConfig.cs @@ -1,43 +1,43 @@ -using System; - -namespace Shadowsocks.Model -{ - [Serializable] - public class ProxyConfig - { - public const int PROXY_SOCKS5 = 0; - public const int PROXY_HTTP = 1; - - public const int MaxProxyTimeoutSec = 10; - private const int DefaultProxyTimeoutSec = 3; - - public bool useProxy; - public int proxyType; - public string proxyServer; - public int proxyPort; - public int proxyTimeout; - public bool useAuth; - public string authUser; - public string authPwd; - - public ProxyConfig() - { - useProxy = false; - proxyType = PROXY_SOCKS5; - proxyServer = ""; - proxyPort = 0; - proxyTimeout = DefaultProxyTimeoutSec; - useAuth = false; - authUser = ""; - authPwd = ""; - } - - public void CheckConfig() - { - if (proxyType < PROXY_SOCKS5 || proxyType > PROXY_HTTP) - { - proxyType = PROXY_SOCKS5; - } - } - } -} +using System; + +namespace Shadowsocks.Model +{ + [Serializable] + public class ForwardProxyConfig + { + public const int PROXY_SOCKS5 = 0; + public const int PROXY_HTTP = 1; + + public const int MaxProxyTimeoutSec = 10; + private const int DefaultProxyTimeoutSec = 3; + + public bool useProxy; + public int proxyType; + public string proxyServer; + public int proxyPort; + public int proxyTimeout; + public bool useAuth; + public string authUser; + public string authPwd; + + public ForwardProxyConfig() + { + useProxy = false; + proxyType = PROXY_SOCKS5; + proxyServer = ""; + proxyPort = 0; + proxyTimeout = DefaultProxyTimeoutSec; + useAuth = false; + authUser = ""; + authPwd = ""; + } + + public void CheckConfig() + { + if (proxyType < PROXY_SOCKS5 || proxyType > PROXY_HTTP) + { + proxyType = PROXY_SOCKS5; + } + } + } +} diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 9e266105..a76633fd 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.IO; using System.IO.Pipes; using System.Net; +using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -10,10 +11,12 @@ using System.Windows.Forms; using CommandLine; using Microsoft.Win32; using NLog; +using ReactiveUI; using Shadowsocks.Controller; using Shadowsocks.Controller.Hotkeys; using Shadowsocks.Util; using Shadowsocks.View; +using Splat; namespace Shadowsocks { @@ -109,6 +112,10 @@ namespace Shadowsocks AutoStartup.RegisterForRestart(true); #endregion + // We would use this in v5. + // Parameters would have to be dropped from views' constructors (VersionUpdatePromptView) + //Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetCallingAssembly()); + #if DEBUG // truncate privoxy log file while debugging string privoxyLogFilename = Utils.GetTempPath("privoxy.log"); diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index f3d0fbe1..3d0151b1 100644 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// 此代码由工具生成。 -// 运行时版本:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将会丢失。 +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -13,16 +13,16 @@ namespace Shadowsocks.Properties { /// - /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// A strongly-typed resource class, for looking up localized strings, etc. /// - // 此类是由 StronglyTypedResourceBuilder - // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 - // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen - // (以 /str 作为命令选项),或重新生成 VS 项目。 + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { + public class Resources { private static global::System.Resources.ResourceManager resourceMan; @@ -33,10 +33,10 @@ namespace Shadowsocks.Properties { } /// - /// 返回此类使用的缓存的 ResourceManager 实例。 + /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { + public static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Shadowsocks.Properties.Resources", typeof(Resources).Assembly); @@ -47,11 +47,11 @@ namespace Shadowsocks.Properties { } /// - /// 重写当前线程的 CurrentUICulture 属性 - /// 重写当前线程的 CurrentUICulture 属性。 + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { + public static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } @@ -61,7 +61,7 @@ namespace Shadowsocks.Properties { } /// - /// 查找类似 /* eslint-disable */ + /// Looks up a localized string similar to /* eslint-disable */ ///// Was generated by gfwlist2pac in precise mode ///// https://github.com/clowwindy/gfwlist2pac /// @@ -69,25 +69,28 @@ namespace Shadowsocks.Properties { ///// 2019-02-08: Updated to support shadowsocks-windows user rules. /// ///var proxy = __PROXY__; - ///var userrules = __USERRULES__; - ///var rules = __RULES__; + ///var userrules = []; + ///var rules = []; /// - ////* - ///* This file is part of Adblock Plus <http://adblockplus.org/>, - ///* Copyright (C) 2006-2014 Eyeo GmbH - ///* - ///* Adblock Plus is free software: you can redistribute it and/or [字符串的其余部分被截断]"; 的本地化字符串。 + ///// convert to abp grammar + ///for (var i = 0; i < __RULES__.length; i++) { + /// var s = __RULES__[i]; + /// if (s.substring(0, 2) == "||") s += "^"; + /// rules.push(s); + ///} + /// + ///for (var i = 0; i < [rest of string was truncated]";. /// - internal static string abp_js { + public static string abp_js { get { return ResourceManager.GetString("abp_js", resourceCulture); } } /// - /// 查找 System.Byte[] 类型的本地化资源。 + /// Looks up a localized resource of type System.Byte[]. /// - internal static byte[] dlc_dat { + public static byte[] dlc_dat { get { object obj = ResourceManager.GetObject("dlc_dat", resourceCulture); return ((byte[])(obj)); @@ -95,7 +98,7 @@ namespace Shadowsocks.Properties { } /// - /// 查找类似 en,ru-RU,zh-CN,zh-TW,ja,ko,fr + /// Looks up a localized string similar to en,ru-RU,zh-CN,zh-TW,ja,ko,fr ///#Restart program to apply translation,,,,,, ///#This is comment line,,,,,, ///#Always keep language name at head of file,,,,,, @@ -107,18 +110,18 @@ namespace Shadowsocks.Properties { ///,,,,,, ///#Menu,,,,,, ///,,,,,, - ///System Proxy,Системный прокси-сервер,系统代理,系統代理,システムプロキシ,시스템 프록시,P [字符串的其余部分被截断]"; 的本地化字符串。 + ///System Proxy,Системный прокси-сервер,系统代理,系統代理,システムプロキシ,시스템 프록시,P [rest of string was truncated]";. /// - internal static string i18n_csv { + public static string i18n_csv { get { return ResourceManager.GetString("i18n_csv", resourceCulture); } } /// - /// 查找 System.Byte[] 类型的本地化资源。 + /// Looks up a localized resource of type System.Byte[]. /// - internal static byte[] libsscrypto_dll { + public static byte[] libsscrypto_dll { get { object obj = ResourceManager.GetObject("libsscrypto_dll", resourceCulture); return ((byte[])(obj)); @@ -126,22 +129,22 @@ namespace Shadowsocks.Properties { } /// - /// 查找类似 <?xml version="1.0" encoding="utf-8" ?> + /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> ///<!-- Warning: Configuration may reset after shadowsocks upgrade. --> ///<!-- If you messed it up, delete this file and Shadowsocks will create a new one. --> ///<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> /// <targets> /// <!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.--> - /// <target name="file" xsi:type="File" fileName="ss_win_temp\shadowsocks.log" writ [字符串的其余部分被截断]"; 的本地化字符串。 + /// <target name="file" xsi:type="File" fileName="ss_win_temp\shadowsocks.log" writ [rest of string was truncated]";. /// - internal static string NLog_config { + public static string NLog_config { get { return ResourceManager.GetString("NLog_config", resourceCulture); } } /// - /// 查找类似 listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__ + /// Looks up a localized string similar to listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__ ///toggle 0 ///logfile ss_privoxy.log ///show-on-task-bar 0 @@ -149,18 +152,18 @@ namespace Shadowsocks.Properties { ///forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ . ///max-client-connections 2048 ///hide-console - /// 的本地化字符串。 + ///. /// - internal static string privoxy_conf { + public static string privoxy_conf { get { return ResourceManager.GetString("privoxy_conf", resourceCulture); } } /// - /// 查找 System.Byte[] 类型的本地化资源。 + /// Looks up a localized resource of type System.Byte[]. /// - internal static byte[] privoxy_exe { + public static byte[] privoxy_exe { get { object obj = ResourceManager.GetObject("privoxy_exe", resourceCulture); return ((byte[])(obj)); @@ -168,9 +171,9 @@ namespace Shadowsocks.Properties { } /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap ss32Fill { + public static System.Drawing.Bitmap ss32Fill { get { object obj = ResourceManager.GetObject("ss32Fill", resourceCulture); return ((System.Drawing.Bitmap)(obj)); @@ -178,9 +181,9 @@ namespace Shadowsocks.Properties { } /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap ss32In { + public static System.Drawing.Bitmap ss32In { get { object obj = ResourceManager.GetObject("ss32In", resourceCulture); return ((System.Drawing.Bitmap)(obj)); @@ -188,9 +191,9 @@ namespace Shadowsocks.Properties { } /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap ss32Out { + public static System.Drawing.Bitmap ss32Out { get { object obj = ResourceManager.GetObject("ss32Out", resourceCulture); return ((System.Drawing.Bitmap)(obj)); @@ -198,9 +201,9 @@ namespace Shadowsocks.Properties { } /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap ss32Outline { + public static System.Drawing.Bitmap ss32Outline { get { object obj = ResourceManager.GetObject("ss32Outline", resourceCulture); return ((System.Drawing.Bitmap)(obj)); @@ -208,9 +211,9 @@ namespace Shadowsocks.Properties { } /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap ssw128 { + public static System.Drawing.Bitmap ssw128 { get { object obj = ResourceManager.GetObject("ssw128", resourceCulture); return ((System.Drawing.Bitmap)(obj)); @@ -218,9 +221,9 @@ namespace Shadowsocks.Properties { } /// - /// 查找 System.Byte[] 类型的本地化资源。 + /// Looks up a localized resource of type System.Byte[]. /// - internal static byte[] sysproxy_exe { + public static byte[] sysproxy_exe { get { object obj = ResourceManager.GetObject("sysproxy_exe", resourceCulture); return ((byte[])(obj)); @@ -228,9 +231,9 @@ namespace Shadowsocks.Properties { } /// - /// 查找 System.Byte[] 类型的本地化资源。 + /// Looks up a localized resource of type System.Byte[]. /// - internal static byte[] sysproxy64_exe { + public static byte[] sysproxy64_exe { get { object obj = ResourceManager.GetObject("sysproxy64_exe", resourceCulture); return ((byte[])(obj)); @@ -238,11 +241,11 @@ namespace Shadowsocks.Properties { } /// - /// 查找类似 ! Put user rules line by line in this file. + /// Looks up a localized string similar to ! Put user rules line by line in this file. ///! See https://adblockplus.org/en/filter-cheatsheet - /// 的本地化字符串。 + ///. /// - internal static string user_rule { + public static string user_rule { get { return ResourceManager.GetString("user_rule", resourceCulture); } diff --git a/shadowsocks-csharp/View/HotkeySettingsForm.cs b/shadowsocks-csharp/View/HotkeySettingsForm.cs deleted file mode 100644 index 58c0f6bd..00000000 --- a/shadowsocks-csharp/View/HotkeySettingsForm.cs +++ /dev/null @@ -1,190 +0,0 @@ -using Shadowsocks.Controller; -using Shadowsocks.Model; -using Shadowsocks.Properties; -using System; -using System.Drawing; -using System.Text; -using System.Windows.Forms; -using static Shadowsocks.Controller.HotkeyReg; - -namespace Shadowsocks.View -{ - public partial class HotkeySettingsForm : Form - { - private readonly ShadowsocksController _controller; - - // this is a copy of hotkey configuration that we are working on - private HotkeyConfig _modifiedHotkeyConfig; - - public HotkeySettingsForm(ShadowsocksController controller) - { - InitializeComponent(); - UpdateTexts(); - Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); - - _controller = controller; - _controller.ConfigChanged += controller_ConfigChanged; - - LoadCurrentConfiguration(); - } - - private void UpdateTexts() - { - I18N.TranslateForm(this); - } - - private void controller_ConfigChanged(object sender, EventArgs e) - { - LoadCurrentConfiguration(); - } - - private void LoadCurrentConfiguration() - { - _modifiedHotkeyConfig = _controller.GetCurrentConfiguration().hotkey; - SetConfigToUI(_modifiedHotkeyConfig); - } - - private void SetConfigToUI(HotkeyConfig config) - { - SwitchSystemProxyTextBox.Text = config.SwitchSystemProxy; - SwitchProxyModeTextBox.Text = config.SwitchSystemProxyMode; - SwitchAllowLanTextBox.Text = config.SwitchAllowLan; - ShowLogsTextBox.Text = config.ShowLogs; - ServerMoveUpTextBox.Text = config.ServerMoveUp; - ServerMoveDownTextBox.Text = config.ServerMoveDown; - RegHotkeysAtStartupCheckBox.Checked = config.RegHotkeysAtStartup; - } - - private void SaveConfig() - { - _controller.SaveHotkeyConfig(_modifiedHotkeyConfig); - } - - private HotkeyConfig GetConfigFromUI() - { - return new HotkeyConfig - { - SwitchSystemProxy = SwitchSystemProxyTextBox.Text, - SwitchSystemProxyMode = SwitchProxyModeTextBox.Text, - SwitchAllowLan = SwitchAllowLanTextBox.Text, - ShowLogs = ShowLogsTextBox.Text, - ServerMoveUp = ServerMoveUpTextBox.Text, - ServerMoveDown = ServerMoveDownTextBox.Text, - RegHotkeysAtStartup = RegHotkeysAtStartupCheckBox.Checked - }; - } - - /// - /// Capture hotkey - Press key - /// - private void HotkeyDown(object sender, KeyEventArgs e) - { - StringBuilder sb = new StringBuilder(); - //Combination key only - if (e.Modifiers != 0) - { - // XXX: Hotkey parsing depends on the sequence, more specifically, ModifierKeysConverter. - // Windows key is reserved by operating system, we deny this key. - if (e.Control) - { - sb.Append("Ctrl+"); - } - if (e.Alt) - { - sb.Append("Alt+"); - } - if (e.Shift) - { - sb.Append("Shift+"); - } - - Keys keyvalue = (Keys)e.KeyValue; - if ((keyvalue >= Keys.PageUp && keyvalue <= Keys.Down) || - (keyvalue >= Keys.A && keyvalue <= Keys.Z) || - (keyvalue >= Keys.F1 && keyvalue <= Keys.F12)) - { - sb.Append(e.KeyCode); - } - else if (keyvalue >= Keys.D0 && keyvalue <= Keys.D9) - { - sb.Append('D').Append((char)e.KeyValue); - } - else if (keyvalue >= Keys.NumPad0 && keyvalue <= Keys.NumPad9) - { - sb.Append("NumPad").Append((char)(e.KeyValue - 48)); - } - } - ((TextBox)sender).Text = sb.ToString(); - } - - /// - /// Capture hotkey - Release key - /// - private void HotkeyUp(object sender, KeyEventArgs e) - { - var tb = (TextBox)sender; - var content = tb.Text.TrimEnd(); - if (content.Length >= 1 && content[content.Length - 1] == '+') - { - tb.Text = ""; - } - } - - private void CancelButton_Click(object sender, EventArgs e) - { - this.Close(); - } - - private void OKButton_Click(object sender, EventArgs e) - { - _modifiedHotkeyConfig = GetConfigFromUI(); - // try to register, notify to change settings if failed - if (!RegisterAllHotkeys(_modifiedHotkeyConfig)) - { - MessageBox.Show(I18N.GetString("Register hotkey failed")); - } - - // All check passed, saving - SaveConfig(); - this.Close(); - } - - private void RegisterAllButton_Click(object sender, EventArgs e) - { - _modifiedHotkeyConfig = GetConfigFromUI(); - RegisterAllHotkeys(_modifiedHotkeyConfig); - } - - private bool RegisterAllHotkeys(HotkeyConfig hotkeyConfig) - { - return - RegHotkeyFromString(hotkeyConfig.SwitchSystemProxy, "SwitchSystemProxyCallback", result => HandleRegResult(hotkeyConfig.SwitchSystemProxy, SwitchSystemProxyLabel, result)) - && RegHotkeyFromString(hotkeyConfig.SwitchSystemProxyMode, "SwitchSystemProxyModeCallback", result => HandleRegResult(hotkeyConfig.SwitchSystemProxyMode, SwitchProxyModeLabel, result)) - && RegHotkeyFromString(hotkeyConfig.SwitchAllowLan, "SwitchAllowLanCallback", result => HandleRegResult(hotkeyConfig.SwitchAllowLan, SwitchAllowLanLabel, result)) - && RegHotkeyFromString(hotkeyConfig.ShowLogs, "ShowLogsCallback", result => HandleRegResult(hotkeyConfig.ShowLogs, ShowLogsLabel, result)) - && RegHotkeyFromString(hotkeyConfig.ServerMoveUp, "ServerMoveUpCallback", result => HandleRegResult(hotkeyConfig.ServerMoveUp, ServerMoveUpLabel, result)) - && RegHotkeyFromString(hotkeyConfig.ServerMoveDown, "ServerMoveDownCallback", result => HandleRegResult(hotkeyConfig.ServerMoveDown, ServerMoveDownLabel, result)); - } - - private void HandleRegResult(string hotkeyStr, Label label, RegResult result) - { - switch (result) - { - case RegResult.ParseError: - MessageBox.Show(I18N.GetString("Cannot parse hotkey: {0}", hotkeyStr)); - break; - case RegResult.UnregSuccess: - label.ResetBackColor(); - break; - case RegResult.RegSuccess: - label.BackColor = Color.Green; - break; - case RegResult.RegFailure: - label.BackColor = Color.Red; - break; - default: - break; - } - } - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/View/HotkeySettingsForm.designer.cs b/shadowsocks-csharp/View/HotkeySettingsForm.designer.cs deleted file mode 100644 index 47f89946..00000000 --- a/shadowsocks-csharp/View/HotkeySettingsForm.designer.cs +++ /dev/null @@ -1,346 +0,0 @@ -namespace Shadowsocks.View -{ - partial class HotkeySettingsForm - { - /// - /// 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() - { - System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; - this.btnOK = new System.Windows.Forms.Button(); - this.btnCancel = new System.Windows.Forms.Button(); - this.btnRegisterAll = new System.Windows.Forms.Button(); - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.RegHotkeysAtStartupLabel = new System.Windows.Forms.Label(); - this.SwitchSystemProxyLabel = new System.Windows.Forms.Label(); - this.SwitchProxyModeLabel = new System.Windows.Forms.Label(); - this.SwitchAllowLanLabel = new System.Windows.Forms.Label(); - this.ShowLogsLabel = new System.Windows.Forms.Label(); - this.ServerMoveUpLabel = new System.Windows.Forms.Label(); - this.ServerMoveDownLabel = new System.Windows.Forms.Label(); - this.SwitchSystemProxyTextBox = new System.Windows.Forms.TextBox(); - this.SwitchProxyModeTextBox = new System.Windows.Forms.TextBox(); - this.SwitchAllowLanTextBox = new System.Windows.Forms.TextBox(); - this.ShowLogsTextBox = new System.Windows.Forms.TextBox(); - this.ServerMoveUpTextBox = new System.Windows.Forms.TextBox(); - this.ServerMoveDownTextBox = new System.Windows.Forms.TextBox(); - this.RegHotkeysAtStartupCheckBox = new System.Windows.Forms.CheckBox(); - flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); - flowLayoutPanel1.SuspendLayout(); - this.tableLayoutPanel1.SuspendLayout(); - this.SuspendLayout(); - // - // flowLayoutPanel1 - // - this.tableLayoutPanel1.SetColumnSpan(flowLayoutPanel1, 2); - flowLayoutPanel1.Controls.Add(this.btnOK); - flowLayoutPanel1.Controls.Add(this.btnCancel); - flowLayoutPanel1.Controls.Add(this.btnRegisterAll); - flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.BottomUp; - flowLayoutPanel1.Location = new System.Drawing.Point(0, 248); - flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); - flowLayoutPanel1.Name = "flowLayoutPanel1"; - flowLayoutPanel1.Padding = new System.Windows.Forms.Padding(0, 0, 20, 0); - flowLayoutPanel1.RightToLeft = System.Windows.Forms.RightToLeft.Yes; - flowLayoutPanel1.Size = new System.Drawing.Size(594, 52); - flowLayoutPanel1.TabIndex = 6; - // - // btnOK - // - this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK; - this.btnOK.Location = new System.Drawing.Point(416, 9); - this.btnOK.Margin = new System.Windows.Forms.Padding(4); - this.btnOK.Name = "btnOK"; - this.btnOK.Size = new System.Drawing.Size(154, 39); - this.btnOK.TabIndex = 0; - this.btnOK.Text = "OK"; - this.btnOK.UseVisualStyleBackColor = true; - this.btnOK.Click += new System.EventHandler(this.OKButton_Click); - // - // btnCancel - // - this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.btnCancel.Location = new System.Drawing.Point(254, 9); - this.btnCancel.Margin = new System.Windows.Forms.Padding(4); - this.btnCancel.Name = "btnCancel"; - this.btnCancel.Size = new System.Drawing.Size(154, 39); - this.btnCancel.TabIndex = 1; - this.btnCancel.Text = "Cancel"; - this.btnCancel.UseVisualStyleBackColor = true; - this.btnCancel.Click += new System.EventHandler(this.CancelButton_Click); - // - // btnRegisterAll - // - this.btnRegisterAll.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.btnRegisterAll.Location = new System.Drawing.Point(92, 9); - this.btnRegisterAll.Margin = new System.Windows.Forms.Padding(4); - this.btnRegisterAll.Name = "btnRegisterAll"; - this.btnRegisterAll.Size = new System.Drawing.Size(154, 39); - this.btnRegisterAll.TabIndex = 2; - this.btnRegisterAll.Text = "Reg All"; - this.btnRegisterAll.UseVisualStyleBackColor = true; - this.btnRegisterAll.Click += new System.EventHandler(this.RegisterAllButton_Click); - // - // tableLayoutPanel1 - // - this.tableLayoutPanel1.ColumnCount = 2; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.Controls.Add(this.RegHotkeysAtStartupLabel, 0, 6); - this.tableLayoutPanel1.Controls.Add(this.SwitchSystemProxyLabel, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.SwitchProxyModeLabel, 0, 1); - this.tableLayoutPanel1.Controls.Add(this.SwitchAllowLanLabel, 0, 2); - this.tableLayoutPanel1.Controls.Add(this.ShowLogsLabel, 0, 3); - this.tableLayoutPanel1.Controls.Add(this.ServerMoveUpLabel, 0, 4); - this.tableLayoutPanel1.Controls.Add(this.ServerMoveDownLabel, 0, 5); - this.tableLayoutPanel1.Controls.Add(flowLayoutPanel1, 0, 7); - this.tableLayoutPanel1.Controls.Add(this.SwitchSystemProxyTextBox, 1, 0); - this.tableLayoutPanel1.Controls.Add(this.SwitchProxyModeTextBox, 1, 1); - this.tableLayoutPanel1.Controls.Add(this.SwitchAllowLanTextBox, 1, 2); - this.tableLayoutPanel1.Controls.Add(this.ShowLogsTextBox, 1, 3); - this.tableLayoutPanel1.Controls.Add(this.ServerMoveUpTextBox, 1, 4); - this.tableLayoutPanel1.Controls.Add(this.ServerMoveDownTextBox, 1, 5); - this.tableLayoutPanel1.Controls.Add(this.RegHotkeysAtStartupCheckBox, 1, 6); - this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 8; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.16726F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.16726F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.16726F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.16726F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.7784F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.38949F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.16309F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(582, 303); - this.tableLayoutPanel1.TabIndex = 0; - // - // RegHotkeysAtStartupLabel - // - this.RegHotkeysAtStartupLabel.AutoSize = true; - this.RegHotkeysAtStartupLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.RegHotkeysAtStartupLabel.Location = new System.Drawing.Point(40, 213); - this.RegHotkeysAtStartupLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.RegHotkeysAtStartupLabel.Name = "RegHotkeysAtStartupLabel"; - this.RegHotkeysAtStartupLabel.Size = new System.Drawing.Size(199, 35); - this.RegHotkeysAtStartupLabel.TabIndex = 16; - this.RegHotkeysAtStartupLabel.Text = "Reg Hotkeys At Startup"; - this.RegHotkeysAtStartupLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // SwitchSystemProxyLabel - // - this.SwitchSystemProxyLabel.AutoSize = true; - this.SwitchSystemProxyLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.SwitchSystemProxyLabel.Location = new System.Drawing.Point(63, 0); - this.SwitchSystemProxyLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.SwitchSystemProxyLabel.Name = "SwitchSystemProxyLabel"; - this.SwitchSystemProxyLabel.Size = new System.Drawing.Size(176, 35); - this.SwitchSystemProxyLabel.TabIndex = 0; - this.SwitchSystemProxyLabel.Text = "Switch system proxy"; - this.SwitchSystemProxyLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // SwitchProxyModeLabel - // - this.SwitchProxyModeLabel.AutoSize = true; - this.SwitchProxyModeLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.SwitchProxyModeLabel.Location = new System.Drawing.Point(10, 35); - this.SwitchProxyModeLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.SwitchProxyModeLabel.Name = "SwitchProxyModeLabel"; - this.SwitchProxyModeLabel.Size = new System.Drawing.Size(229, 35); - this.SwitchProxyModeLabel.TabIndex = 1; - this.SwitchProxyModeLabel.Text = "Switch system proxy mode"; - this.SwitchProxyModeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // SwitchAllowLanLabel - // - this.SwitchAllowLanLabel.AutoSize = true; - this.SwitchAllowLanLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.SwitchAllowLanLabel.Location = new System.Drawing.Point(39, 70); - this.SwitchAllowLanLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.SwitchAllowLanLabel.Name = "SwitchAllowLanLabel"; - this.SwitchAllowLanLabel.Size = new System.Drawing.Size(200, 35); - this.SwitchAllowLanLabel.TabIndex = 3; - this.SwitchAllowLanLabel.Text = "Allow Clients from LAN"; - this.SwitchAllowLanLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // ShowLogsLabel - // - this.ShowLogsLabel.AutoSize = true; - this.ShowLogsLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.ShowLogsLabel.Location = new System.Drawing.Point(129, 105); - this.ShowLogsLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.ShowLogsLabel.Name = "ShowLogsLabel"; - this.ShowLogsLabel.Size = new System.Drawing.Size(110, 35); - this.ShowLogsLabel.TabIndex = 4; - this.ShowLogsLabel.Text = "Show Logs..."; - this.ShowLogsLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // ServerMoveUpLabel - // - this.ServerMoveUpLabel.AutoSize = true; - this.ServerMoveUpLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.ServerMoveUpLabel.Location = new System.Drawing.Point(25, 140); - this.ServerMoveUpLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.ServerMoveUpLabel.Name = "ServerMoveUpLabel"; - this.ServerMoveUpLabel.Size = new System.Drawing.Size(214, 37); - this.ServerMoveUpLabel.TabIndex = 4; - this.ServerMoveUpLabel.Text = "Switch to previous server"; - this.ServerMoveUpLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // ServerMoveDownLabel - // - this.ServerMoveDownLabel.AutoSize = true; - this.ServerMoveDownLabel.Dock = System.Windows.Forms.DockStyle.Right; - this.ServerMoveDownLabel.Location = new System.Drawing.Point(60, 177); - this.ServerMoveDownLabel.Margin = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.ServerMoveDownLabel.Name = "ServerMoveDownLabel"; - this.ServerMoveDownLabel.Size = new System.Drawing.Size(179, 36); - this.ServerMoveDownLabel.TabIndex = 4; - this.ServerMoveDownLabel.Text = "Switch to next server"; - this.ServerMoveDownLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // SwitchSystemProxyTextBox - // - this.SwitchSystemProxyTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.SwitchSystemProxyTextBox.Location = new System.Drawing.Point(252, 3); - this.SwitchSystemProxyTextBox.Name = "SwitchSystemProxyTextBox"; - this.SwitchSystemProxyTextBox.ReadOnly = true; - this.SwitchSystemProxyTextBox.Size = new System.Drawing.Size(339, 29); - this.SwitchSystemProxyTextBox.TabIndex = 7; - this.SwitchSystemProxyTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); - this.SwitchSystemProxyTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); - // - // SwitchProxyModeTextBox - // - this.SwitchProxyModeTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.SwitchProxyModeTextBox.Location = new System.Drawing.Point(252, 38); - this.SwitchProxyModeTextBox.Name = "SwitchProxyModeTextBox"; - this.SwitchProxyModeTextBox.ReadOnly = true; - this.SwitchProxyModeTextBox.Size = new System.Drawing.Size(339, 29); - this.SwitchProxyModeTextBox.TabIndex = 8; - this.SwitchProxyModeTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); - this.SwitchProxyModeTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); - // - // SwitchAllowLanTextBox - // - this.SwitchAllowLanTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.SwitchAllowLanTextBox.Location = new System.Drawing.Point(252, 73); - this.SwitchAllowLanTextBox.Name = "SwitchAllowLanTextBox"; - this.SwitchAllowLanTextBox.ReadOnly = true; - this.SwitchAllowLanTextBox.Size = new System.Drawing.Size(339, 29); - this.SwitchAllowLanTextBox.TabIndex = 10; - this.SwitchAllowLanTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); - this.SwitchAllowLanTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); - // - // ShowLogsTextBox - // - this.ShowLogsTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.ShowLogsTextBox.Location = new System.Drawing.Point(252, 108); - this.ShowLogsTextBox.Name = "ShowLogsTextBox"; - this.ShowLogsTextBox.ReadOnly = true; - this.ShowLogsTextBox.Size = new System.Drawing.Size(339, 29); - this.ShowLogsTextBox.TabIndex = 11; - this.ShowLogsTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); - this.ShowLogsTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); - // - // ServerMoveUpTextBox - // - this.ServerMoveUpTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.ServerMoveUpTextBox.Location = new System.Drawing.Point(252, 143); - this.ServerMoveUpTextBox.Name = "ServerMoveUpTextBox"; - this.ServerMoveUpTextBox.ReadOnly = true; - this.ServerMoveUpTextBox.Size = new System.Drawing.Size(339, 29); - this.ServerMoveUpTextBox.TabIndex = 12; - this.ServerMoveUpTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); - this.ServerMoveUpTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); - // - // ServerMoveDownTextBox - // - this.ServerMoveDownTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.ServerMoveDownTextBox.Location = new System.Drawing.Point(252, 180); - this.ServerMoveDownTextBox.Name = "ServerMoveDownTextBox"; - this.ServerMoveDownTextBox.ReadOnly = true; - this.ServerMoveDownTextBox.Size = new System.Drawing.Size(339, 29); - this.ServerMoveDownTextBox.TabIndex = 13; - this.ServerMoveDownTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HotkeyDown); - this.ServerMoveDownTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HotkeyUp); - // - // RegHotkeysAtStartupCheckBox - // - this.RegHotkeysAtStartupCheckBox.AutoSize = true; - this.RegHotkeysAtStartupCheckBox.Dock = System.Windows.Forms.DockStyle.Left; - this.RegHotkeysAtStartupCheckBox.Location = new System.Drawing.Point(252, 216); - this.RegHotkeysAtStartupCheckBox.Name = "RegHotkeysAtStartupCheckBox"; - this.RegHotkeysAtStartupCheckBox.Size = new System.Drawing.Size(18, 29); - this.RegHotkeysAtStartupCheckBox.TabIndex = 17; - this.RegHotkeysAtStartupCheckBox.UseVisualStyleBackColor = true; - // - // HotkeySettingsForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(582, 303); - this.Controls.Add(this.tableLayoutPanel1); - this.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - this.Margin = new System.Windows.Forms.Padding(5, 6, 5, 6); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "HotkeySettingsForm"; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Edit Hotkeys..."; - flowLayoutPanel1.ResumeLayout(false); - this.tableLayoutPanel1.ResumeLayout(false); - this.tableLayoutPanel1.PerformLayout(); - this.ResumeLayout(false); - - } - - #endregion - private System.Windows.Forms.Label SwitchSystemProxyLabel; - private System.Windows.Forms.Label SwitchProxyModeLabel; - private System.Windows.Forms.Label SwitchAllowLanLabel; - private System.Windows.Forms.Label ShowLogsLabel; - private System.Windows.Forms.Label ServerMoveUpLabel; - private System.Windows.Forms.Label ServerMoveDownLabel; - private System.Windows.Forms.Button btnOK; - private System.Windows.Forms.Button btnCancel; - private System.Windows.Forms.TextBox ShowLogsTextBox; - private System.Windows.Forms.TextBox SwitchAllowLanTextBox; - private System.Windows.Forms.TextBox SwitchProxyModeTextBox; - private System.Windows.Forms.TextBox SwitchSystemProxyTextBox; - private System.Windows.Forms.TextBox ServerMoveUpTextBox; - private System.Windows.Forms.TextBox ServerMoveDownTextBox; - private System.Windows.Forms.Button btnRegisterAll; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; - private System.Windows.Forms.Label RegHotkeysAtStartupLabel; - private System.Windows.Forms.CheckBox RegHotkeysAtStartupCheckBox; - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 8ba600ac..da3ea91e 100644 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -1,5 +1,6 @@ using NLog; using Shadowsocks.Controller; +using Shadowsocks.Localization; using Shadowsocks.Model; using Shadowsocks.Properties; using Shadowsocks.Util; @@ -11,6 +12,8 @@ using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; +using System.Windows.Forms.Integration; +using System.Windows.Threading; using ZXing; using ZXing.Common; using ZXing.QrCode; @@ -19,18 +22,14 @@ namespace Shadowsocks.View { public class MenuViewController { - private static Logger logger = LogManager.GetCurrentClassLogger(); - // yes this is just a menu view controller - // when config form is closed, it moves away from RAM - // and it should just do anything related to the config form + private readonly Logger logger = LogManager.GetCurrentClassLogger(); private ShadowsocksController controller; - private UpdateChecker updateChecker; + public UpdateChecker updateChecker; private NotifyIcon _notifyIcon; private Icon icon, icon_in, icon_out, icon_both, previousIcon; - private bool _isStartupChecking; private string _urlToOpen; private ContextMenu contextMenu1; @@ -61,12 +60,12 @@ namespace Shadowsocks.View private MenuItem onlineConfigItem; private ConfigForm configForm; - private ProxyForm proxyForm; private LogForm logForm; - private HotkeySettingsForm hotkeySettingsForm; - private OnlineConfigForm onlineConfigForm; private System.Windows.Window serverSharingWindow; + private System.Windows.Window hotkeysWindow; + private System.Windows.Window forwardProxyWindow; + private System.Windows.Window onlineConfigWindow; // color definition for icon color transformation private readonly Color colorMaskBlue = Color.FromArgb(255, 25, 125, 191); @@ -102,7 +101,7 @@ namespace Shadowsocks.View _notifyIcon.BalloonTipClosed += _notifyIcon_BalloonTipClosed; controller.TrafficChanged += controller_TrafficChanged; - this.updateChecker = new UpdateChecker(); + updateChecker = new UpdateChecker(); updateChecker.CheckUpdateCompleted += updateChecker_CheckUpdateCompleted; LoadCurrentConfiguration(); @@ -115,8 +114,7 @@ namespace Shadowsocks.View } else if (config.autoCheckUpdate) { - _isStartupChecking = true; - updateChecker.CheckUpdate(config, 3000); + Dispatcher.CurrentDispatcher.Invoke(() => updateChecker.CheckForVersionUpdate(3000)); } } @@ -383,36 +381,6 @@ namespace Shadowsocks.View } } - private void ShowProxyForm() - { - if (proxyForm != null) - { - proxyForm.Activate(); - } - else - { - proxyForm = new ProxyForm(controller); - proxyForm.Show(); - proxyForm.Activate(); - proxyForm.FormClosed += proxyForm_FormClosed; - } - } - - private void ShowHotKeySettingsForm() - { - if (hotkeySettingsForm != null) - { - hotkeySettingsForm.Activate(); - } - else - { - hotkeySettingsForm = new HotkeySettingsForm(controller); - hotkeySettingsForm.Show(); - hotkeySettingsForm.Activate(); - hotkeySettingsForm.FormClosed += hotkeySettingsForm_FormClosed; - } - } - private void ShowLogForm() { if (logForm != null) @@ -428,22 +396,6 @@ 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(); @@ -468,24 +420,6 @@ namespace Shadowsocks.View } } - void proxyForm_FormClosed(object sender, FormClosedEventArgs e) - { - proxyForm.Dispose(); - proxyForm = null; - } - - void hotkeySettingsForm_FormClosed(object sender, FormClosedEventArgs e) - { - hotkeySettingsForm.Dispose(); - hotkeySettingsForm = null; - } - - void onlineConfigForm_FormClosed(object sender, FormClosedEventArgs e) - { - onlineConfigForm.Dispose(); - onlineConfigForm = null; - } - #endregion #region Misc @@ -500,23 +434,10 @@ namespace Shadowsocks.View void notifyIcon1_BalloonTipClicked(object sender, EventArgs 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); - } - } } private void _notifyIcon_BalloonTipClosed(object sender, EventArgs e) { - if (updateChecker.NewVersionFound) - { - updateChecker.NewVersionFound = false; /* Reset the flag */ - } } private void notifyIcon1_Click(object sender, MouseEventArgs e) @@ -541,8 +462,7 @@ namespace Shadowsocks.View Configuration config = controller.GetCurrentConfiguration(); if (config.firstRun) return; - _isStartupChecking = true; - updateChecker.CheckUpdate(config, 3000); + Dispatcher.CurrentDispatcher.Invoke(() => updateChecker.CheckForVersionUpdate(3000)); } public void ShowLogForm_HotKey() @@ -561,19 +481,83 @@ namespace Shadowsocks.View private void proxyItem_Click(object sender, EventArgs e) { - ShowProxyForm(); + if (forwardProxyWindow == null) + { + forwardProxyWindow = new System.Windows.Window() + { + Title = LocalizationProvider.GetLocalizedValue("ForwardProxy"), + Height = 400, + Width = 280, + MinHeight = 400, + MinWidth = 280, + Content = new ForwardProxyView() + }; + forwardProxyWindow.Closed += ForwardProxyWindow_Closed; + ElementHost.EnableModelessKeyboardInterop(forwardProxyWindow); + forwardProxyWindow.Show(); + } + forwardProxyWindow.Activate(); + } + + private void ForwardProxyWindow_Closed(object sender, EventArgs e) + { + forwardProxyWindow = null; } + public void CloseForwardProxyWindow() => forwardProxyWindow.Close(); + private void OnlineConfig_Click(object sender, EventArgs e) { - ShowOnlineConfigForm(); + if (onlineConfigWindow == null) + { + onlineConfigWindow = new System.Windows.Window() + { + Title = LocalizationProvider.GetLocalizedValue("OnlineConfigDelivery"), + Height = 510, + Width = 480, + MinHeight = 510, + MinWidth = 480, + Content = new OnlineConfigView() + }; + onlineConfigWindow.Closed += OnlineConfigWindow_Closed; + ElementHost.EnableModelessKeyboardInterop(onlineConfigWindow); + onlineConfigWindow.Show(); + } + onlineConfigWindow.Activate(); + } + + private void OnlineConfigWindow_Closed(object sender, EventArgs e) + { + onlineConfigWindow = null; } private void hotKeyItem_Click(object sender, EventArgs e) { - ShowHotKeySettingsForm(); + if (hotkeysWindow == null) + { + hotkeysWindow = new System.Windows.Window() + { + Title = LocalizationProvider.GetLocalizedValue("Hotkeys"), + Height = 260, + Width = 320, + MinHeight = 260, + MinWidth = 320, + Content = new HotkeysView() + }; + hotkeysWindow.Closed += HotkeysWindow_Closed; + ElementHost.EnableModelessKeyboardInterop(hotkeysWindow); + hotkeysWindow.Show(); + } + hotkeysWindow.Activate(); + } + + private void HotkeysWindow_Closed(object sender, EventArgs e) + { + hotkeysWindow = null; } + public void CloseHotkeysWindow() => hotkeysWindow.Close(); + private void ShareOverLANItem_Click(object sender, EventArgs e) { ShareOverLANItem.Checked = !ShareOverLANItem.Checked; @@ -750,12 +734,15 @@ namespace Shadowsocks.View { serverSharingWindow = new System.Windows.Window() { - Title = "Server Sharing", + Title = LocalizationProvider.GetLocalizedValue("ServerSharing"), Height = 400, Width = 660, + MinHeight = 400, + MinWidth = 660, Content = new ServerSharingView() }; serverSharingWindow.Closed += ServerSharingWindow_Closed; + ElementHost.EnableModelessKeyboardInterop(serverSharingWindow); serverSharingWindow.Show(); } serverSharingWindow.Activate(); @@ -1017,15 +1004,10 @@ namespace Shadowsocks.View 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 (updateChecker.NewReleaseZipFilename == null) { ShowBalloonTip(I18N.GetString("Shadowsocks"), I18N.GetString("No update is available"), ToolTipIcon.Info, 5000); } - _isStartupChecking = false; } private void UpdateUpdateMenu() @@ -1049,9 +1031,9 @@ namespace Shadowsocks.View UpdateUpdateMenu(); } - private void checkUpdatesItem_Click(object sender, EventArgs e) + private async void checkUpdatesItem_Click(object sender, EventArgs e) { - updateChecker.CheckUpdate(controller.GetCurrentConfiguration()); + await updateChecker.CheckForVersionUpdate(); } private void AboutItem_Click(object sender, EventArgs e) diff --git a/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs b/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs deleted file mode 100644 index 89b4f12a..00000000 --- a/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs +++ /dev/null @@ -1,218 +0,0 @@ -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.OkButton = new System.Windows.Forms.Button(); - this.UpdateAllButton = 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.Padding = new System.Windows.Forms.Padding(3); - 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(482, 453); - 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(13, 13); - this.UrlListBox.Margin = new System.Windows.Forms.Padding(10); - this.UrlListBox.Name = "UrlListBox"; - this.UrlListBox.Size = new System.Drawing.Size(456, 334); - this.UrlListBox.TabIndex = 0; - this.UrlListBox.SelectedIndexChanged += new System.EventHandler(this.UrlListBox_SelectedIndexChanged); - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Dock = System.Windows.Forms.DockStyle.Fill; - this.label1.Location = new System.Drawing.Point(6, 357); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(152, 31); - this.label1.TabIndex = 1; - this.label1.Text = "Online config URL"; - this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // UrlTextBox - // - this.tableLayoutPanel1.SetColumnSpan(this.UrlTextBox, 2); - this.UrlTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.UrlTextBox.Location = new System.Drawing.Point(164, 360); - this.UrlTextBox.Margin = new System.Windows.Forms.Padding(3, 3, 15, 3); - this.UrlTextBox.Name = "UrlTextBox"; - this.UrlTextBox.Size = new System.Drawing.Size(300, 25); - this.UrlTextBox.TabIndex = 2; - // - // UpdateButton - // - this.UpdateButton.Dock = System.Windows.Forms.DockStyle.Fill; - this.UpdateButton.Location = new System.Drawing.Point(23, 391); - this.UpdateButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); - this.UpdateButton.MaximumSize = new System.Drawing.Size(0, 25); - this.UpdateButton.MinimumSize = new System.Drawing.Size(0, 25); - this.UpdateButton.Name = "UpdateButton"; - this.UpdateButton.Size = new System.Drawing.Size(118, 25); - this.UpdateButton.TabIndex = 3; - this.UpdateButton.Text = "&Update"; - this.UpdateButton.UseVisualStyleBackColor = true; - this.UpdateButton.Click += new System.EventHandler(this.UpdateButton_Click); - // - // AddButton - // - this.AddButton.Dock = System.Windows.Forms.DockStyle.Fill; - this.AddButton.Location = new System.Drawing.Point(181, 391); - this.AddButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); - this.AddButton.MaximumSize = new System.Drawing.Size(0, 25); - this.AddButton.MinimumSize = new System.Drawing.Size(0, 25); - this.AddButton.Name = "AddButton"; - this.AddButton.Size = new System.Drawing.Size(118, 25); - 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(339, 391); - this.DeleteButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); - this.DeleteButton.MaximumSize = new System.Drawing.Size(0, 25); - this.DeleteButton.MinimumSize = new System.Drawing.Size(0, 25); - this.DeleteButton.Name = "DeleteButton"; - this.DeleteButton.Size = new System.Drawing.Size(120, 25); - this.DeleteButton.TabIndex = 5; - this.DeleteButton.Text = "&Delete"; - this.DeleteButton.UseVisualStyleBackColor = true; - this.DeleteButton.Click += new System.EventHandler(this.DeleteButton_Click); - // - // OkButton - // - this.OkButton.Dock = System.Windows.Forms.DockStyle.Fill; - this.OkButton.Location = new System.Drawing.Point(181, 422); - this.OkButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); - this.OkButton.MaximumSize = new System.Drawing.Size(0, 25); - this.OkButton.MinimumSize = new System.Drawing.Size(0, 25); - this.OkButton.Name = "OkButton"; - this.OkButton.Size = new System.Drawing.Size(118, 25); - this.OkButton.TabIndex = 7; - this.OkButton.Text = "OK"; - this.OkButton.UseVisualStyleBackColor = true; - this.OkButton.Click += new System.EventHandler(this.OkButton_Click); - // - // UpdateAllButton - // - this.UpdateAllButton.Dock = System.Windows.Forms.DockStyle.Fill; - this.UpdateAllButton.Location = new System.Drawing.Point(23, 422); - this.UpdateAllButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); - this.UpdateAllButton.MaximumSize = new System.Drawing.Size(0, 25); - this.UpdateAllButton.MinimumSize = new System.Drawing.Size(0, 25); - this.UpdateAllButton.Name = "UpdateAllButton"; - this.UpdateAllButton.Size = new System.Drawing.Size(118, 25); - this.UpdateAllButton.TabIndex = 6; - this.UpdateAllButton.Text = "U&pdate All"; - this.UpdateAllButton.UseVisualStyleBackColor = true; - this.UpdateAllButton.Click += new System.EventHandler(this.UpdateAllButton_Click); - // - // CancelButton - // - this.CancelButton.Dock = System.Windows.Forms.DockStyle.Fill; - this.CancelButton.Location = new System.Drawing.Point(339, 422); - this.CancelButton.Margin = new System.Windows.Forms.Padding(20, 3, 20, 3); - this.CancelButton.MaximumSize = new System.Drawing.Size(0, 25); - this.CancelButton.MinimumSize = new System.Drawing.Size(0, 25); - this.CancelButton.Name = "CancelButton"; - this.CancelButton.Size = new System.Drawing.Size(120, 25); - this.CancelButton.TabIndex = 8; - this.CancelButton.Text = "Cancel"; - this.CancelButton.UseVisualStyleBackColor = true; - this.CancelButton.Click += new System.EventHandler(this.CancelButton_Click); - // - // OnlineConfigForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(482, 453); - this.Controls.Add(this.tableLayoutPanel1); - this.MinimizeBox = false; - this.MinimumSize = new System.Drawing.Size(400, 400); - this.Name = "OnlineConfigForm"; - this.Text = "Online config"; - 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 new 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 deleted file mode 100644 index 344472da..00000000 --- a/shadowsocks-csharp/View/OnlineConfigForm.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System; -using System.Data; -using System.Linq; -using System.Windows.Forms; -using Shadowsocks.Controller; -using Shadowsocks.Model; -using Shadowsocks.Properties; - -namespace Shadowsocks.View -{ - public partial class OnlineConfigForm : Form - { - private ShadowsocksController controller; - private Configuration config; - - public OnlineConfigForm(ShadowsocksController controller) - { - this.controller = controller; - InitializeComponent(); - LoadConfig(); - Icon = System.Drawing.Icon.FromHandle(Resources.ssw128.GetHicon()); - I18N.TranslateForm(this); - } - - private void LoadConfig() - { - config = controller.GetCurrentConfiguration(); - var idx = UrlListBox.SelectedIndex; - UrlListBox.Items.Clear(); - - foreach (var item in config.onlineConfigSource) - { - UrlListBox.Items.Add(item); - } - - if (idx >= UrlListBox.Items.Count) idx = 0; - if (idx < 0 && UrlListBox.Items.Count > 0) idx = 0; - if (UrlListBox.Items.Count == 0) return; - UrlListBox.SelectedIndex = idx; - SelectItem(); - } - - private void SelectItem() - { - UrlTextBox.Text = (string)UrlListBox.SelectedItem; - } - - private bool ValidateUrl() - { - try - { - var scheme = new Uri(UrlTextBox.Text).Scheme; - if (scheme != "http" && scheme != "https") return false; - if (UrlListBox.Items.OfType().Contains(UrlTextBox.Text)) return false; - } - catch - { - return false; - } - return true; - } - - private void Commit() - { - if (UrlListBox.SelectedIndex < 0) return; - if ((string)UrlListBox.SelectedItem == UrlTextBox.Text) - { - LoadConfig(); - return; - } - - if (ValidateUrl()) - { - - UrlListBox.Items[UrlListBox.SelectedIndex] = UrlTextBox.Text; - } - controller.SaveOnlineConfigSource(UrlListBox.Items.OfType().Where(s => !string.IsNullOrWhiteSpace(s)).Distinct()); - LoadConfig(); - return; - } - - private void AddButton_Click(object sender, EventArgs e) - { - if (string.IsNullOrWhiteSpace(UrlTextBox.Text)) return; - UrlListBox.Items.Add(UrlTextBox.Text); - UrlListBox.SelectedIndex = UrlListBox.Items.Count - 1; - UrlTextBox.Text = ""; - Commit(); - } - - private async void UpdateButton_Click(object sender, EventArgs e) - { - string old = (string)UrlListBox.SelectedItem; - // update content, also update online config - Commit(); - string current = (string)UrlListBox.SelectedItem; - if (UrlListBox.Items.Count == 0) return; - tableLayoutPanel1.Enabled = false; - bool ok = await controller.UpdateOnlineConfig(current); - if (!ok) - { - MessageBox.Show(I18N.GetString("online config failed to update")); - tableLayoutPanel1.Enabled = true; - return; - } - if (old != current) controller.RemoveOnlineConfig(old); - tableLayoutPanel1.Enabled = true; - } - - private void UrlListBox_SelectedIndexChanged(object sender, EventArgs e) - { - if (!UrlListBox.CanSelect) - { - return; - } - SelectItem(); - } - - private void DeleteButton_Click(object sender, EventArgs e) - { - if (UrlListBox.Items.Count == 0) return; - string url = (string)UrlListBox.SelectedItem; - if (!string.IsNullOrWhiteSpace(url)) - { - controller.RemoveOnlineConfig(url); - } - LoadConfig(); - } - - private async void UpdateAllButton_Click(object sender, EventArgs e) - { - if (UrlListBox.Items.Count == 0) return; - tableLayoutPanel1.Enabled = false; - int fail = await controller.UpdateAllOnlineConfig(); - if (fail > 0) - { - MessageBox.Show(I18N.GetString("{0} online config failed to update", fail)); - } - tableLayoutPanel1.Enabled = true; - } - - private void OkButton_Click(object sender, EventArgs e) - { - Commit(); - Close(); - } - - private void CancelButton_Click(object sender, EventArgs e) - { - Close(); - } - } -} diff --git a/shadowsocks-csharp/View/ProxyForm.Designer.cs b/shadowsocks-csharp/View/ProxyForm.Designer.cs deleted file mode 100644 index abbf6527..00000000 --- a/shadowsocks-csharp/View/ProxyForm.Designer.cs +++ /dev/null @@ -1,333 +0,0 @@ -namespace Shadowsocks.View -{ - partial class ProxyForm - { - /// - /// 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.MyCancelButton = new System.Windows.Forms.Button(); - this.OKButton = new System.Windows.Forms.Button(); - this.UseProxyCheckBox = new System.Windows.Forms.CheckBox(); - this.ProxyAddrLabel = new System.Windows.Forms.Label(); - this.ProxyServerTextBox = new System.Windows.Forms.TextBox(); - this.ProxyPortLabel = new System.Windows.Forms.Label(); - this.ProxyPortTextBox = new System.Windows.Forms.TextBox(); - this.ProxyTypeLabel = new System.Windows.Forms.Label(); - this.ProxyTypeComboBox = new System.Windows.Forms.ComboBox(); - this.ProxyTimeoutTextBox = new System.Windows.Forms.TextBox(); - this.ProxyTimeoutLabel = new System.Windows.Forms.Label(); - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.ProxyNotificationLabel = new System.Windows.Forms.Label(); - this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); - this.AuthUserLabel = new System.Windows.Forms.Label(); - this.AuthPwdLabel = new System.Windows.Forms.Label(); - this.UseAuthCheckBox = new System.Windows.Forms.CheckBox(); - this.AuthUserTextBox = new System.Windows.Forms.TextBox(); - this.AuthPwdTextBox = new System.Windows.Forms.TextBox(); - this.tableLayoutPanel1.SuspendLayout(); - this.flowLayoutPanel1.SuspendLayout(); - this.SuspendLayout(); - // - // MyCancelButton - // - this.MyCancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.MyCancelButton.Location = new System.Drawing.Point(84, 3); - this.MyCancelButton.Margin = new System.Windows.Forms.Padding(3, 3, 0, 0); - this.MyCancelButton.Name = "MyCancelButton"; - this.MyCancelButton.Size = new System.Drawing.Size(75, 23); - this.MyCancelButton.TabIndex = 13; - this.MyCancelButton.Text = "Cancel"; - this.MyCancelButton.UseVisualStyleBackColor = true; - this.MyCancelButton.Click += new System.EventHandler(this.CancelButton_Click); - // - // OKButton - // - this.OKButton.DialogResult = System.Windows.Forms.DialogResult.OK; - this.OKButton.Location = new System.Drawing.Point(3, 3); - this.OKButton.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0); - this.OKButton.Name = "OKButton"; - this.OKButton.Size = new System.Drawing.Size(75, 23); - this.OKButton.TabIndex = 12; - this.OKButton.Text = "OK"; - this.OKButton.UseVisualStyleBackColor = true; - this.OKButton.Click += new System.EventHandler(this.OKButton_Click); - // - // UseProxyCheckBox - // - this.UseProxyCheckBox.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.UseProxyCheckBox.AutoSize = true; - this.tableLayoutPanel1.SetColumnSpan(this.UseProxyCheckBox, 2); - this.UseProxyCheckBox.Location = new System.Drawing.Point(3, 6); - this.UseProxyCheckBox.Name = "UseProxyCheckBox"; - this.UseProxyCheckBox.Size = new System.Drawing.Size(78, 16); - this.UseProxyCheckBox.TabIndex = 0; - this.UseProxyCheckBox.Text = "Use Proxy"; - this.UseProxyCheckBox.UseVisualStyleBackColor = true; - this.UseProxyCheckBox.CheckedChanged += new System.EventHandler(this.UseProxyCheckBox_CheckedChanged); - // - // ProxyAddrLabel - // - this.ProxyAddrLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ProxyAddrLabel.AutoSize = true; - this.ProxyAddrLabel.Location = new System.Drawing.Point(3, 64); - this.ProxyAddrLabel.Name = "ProxyAddrLabel"; - this.ProxyAddrLabel.Size = new System.Drawing.Size(65, 12); - this.ProxyAddrLabel.TabIndex = 0; - this.ProxyAddrLabel.Text = "Proxy Addr"; - // - // ProxyServerTextBox - // - this.ProxyServerTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ProxyServerTextBox.Location = new System.Drawing.Point(74, 59); - this.ProxyServerTextBox.MaxLength = 512; - this.ProxyServerTextBox.Name = "ProxyServerTextBox"; - this.ProxyServerTextBox.Size = new System.Drawing.Size(138, 21); - this.ProxyServerTextBox.TabIndex = 1; - this.ProxyServerTextBox.WordWrap = false; - // - // ProxyPortLabel - // - this.ProxyPortLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ProxyPortLabel.AutoSize = true; - this.ProxyPortLabel.Location = new System.Drawing.Point(218, 64); - this.ProxyPortLabel.Name = "ProxyPortLabel"; - this.ProxyPortLabel.Size = new System.Drawing.Size(77, 12); - this.ProxyPortLabel.TabIndex = 2; - this.ProxyPortLabel.Text = "Proxy Port"; - // - // ProxyPortTextBox - // - this.ProxyPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ProxyPortTextBox.Location = new System.Drawing.Point(301, 59); - this.ProxyPortTextBox.MaxLength = 10; - this.ProxyPortTextBox.Name = "ProxyPortTextBox"; - this.ProxyPortTextBox.Size = new System.Drawing.Size(91, 21); - this.ProxyPortTextBox.TabIndex = 3; - this.ProxyPortTextBox.WordWrap = false; - // - // ProxyTypeLabel - // - this.ProxyTypeLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ProxyTypeLabel.AutoSize = true; - this.ProxyTypeLabel.Location = new System.Drawing.Point(3, 36); - this.ProxyTypeLabel.Name = "ProxyTypeLabel"; - this.ProxyTypeLabel.Size = new System.Drawing.Size(65, 12); - this.ProxyTypeLabel.TabIndex = 1; - this.ProxyTypeLabel.Text = "Proxy Type"; - // - // ProxyTypeComboBox - // - this.ProxyTypeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ProxyTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.ProxyTypeComboBox.FormattingEnabled = true; - this.ProxyTypeComboBox.Items.AddRange(new object[] { - "SOCKS5", - "HTTP"}); - this.ProxyTypeComboBox.Location = new System.Drawing.Point(74, 33); - this.ProxyTypeComboBox.Margin = new System.Windows.Forms.Padding(3, 5, 3, 5); - this.ProxyTypeComboBox.Name = "ProxyTypeComboBox"; - this.ProxyTypeComboBox.Size = new System.Drawing.Size(138, 20); - this.ProxyTypeComboBox.TabIndex = 2; - this.ProxyTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.ProxyTypeComboBox_SelectedIndexChanged); - // - // ProxyTimeoutTextBox - // - this.ProxyTimeoutTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ProxyTimeoutTextBox.Location = new System.Drawing.Point(301, 31); - this.ProxyTimeoutTextBox.Name = "ProxyTimeoutTextBox"; - this.ProxyTimeoutTextBox.Size = new System.Drawing.Size(91, 21); - this.ProxyTimeoutTextBox.TabIndex = 3; - // - // ProxyTimeoutLabel - // - this.ProxyTimeoutLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ProxyTimeoutLabel.AutoSize = true; - this.ProxyTimeoutLabel.Location = new System.Drawing.Point(218, 36); - this.ProxyTimeoutLabel.Name = "ProxyTimeoutLabel"; - this.ProxyTimeoutLabel.Size = new System.Drawing.Size(77, 12); - this.ProxyTimeoutLabel.TabIndex = 4; - this.ProxyTimeoutLabel.Text = "Timeout(Sec)"; - // - // tableLayoutPanel1 - // - this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.tableLayoutPanel1.ColumnCount = 4; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 60F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 40F)); - this.tableLayoutPanel1.Controls.Add(this.UseProxyCheckBox, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.ProxyTypeLabel, 0, 1); - this.tableLayoutPanel1.Controls.Add(this.ProxyPortTextBox, 3, 2); - this.tableLayoutPanel1.Controls.Add(this.ProxyTypeComboBox, 1, 1); - this.tableLayoutPanel1.Controls.Add(this.ProxyTimeoutLabel, 2, 1); - this.tableLayoutPanel1.Controls.Add(this.ProxyPortLabel, 2, 2); - this.tableLayoutPanel1.Controls.Add(this.ProxyTimeoutTextBox, 3, 1); - this.tableLayoutPanel1.Controls.Add(this.ProxyServerTextBox, 1, 2); - this.tableLayoutPanel1.Controls.Add(this.ProxyAddrLabel, 0, 2); - this.tableLayoutPanel1.Controls.Add(this.ProxyNotificationLabel, 0, 3); - this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 0, 6); - this.tableLayoutPanel1.Controls.Add(this.AuthUserLabel, 0, 5); - this.tableLayoutPanel1.Controls.Add(this.AuthPwdLabel, 2, 5); - this.tableLayoutPanel1.Controls.Add(this.UseAuthCheckBox, 0, 4); - this.tableLayoutPanel1.Controls.Add(this.AuthUserTextBox, 1, 5); - this.tableLayoutPanel1.Controls.Add(this.AuthPwdTextBox, 3, 5); - this.tableLayoutPanel1.Location = new System.Drawing.Point(15, 15); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 7; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66713F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66713F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66713F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.6662F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.6662F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.6662F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.Size = new System.Drawing.Size(395, 204); - this.tableLayoutPanel1.TabIndex = 14; - // - // ProxyNotificationLabel - // - this.ProxyNotificationLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ProxyNotificationLabel.AutoSize = true; - this.tableLayoutPanel1.SetColumnSpan(this.ProxyNotificationLabel, 4); - this.ProxyNotificationLabel.ForeColor = System.Drawing.Color.Red; - this.ProxyNotificationLabel.Location = new System.Drawing.Point(3, 92); - this.ProxyNotificationLabel.Name = "ProxyNotificationLabel"; - this.ProxyNotificationLabel.Size = new System.Drawing.Size(389, 12); - this.ProxyNotificationLabel.TabIndex = 5; - this.ProxyNotificationLabel.Text = "If server has a plugin, proxy will not be used"; - // - // flowLayoutPanel1 - // - this.flowLayoutPanel1.AutoSize = true; - this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.tableLayoutPanel1.SetColumnSpan(this.flowLayoutPanel1, 4); - this.flowLayoutPanel1.Controls.Add(this.MyCancelButton); - this.flowLayoutPanel1.Controls.Add(this.OKButton); - this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Right; - this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; - this.flowLayoutPanel1.Location = new System.Drawing.Point(233, 171); - this.flowLayoutPanel1.Name = "flowLayoutPanel1"; - this.flowLayoutPanel1.Size = new System.Drawing.Size(159, 30); - this.flowLayoutPanel1.TabIndex = 6; - // - // AuthUserLabel - // - this.AuthUserLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.AuthUserLabel.AutoSize = true; - this.AuthUserLabel.Location = new System.Drawing.Point(3, 148); - this.AuthUserLabel.Name = "AuthUserLabel"; - this.AuthUserLabel.Size = new System.Drawing.Size(65, 12); - this.AuthUserLabel.TabIndex = 7; - this.AuthUserLabel.Text = "User Name"; - // - // AuthPwdLabel - // - this.AuthPwdLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.AuthPwdLabel.AutoSize = true; - this.AuthPwdLabel.Location = new System.Drawing.Point(218, 148); - this.AuthPwdLabel.Name = "AuthPwdLabel"; - this.AuthPwdLabel.Size = new System.Drawing.Size(77, 12); - this.AuthPwdLabel.TabIndex = 8; - this.AuthPwdLabel.Text = "Password"; - // - // UseAuthCheckBox - // - this.UseAuthCheckBox.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.UseAuthCheckBox.AutoSize = true; - this.tableLayoutPanel1.SetColumnSpan(this.UseAuthCheckBox, 2); - this.UseAuthCheckBox.Location = new System.Drawing.Point(3, 118); - this.UseAuthCheckBox.Name = "UseAuthCheckBox"; - this.UseAuthCheckBox.Size = new System.Drawing.Size(72, 16); - this.UseAuthCheckBox.TabIndex = 9; - this.UseAuthCheckBox.Text = "Use Auth"; - this.UseAuthCheckBox.UseVisualStyleBackColor = true; - this.UseAuthCheckBox.CheckedChanged += new System.EventHandler(this.UseAuthCheckBox_CheckedChanged); - // - // AuthUserTextBox - // - this.AuthUserTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.AuthUserTextBox.Location = new System.Drawing.Point(74, 143); - this.AuthUserTextBox.Name = "AuthUserTextBox"; - this.AuthUserTextBox.Size = new System.Drawing.Size(138, 21); - this.AuthUserTextBox.TabIndex = 10; - // - // AuthPwdTextBox - // - this.AuthPwdTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.AuthPwdTextBox.Location = new System.Drawing.Point(301, 143); - this.AuthPwdTextBox.Name = "AuthPwdTextBox"; - this.AuthPwdTextBox.PasswordChar = '*'; - this.AuthPwdTextBox.Size = new System.Drawing.Size(91, 21); - this.AuthPwdTextBox.TabIndex = 11; - // - // ProxyForm - // - this.AcceptButton = this.OKButton; - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.AutoSize = true; - this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.CancelButton = this.MyCancelButton; - this.ClientSize = new System.Drawing.Size(448, 231); - this.Controls.Add(this.tableLayoutPanel1); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "ProxyForm"; - this.Padding = new System.Windows.Forms.Padding(12, 12, 12, 9); - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Edit Proxy"; - this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ProxyForm_FormClosed); - this.tableLayoutPanel1.ResumeLayout(false); - this.tableLayoutPanel1.PerformLayout(); - this.flowLayoutPanel1.ResumeLayout(false); - this.ResumeLayout(false); - - } - - #endregion - private System.Windows.Forms.CheckBox UseProxyCheckBox; - private System.Windows.Forms.Label ProxyAddrLabel; - private System.Windows.Forms.TextBox ProxyServerTextBox; - private System.Windows.Forms.Label ProxyPortLabel; - private System.Windows.Forms.TextBox ProxyPortTextBox; - private System.Windows.Forms.Button MyCancelButton; - private System.Windows.Forms.Button OKButton; - private System.Windows.Forms.Label ProxyTypeLabel; - private System.Windows.Forms.ComboBox ProxyTypeComboBox; - private System.Windows.Forms.TextBox ProxyTimeoutTextBox; - private System.Windows.Forms.Label ProxyTimeoutLabel; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; - private System.Windows.Forms.Label ProxyNotificationLabel; - private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; - private System.Windows.Forms.Label AuthUserLabel; - private System.Windows.Forms.Label AuthPwdLabel; - private System.Windows.Forms.CheckBox UseAuthCheckBox; - private System.Windows.Forms.TextBox AuthUserTextBox; - private System.Windows.Forms.TextBox AuthPwdTextBox; - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/View/ProxyForm.cs b/shadowsocks-csharp/View/ProxyForm.cs deleted file mode 100644 index 240c38e1..00000000 --- a/shadowsocks-csharp/View/ProxyForm.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using System.Drawing; -using System.Windows.Forms; -using Shadowsocks.Controller; -using Shadowsocks.Model; -using Shadowsocks.Properties; - -namespace Shadowsocks.View -{ - public partial class ProxyForm : Form - { - private ShadowsocksController controller; - - // this is a copy of configuration that we are working on - private ProxyConfig _modifiedProxyConfig; - - public ProxyForm(ShadowsocksController controller) - { - this.Font = System.Drawing.SystemFonts.MessageBoxFont; - InitializeComponent(); - - UpdateTexts(); - this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); - - this.controller = controller; - controller.ConfigChanged += controller_ConfigChanged; - - UpdateEnabled(); - LoadCurrentConfiguration(); - } - - private void UpdateTexts() - { - I18N.TranslateForm(this); - } - - private void controller_ConfigChanged(object sender, EventArgs e) - { - LoadCurrentConfiguration(); - } - - private void LoadCurrentConfiguration() - { - _modifiedProxyConfig = controller.GetCurrentConfiguration().proxy; - UseProxyCheckBox.Checked = _modifiedProxyConfig.useProxy; - ProxyServerTextBox.Text = _modifiedProxyConfig.proxyServer; - ProxyPortTextBox.Text = _modifiedProxyConfig.proxyPort.ToString(); - ProxyTimeoutTextBox.Text = _modifiedProxyConfig.proxyTimeout.ToString(); - ProxyTypeComboBox.SelectedIndex = _modifiedProxyConfig.proxyType; - UseAuthCheckBox.Checked = _modifiedProxyConfig.useAuth; - AuthUserTextBox.Text = _modifiedProxyConfig.authUser; - AuthPwdTextBox.Text = _modifiedProxyConfig.authPwd; - } - - private void OKButton_Click(object sender, EventArgs e) - { - _modifiedProxyConfig.useProxy = UseProxyCheckBox.Checked; - if (_modifiedProxyConfig.useProxy) - { - if (!int.TryParse(ProxyPortTextBox.Text, out _modifiedProxyConfig.proxyPort)) - { - MessageBox.Show(I18N.GetString("Illegal port number format")); - return; - } - - if (!int.TryParse(ProxyTimeoutTextBox.Text, out _modifiedProxyConfig.proxyTimeout)) - { - MessageBox.Show(I18N.GetString("Illegal timeout format")); - return; - } - - _modifiedProxyConfig.proxyType = ProxyTypeComboBox.SelectedIndex; - - try - { - Configuration.CheckServer(_modifiedProxyConfig.proxyServer = ProxyServerTextBox.Text); - Configuration.CheckPort(_modifiedProxyConfig.proxyPort); - Configuration.CheckTimeout(_modifiedProxyConfig.proxyTimeout, ProxyConfig.MaxProxyTimeoutSec); - - _modifiedProxyConfig.useAuth = UseAuthCheckBox.Checked; - if (_modifiedProxyConfig.useAuth) - { - Configuration.CheckProxyAuthUser(_modifiedProxyConfig.authUser = AuthUserTextBox.Text); - Configuration.CheckProxyAuthPwd(_modifiedProxyConfig.authPwd = AuthPwdTextBox.Text); - } - } - catch (Exception ex) - { - MessageBox.Show(ex.Message); - return; - } - } - - controller.SaveProxy(_modifiedProxyConfig); - - this.Close(); - } - - private void CancelButton_Click(object sender, EventArgs e) - { - this.Close(); - } - - private void ProxyForm_FormClosed(object sender, FormClosedEventArgs e) - { - controller.ConfigChanged -= controller_ConfigChanged; - } - - private void UseProxyCheckBox_CheckedChanged(object sender, EventArgs e) - { - UpdateEnabled(); - } - - private void UpdateEnabled() - { - if (UseProxyCheckBox.Checked) - { - ProxyServerTextBox.Enabled = - ProxyPortTextBox.Enabled = - ProxyTimeoutTextBox.Enabled = - ProxyTypeComboBox.Enabled = true; - - if (ProxyTypeComboBox.SelectedIndex == ProxyConfig.PROXY_HTTP) - { - UseAuthCheckBox.Enabled = true; - - if (UseAuthCheckBox.Checked) - { - AuthUserTextBox.Enabled = - AuthPwdTextBox.Enabled = true; - } - else - { - AuthUserTextBox.Enabled = - AuthPwdTextBox.Enabled = false; - } - } - else - { - // TODO support for SOCK5 auth - UseAuthCheckBox.Enabled = - AuthUserTextBox.Enabled = - AuthPwdTextBox.Enabled = false; - } - } - else - { - ProxyServerTextBox.Enabled = - ProxyPortTextBox.Enabled = - ProxyTimeoutTextBox.Enabled = - ProxyTypeComboBox.Enabled = - UseAuthCheckBox.Enabled = - AuthUserTextBox.Enabled = - AuthPwdTextBox.Enabled = false; - } - } - - private void ProxyTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) - { - // TODO support for SOCK5 auth - if (ProxyTypeComboBox.SelectedIndex != ProxyConfig.PROXY_HTTP) - { - UseAuthCheckBox.Checked = false; - AuthUserTextBox.Clear(); - AuthPwdTextBox.Clear(); - } - - UpdateEnabled(); - } - - private void UseAuthCheckBox_CheckedChanged(object sender, EventArgs e) - { - UpdateEnabled(); - } - } -} diff --git a/shadowsocks-csharp/ViewModels/ForwardProxyViewModel.cs b/shadowsocks-csharp/ViewModels/ForwardProxyViewModel.cs new file mode 100644 index 00000000..2d9e9bb0 --- /dev/null +++ b/shadowsocks-csharp/ViewModels/ForwardProxyViewModel.cs @@ -0,0 +1,125 @@ +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using ReactiveUI.Validation.Extensions; +using ReactiveUI.Validation.Helpers; +using Shadowsocks.Controller; +using Shadowsocks.Model; +using Shadowsocks.View; +using System.Linq; +using System.Reactive; +using System.Reactive.Linq; + +namespace Shadowsocks.ViewModels +{ + public class ForwardProxyViewModel : ReactiveValidationObject + { + public ForwardProxyViewModel() + { + _config = Program.MainController.GetCurrentConfiguration(); + _controller = Program.MainController; + _menuViewController = Program.MenuController; + + if (!_config.proxy.useProxy) + NoProxy = true; + else if (_config.proxy.proxyType == 0) + UseSocks5Proxy = true; + else + UseHttpProxy = true; + + Address = _config.proxy.proxyServer; + Port = _config.proxy.proxyPort; + Timeout = _config.proxy.proxyTimeout; + + Username = _config.proxy.authUser; + Password = _config.proxy.authPwd; + + AddressRule = this.ValidationRule( + viewModel => viewModel.Address, + address => !string.IsNullOrWhiteSpace(address), + "Address can't be empty or whitespaces."); + PortRule = this.ValidationRule( + viewModel => viewModel.Port, + port => port > 0 && port <= 65535, + port => $"{port} is out of range (0, 65535]."); + TimeoutRule = this.ValidationRule( + viewModel => viewModel.Timeout, + timeout => timeout > 0 && timeout <= 10, + timeout => $"{timeout} is out of range (0, 10]."); + + var authValid = this + .WhenAnyValue(x => x.Username, x => x.Password, (username, password) => new { Username = username, Password = password }) + .Select(x => string.IsNullOrWhiteSpace(x.Username) == string.IsNullOrWhiteSpace(x.Password)); + AuthRule = this.ValidationRule(authValid, "You must provide both username and password."); + + var canSave = this.IsValid(); + + Save = ReactiveCommand.Create(() => + { + _controller.SaveProxy(GetForwardProxyConfig()); + _menuViewController.CloseForwardProxyWindow(); + }, canSave); + Cancel = ReactiveCommand.Create(_menuViewController.CloseForwardProxyWindow); + } + + private readonly Configuration _config; + private readonly ShadowsocksController _controller; + private readonly MenuViewController _menuViewController; + + public ValidationHelper AddressRule { get; } + public ValidationHelper PortRule { get; } + public ValidationHelper TimeoutRule { get; } + public ValidationHelper AuthRule { get; } + + public ReactiveCommand Save { get; } + public ReactiveCommand Cancel { get; } + + [Reactive] + public bool NoProxy { get; set; } + + [Reactive] + public bool UseSocks5Proxy { get; set; } + + [Reactive] + public bool UseHttpProxy { get; set; } + + [Reactive] + public string Address { get; set; } + + [Reactive] + public int Port { get; set; } + + [Reactive] + public int Timeout { get; set; } + + [Reactive] + public string Username { get; set; } + + [Reactive] + public string Password { get; set; } + + private ForwardProxyConfig GetForwardProxyConfig() + { + var forwardProxyConfig = new ForwardProxyConfig() + { + proxyServer = Address, + proxyPort = Port, + proxyTimeout = Timeout, + authUser = Username, + authPwd = Password + }; + if (NoProxy) + forwardProxyConfig.useProxy = false; + else if (UseSocks5Proxy) + { + forwardProxyConfig.useProxy = true; + forwardProxyConfig.proxyType = 0; + } + else + { + forwardProxyConfig.useProxy = true; + forwardProxyConfig.proxyType = 1; + } + return forwardProxyConfig; + } + } +} diff --git a/shadowsocks-csharp/ViewModels/HotkeysViewModel.cs b/shadowsocks-csharp/ViewModels/HotkeysViewModel.cs new file mode 100644 index 00000000..141d2cf9 --- /dev/null +++ b/shadowsocks-csharp/ViewModels/HotkeysViewModel.cs @@ -0,0 +1,189 @@ +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using Shadowsocks.Controller; +using Shadowsocks.Model; +using Shadowsocks.View; +using System.Reactive; +using System.Text; +using System.Windows.Input; + +namespace Shadowsocks.ViewModels +{ + public class HotkeysViewModel : ReactiveObject + { + public HotkeysViewModel() + { + _config = Program.MainController.GetCurrentConfiguration(); + _controller = Program.MainController; + _menuViewController = Program.MenuController; + + HotkeySystemProxy = _config.hotkey.SwitchSystemProxy; + HotkeyProxyMode = _config.hotkey.SwitchSystemProxyMode; + HotkeyAllowLan = _config.hotkey.SwitchAllowLan; + HotkeyOpenLogs = _config.hotkey.ShowLogs; + HotkeySwitchPrev = _config.hotkey.ServerMoveUp; + HotkeySwitchNext = _config.hotkey.ServerMoveDown; + RegisterAtStartup = _config.hotkey.RegHotkeysAtStartup; + + HotkeySystemProxyStatus = "✔"; + HotkeyProxyModeStatus = "✔"; + HotkeyAllowLanStatus = "✔"; + HotkeyOpenLogsStatus = "✔"; + HotkeySwitchPrevStatus = "✔"; + HotkeySwitchNextStatus = "✔"; + + RegisterAll = ReactiveCommand.Create(() => RegisterAllAndUpdateStatus()); + Save = ReactiveCommand.Create(() => RegisterAllAndUpdateStatus(true)); + Cancel = ReactiveCommand.Create(_menuViewController.CloseHotkeysWindow); + } + + private readonly Configuration _config; + private readonly ShadowsocksController _controller; + private readonly MenuViewController _menuViewController; + + public ReactiveCommand RegisterAll { get; } + public ReactiveCommand Save { get; } + public ReactiveCommand Cancel { get; } + + [Reactive] + public string HotkeySystemProxy { get; set; } + + [Reactive] + public string HotkeyProxyMode { get; set; } + + [Reactive] + public string HotkeyAllowLan { get; set; } + + [Reactive] + public string HotkeyOpenLogs { get; set; } + + [Reactive] + public string HotkeySwitchPrev { get; set; } + + [Reactive] + public string HotkeySwitchNext { get; set; } + + [Reactive] + public bool RegisterAtStartup { get; set; } + + [Reactive] + public string HotkeySystemProxyStatus { get; set; } + + [Reactive] + public string HotkeyProxyModeStatus { get; set; } + + [Reactive] + public string HotkeyAllowLanStatus { get; set; } + + [Reactive] + public string HotkeyOpenLogsStatus { get; set; } + + [Reactive] + public string HotkeySwitchPrevStatus { get; set; } + + [Reactive] + public string HotkeySwitchNextStatus { get; set; } + + public void RecordKeyDown(int hotkeyIndex, KeyEventArgs keyEventArgs) + { + var recordedKeyStringBuilder = new StringBuilder(); + + // record modifiers + if ((Keyboard.Modifiers & ModifierKeys.Control) > 0) + recordedKeyStringBuilder.Append("Ctrl+"); + if ((Keyboard.Modifiers & ModifierKeys.Alt) > 0) + recordedKeyStringBuilder.Append("Alt+"); + if ((Keyboard.Modifiers & ModifierKeys.Shift) > 0) + recordedKeyStringBuilder.Append("Shift+"); + + // record other keys when at least one modifier is pressed + if (recordedKeyStringBuilder.Length > 0 && (keyEventArgs.Key < Key.LeftShift || keyEventArgs.Key > Key.RightAlt)) + recordedKeyStringBuilder.Append(keyEventArgs.Key); + + switch (hotkeyIndex) + { + case 0: + HotkeySystemProxy = recordedKeyStringBuilder.ToString(); + break; + case 1: + HotkeyProxyMode = recordedKeyStringBuilder.ToString(); + break; + case 2: + HotkeyAllowLan = recordedKeyStringBuilder.ToString(); + break; + case 3: + HotkeyOpenLogs = recordedKeyStringBuilder.ToString(); + break; + case 4: + HotkeySwitchPrev = recordedKeyStringBuilder.ToString(); + break; + case 5: + HotkeySwitchNext = recordedKeyStringBuilder.ToString(); + break; + } + } + + public void FinishOnKeyUp(int hotkeyIndex, KeyEventArgs keyEventArgs) + { + switch (hotkeyIndex) + { + case 0: + if (HotkeySystemProxy.EndsWith("+")) + HotkeySystemProxy = ""; + break; + case 1: + if (HotkeyProxyMode.EndsWith("+")) + HotkeyProxyMode = ""; + break; + case 2: + if (HotkeyAllowLan.EndsWith("+")) + HotkeyAllowLan = ""; + break; + case 3: + if (HotkeyOpenLogs.EndsWith("+")) + HotkeyOpenLogs = ""; + break; + case 4: + if (HotkeySwitchPrev.EndsWith("+")) + HotkeySwitchPrev = ""; + break; + case 5: + if (HotkeySwitchNext.EndsWith("+")) + HotkeySwitchNext = ""; + break; + } + } + + private void RegisterAllAndUpdateStatus(bool save = false) + { + HotkeySystemProxyStatus = HotkeyReg.RegHotkeyFromString(HotkeySystemProxy, "SwitchSystemProxyCallback") ? "✔" : "❌"; + HotkeyProxyModeStatus = HotkeyReg.RegHotkeyFromString(HotkeyProxyMode, "SwitchSystemProxyModeCallback") ? "✔" : "❌"; + HotkeyAllowLanStatus = HotkeyReg.RegHotkeyFromString(HotkeyAllowLan, "SwitchAllowLanCallback") ? "✔" : "❌"; + HotkeyOpenLogsStatus = HotkeyReg.RegHotkeyFromString(HotkeyOpenLogs, "ShowLogsCallback") ? "✔" : "❌"; + HotkeySwitchPrevStatus = HotkeyReg.RegHotkeyFromString(HotkeySwitchPrev, "ServerMoveUpCallback") ? "✔" : "❌"; + HotkeySwitchNextStatus = HotkeyReg.RegHotkeyFromString(HotkeySwitchNext, "ServerMoveDownCallback") ? "✔" : "❌"; + + if (HotkeySystemProxyStatus == "✔" && + HotkeyProxyModeStatus == "✔" && + HotkeyAllowLanStatus == "✔" && + HotkeyOpenLogsStatus == "✔" && + HotkeySwitchPrevStatus == "✔" && + HotkeySwitchNextStatus == "✔" && save) + { + _controller.SaveHotkeyConfig(GetHotkeyConfig); + _menuViewController.CloseHotkeysWindow(); + } + } + + private HotkeyConfig GetHotkeyConfig => new HotkeyConfig() + { + SwitchSystemProxy = HotkeySystemProxy, + SwitchSystemProxyMode = HotkeyProxyMode, + SwitchAllowLan = HotkeyAllowLan, + ShowLogs = HotkeyOpenLogs, + ServerMoveUp = HotkeySwitchPrev, + ServerMoveDown = HotkeySwitchNext, + RegHotkeysAtStartup = RegisterAtStartup + }; + } +} diff --git a/shadowsocks-csharp/ViewModels/OnlineConfigViewModel.cs b/shadowsocks-csharp/ViewModels/OnlineConfigViewModel.cs new file mode 100644 index 00000000..f803b351 --- /dev/null +++ b/shadowsocks-csharp/ViewModels/OnlineConfigViewModel.cs @@ -0,0 +1,115 @@ +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using ReactiveUI.Validation.Extensions; +using ReactiveUI.Validation.Helpers; +using Shadowsocks.Controller; +using Shadowsocks.Localization; +using Shadowsocks.Model; +using Shadowsocks.View; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reactive; +using System.Reactive.Linq; +using System.Text; +using System.Windows; + +namespace Shadowsocks.ViewModels +{ + public class OnlineConfigViewModel : ReactiveValidationObject + { + public OnlineConfigViewModel() + { + _config = Program.MainController.GetCurrentConfiguration(); + _controller = Program.MainController; + _menuViewController = Program.MenuController; + + Sources = new ObservableCollection(_config.onlineConfigSource); + SelectedSource = ""; + Address = ""; + + // TODO in v5: if http:// show warning as materialDesign:HintAssist.HelperText + AddressRule = this.ValidationRule( + viewModel => viewModel.Address, + address => address.StartsWith("http://"), + "Warning: getting online configuration from plain HTTP sources is NOT secure!"); + + var canUpdateCopyRemove = this.WhenAnyValue( + x => x.SelectedSource, + selectedSource => !string.IsNullOrWhiteSpace(selectedSource)); + var canUpdateAll = this.WhenAnyValue( + x => x.Sources.Count, + count => count > 0); + var canAdd = this.WhenAnyValue( + x => x.Address, + address => Uri.IsWellFormedUriString(address, UriKind.Absolute) && + (address.StartsWith("https://") || address.StartsWith("http://"))); + + Update = ReactiveCommand.CreateFromTask(() => _controller.UpdateOnlineConfig(SelectedSource), canUpdateCopyRemove); + UpdateAll = ReactiveCommand.CreateFromTask(_controller.UpdateAllOnlineConfig, canUpdateAll); + CopyLink = ReactiveCommand.Create(() => Clipboard.SetText(SelectedSource), canUpdateCopyRemove); + Remove = ReactiveCommand.Create(() => + { + bool result; + var urlToRemove = SelectedSource; // save it here because SelectedSource is lost once we remove the selection + do + { + result = Sources.Remove(urlToRemove); + } while (result); + _controller.RemoveOnlineConfig(urlToRemove); + }, canUpdateCopyRemove); + Add = ReactiveCommand.Create(() => + { + Sources.Add(Address); + SelectedSource = Address; + _controller.SaveOnlineConfigSource(Sources.ToList()); + Address = ""; + }, canAdd); + + // TODO in v5: use MaterialDesignThemes snackbar messages + this.WhenAnyObservable(x => x.Update) + .Subscribe(x => + { + if (x) + MessageBox.Show(LocalizationProvider.GetLocalizedValue("sip008UpdateSuccess")); + else + MessageBox.Show(LocalizationProvider.GetLocalizedValue("sip008UpdateFailure")); + }); + this.WhenAnyObservable(x => x.UpdateAll) + .Subscribe(x => + { + if (x.Count == 0) + MessageBox.Show(LocalizationProvider.GetLocalizedValue("sip008UpdateAllSuccess")); + else + { + var stringBuilder = new StringBuilder(LocalizationProvider.GetLocalizedValue("sip008UpdateAllFailure")); + foreach (var url in x) + stringBuilder.AppendLine(url); + MessageBox.Show(stringBuilder.ToString()); + } + }); + } + + private readonly Configuration _config; + private readonly ShadowsocksController _controller; + private readonly MenuViewController _menuViewController; + + public ValidationHelper AddressRule { get; } + + public ReactiveCommand Update { get; } + public ReactiveCommand> UpdateAll { get; } + public ReactiveCommand CopyLink { get; } + public ReactiveCommand Remove { get; } + public ReactiveCommand Add { get; } + + [Reactive] + public ObservableCollection Sources { get; private set; } + + [Reactive] + public string SelectedSource { get; set; } + + [Reactive] + public string Address { get; set; } + } +} diff --git a/shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs b/shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs index 1ed4d785..f1375690 100644 --- a/shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs +++ b/shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs @@ -1,10 +1,13 @@ using ReactiveUI; +using ReactiveUI.Fody.Helpers; using Shadowsocks.Model; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; +using System.Reactive; +using System.Windows; using System.Windows.Media.Imaging; namespace Shadowsocks.ViewModels @@ -17,18 +20,30 @@ namespace Shadowsocks.ViewModels public ServerSharingViewModel() { _config = Program.MainController.GetCurrentConfiguration(); - _servers = _config.configs; - _selectedServer = _servers.First(); - //_selectedServerUrlImage = new BitmapImage(); - UpdateUrlAndImage(); + Servers = _config.configs; + SelectedServer = Servers[0]; + + this.WhenAnyValue(x => x.SelectedServer) + .Subscribe(_ => UpdateUrlAndImage()); + + CopyLink = ReactiveCommand.Create(() => Clipboard.SetText(SelectedServerUrl)); } private readonly Configuration _config; - private List _servers; - private Server _selectedServer; - private string _selectedServerUrl; - private BitmapImage _selectedServerUrlImage; + public ReactiveCommand CopyLink { get; } + + [Reactive] + public List Servers { get; private set; } + + [Reactive] + public Server SelectedServer { get; set; } + + [Reactive] + public string SelectedServerUrl { get; private set; } + + [Reactive] + public BitmapImage SelectedServerUrlImage { get; private set; } /// /// Called when SelectedServer changed @@ -37,10 +52,10 @@ namespace Shadowsocks.ViewModels private void UpdateUrlAndImage() { // update SelectedServerUrl - SelectedServerUrl = _selectedServer.GetURL(_config.generateLegacyUrl); + SelectedServerUrl = SelectedServer.GetURL(_config.generateLegacyUrl); // generate QR code - var qrCode = ZXing.QrCode.Internal.Encoder.encode(_selectedServerUrl, ZXing.QrCode.Internal.ErrorCorrectionLevel.L); + var qrCode = ZXing.QrCode.Internal.Encoder.encode(SelectedServerUrl, ZXing.QrCode.Internal.ErrorCorrectionLevel.L); var byteMatrix = qrCode.Matrix; // paint bitmap @@ -77,33 +92,5 @@ namespace Shadowsocks.ViewModels } SelectedServerUrlImage = bitmapImage; } - - public List Servers - { - get => _servers; - set => this.RaiseAndSetIfChanged(ref _servers, value); - } - - public Server SelectedServer - { - get => _selectedServer; - set - { - this.RaiseAndSetIfChanged(ref _selectedServer, value); - UpdateUrlAndImage(); - } - } - - public string SelectedServerUrl - { - get => _selectedServerUrl; - set => this.RaiseAndSetIfChanged(ref _selectedServerUrl, value); - } - - public BitmapImage SelectedServerUrlImage - { - get => _selectedServerUrlImage; - set => this.RaiseAndSetIfChanged(ref _selectedServerUrlImage, value); - } } } diff --git a/shadowsocks-csharp/ViewModels/VersionUpdatePromptViewModel.cs b/shadowsocks-csharp/ViewModels/VersionUpdatePromptViewModel.cs new file mode 100644 index 00000000..0ae9f2d1 --- /dev/null +++ b/shadowsocks-csharp/ViewModels/VersionUpdatePromptViewModel.cs @@ -0,0 +1,34 @@ +using Newtonsoft.Json.Linq; +using ReactiveUI; +using Shadowsocks.Controller; +using System.Reactive; + +namespace Shadowsocks.ViewModels +{ + public class VersionUpdatePromptViewModel : ReactiveObject + { + public VersionUpdatePromptViewModel(JToken releaseObject) + { + _updateChecker = Program.MenuController.updateChecker; + _releaseObject = releaseObject; + ReleaseNotes = string.Concat( + $"# {((bool)_releaseObject["prerelease"] ? "⚠ Pre-release" : "ℹ Release")} {(string)_releaseObject["tag_name"] ?? "Failed to get tag name"}\r\n", + (string)_releaseObject["body"] ?? "Failed to get release notes"); + + Update = ReactiveCommand.CreateFromTask(_updateChecker.DoUpdate); + SkipVersion = ReactiveCommand.Create(_updateChecker.SkipUpdate); + NotNow = ReactiveCommand.Create(_updateChecker.CloseVersionUpdatePromptWindow); + } + + private readonly UpdateChecker _updateChecker; + private readonly JToken _releaseObject; + + public string ReleaseNotes { get; } + + public ReactiveCommand Update { get; } + + public ReactiveCommand SkipVersion { get; } + + public ReactiveCommand NotNow { get; } + } +} diff --git a/shadowsocks-csharp/Views/ForwardProxyView.xaml b/shadowsocks-csharp/Views/ForwardProxyView.xaml new file mode 100644 index 00000000..0c6a9319 --- /dev/null +++ b/shadowsocks-csharp/Views/ForwardProxyView.xaml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +