Browse Source

🎂 ForwardProxyView + HotkeysView + OnlineConfigView + VersionUpdatePromptView

- Infrastructure: use one HttpClient instance throughout the lifecycle
- Version update: rewrite the update service and add update prompt window
- Server sharing: add copy link button
- Dependencies: add ReactiveUI.Events.WPF, ReactiveUI.Fody, ReactiveUI.Validation, WPFLocalizeExtension, MdXaml
tags/4.3.0.0
database64128 3 years ago
parent
commit
d37600231f
No known key found for this signature in database GPG Key ID: 1CA27546BEDB8B01
47 changed files with 3391 additions and 2322 deletions
  1. +2
    -32
      shadowsocks-csharp/Controller/Service/GeositeUpdater.cs
  2. +2
    -15
      shadowsocks-csharp/Controller/Service/OnlineConfigResolver.cs
  3. +3
    -3
      shadowsocks-csharp/Controller/Service/TCPRelay.cs
  4. +116
    -196
      shadowsocks-csharp/Controller/Service/UpdateChecker.cs
  5. +34
    -10
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  6. +0
    -34
      shadowsocks-csharp/Data/i18n.csv
  7. +1
    -0
      shadowsocks-csharp/FodyWeavers.xml
  8. +1
    -0
      shadowsocks-csharp/FodyWeavers.xsd
  9. +13
    -0
      shadowsocks-csharp/Localization/LocalizationProvider.cs
  10. +432
    -0
      shadowsocks-csharp/Localization/Strings.Designer.cs
  11. +182
    -119
      shadowsocks-csharp/Localization/Strings.fr.resx
  12. +179
    -182
      shadowsocks-csharp/Localization/Strings.ja.resx
  13. +60
    -0
      shadowsocks-csharp/Localization/Strings.ko.resx
  14. +243
    -0
      shadowsocks-csharp/Localization/Strings.resx
  15. +183
    -0
      shadowsocks-csharp/Localization/Strings.ru.resx
  16. +237
    -0
      shadowsocks-csharp/Localization/Strings.zh-Hans.resx
  17. +189
    -0
      shadowsocks-csharp/Localization/Strings.zh-Hant.resx
  18. +13
    -15
      shadowsocks-csharp/Model/Configuration.cs
  19. +43
    -43
      shadowsocks-csharp/Model/ForwardProxyConfig.cs
  20. +7
    -0
      shadowsocks-csharp/Program.cs
  21. +59
    -56
      shadowsocks-csharp/Properties/Resources.Designer.cs
  22. +0
    -190
      shadowsocks-csharp/View/HotkeySettingsForm.cs
  23. +0
    -346
      shadowsocks-csharp/View/HotkeySettingsForm.designer.cs
  24. +85
    -103
      shadowsocks-csharp/View/MenuViewController.cs
  25. +0
    -218
      shadowsocks-csharp/View/OnlineConfigForm.Designer.cs
  26. +0
    -153
      shadowsocks-csharp/View/OnlineConfigForm.cs
  27. +0
    -333
      shadowsocks-csharp/View/ProxyForm.Designer.cs
  28. +0
    -176
      shadowsocks-csharp/View/ProxyForm.cs
  29. +125
    -0
      shadowsocks-csharp/ViewModels/ForwardProxyViewModel.cs
  30. +189
    -0
      shadowsocks-csharp/ViewModels/HotkeysViewModel.cs
  31. +115
    -0
      shadowsocks-csharp/ViewModels/OnlineConfigViewModel.cs
  32. +25
    -38
      shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs
  33. +34
    -0
      shadowsocks-csharp/ViewModels/VersionUpdatePromptViewModel.cs
  34. +100
    -0
      shadowsocks-csharp/Views/ForwardProxyView.xaml
  35. +72
    -0
      shadowsocks-csharp/Views/ForwardProxyView.xaml.cs
  36. +115
    -0
      shadowsocks-csharp/Views/HotkeysView.xaml
  37. +169
    -0
      shadowsocks-csharp/Views/HotkeysView.xaml.cs
  38. +61
    -0
      shadowsocks-csharp/Views/OnlineConfigView.xaml
  39. +54
    -0
      shadowsocks-csharp/Views/OnlineConfigView.xaml.cs
  40. +38
    -21
      shadowsocks-csharp/Views/ServerSharingView.xaml
  41. +28
    -4
      shadowsocks-csharp/Views/ServerSharingView.xaml.cs
  42. +43
    -0
      shadowsocks-csharp/Views/VersionUpdatePromptView.xaml
  43. +40
    -0
      shadowsocks-csharp/Views/VersionUpdatePromptView.xaml.cs
  44. +4
    -0
      shadowsocks-csharp/app.config
  45. +10
    -2
      shadowsocks-csharp/packages.config
  46. +81
    -33
      shadowsocks-csharp/shadowsocks-csharp.csproj
  47. +4
    -0
      test/app.config

+ 2
- 32
shadowsocks-csharp/Controller/Service/GeositeUpdater.cs View File

@@ -35,8 +35,6 @@ namespace Shadowsocks.Controller


private static readonly string DATABASE_PATH = Utils.GetTempPath("dlc.dat"); 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_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 readonly string GEOSITE_SHA256SUM_URL = "https://github.com/v2fly/domain-list-community/raw/release/dlc.dat.sha256sum";
private static byte[] geositeDB; private static byte[] geositeDB;
@@ -82,7 +80,8 @@ namespace Shadowsocks.Controller
SHA256 mySHA256 = SHA256.Create(); SHA256 mySHA256 = SHA256.Create();
var config = Program.MainController.GetCurrentConfiguration(); var config = Program.MainController.GetCurrentConfiguration();
bool blacklist = config.geositePreferDirect; bool blacklist = config.geositePreferDirect;
var httpClient = Program.MainController.GetHttpClient();

if (!string.IsNullOrWhiteSpace(config.geositeUrl)) if (!string.IsNullOrWhiteSpace(config.geositeUrl))
{ {
logger.Info("Found custom Geosite URL in config file"); logger.Info("Found custom Geosite URL in config file");
@@ -90,22 +89,6 @@ namespace Shadowsocks.Controller
} }
logger.Info($"Checking Geosite from {geositeUrl}"); 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 try
{ {
// download checksum first // download checksum first
@@ -154,19 +137,6 @@ namespace Shadowsocks.Controller
{ {
Error?.Invoke(null, new ErrorEventArgs(ex)); Error?.Invoke(null, new ErrorEventArgs(ex));
} }
finally
{
if (httpClientHandler != null)
{
httpClientHandler.Dispose();
httpClientHandler = null;
}
if (httpClient != null)
{
httpClient.Dispose();
httpClient = null;
}
}
} }


/// <summary> /// <summary>


+ 2
- 15
shadowsocks-csharp/Controller/Service/OnlineConfigResolver.cs View File

@@ -11,28 +11,15 @@ namespace Shadowsocks.Controller.Service
{ {
public class OnlineConfigResolver public class OnlineConfigResolver
{ {
public static async Task<List<Server>> GetOnline(string url, string userAgentString, IWebProxy proxy = null)
public static async Task<List<Server>> 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); string server_json = await httpClient.GetStringAsync(url);

var servers = server_json.GetServers(); var servers = server_json.GetServers();

foreach (var server in servers) foreach (var server in servers)
{ {
server.group = url; server.group = url;
} }

return servers.ToList(); return servers.ToList();
} }
} }


+ 3
- 3
shadowsocks-csharp/Controller/Service/TCPRelay.cs View File

@@ -191,7 +191,7 @@ namespace Shadowsocks.Controller
public DateTime lastActivity; public DateTime lastActivity;
private readonly ShadowsocksController _controller; private readonly ShadowsocksController _controller;
private readonly ProxyConfig _config;
private readonly ForwardProxyConfig _config;
private readonly Socket _connection; private readonly Socket _connection;
private IEncryptor _encryptor; private IEncryptor _encryptor;
@@ -665,10 +665,10 @@ namespace Shadowsocks.Controller
{ {
switch (_config.proxyType) switch (_config.proxyType)
{ {
case ProxyConfig.PROXY_SOCKS5:
case ForwardProxyConfig.PROXY_SOCKS5:
remote = new Socks5Proxy(); remote = new Socks5Proxy();
break; break;
case ProxyConfig.PROXY_HTTP:
case ForwardProxyConfig.PROXY_HTTP:
remote = new HttpProxy(); remote = new HttpProxy();
break; break;
default: default:


+ 116
- 196
shadowsocks-csharp/Controller/Service/UpdateChecker.cs View File

@@ -1,254 +1,174 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net; using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using NLog; using NLog;
using Shadowsocks.Localization;
using Shadowsocks.Model; using Shadowsocks.Model;
using Shadowsocks.Util; using Shadowsocks.Util;
using Shadowsocks.Views;
namespace Shadowsocks.Controller namespace Shadowsocks.Controller
{ {
public class UpdateChecker 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 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)
/// <summary>
/// Checks for updates and asks the user if updates are found.
/// </summary>
/// <param name="millisecondsDelay">A delay in milliseconds before checking.</param>
/// <returns></returns>
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 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<Asset> asserts = new List<Asset>();
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()
/// <summary>
/// Opens a window to show the update's information.
/// </summary>
/// <param name="releaseObject">The update release object.</param>
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<string>("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;
}
/// <summary>
/// Downloads the selected update and notifies the user.
/// </summary>
/// <returns></returns>
public async Task DoUpdate()
{ {
try 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()
/// <summary>
/// Saves the skipped update version.
/// </summary>
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<Asset> asserts)
/// <summary>
/// Closes the update prompt window.
/// </summary>
public void CloseVersionUpdatePromptWindow()
{ {
asserts.Sort();
}
public class Asset : IComparable<Asset>
{
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-(?<version>\d+(?:\.\d+)*)(?:|-(?<suffix>.+))\.\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;
} }
} }
} }


+ 34
- 10
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Http;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@@ -20,7 +21,8 @@ namespace Shadowsocks.Controller
{ {
public class ShadowsocksController public class ShadowsocksController
{ {
private static Logger logger = LogManager.GetCurrentClassLogger();
private readonly Logger logger;
private readonly HttpClient httpClient;
// controller: // controller:
// handle user actions // handle user actions
@@ -91,6 +93,8 @@ namespace Shadowsocks.Controller
public ShadowsocksController() public ShadowsocksController()
{ {
logger = LogManager.GetCurrentClassLogger();
httpClient = new HttpClient();
_config = Configuration.Load(); _config = Configuration.Load();
Configuration.Process(ref _config); Configuration.Process(ref _config);
StatisticsConfiguration = StatisticsStrategyConfiguration.Load(); StatisticsConfiguration = StatisticsStrategyConfiguration.Load();
@@ -168,6 +172,19 @@ namespace Shadowsocks.Controller
NLogConfig.LoadConfiguration(); 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(); StatisticsConfiguration = StatisticsStrategyConfiguration.Load();
privoxyRunner = privoxyRunner ?? new PrivoxyRunner(); privoxyRunner = privoxyRunner ?? new PrivoxyRunner();
@@ -250,6 +267,7 @@ namespace Shadowsocks.Controller
Errored?.Invoke(this, new ErrorEventArgs(e)); Errored?.Invoke(this, new ErrorEventArgs(e));
} }
public HttpClient GetHttpClient() => httpClient;
public Server GetCurrentServer() => _config.GetCurrentServer(); public Server GetCurrentServer() => _config.GetCurrentServer();
public Configuration GetCurrentConfiguration() => _config; public Configuration GetCurrentConfiguration() => _config;
@@ -310,7 +328,7 @@ namespace Shadowsocks.Controller
EnableGlobalChanged?.Invoke(this, new EventArgs()); EnableGlobalChanged?.Invoke(this, new EventArgs());
} }
public void SaveProxy(ProxyConfig proxyConfig)
public void SaveProxy(ForwardProxyConfig proxyConfig)
{ {
_config.proxy = proxyConfig; _config.proxy = proxyConfig;
SaveConfig(_config); SaveConfig(_config);
@@ -478,6 +496,12 @@ namespace Shadowsocks.Controller
ConfigChanged?.Invoke(this, new EventArgs()); ConfigChanged?.Invoke(this, new EventArgs());
} }
public void SaveSkippedUpdateVerion(string version)
{
_config.skippedUpdateVersion = version;
Configuration.Save(_config);
}
public void SaveLogViewerConfig(LogViewerConfig newConfig) public void SaveLogViewerConfig(LogViewerConfig newConfig)
{ {
_config.logViewer = newConfig; _config.logViewer = newConfig;
@@ -497,7 +521,7 @@ namespace Shadowsocks.Controller
#endregion #endregion
#region Statistic
#region Statistics
public void SelectStrategy(string strategyID) public void SelectStrategy(string strategyID)
{ {
@@ -672,7 +696,7 @@ namespace Shadowsocks.Controller
public async Task<int> UpdateOnlineConfigInternal(string url) public async Task<int> 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 = Configuration.SortByOnlineConfig(
_config.configs _config.configs
.Where(c => c.group != url) .Where(c => c.group != url)
@@ -699,10 +723,10 @@ namespace Shadowsocks.Controller
return true; return true;
} }
public async Task<int> UpdateAllOnlineConfig()
public async Task<List<string>> UpdateAllOnlineConfig()
{ {
var selected = GetCurrentServer(); var selected = GetCurrentServer();
int failCount = 0;
var failedUrls = new List<string>();
foreach (var url in _config.onlineConfigSource) foreach (var url in _config.onlineConfigSource)
{ {
try try
@@ -712,18 +736,18 @@ namespace Shadowsocks.Controller
catch (Exception e) catch (Exception e)
{ {
logger.LogUsefulException(e); logger.LogUsefulException(e);
failCount++;
failedUrls.Add(url);
} }
} }
_config.index = _config.configs.IndexOf(selected); _config.index = _config.configs.IndexOf(selected);
SaveConfig(_config); SaveConfig(_config);
return failCount;
return failedUrls;
} }
public void SaveOnlineConfigSource(IEnumerable<string> vs)
public void SaveOnlineConfigSource(List<string> sources)
{ {
_config.onlineConfigSource = vs.ToList();
_config.onlineConfigSource = sources;
SaveConfig(_config); SaveConfig(_config);
} }


+ 0
- 34
shadowsocks-csharp/Data/i18n.csv View File

@@ -81,13 +81,6 @@ Move D&own,Ниже,下移(&O),下移 (&O),下に移動 (&O),아래로 (&O),Desc
deprecated,Устаревшее,不推荐,不推薦,非推奨,더 이상 사용되지 않음,Obsolète 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}" "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,,,,,, #Statistics Config,,,,,,
,,,,,, ,,,,,,
Enable Statistics,Включить сбор статистики,启用统计,,統計を有効にする,통계 활성화,Activer statistiques Enable Statistics,Включить сбор статистики,启用统计,,統計を有効にする,통계 활성화,Activer statistiques
@@ -118,18 +111,6 @@ Chart Mode,График,图表模式,,図表モード,차트 모드,Mode graphiq
24h,24ч,24小时,,24時間,24시간,24h 24h,24ч,24小时,,24時間,24시간,24h
all,За все время,全部,,すべて,전체,tout 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,,,,,, # Log Form,,,,,,
,,,,,, ,,,,,,
&File,Файл,文件(&F),檔案 (&F),ファイル (&F),파일 (&F),Fichier &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 ... 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 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,,,,,, # Messages,,,,,,
,,,,,, ,,,,,,
Shadowsocks Error: {0},Ошибка Shadowsocks: {0},Shadowsocks 错误: {0},Shadowsocks 錯誤: {0},Shadowsocks エラー: {0},Shadowsocks 오류: {0},Erreur shadowsocks: {0} 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 Password can not be blank,Пароль не может быть пустым,密码不能为空,密碼不能為空,パスワードが指定されていません。,비밀번호는 비어있으면 안됩니다.,Le mot de passe ne peut pas être vide
Port out of range,Порт выходит за допустимый диапазон,端口超出范围,連接埠號碼超出範圍,ポート番号は範囲外です。,올바른 포트 범위가 아닙니다.,Port hors de portée 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 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 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 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 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é 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? "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" "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

+ 1
- 0
shadowsocks-csharp/FodyWeavers.xml View File

@@ -2,4 +2,5 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Caseless StringComparison="Ordinal" /> <Caseless StringComparison="Ordinal" />
<Costura /> <Costura />
<ReactiveUI />
</Weavers> </Weavers>

+ 1
- 0
shadowsocks-csharp/FodyWeavers.xsd View File

@@ -4,6 +4,7 @@
<xs:element name="Weavers"> <xs:element name="Weavers">
<xs:complexType> <xs:complexType>
<xs:all> <xs:all>
<xs:element name="ReactiveUI" minOccurs="0" maxOccurs="1" type="xs:anyType" />
<xs:element name="Costura" minOccurs="0" maxOccurs="1"> <xs:element name="Costura" minOccurs="0" maxOccurs="1">
<xs:complexType> <xs:complexType>
<xs:all> <xs:all>


+ 13
- 0
shadowsocks-csharp/Localization/LocalizationProvider.cs View File

@@ -0,0 +1,13 @@
using System.Reflection;
using WPFLocalizeExtension.Extensions;

namespace Shadowsocks.Localization
{
public static class LocalizationProvider
{
public static T GetLocalizedValue<T>(string key)
{
return LocExtension.GetLocalizedValue<T>(Assembly.GetCallingAssembly().GetName().Name + ":Strings:" + key);
}
}
}

+ 432
- 0
shadowsocks-csharp/Localization/Strings.Designer.cs View File

@@ -0,0 +1,432 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Shadowsocks.Localization {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[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;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to _Add.
/// </summary>
internal static string addButton_Content {
get {
return ResourceManager.GetString("addButton_Content", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Address.
/// </summary>
internal static string Address {
get {
return ResourceManager.GetString("Address", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Allow clients from LAN.
/// </summary>
internal static string AllowClientsFromLAN {
get {
return ResourceManager.GetString("AllowClientsFromLAN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Cancel.
/// </summary>
internal static string cancelButton_Content {
get {
return ResourceManager.GetString("cancelButton_Content", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Copy.
/// </summary>
internal static string Copy {
get {
return ResourceManager.GetString("Copy", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Copy link.
/// </summary>
internal static string copyLinkButton_Content {
get {
return ResourceManager.GetString("copyLinkButton_Content", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Credentials (optional).
/// </summary>
internal static string CredentialsOptional {
get {
return ResourceManager.GetString("CredentialsOptional", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Details.
/// </summary>
internal static string Details {
get {
return ResourceManager.GetString("Details", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Forward Proxy.
/// </summary>
internal static string ForwardProxy {
get {
return ResourceManager.GetString("ForwardProxy", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Hotkeys.
/// </summary>
internal static string Hotkeys {
get {
return ResourceManager.GetString("Hotkeys", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to HTTP.
/// </summary>
internal static string HTTP {
get {
return ResourceManager.GetString("HTTP", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No proxy.
/// </summary>
internal static string NoProxy {
get {
return ResourceManager.GetString("NoProxy", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Not now.
/// </summary>
internal static string notNowButton_Content {
get {
return ResourceManager.GetString("notNowButton_Content", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _OK.
/// </summary>
internal static string okButton_Content {
get {
return ResourceManager.GetString("okButton_Content", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Online Configuration Delivery.
/// </summary>
internal static string OnlineConfigDelivery {
get {
return ResourceManager.GetString("OnlineConfigDelivery", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Open logs window.
/// </summary>
internal static string OpenLogsWindow {
get {
return ResourceManager.GetString("OpenLogsWindow", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Password.
/// </summary>
internal static string Password {
get {
return ResourceManager.GetString("Password", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Port.
/// </summary>
internal static string Port {
get {
return ResourceManager.GetString("Port", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Register all.
/// </summary>
internal static string registerAllButton_Content {
get {
return ResourceManager.GetString("registerAllButton_Content", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Register hotkeys at startup.
/// </summary>
internal static string RegisterHotkeysAtStartup {
get {
return ResourceManager.GetString("RegisterHotkeysAtStartup", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Remove.
/// </summary>
internal static string removeButton_Content {
get {
return ResourceManager.GetString("removeButton_Content", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Save.
/// </summary>
internal static string saveButton_Content {
get {
return ResourceManager.GetString("saveButton_Content", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Server Sharing.
/// </summary>
internal static string ServerSharing {
get {
return ResourceManager.GetString("ServerSharing", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The following sources failed to update:\n\n.
/// </summary>
internal static string sip008UpdateAllFailure {
get {
return ResourceManager.GetString("sip008UpdateAllFailure", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully updated all sources!.
/// </summary>
internal static string sip008UpdateAllSuccess {
get {
return ResourceManager.GetString("sip008UpdateAllSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Update failed. See the logs for more information..
/// </summary>
internal static string sip008UpdateFailure {
get {
return ResourceManager.GetString("sip008UpdateFailure", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully updated the selected source!.
/// </summary>
internal static string sip008UpdateSuccess {
get {
return ResourceManager.GetString("sip008UpdateSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Skip version.
/// </summary>
internal static string skipVersionButton_Content {
get {
return ResourceManager.GetString("skipVersionButton_Content", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to SOCKS5.
/// </summary>
internal static string SOCKS5 {
get {
return ResourceManager.GetString("SOCKS5", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Switch to next server.
/// </summary>
internal static string SwitchToNextServer {
get {
return ResourceManager.GetString("SwitchToNextServer", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Switch to previous server.
/// </summary>
internal static string SwitchToPreviousServer {
get {
return ResourceManager.GetString("SwitchToPreviousServer", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Timeout.
/// </summary>
internal static string Timeout {
get {
return ResourceManager.GetString("Timeout", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Toggle proxy mode.
/// </summary>
internal static string ToggleProxyMode {
get {
return ResourceManager.GetString("ToggleProxyMode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Toggle system proxy.
/// </summary>
internal static string ToggleSystemProxy {
get {
return ResourceManager.GetString("ToggleSystemProxy", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Type.
/// </summary>
internal static string Type {
get {
return ResourceManager.GetString("Type", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Update all.
/// </summary>
internal static string updateAllButton_Content {
get {
return ResourceManager.GetString("updateAllButton_Content", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Update.
/// </summary>
internal static string updateButton_Content {
get {
return ResourceManager.GetString("updateButton_Content", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please read the release notes carefully. Then decide whether to update..
/// </summary>
internal static string updatePromptBody {
get {
return ResourceManager.GetString("updatePromptBody", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An update is available..
/// </summary>
internal static string updatePromptTitle {
get {
return ResourceManager.GetString("updatePromptTitle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Username.
/// </summary>
internal static string Username {
get {
return ResourceManager.GetString("Username", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to VersionUpdate.
/// </summary>
internal static string VersionUpdate {
get {
return ResourceManager.GetString("VersionUpdate", resourceCulture);
}
}
}
}

shadowsocks-csharp/View/ProxyForm.resx → shadowsocks-csharp/Localization/Strings.fr.resx View File

@@ -1,120 +1,183 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Password" xml:space="preserve">
<value>Mot de passe</value>
</data>
<data name="Port" xml:space="preserve">
<value>Port</value>
</data>
<data name="Type" xml:space="preserve">
<value>Type</value>
</data>
<data name="Address" xml:space="preserve">
<value>adresse</value>
</data>
<data name="Timeout" xml:space="preserve">
<value>Délai d'attente</value>
</data>
<data name="cancelButton_Content" xml:space="preserve">
<value>Annuler</value>
</data>
<data name="okButton_Content" xml:space="preserve">
<value>OK</value>
</data>
<data name="ToggleSystemProxy" xml:space="preserve">
<value>Changer l'état de proxy système</value>
</data>
<data name="ToggleProxyMode" xml:space="preserve">
<value>Changer le mode de proxy système</value>
</data>
<data name="AllowClientsFromLAN" xml:space="preserve">
<value>Autoriser les clients du LAN</value>
</data>
<data name="OpenLogsWindow" xml:space="preserve">
<value>Afficher les journaux</value>
</data>
<data name="SwitchToPreviousServer" xml:space="preserve">
<value>Passer au serveur précédent</value>
</data>
<data name="SwitchToNextServer" xml:space="preserve">
<value>Passer au serveur suivant</value>
</data>
<data name="RegisterHotkeysAtStartup" xml:space="preserve">
<value>Enregistrer tout</value>
</data>
<data name="registerAllButton_Content" xml:space="preserve">
<value>Enregistrer tout au démarrage</value>
</data>
<data name="addButton_Content" xml:space="preserve">
<value>Ajouter</value>
</data>
<data name="skipVersionButton_Content" xml:space="preserve">
<value>sauter la version</value>
</data>
<data name="copyLinkButton_Content" xml:space="preserve">
<value>Copier le lien</value>
</data>
<data name="removeButton_Content" xml:space="preserve">
<value>retirer</value>
</data>
<data name="updateButton_Content" xml:space="preserve">
<value>mise à jour</value>
</data>
<data name="Copy" xml:space="preserve">
<value>copie</value>
</data>
</root> </root>

shadowsocks-csharp/View/HotkeySettingsForm.resx → shadowsocks-csharp/Localization/Strings.ja.resx View File

@@ -1,183 +1,180 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="flowLayoutPanel1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="flowLayoutPanel1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="tableLayoutPanel1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="RegHotkeysAtStartupLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="SwitchSystemProxyLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="SwitchProxyModeLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="SwitchAllowLanLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ShowLogsLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ServerMoveUpLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ServerMoveDownLabel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="SwitchSystemProxyTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="SwitchProxyModeTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="SwitchAllowLanTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ShowLogsTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ServerMoveUpTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ServerMoveDownTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="RegHotkeysAtStartupCheckBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnOK.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnCancel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnRegisterAll.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Password" xml:space="preserve">
<value>パスワード</value>
</data>
<data name="Type" xml:space="preserve">
<value>タイプ</value>
</data>
<data name="Address" xml:space="preserve">
<value>アドレス</value>
</data>
<data name="Port" xml:space="preserve">
<value>ポート</value>
</data>
<data name="Timeout" xml:space="preserve">
<value>タイムアウト</value>
</data>
<data name="cancelButton_Content" xml:space="preserve">
<value>キャンセル</value>
</data>
<data name="okButton_Content" xml:space="preserve">
<value>OK</value>
</data>
<data name="ToggleSystemProxy" xml:space="preserve">
<value>システム プロキシの状態を切り替える</value>
</data>
<data name="ToggleProxyMode" xml:space="preserve">
<value>プロキシモードを切り替える</value>
</data>
<data name="AllowClientsFromLAN" xml:space="preserve">
<value>LAN からのアクセスの許可を切り替える</value>
</data>
<data name="OpenLogsWindow" xml:space="preserve">
<value>ログの表示</value>
</data>
<data name="SwitchToPreviousServer" xml:space="preserve">
<value>前のサーバーに切り替える</value>
</data>
<data name="SwitchToNextServer" xml:space="preserve">
<value>次のサーバーに切り替える</value>
</data>
<data name="RegisterHotkeysAtStartup" xml:space="preserve">
<value>全部登録する</value>
</data>
<data name="registerAllButton_Content" xml:space="preserve">
<value>起動時にホットキーを登録する</value>
</data>
<data name="addButton_Content" xml:space="preserve">
<value>新規</value>
</data>
<data name="skipVersionButton_Content" xml:space="preserve">
<value>バージョンをスキップ</value>
</data>
<data name="copyLinkButton_Content" xml:space="preserve">
<value>リンクをコピーする</value>
</data>
<data name="updateButton_Content" xml:space="preserve">
<value>更新</value>
</data>
<data name="Copy" xml:space="preserve">
<value>コピー</value>
</data>
</root> </root>

shadowsocks-csharp/View/OnlineConfigForm.resx → shadowsocks-csharp/Localization/Strings.ko.resx View File

@@ -117,4 +117,64 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="Password" xml:space="preserve">
<value>비밀번호</value>
</data>
<data name="Type" xml:space="preserve">
<value>유형</value>
</data>
<data name="Address" xml:space="preserve">
<value>주소</value>
</data>
<data name="Port" xml:space="preserve">
<value>포트</value>
</data>
<data name="Timeout" xml:space="preserve">
<value>시간 초과</value>
</data>
<data name="cancelButton_Content" xml:space="preserve">
<value>취소</value>
</data>
<data name="okButton_Content" xml:space="preserve">
<value>확인</value>
</data>
<data name="ToggleSystemProxy" xml:space="preserve">
<value>시스템 프록시 전환</value>
</data>
<data name="ToggleProxyMode" xml:space="preserve">
<value>시스템 프록시 모드 전환</value>
</data>
<data name="AllowClientsFromLAN" xml:space="preserve">
<value>LAN으로부터 클라이언트 허용</value>
</data>
<data name="OpenLogsWindow" xml:space="preserve">
<value>로그 보기…</value>
</data>
<data name="SwitchToPreviousServer" xml:space="preserve">
<value>이전 서버로 전환</value>
</data>
<data name="SwitchToNextServer" xml:space="preserve">
<value>다음 서버로 전환</value>
</data>
<data name="RegisterHotkeysAtStartup" xml:space="preserve">
<value>모두 등록</value>
</data>
<data name="registerAllButton_Content" xml:space="preserve">
<value>시스템 시작 시 단축키 등록</value>
</data>
<data name="addButton_Content" xml:space="preserve">
<value>추가</value>
</data>
<data name="skipVersionButton_Content" xml:space="preserve">
<value>버전 건너 뛰기</value>
</data>
<data name="copyLinkButton_Content" xml:space="preserve">
<value>링크 복사</value>
</data>
<data name="updateButton_Content" xml:space="preserve">
<value>새롭게 함</value>
</data>
<data name="Copy" xml:space="preserve">
<value>부</value>
</data>
</root> </root>

+ 243
- 0
shadowsocks-csharp/Localization/Strings.resx View File

@@ -0,0 +1,243 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Type" xml:space="preserve">
<value>Type</value>
</data>
<data name="NoProxy" xml:space="preserve">
<value>No proxy</value>
</data>
<data name="SOCKS5" xml:space="preserve">
<value>SOCKS5</value>
</data>
<data name="HTTP" xml:space="preserve">
<value>HTTP</value>
</data>
<data name="Details" xml:space="preserve">
<value>Details</value>
</data>
<data name="Address" xml:space="preserve">
<value>Address</value>
</data>
<data name="Port" xml:space="preserve">
<value>Port</value>
</data>
<data name="Timeout" xml:space="preserve">
<value>Timeout</value>
</data>
<data name="CredentialsOptional" xml:space="preserve">
<value>Credentials (optional)</value>
</data>
<data name="Username" xml:space="preserve">
<value>Username</value>
</data>
<data name="Password" xml:space="preserve">
<value>Password</value>
</data>
<data name="saveButton_Content" xml:space="preserve">
<value>_Save</value>
</data>
<data name="cancelButton_Content" xml:space="preserve">
<value>_Cancel</value>
</data>
<data name="okButton_Content" xml:space="preserve">
<value>_OK</value>
</data>
<data name="ToggleSystemProxy" xml:space="preserve">
<value>Toggle system proxy</value>
</data>
<data name="ToggleProxyMode" xml:space="preserve">
<value>Toggle proxy mode</value>
</data>
<data name="AllowClientsFromLAN" xml:space="preserve">
<value>Allow clients from LAN</value>
</data>
<data name="OpenLogsWindow" xml:space="preserve">
<value>Open logs window</value>
</data>
<data name="SwitchToPreviousServer" xml:space="preserve">
<value>Switch to previous server</value>
</data>
<data name="SwitchToNextServer" xml:space="preserve">
<value>Switch to next server</value>
</data>
<data name="RegisterHotkeysAtStartup" xml:space="preserve">
<value>Register hotkeys at startup</value>
</data>
<data name="registerAllButton_Content" xml:space="preserve">
<value>_Register all</value>
</data>
<data name="updateButton_Content" xml:space="preserve">
<value>_Update</value>
</data>
<data name="updateAllButton_Content" xml:space="preserve">
<value>Update all</value>
</data>
<data name="copyLinkButton_Content" xml:space="preserve">
<value>_Copy link</value>
</data>
<data name="removeButton_Content" xml:space="preserve">
<value>Remove</value>
</data>
<data name="addButton_Content" xml:space="preserve">
<value>_Add</value>
</data>
<data name="updatePromptTitle" xml:space="preserve">
<value>An update is available.</value>
</data>
<data name="updatePromptBody" xml:space="preserve">
<value>Please read the release notes carefully. Then decide whether to update.</value>
</data>
<data name="skipVersionButton_Content" xml:space="preserve">
<value>_Skip version</value>
</data>
<data name="notNowButton_Content" xml:space="preserve">
<value>_Not now</value>
</data>
<data name="Copy" xml:space="preserve">
<value>_Copy</value>
</data>
<data name="ForwardProxy" xml:space="preserve">
<value>Forward Proxy</value>
</data>
<data name="ServerSharing" xml:space="preserve">
<value>Server Sharing</value>
</data>
<data name="Hotkeys" xml:space="preserve">
<value>Hotkeys</value>
</data>
<data name="OnlineConfigDelivery" xml:space="preserve">
<value>Online Configuration Delivery</value>
</data>
<data name="VersionUpdate" xml:space="preserve">
<value>VersionUpdate</value>
</data>
<data name="sip008UpdateSuccess" xml:space="preserve">
<value>Successfully updated the selected source!</value>
</data>
<data name="sip008UpdateFailure" xml:space="preserve">
<value>Update failed. See the logs for more information.</value>
</data>
<data name="sip008UpdateAllSuccess" xml:space="preserve">
<value>Successfully updated all sources!</value>
</data>
<data name="sip008UpdateAllFailure" xml:space="preserve">
<value>The following sources failed to update:\n\n</value>
</data>
</root>

+ 183
- 0
shadowsocks-csharp/Localization/Strings.ru.resx View File

@@ -0,0 +1,183 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Password" xml:space="preserve">
<value>Пароль</value>
</data>
<data name="Type" xml:space="preserve">
<value>тип</value>
</data>
<data name="Address" xml:space="preserve">
<value>адрес</value>
</data>
<data name="Port" xml:space="preserve">
<value>порт</value>
</data>
<data name="Timeout" xml:space="preserve">
<value>Таймаут</value>
</data>
<data name="cancelButton_Content" xml:space="preserve">
<value>Отмена</value>
</data>
<data name="okButton_Content" xml:space="preserve">
<value>ОК</value>
</data>
<data name="ToggleSystemProxy" xml:space="preserve">
<value>ВКЛ/ВЫКЛ системный прокси-сервер</value>
</data>
<data name="ToggleProxyMode" xml:space="preserve">
<value>Переключение режима прокси-сервера</value>
</data>
<data name="AllowClientsFromLAN" xml:space="preserve">
<value>Общий доступ к подключению</value>
</data>
<data name="OpenLogsWindow" xml:space="preserve">
<value>Просмотр журналов</value>
</data>
<data name="SwitchToPreviousServer" xml:space="preserve">
<value>Переключить на пред. сервер</value>
</data>
<data name="SwitchToNextServer" xml:space="preserve">
<value>Переключить на след. сервер</value>
</data>
<data name="RegisterHotkeysAtStartup" xml:space="preserve">
<value>Применить все</value>
</data>
<data name="registerAllButton_Content" xml:space="preserve">
<value>Применять при запуске программы</value>
</data>
<data name="addButton_Content" xml:space="preserve">
<value>Добавить</value>
</data>
<data name="skipVersionButton_Content" xml:space="preserve">
<value>пропустить версию</value>
</data>
<data name="copyLinkButton_Content" xml:space="preserve">
<value>копировать ссылку</value>
</data>
<data name="removeButton_Content" xml:space="preserve">
<value>Удалить</value>
</data>
<data name="updateButton_Content" xml:space="preserve">
<value>Обновить</value>
</data>
<data name="Copy" xml:space="preserve">
<value>копировать</value>
</data>
</root>

+ 237
- 0
shadowsocks-csharp/Localization/Strings.zh-Hans.resx View File

@@ -0,0 +1,237 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="NoProxy" xml:space="preserve">
<value>不使用代理</value>
</data>
<data name="Type" xml:space="preserve">
<value>类型</value>
</data>
<data name="CredentialsOptional" xml:space="preserve">
<value>认证 (可选)</value>
</data>
<data name="Details" xml:space="preserve">
<value>详细设置</value>
</data>
<data name="Address" xml:space="preserve">
<value>地址</value>
</data>
<data name="saveButton_Content" xml:space="preserve">
<value>保存</value>
</data>
<data name="cancelButton_Content" xml:space="preserve">
<value>取消</value>
</data>
<data name="Username" xml:space="preserve">
<value>用户名</value>
</data>
<data name="Password" xml:space="preserve">
<value>密码</value>
</data>
<data name="Port" xml:space="preserve">
<value>端口</value>
</data>
<data name="Timeout" xml:space="preserve">
<value>超时</value>
</data>
<data name="okButton_Content" xml:space="preserve">
<value>确定</value>
</data>
<data name="registerAllButton_Content" xml:space="preserve">
<value>全部注册</value>
</data>
<data name="ToggleSystemProxy" xml:space="preserve">
<value>切换系统代理</value>
</data>
<data name="ToggleProxyMode" xml:space="preserve">
<value>切换代理模式</value>
</data>
<data name="AllowClientsFromLAN" xml:space="preserve">
<value>允许内网客户端连接</value>
</data>
<data name="OpenLogsWindow" xml:space="preserve">
<value>打开日志窗口</value>
</data>
<data name="SwitchToPreviousServer" xml:space="preserve">
<value>切换到上一个服务器</value>
</data>
<data name="SwitchToNextServer" xml:space="preserve">
<value>切换到下一个服务器</value>
</data>
<data name="RegisterHotkeysAtStartup" xml:space="preserve">
<value>启动时注册快捷键</value>
</data>
<data name="updateButton_Content" xml:space="preserve">
<value>更新</value>
</data>
<data name="updateAllButton_Content" xml:space="preserve">
<value>全部更新</value>
</data>
<data name="copyLinkButton_Content" xml:space="preserve">
<value>复制链接</value>
</data>
<data name="removeButton_Content" xml:space="preserve">
<value>移除</value>
</data>
<data name="addButton_Content" xml:space="preserve">
<value>添加</value>
</data>
<data name="skipVersionButton_Content" xml:space="preserve">
<value>跳过版本</value>
</data>
<data name="notNowButton_Content" xml:space="preserve">
<value>暂不更新</value>
</data>
<data name="updatePromptTitle" xml:space="preserve">
<value>发现可用更新</value>
</data>
<data name="updatePromptBody" xml:space="preserve">
<value>请仔细阅读发布信息,然后决定是否更新。</value>
</data>
<data name="Copy" xml:space="preserve">
<value>复制</value>
</data>
<data name="ForwardProxy" xml:space="preserve">
<value>前置代理</value>
</data>
<data name="OnlineConfigDelivery" xml:space="preserve">
<value>在线配置下发</value>
</data>
<data name="Hotkeys" xml:space="preserve">
<value>热键</value>
</data>
<data name="ServerSharing" xml:space="preserve">
<value>服务器分享</value>
</data>
<data name="VersionUpdate" xml:space="preserve">
<value>版本更新</value>
</data>
<data name="sip008UpdateSuccess" xml:space="preserve">
<value>成功更新选定来源!</value>
</data>
<data name="sip008UpdateFailure" xml:space="preserve">
<value>更新失败,请查看日志获取更多信息。</value>
</data>
<data name="sip008UpdateAllSuccess" xml:space="preserve">
<value>成功更新所有来源!</value>
</data>
<data name="sip008UpdateAllFailure" xml:space="preserve">
<value>下列来源更新失败:\n\n</value>
</data>
</root>

+ 189
- 0
shadowsocks-csharp/Localization/Strings.zh-Hant.resx View File

@@ -0,0 +1,189 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Password" xml:space="preserve">
<value>密碼</value>
</data>
<data name="Port" xml:space="preserve">
<value>Port</value>
</data>
<data name="Type" xml:space="preserve">
<value>類型</value>
</data>
<data name="Address" xml:space="preserve">
<value>位址</value>
</data>
<data name="Timeout" xml:space="preserve">
<value>逾時</value>
</data>
<data name="cancelButton_Content" xml:space="preserve">
<value>取消</value>
</data>
<data name="okButton_Content" xml:space="preserve">
<value>確定</value>
</data>
<data name="ToggleSystemProxy" xml:space="preserve">
<value>切換系統 Proxy 狀態</value>
</data>
<data name="ToggleProxyMode" xml:space="preserve">
<value>切換系統 Proxy 模式</value>
</data>
<data name="AllowClientsFromLAN" xml:space="preserve">
<value>切換區域網路共用</value>
</data>
<data name="OpenLogsWindow" xml:space="preserve">
<value>顯示記錄檔</value>
</data>
<data name="SwitchToPreviousServer" xml:space="preserve">
<value>切換上一個伺服器</value>
</data>
<data name="SwitchToNextServer" xml:space="preserve">
<value>切換下一個伺服器</value>
</data>
<data name="RegisterHotkeysAtStartup" xml:space="preserve">
<value>註冊所有快速鍵</value>
</data>
<data name="registerAllButton_Content" xml:space="preserve">
<value>啟動時註冊快速鍵</value>
</data>
<data name="updateButton_Content" xml:space="preserve">
<value>更新</value>
</data>
<data name="updateAllButton_Content" xml:space="preserve">
<value>全部更新</value>
</data>
<data name="addButton_Content" xml:space="preserve">
<value>新增</value>
</data>
<data name="skipVersionButton_Content" xml:space="preserve">
<value>跳過版本</value>
</data>
<data name="notNowButton_Content" xml:space="preserve">
<value>暫不更新</value>
</data>
<data name="updatePromptTitle" xml:space="preserve">
<value>發現可用更新</value>
</data>
<data name="copyLinkButton_Content" xml:space="preserve">
<value>複製鏈接</value>
</data>
<data name="Copy" xml:space="preserve">
<value>複製</value>
</data>
</root>

+ 13
- 15
shadowsocks-csharp/Model/Configuration.cs View File

@@ -40,6 +40,7 @@ namespace Shadowsocks.Model
public bool availabilityStatistics; public bool availabilityStatistics;
public bool autoCheckUpdate; public bool autoCheckUpdate;
public bool checkPreRelease; public bool checkPreRelease;
public string skippedUpdateVersion; // skip the update with this version number
public bool isVerboseLogging; public bool isVerboseLogging;
// hidden options // hidden options
@@ -53,7 +54,7 @@ namespace Shadowsocks.Model
//public NLogConfig.LogLevel logLevel; //public NLogConfig.LogLevel logLevel;
public LogViewerConfig logViewer; public LogViewerConfig logViewer;
public ProxyConfig proxy;
public ForwardProxyConfig proxy;
public HotkeyConfig hotkey; public HotkeyConfig hotkey;
[JsonIgnore] [JsonIgnore]
@@ -78,6 +79,7 @@ namespace Shadowsocks.Model
availabilityStatistics = false; availabilityStatistics = false;
autoCheckUpdate = false; autoCheckUpdate = false;
checkPreRelease = false; checkPreRelease = false;
skippedUpdateVersion = "";
isVerboseLogging = false; isVerboseLogging = false;
// hidden options // hidden options
@@ -97,7 +99,7 @@ namespace Shadowsocks.Model
userAgent = "ShadowsocksWindows/$version"; userAgent = "ShadowsocksWindows/$version";
logViewer = new LogViewerConfig(); logViewer = new LogViewerConfig();
proxy = new ProxyConfig();
proxy = new ForwardProxyConfig();
hotkey = new HotkeyConfig(); hotkey = new HotkeyConfig();
firstRunOnNewVersion = false; firstRunOnNewVersion = false;
@@ -193,7 +195,9 @@ namespace Shadowsocks.Model
ResetGeositeProxiedGroup(ref config.geositeProxiedGroups); ResetGeositeProxiedGroup(ref config.geositeProxiedGroups);
// Mark the first run of a new version. // 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; config.firstRunOnNewVersion = true;
} }
@@ -316,6 +320,12 @@ namespace Shadowsocks.Model
geositeProxiedGroups.Add("geolocation-!cn"); 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) public static Server AddDefaultServerOrServer(Configuration config, Server server = null, int? index = null)
{ {
if (config?.configs != null) if (config?.configs != null)
@@ -368,17 +378,5 @@ namespace Shadowsocks.Model
throw new ArgumentException( throw new ArgumentException(
I18N.GetString("Timeout is invalid, it should not exceed {0}", maxTimeout)); 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"));
}
} }
} }

shadowsocks-csharp/Model/ProxyConfig.cs → shadowsocks-csharp/Model/ForwardProxyConfig.cs View File

@@ -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;
}
}
}
}

+ 7
- 0
shadowsocks-csharp/Program.cs View File

@@ -3,6 +3,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Pipes; using System.IO.Pipes;
using System.Net; using System.Net;
using System.Reflection;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -10,10 +11,12 @@ using System.Windows.Forms;
using CommandLine; using CommandLine;
using Microsoft.Win32; using Microsoft.Win32;
using NLog; using NLog;
using ReactiveUI;
using Shadowsocks.Controller; using Shadowsocks.Controller;
using Shadowsocks.Controller.Hotkeys; using Shadowsocks.Controller.Hotkeys;
using Shadowsocks.Util; using Shadowsocks.Util;
using Shadowsocks.View; using Shadowsocks.View;
using Splat;
namespace Shadowsocks namespace Shadowsocks
{ {
@@ -109,6 +112,10 @@ namespace Shadowsocks
AutoStartup.RegisterForRestart(true); AutoStartup.RegisterForRestart(true);
#endregion #endregion
// We would use this in v5.
// Parameters would have to be dropped from views' constructors (VersionUpdatePromptView)
//Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetCallingAssembly());
#if DEBUG #if DEBUG
// truncate privoxy log file while debugging // truncate privoxy log file while debugging
string privoxyLogFilename = Utils.GetTempPath("privoxy.log"); string privoxyLogFilename = Utils.GetTempPath("privoxy.log");


+ 59
- 56
shadowsocks-csharp/Properties/Resources.Designer.cs View File

@@ -1,10 +1,10 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// 此代码由工具生成。
// 运行时版本: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.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -13,16 +13,16 @@ namespace Shadowsocks.Properties {
/// <summary> /// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary> /// </summary>
// 此类是由 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.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
public class Resources {
private static global::System.Resources.ResourceManager resourceMan; private static global::System.Resources.ResourceManager resourceMan;
@@ -33,10 +33,10 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
public static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Shadowsocks.Properties.Resources", typeof(Resources).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Shadowsocks.Properties.Resources", typeof(Resources).Assembly);
@@ -47,11 +47,11 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 重写当前线程的 CurrentUICulture 属性
/// 重写当前线程的 CurrentUICulture 属性。
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
public static global::System.Globalization.CultureInfo Culture {
get { get {
return resourceCulture; return resourceCulture;
} }
@@ -61,7 +61,7 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 查找类似 /* eslint-disable */
/// Looks up a localized string similar to /* eslint-disable */
///// Was generated by gfwlist2pac in precise mode ///// Was generated by gfwlist2pac in precise mode
///// https://github.com/clowwindy/gfwlist2pac ///// https://github.com/clowwindy/gfwlist2pac
/// ///
@@ -69,25 +69,28 @@ namespace Shadowsocks.Properties {
///// 2019-02-08: Updated to support shadowsocks-windows user rules. ///// 2019-02-08: Updated to support shadowsocks-windows user rules.
/// ///
///var proxy = __PROXY__; ///var proxy = __PROXY__;
///var userrules = __USERRULES__;
///var rules = __RULES__;
///var userrules = [];
///var rules = [];
/// ///
////*
///* This file is part of Adblock Plus &lt;http://adblockplus.org/&gt;,
///* Copyright (C) 2006-2014 Eyeo GmbH
///*
///* Adblock Plus is free software: you can redistribute it and/or [字符串的其余部分被截断]&quot;; 的本地化字符串。
///// convert to abp grammar
///for (var i = 0; i &lt; __RULES__.length; i++) {
/// var s = __RULES__[i];
/// if (s.substring(0, 2) == &quot;||&quot;) s += &quot;^&quot;;
/// rules.push(s);
///}
///
///for (var i = 0; i &lt; [rest of string was truncated]&quot;;.
/// </summary> /// </summary>
internal static string abp_js {
public static string abp_js {
get { get {
return ResourceManager.GetString("abp_js", resourceCulture); return ResourceManager.GetString("abp_js", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// Looks up a localized resource of type System.Byte[].
/// </summary> /// </summary>
internal static byte[] dlc_dat {
public static byte[] dlc_dat {
get { get {
object obj = ResourceManager.GetObject("dlc_dat", resourceCulture); object obj = ResourceManager.GetObject("dlc_dat", resourceCulture);
return ((byte[])(obj)); return ((byte[])(obj));
@@ -95,7 +98,7 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 查找类似 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,,,,,, ///#Restart program to apply translation,,,,,,
///#This is comment line,,,,,, ///#This is comment line,,,,,,
///#Always keep language name at head of file,,,,,, ///#Always keep language name at head of file,,,,,,
@@ -107,18 +110,18 @@ namespace Shadowsocks.Properties {
///,,,,,, ///,,,,,,
///#Menu,,,,,, ///#Menu,,,,,,
///,,,,,, ///,,,,,,
///System Proxy,Системный прокси-сервер,系统代理,系統代理,システムプロキシ,시스템 프록시,P [字符串的其余部分被截断]&quot;; 的本地化字符串。
///System Proxy,Системный прокси-сервер,系统代理,系統代理,システムプロキシ,시스템 프록시,P [rest of string was truncated]&quot;;.
/// </summary> /// </summary>
internal static string i18n_csv {
public static string i18n_csv {
get { get {
return ResourceManager.GetString("i18n_csv", resourceCulture); return ResourceManager.GetString("i18n_csv", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// Looks up a localized resource of type System.Byte[].
/// </summary> /// </summary>
internal static byte[] libsscrypto_dll {
public static byte[] libsscrypto_dll {
get { get {
object obj = ResourceManager.GetObject("libsscrypto_dll", resourceCulture); object obj = ResourceManager.GetObject("libsscrypto_dll", resourceCulture);
return ((byte[])(obj)); return ((byte[])(obj));
@@ -126,22 +129,22 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 查找类似 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
///&lt;!-- Warning: Configuration may reset after shadowsocks upgrade. --&gt; ///&lt;!-- Warning: Configuration may reset after shadowsocks upgrade. --&gt;
///&lt;!-- If you messed it up, delete this file and Shadowsocks will create a new one. --&gt; ///&lt;!-- If you messed it up, delete this file and Shadowsocks will create a new one. --&gt;
///&lt;nlog xmlns=&quot;http://www.nlog-project.org/schemas/NLog.xsd&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&gt; ///&lt;nlog xmlns=&quot;http://www.nlog-project.org/schemas/NLog.xsd&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&gt;
/// &lt;targets&gt; /// &lt;targets&gt;
/// &lt;!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.--&gt; /// &lt;!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.--&gt;
/// &lt;target name=&quot;file&quot; xsi:type=&quot;File&quot; fileName=&quot;ss_win_temp\shadowsocks.log&quot; writ [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// &lt;target name=&quot;file&quot; xsi:type=&quot;File&quot; fileName=&quot;ss_win_temp\shadowsocks.log&quot; writ [rest of string was truncated]&quot;;.
/// </summary> /// </summary>
internal static string NLog_config {
public static string NLog_config {
get { get {
return ResourceManager.GetString("NLog_config", resourceCulture); return ResourceManager.GetString("NLog_config", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// 查找类似 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 ///toggle 0
///logfile ss_privoxy.log ///logfile ss_privoxy.log
///show-on-task-bar 0 ///show-on-task-bar 0
@@ -149,18 +152,18 @@ namespace Shadowsocks.Properties {
///forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ . ///forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ .
///max-client-connections 2048 ///max-client-connections 2048
///hide-console ///hide-console
/// 的本地化字符串。
///.
/// </summary> /// </summary>
internal static string privoxy_conf {
public static string privoxy_conf {
get { get {
return ResourceManager.GetString("privoxy_conf", resourceCulture); return ResourceManager.GetString("privoxy_conf", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// Looks up a localized resource of type System.Byte[].
/// </summary> /// </summary>
internal static byte[] privoxy_exe {
public static byte[] privoxy_exe {
get { get {
object obj = ResourceManager.GetObject("privoxy_exe", resourceCulture); object obj = ResourceManager.GetObject("privoxy_exe", resourceCulture);
return ((byte[])(obj)); return ((byte[])(obj));
@@ -168,9 +171,9 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
internal static System.Drawing.Bitmap ss32Fill {
public static System.Drawing.Bitmap ss32Fill {
get { get {
object obj = ResourceManager.GetObject("ss32Fill", resourceCulture); object obj = ResourceManager.GetObject("ss32Fill", resourceCulture);
return ((System.Drawing.Bitmap)(obj)); return ((System.Drawing.Bitmap)(obj));
@@ -178,9 +181,9 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
internal static System.Drawing.Bitmap ss32In {
public static System.Drawing.Bitmap ss32In {
get { get {
object obj = ResourceManager.GetObject("ss32In", resourceCulture); object obj = ResourceManager.GetObject("ss32In", resourceCulture);
return ((System.Drawing.Bitmap)(obj)); return ((System.Drawing.Bitmap)(obj));
@@ -188,9 +191,9 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
internal static System.Drawing.Bitmap ss32Out {
public static System.Drawing.Bitmap ss32Out {
get { get {
object obj = ResourceManager.GetObject("ss32Out", resourceCulture); object obj = ResourceManager.GetObject("ss32Out", resourceCulture);
return ((System.Drawing.Bitmap)(obj)); return ((System.Drawing.Bitmap)(obj));
@@ -198,9 +201,9 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
internal static System.Drawing.Bitmap ss32Outline {
public static System.Drawing.Bitmap ss32Outline {
get { get {
object obj = ResourceManager.GetObject("ss32Outline", resourceCulture); object obj = ResourceManager.GetObject("ss32Outline", resourceCulture);
return ((System.Drawing.Bitmap)(obj)); return ((System.Drawing.Bitmap)(obj));
@@ -208,9 +211,9 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
internal static System.Drawing.Bitmap ssw128 {
public static System.Drawing.Bitmap ssw128 {
get { get {
object obj = ResourceManager.GetObject("ssw128", resourceCulture); object obj = ResourceManager.GetObject("ssw128", resourceCulture);
return ((System.Drawing.Bitmap)(obj)); return ((System.Drawing.Bitmap)(obj));
@@ -218,9 +221,9 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// Looks up a localized resource of type System.Byte[].
/// </summary> /// </summary>
internal static byte[] sysproxy_exe {
public static byte[] sysproxy_exe {
get { get {
object obj = ResourceManager.GetObject("sysproxy_exe", resourceCulture); object obj = ResourceManager.GetObject("sysproxy_exe", resourceCulture);
return ((byte[])(obj)); return ((byte[])(obj));
@@ -228,9 +231,9 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// Looks up a localized resource of type System.Byte[].
/// </summary> /// </summary>
internal static byte[] sysproxy64_exe {
public static byte[] sysproxy64_exe {
get { get {
object obj = ResourceManager.GetObject("sysproxy64_exe", resourceCulture); object obj = ResourceManager.GetObject("sysproxy64_exe", resourceCulture);
return ((byte[])(obj)); return ((byte[])(obj));
@@ -238,11 +241,11 @@ namespace Shadowsocks.Properties {
} }
/// <summary> /// <summary>
/// 查找类似 ! 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 ///! See https://adblockplus.org/en/filter-cheatsheet
/// 的本地化字符串。
///.
/// </summary> /// </summary>
internal static string user_rule {
public static string user_rule {
get { get {
return ResourceManager.GetString("user_rule", resourceCulture); return ResourceManager.GetString("user_rule", resourceCulture);
} }


+ 0
- 190
shadowsocks-csharp/View/HotkeySettingsForm.cs View File

@@ -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
};
}
/// <summary>
/// Capture hotkey - Press key
/// </summary>
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();
}
/// <summary>
/// Capture hotkey - Release key
/// </summary>
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;
}
}
}
}

+ 0
- 346
shadowsocks-csharp/View/HotkeySettingsForm.designer.cs View File

@@ -1,346 +0,0 @@
namespace Shadowsocks.View
{
partial class HotkeySettingsForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
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;
}
}

+ 85
- 103
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -1,5 +1,6 @@
using NLog; using NLog;
using Shadowsocks.Controller; using Shadowsocks.Controller;
using Shadowsocks.Localization;
using Shadowsocks.Model; using Shadowsocks.Model;
using Shadowsocks.Properties; using Shadowsocks.Properties;
using Shadowsocks.Util; using Shadowsocks.Util;
@@ -11,6 +12,8 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Forms.Integration;
using System.Windows.Threading;
using ZXing; using ZXing;
using ZXing.Common; using ZXing.Common;
using ZXing.QrCode; using ZXing.QrCode;
@@ -19,18 +22,14 @@ namespace Shadowsocks.View
{ {
public class MenuViewController 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 ShadowsocksController controller;
private UpdateChecker updateChecker;
public UpdateChecker updateChecker;
private NotifyIcon _notifyIcon; private NotifyIcon _notifyIcon;
private Icon icon, icon_in, icon_out, icon_both, previousIcon; private Icon icon, icon_in, icon_out, icon_both, previousIcon;
private bool _isStartupChecking;
private string _urlToOpen; private string _urlToOpen;
private ContextMenu contextMenu1; private ContextMenu contextMenu1;
@@ -61,12 +60,12 @@ namespace Shadowsocks.View
private MenuItem onlineConfigItem; private MenuItem onlineConfigItem;
private ConfigForm configForm; private ConfigForm configForm;
private ProxyForm proxyForm;
private LogForm logForm; private LogForm logForm;
private HotkeySettingsForm hotkeySettingsForm;
private OnlineConfigForm onlineConfigForm;
private System.Windows.Window serverSharingWindow; 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 // color definition for icon color transformation
private readonly Color colorMaskBlue = Color.FromArgb(255, 25, 125, 191); private readonly Color colorMaskBlue = Color.FromArgb(255, 25, 125, 191);
@@ -102,7 +101,7 @@ namespace Shadowsocks.View
_notifyIcon.BalloonTipClosed += _notifyIcon_BalloonTipClosed; _notifyIcon.BalloonTipClosed += _notifyIcon_BalloonTipClosed;
controller.TrafficChanged += controller_TrafficChanged; controller.TrafficChanged += controller_TrafficChanged;
this.updateChecker = new UpdateChecker();
updateChecker = new UpdateChecker();
updateChecker.CheckUpdateCompleted += updateChecker_CheckUpdateCompleted; updateChecker.CheckUpdateCompleted += updateChecker_CheckUpdateCompleted;
LoadCurrentConfiguration(); LoadCurrentConfiguration();
@@ -115,8 +114,7 @@ namespace Shadowsocks.View
} }
else if (config.autoCheckUpdate) 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() private void ShowLogForm()
{ {
if (logForm != null) 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) void logForm_FormClosed(object sender, FormClosedEventArgs e)
{ {
logForm.Dispose(); 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 #endregion
#region Misc #region Misc
@@ -500,23 +434,10 @@ namespace Shadowsocks.View
void notifyIcon1_BalloonTipClicked(object sender, EventArgs e) 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) 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) private void notifyIcon1_Click(object sender, MouseEventArgs e)
@@ -541,8 +462,7 @@ namespace Shadowsocks.View
Configuration config = controller.GetCurrentConfiguration(); Configuration config = controller.GetCurrentConfiguration();
if (config.firstRun) if (config.firstRun)
return; return;
_isStartupChecking = true;
updateChecker.CheckUpdate(config, 3000);
Dispatcher.CurrentDispatcher.Invoke(() => updateChecker.CheckForVersionUpdate(3000));
} }
public void ShowLogForm_HotKey() public void ShowLogForm_HotKey()
@@ -561,19 +481,83 @@ namespace Shadowsocks.View
private void proxyItem_Click(object sender, EventArgs e) private void proxyItem_Click(object sender, EventArgs e)
{ {
ShowProxyForm();
if (forwardProxyWindow == null)
{
forwardProxyWindow = new System.Windows.Window()
{
Title = LocalizationProvider.GetLocalizedValue<string>("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) private void OnlineConfig_Click(object sender, EventArgs e)
{ {
ShowOnlineConfigForm();
if (onlineConfigWindow == null)
{
onlineConfigWindow = new System.Windows.Window()
{
Title = LocalizationProvider.GetLocalizedValue<string>("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) private void hotKeyItem_Click(object sender, EventArgs e)
{ {
ShowHotKeySettingsForm();
if (hotkeysWindow == null)
{
hotkeysWindow = new System.Windows.Window()
{
Title = LocalizationProvider.GetLocalizedValue<string>("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) private void ShareOverLANItem_Click(object sender, EventArgs e)
{ {
ShareOverLANItem.Checked = !ShareOverLANItem.Checked; ShareOverLANItem.Checked = !ShareOverLANItem.Checked;
@@ -750,12 +734,15 @@ namespace Shadowsocks.View
{ {
serverSharingWindow = new System.Windows.Window() serverSharingWindow = new System.Windows.Window()
{ {
Title = "Server Sharing",
Title = LocalizationProvider.GetLocalizedValue<string>("ServerSharing"),
Height = 400, Height = 400,
Width = 660, Width = 660,
MinHeight = 400,
MinWidth = 660,
Content = new ServerSharingView() Content = new ServerSharingView()
}; };
serverSharingWindow.Closed += ServerSharingWindow_Closed; serverSharingWindow.Closed += ServerSharingWindow_Closed;
ElementHost.EnableModelessKeyboardInterop(serverSharingWindow);
serverSharingWindow.Show(); serverSharingWindow.Show();
} }
serverSharingWindow.Activate(); serverSharingWindow.Activate();
@@ -1017,15 +1004,10 @@ namespace Shadowsocks.View
void updateChecker_CheckUpdateCompleted(object sender, EventArgs e) 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); ShowBalloonTip(I18N.GetString("Shadowsocks"), I18N.GetString("No update is available"), ToolTipIcon.Info, 5000);
} }
_isStartupChecking = false;
} }
private void UpdateUpdateMenu() private void UpdateUpdateMenu()
@@ -1049,9 +1031,9 @@ namespace Shadowsocks.View
UpdateUpdateMenu(); 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) private void AboutItem_Click(object sender, EventArgs e)


+ 0
- 218
shadowsocks-csharp/View/OnlineConfigForm.Designer.cs View File

@@ -1,218 +0,0 @@
namespace Shadowsocks.View
{
partial class OnlineConfigForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.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;
}
}

+ 0
- 153
shadowsocks-csharp/View/OnlineConfigForm.cs View File

@@ -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<string>().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<string>().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();
}
}
}

+ 0
- 333
shadowsocks-csharp/View/ProxyForm.Designer.cs View File

@@ -1,333 +0,0 @@
namespace Shadowsocks.View
{
partial class ProxyForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.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;
}
}

+ 0
- 176
shadowsocks-csharp/View/ProxyForm.cs View File

@@ -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();
}
}
}

+ 125
- 0
shadowsocks-csharp/ViewModels/ForwardProxyViewModel.cs View File

@@ -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<Unit, Unit> Save { get; }
public ReactiveCommand<Unit, Unit> 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;
}
}
}

+ 189
- 0
shadowsocks-csharp/ViewModels/HotkeysViewModel.cs View File

@@ -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<Unit, Unit> RegisterAll { get; }
public ReactiveCommand<Unit, Unit> Save { get; }
public ReactiveCommand<Unit, Unit> 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
};
}
}

+ 115
- 0
shadowsocks-csharp/ViewModels/OnlineConfigViewModel.cs View File

@@ -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<string>(_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<string>("sip008UpdateSuccess"));
else
MessageBox.Show(LocalizationProvider.GetLocalizedValue<string>("sip008UpdateFailure"));
});
this.WhenAnyObservable(x => x.UpdateAll)
.Subscribe(x =>
{
if (x.Count == 0)
MessageBox.Show(LocalizationProvider.GetLocalizedValue<string>("sip008UpdateAllSuccess"));
else
{
var stringBuilder = new StringBuilder(LocalizationProvider.GetLocalizedValue<string>("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<Unit, bool> Update { get; }
public ReactiveCommand<Unit, List<string>> UpdateAll { get; }
public ReactiveCommand<Unit, Unit> CopyLink { get; }
public ReactiveCommand<Unit, Unit> Remove { get; }
public ReactiveCommand<Unit, Unit> Add { get; }

[Reactive]
public ObservableCollection<string> Sources { get; private set; }

[Reactive]
public string SelectedSource { get; set; }

[Reactive]
public string Address { get; set; }
}
}

+ 25
- 38
shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs View File

@@ -1,10 +1,13 @@
using ReactiveUI; using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Shadowsocks.Model; using Shadowsocks.Model;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reactive;
using System.Windows;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;


namespace Shadowsocks.ViewModels namespace Shadowsocks.ViewModels
@@ -17,18 +20,30 @@ namespace Shadowsocks.ViewModels
public ServerSharingViewModel() public ServerSharingViewModel()
{ {
_config = Program.MainController.GetCurrentConfiguration(); _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 readonly Configuration _config;


private List<Server> _servers;
private Server _selectedServer;
private string _selectedServerUrl;
private BitmapImage _selectedServerUrlImage;
public ReactiveCommand<Unit, Unit> CopyLink { get; }

[Reactive]
public List<Server> Servers { get; private set; }

[Reactive]
public Server SelectedServer { get; set; }

[Reactive]
public string SelectedServerUrl { get; private set; }

[Reactive]
public BitmapImage SelectedServerUrlImage { get; private set; }


/// <summary> /// <summary>
/// Called when SelectedServer changed /// Called when SelectedServer changed
@@ -37,10 +52,10 @@ namespace Shadowsocks.ViewModels
private void UpdateUrlAndImage() private void UpdateUrlAndImage()
{ {
// update SelectedServerUrl // update SelectedServerUrl
SelectedServerUrl = _selectedServer.GetURL(_config.generateLegacyUrl);
SelectedServerUrl = SelectedServer.GetURL(_config.generateLegacyUrl);


// generate QR code // 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; var byteMatrix = qrCode.Matrix;


// paint bitmap // paint bitmap
@@ -77,33 +92,5 @@ namespace Shadowsocks.ViewModels
} }
SelectedServerUrlImage = bitmapImage; SelectedServerUrlImage = bitmapImage;
} }

public List<Server> 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);
}
} }
} }

+ 34
- 0
shadowsocks-csharp/ViewModels/VersionUpdatePromptViewModel.cs View File

@@ -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<Unit, Unit> Update { get; }

public ReactiveCommand<Unit, Unit> SkipVersion { get; }

public ReactiveCommand<Unit, Unit> NotNow { get; }
}
}

+ 100
- 0
shadowsocks-csharp/Views/ForwardProxyView.xaml View File

@@ -0,0 +1,100 @@
<reactiveui:ReactiveUserControl
x:Class="Shadowsocks.Views.ForwardProxyView"
x:TypeArguments="vms:ForwardProxyViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shadowsocks.Views"
xmlns:vms="clr-namespace:Shadowsocks.ViewModels"
xmlns:reactiveui="http://reactiveui.net"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
lex:LocalizeDictionary.DesignCulture="en"
lex:ResxLocalizationProvider.DefaultAssembly="Shadowsocks"
lex:ResxLocalizationProvider.DefaultDictionary="Strings"
mc:Ignorable="d"
d:DesignHeight="380" d:DesignWidth="280">
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
Margin="4 8 4 8"
FontSize="16"
Text="{lex:Loc Type}"/>
<RadioButton x:Name="noProxyRadioButton" Grid.Row="1" Grid.Column="0"
Margin="4"
GroupName="ProxyType"
Content="{lex:Loc NoProxy}"/>
<RadioButton x:Name="socks5RadioButton" Grid.Row="2" Grid.Column="0"
Margin="4"
GroupName="ProxyType"
Content="{lex:Loc SOCKS5}"/>
<RadioButton x:Name="httpRadioButton" Grid.Row="3" Grid.Column="0"
Margin="4"
GroupName="ProxyType"
Content="{lex:Loc HTTP}"/>

<TextBlock Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2"
Margin="4 8 4 8"
FontSize="16"
Text="{lex:Loc Details}"/>
<TextBlock Grid.Row="5" Grid.Column="0"
Margin="4"
Text="{lex:Loc Address}"/>
<TextBox x:Name="addressTextBox" Grid.Row="5" Grid.Column="1"
Margin="4"/>
<TextBlock Grid.Row="6" Grid.Column="0"
Margin="4"
Text="{lex:Loc Port}"/>
<TextBox x:Name="portTextBox" Grid.Row="6" Grid.Column="1"
Margin="4"
HorizontalContentAlignment="Right"/>
<TextBlock Grid.Row="7" Grid.Column="0"
Margin="4"
Text="{lex:Loc Timeout}"/>
<TextBox x:Name="timeoutTextBox" Grid.Row="7" Grid.Column="1"
Margin="4"
HorizontalContentAlignment="Right"/>

<TextBlock Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="2"
Margin="4 8 4 8"
FontSize="16"
Text="{lex:Loc CredentialsOptional}"/>

<TextBlock Grid.Row="9" Grid.Column="0"
Margin="4"
Text="{lex:Loc Username}"/>
<TextBox x:Name="usernameTextBox" Grid.Row="9" Grid.Column="1"
Margin="4"/>
<TextBlock Grid.Row="10" Grid.Column="0"
Margin="4"
Text="{lex:Loc Password}"/>
<TextBox x:Name="passwordTextBox" Grid.Row="10" Grid.Column="1"
Margin="4"/>

<StackPanel Grid.Row="11" Grid.Column="0" Grid.ColumnSpan="2"
Orientation="Horizontal"
HorizontalAlignment="Right"
VerticalAlignment="Bottom">
<Button x:Name="saveButton" Margin="4" MinWidth="75" Content="{lex:Loc}"/>
<Button x:Name="cancelButton" Margin="4" MinWidth="75" Content="{lex:Loc}"/>
</StackPanel>
</Grid>
</reactiveui:ReactiveUserControl>

+ 72
- 0
shadowsocks-csharp/Views/ForwardProxyView.xaml.cs View File

@@ -0,0 +1,72 @@
using ReactiveUI;
using Shadowsocks.ViewModels;
using System.Reactive.Disposables;

namespace Shadowsocks.Views
{
/// <summary>
/// Interaction logic for ForwardProxyView.xaml
/// </summary>
public partial class ForwardProxyView : ReactiveUserControl<ForwardProxyViewModel>
{
public ForwardProxyView()
{
InitializeComponent();
ViewModel = new ForwardProxyViewModel();
this.WhenActivated(disposables =>
{
this.Bind(ViewModel,
viewModel => viewModel.NoProxy,
view => view.noProxyRadioButton.IsChecked)
.DisposeWith(disposables);
this.Bind(ViewModel,
viewModel => viewModel.UseSocks5Proxy,
view => view.socks5RadioButton.IsChecked)
.DisposeWith(disposables);
this.Bind(ViewModel,
viewModel => viewModel.UseHttpProxy,
view => view.httpRadioButton.IsChecked)
.DisposeWith(disposables);

this.Bind(ViewModel,
viewModel => viewModel.Address,
view => view.addressTextBox.Text)
.DisposeWith(disposables);
this.Bind(ViewModel,
viewModel => viewModel.Port,
view => view.portTextBox.Text)
.DisposeWith(disposables);
this.Bind(ViewModel,
viewModel => viewModel.Timeout,
view => view.timeoutTextBox.Text)
.DisposeWith(disposables);

this.Bind(ViewModel,
viewModel => viewModel.Username,
view => view.usernameTextBox.Text)
.DisposeWith(disposables);
this.Bind(ViewModel,
viewModel => viewModel.Password,
view => view.passwordTextBox.Text)
.DisposeWith(disposables);
this.OneWayBind(ViewModel,
viewModel => viewModel.UseHttpProxy,
view => view.usernameTextBox.IsEnabled)
.DisposeWith(disposables);
this.OneWayBind(ViewModel,
viewModel => viewModel.UseHttpProxy,
view => view.passwordTextBox.IsEnabled)
.DisposeWith(disposables);

this.BindCommand(ViewModel,
viewModel => viewModel.Save,
view => view.saveButton)
.DisposeWith(disposables);
this.BindCommand(ViewModel,
viewModel => viewModel.Cancel,
view => view.cancelButton)
.DisposeWith(disposables);
});
}
}
}

+ 115
- 0
shadowsocks-csharp/Views/HotkeysView.xaml View File

@@ -0,0 +1,115 @@
<reactiveui:ReactiveUserControl
x:Class="Shadowsocks.Views.HotkeysView"
x:TypeArguments="vms:HotkeysViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shadowsocks.Views"
xmlns:vms="clr-namespace:Shadowsocks.ViewModels"
xmlns:reactiveui="http://reactiveui.net"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
lex:LocalizeDictionary.DesignCulture="en"
lex:ResxLocalizationProvider.DefaultAssembly="Shadowsocks"
lex:ResxLocalizationProvider.DefaultDictionary="Strings"
mc:Ignorable="d"
d:DesignHeight="240" d:DesignWidth="280">
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>

<TextBlock Grid.Row="0" Grid.Column="0"
Margin="4"
Text="{lex:Loc ToggleSystemProxy}"/>
<TextBox x:Name="systemProxyTextBox"
Grid.Row="0" Grid.Column="1"
Margin="4" IsReadOnly="True" />
<TextBlock x:Name="systemProxyStatusTextBlock"
Grid.Row="0" Grid.Column="2"
Margin="4" />

<TextBlock Grid.Row="1" Grid.Column="0"
Margin="4"
Text="{lex:Loc ToggleProxyMode}"/>
<TextBox x:Name="proxyModeTextBox"
Grid.Row="1" Grid.Column="1"
Margin="4" IsReadOnly="True" />
<TextBlock x:Name="proxyModeStatusTextBlock"
Grid.Row="1" Grid.Column="2"
Margin="4" />

<TextBlock Grid.Row="2" Grid.Column="0"
Margin="4"
Text="{lex:Loc AllowClientsFromLAN}"/>
<TextBox x:Name="allowLanTextBox"
Grid.Row="2" Grid.Column="1"
Margin="4" IsReadOnly="True" />
<TextBlock x:Name="allowLanStatusTextBlock"
Grid.Row="2" Grid.Column="2"
Margin="4" />

<TextBlock Grid.Row="3" Grid.Column="0"
Margin="4"
Text="{lex:Loc OpenLogsWindow}"/>
<TextBox x:Name="openLogsTextBox"
Grid.Row="3" Grid.Column="1"
Margin="4" IsReadOnly="True" />
<TextBlock x:Name="openLogsStatusTextBlock"
Grid.Row="3" Grid.Column="2"
Margin="4" />

<TextBlock Grid.Row="4" Grid.Column="0"
Margin="4"
Text="{lex:Loc SwitchToPreviousServer}"/>
<TextBox x:Name="switchPrevTextBox"
Grid.Row="4" Grid.Column="1"
Margin="4" IsReadOnly="True" />
<TextBlock x:Name="switchPrevStatusTextBlock"
Grid.Row="4" Grid.Column="2"
Margin="4" />

<TextBlock Grid.Row="5" Grid.Column="0"
Margin="4"
Text="{lex:Loc SwitchToNextServer}"/>
<TextBox x:Name="switchNextTextBox"
Grid.Row="5" Grid.Column="1"
Margin="4" IsReadOnly="True" />
<TextBlock x:Name="switchNextStatusTextBlock"
Grid.Row="5" Grid.Column="2"
Margin="4" />

<StackPanel Grid.Row="6" Grid.ColumnSpan="2" Orientation="Horizontal">
<CheckBox x:Name="registerAtStartupCheckBox" Margin="4" VerticalAlignment="Center"/>
<TextBlock Margin="4" Text="{lex:Loc RegisterHotkeysAtStartup}"/>
</StackPanel>

<StackPanel Grid.Row="7"
Grid.ColumnSpan="3"
Orientation="Horizontal"
HorizontalAlignment="Left"
VerticalAlignment="Bottom">
<Button x:Name="registerAllButton" Margin="4" MinWidth="75" Content="{lex:Loc}"/>
</StackPanel>
<StackPanel Grid.Row="7"
Grid.ColumnSpan="3"
Orientation="Horizontal"
HorizontalAlignment="Right"
VerticalAlignment="Bottom">
<Button x:Name="saveButton" Margin="4" MinWidth="75" Content="{lex:Loc}"/>
<Button x:Name="cancelButton" Margin="4" MinWidth="75" Content="{lex:Loc}"/>
</StackPanel>
</Grid>
</reactiveui:ReactiveUserControl>

+ 169
- 0
shadowsocks-csharp/Views/HotkeysView.xaml.cs View File

@@ -0,0 +1,169 @@
using ReactiveUI;
using Shadowsocks.ViewModels;
using System;
using System.Reactive.Disposables;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;

namespace Shadowsocks.Views
{
/// <summary>
/// Interaction logic for HotkeysView.xaml
/// </summary>
public partial class HotkeysView : ReactiveUserControl<HotkeysViewModel>
{
public HotkeysView()
{
InitializeComponent();
ViewModel = new HotkeysViewModel();
this.WhenActivated(disposables =>
{
systemProxyTextBox
.Events().KeyDown
.Subscribe(keyEventArgs => ViewModel.RecordKeyDown(0, keyEventArgs))
.DisposeWith(disposables);

systemProxyTextBox
.Events().KeyUp
.Subscribe(keyEventArgs => ViewModel.FinishOnKeyUp(0, keyEventArgs))
.DisposeWith(disposables);

proxyModeTextBox
.Events().KeyDown
.Subscribe(keyEventArgs => ViewModel.RecordKeyDown(1, keyEventArgs))
.DisposeWith(disposables);

proxyModeTextBox
.Events().KeyUp
.Subscribe(keyEventArgs => ViewModel.FinishOnKeyUp(1, keyEventArgs))
.DisposeWith(disposables);

allowLanTextBox
.Events().KeyDown
.Subscribe(keyEventArgs => ViewModel.RecordKeyDown(2, keyEventArgs))
.DisposeWith(disposables);

allowLanTextBox
.Events().KeyUp
.Subscribe(keyEventArgs => ViewModel.FinishOnKeyUp(2, keyEventArgs))
.DisposeWith(disposables);

openLogsTextBox
.Events().KeyDown
.Subscribe(keyEventArgs => ViewModel.RecordKeyDown(3, keyEventArgs))
.DisposeWith(disposables);

openLogsTextBox
.Events().KeyUp
.Subscribe(keyEventArgs => ViewModel.FinishOnKeyUp(3, keyEventArgs))
.DisposeWith(disposables);

switchPrevTextBox
.Events().KeyDown
.Subscribe(keyEventArgs => ViewModel.RecordKeyDown(4, keyEventArgs))
.DisposeWith(disposables);

switchPrevTextBox
.Events().KeyUp
.Subscribe(keyEventArgs => ViewModel.FinishOnKeyUp(4, keyEventArgs))
.DisposeWith(disposables);

switchNextTextBox
.Events().KeyDown
.Subscribe(keyEventArgs => ViewModel.RecordKeyDown(5, keyEventArgs))
.DisposeWith(disposables);

switchNextTextBox
.Events().KeyUp
.Subscribe(keyEventArgs => ViewModel.FinishOnKeyUp(5, keyEventArgs))
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeySystemProxy,
view => view.systemProxyTextBox.Text)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeyProxyMode,
view => view.proxyModeTextBox.Text)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeyAllowLan,
view => view.allowLanTextBox.Text)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeyOpenLogs,
view => view.openLogsTextBox.Text)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeySwitchPrev,
view => view.switchPrevTextBox.Text)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeySwitchNext,
view => view.switchNextTextBox.Text)
.DisposeWith(disposables);

this.Bind(ViewModel,
viewModel => viewModel.RegisterAtStartup,
view => view.registerAtStartupCheckBox.IsChecked)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeySystemProxyStatus,
view => view.systemProxyStatusTextBlock.Text)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeyProxyModeStatus,
view => view.proxyModeStatusTextBlock.Text)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeyAllowLanStatus,
view => view.allowLanStatusTextBlock.Text)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeyOpenLogsStatus,
view => view.openLogsStatusTextBlock.Text)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeySwitchPrevStatus,
view => view.switchPrevStatusTextBlock.Text)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.HotkeySwitchNextStatus,
view => view.switchNextStatusTextBlock.Text)
.DisposeWith(disposables);

this.BindCommand(ViewModel,
viewModel => viewModel.RegisterAll,
view => view.registerAllButton)
.DisposeWith(disposables);

this.BindCommand(ViewModel,
viewModel => viewModel.Save,
view => view.saveButton)
.DisposeWith(disposables);

this.BindCommand(ViewModel,
viewModel => viewModel.Cancel,
view => view.cancelButton)
.DisposeWith(disposables);
});
}
}
}

+ 61
- 0
shadowsocks-csharp/Views/OnlineConfigView.xaml View File

@@ -0,0 +1,61 @@
<reactiveui:ReactiveUserControl
x:Class="Shadowsocks.Views.OnlineConfigView"
x:TypeArguments="vms:OnlineConfigViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shadowsocks.Views"
xmlns:vms="clr-namespace:Shadowsocks.ViewModels"
xmlns:reactiveui="http://reactiveui.net"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
lex:LocalizeDictionary.DesignCulture="en"
lex:ResxLocalizationProvider.DefaultAssembly="Shadowsocks"
lex:ResxLocalizationProvider.DefaultDictionary="Strings"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="480">
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>

<ListBox x:Name="sourcesListBox" Margin="8 8 4 4"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="0" Grid.Column="2">
<Button x:Name="updateButton" Margin="4 8 8 4"
MinWidth="75" Content="{lex:Loc}"/>
<Button x:Name="updateAllButton" Margin="4 4 8 4"
MinWidth="75" Content="{lex:Loc}"/>
<Button x:Name="copyLinkButton" Margin="4 4 8 8"
MinWidth="75" Content="{lex:Loc}"/>
<Button x:Name="removeButton" Margin="4 8 8 8"
MinWidth="75" Content="{lex:Loc}"/>
</StackPanel>
<TextBlock Margin="8 4 4 8"
Grid.Row="1"
Grid.Column="0">URL</TextBlock>
<TextBox x:Name="urlTextBox" Margin="4 4 4 8"
Grid.Row="1"
Grid.Column="1"/>
<Button x:Name="addButton" Margin="4 4 8 8"
Grid.Row="1"
Grid.Column="2"
MinWidth="75"
Content="{lex:Loc}"/>
</Grid>
</reactiveui:ReactiveUserControl>

+ 54
- 0
shadowsocks-csharp/Views/OnlineConfigView.xaml.cs View File

@@ -0,0 +1,54 @@
using ReactiveUI;
using Shadowsocks.ViewModels;
using System.Reactive.Disposables;

namespace Shadowsocks.Views
{
/// <summary>
/// Interaction logic for OnlineConfigView.xaml
/// </summary>
public partial class OnlineConfigView : ReactiveUserControl<OnlineConfigViewModel>
{
public OnlineConfigView()
{
InitializeComponent();
ViewModel = new OnlineConfigViewModel();
this.WhenActivated(disposables =>
{
this.OneWayBind(ViewModel,
viewModel => viewModel.Sources,
view => view.sourcesListBox.ItemsSource)
.DisposeWith(disposables);
this.Bind(ViewModel,
viewModel => viewModel.SelectedSource,
view => view.sourcesListBox.SelectedItem)
.DisposeWith(disposables);
this.Bind(ViewModel,
viewModel => viewModel.Address,
view => view.urlTextBox.Text)
.DisposeWith(disposables);

this.BindCommand(ViewModel,
viewModel => viewModel.Update,
view => view.updateButton)
.DisposeWith(disposables);
this.BindCommand(ViewModel,
viewModel => viewModel.UpdateAll,
view => view.updateAllButton)
.DisposeWith(disposables);
this.BindCommand(ViewModel,
viewModel => viewModel.CopyLink,
view => view.copyLinkButton)
.DisposeWith(disposables);
this.BindCommand(ViewModel,
viewModel => viewModel.Remove,
view => view.removeButton)
.DisposeWith(disposables);
this.BindCommand(ViewModel,
viewModel => viewModel.Add,
view => view.addButton)
.DisposeWith(disposables);
});
}
}
}

+ 38
- 21
shadowsocks-csharp/Views/ServerSharingView.xaml View File

@@ -1,11 +1,19 @@
<UserControl x:Class="Shadowsocks.Views.ServerSharingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shadowsocks.Views"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="660">
<reactiveui:ReactiveUserControl
x:Class="Shadowsocks.Views.ServerSharingView"
x:TypeArguments="vms:ServerSharingViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shadowsocks.Views"
xmlns:vms="clr-namespace:Shadowsocks.ViewModels"
xmlns:reactiveui="http://reactiveui.net"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
lex:LocalizeDictionary.DesignCulture="en"
lex:ResxLocalizationProvider.DefaultAssembly="Shadowsocks"
lex:ResxLocalizationProvider.DefaultDictionary="Strings"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="660">
<Grid Margin="8"> <Grid Margin="8">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*" /> <RowDefinition Height="*" />
@@ -15,22 +23,31 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image Grid.Row="0"
<Image x:Name="qrCodeImage" Grid.Row="0"
Grid.Column="0" Grid.Column="0"
Margin="8"
Source="{Binding SelectedServerUrlImage}"/>
<ListBox Grid.Row="0"
Margin="8"/>
<ListBox x:Name="serversListBox" Grid.Row="0"
Grid.Column="1" Grid.Column="1"
Margin="8"
ItemsSource="{Binding Servers}"
SelectedItem="{Binding SelectedServer}"/>
<TextBox x:Name="urlTextBox"
Grid.Row="1"
Margin="8">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Grid Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox x:Name="urlTextBox"
Grid.Column="0" Grid.Column="0"
Grid.ColumnSpan="2"
Margin="8"
Margin="8 8 4 8"
IsReadOnly="True" IsReadOnly="True"
Text="{Binding SelectedServerUrl}"
PreviewMouseDoubleClick="urlTextBox_PreviewMouseDoubleClick"/> PreviewMouseDoubleClick="urlTextBox_PreviewMouseDoubleClick"/>
<Button x:Name="copyLinkButton" Grid.Column="1" Margin="4 8 8 8" MinWidth="36" Content="{lex:Loc Copy}"/>
</Grid>
</Grid> </Grid>
</UserControl>
</reactiveui:ReactiveUserControl>

+ 28
- 4
shadowsocks-csharp/Views/ServerSharingView.xaml.cs View File

@@ -1,5 +1,6 @@
using Shadowsocks.ViewModels;
using System.Windows.Controls;
using ReactiveUI;
using Shadowsocks.ViewModels;
using System.Reactive.Disposables;
using System.Windows.Input; using System.Windows.Input;


namespace Shadowsocks.Views namespace Shadowsocks.Views
@@ -7,13 +8,36 @@ namespace Shadowsocks.Views
/// <summary> /// <summary>
/// Interaction logic for ServerSharingView.xaml /// Interaction logic for ServerSharingView.xaml
/// </summary> /// </summary>
public partial class ServerSharingView : UserControl
public partial class ServerSharingView : ReactiveUserControl<ServerSharingViewModel>
{ {
public ServerSharingView() public ServerSharingView()
{ {
InitializeComponent(); InitializeComponent();
ViewModel = new ServerSharingViewModel();
this.WhenActivated(disposables =>
{
this.OneWayBind(ViewModel,
viewModel => viewModel.SelectedServerUrlImage,
view => view.qrCodeImage.Source)
.DisposeWith(disposables);
this.OneWayBind(ViewModel,
viewModel => viewModel.Servers,
view => view.serversListBox.ItemsSource)
.DisposeWith(disposables);
this.Bind(ViewModel,
viewModel => viewModel.SelectedServer,
view => view.serversListBox.SelectedItem)
.DisposeWith(disposables);
this.OneWayBind(ViewModel,
viewModel => viewModel.SelectedServerUrl,
view => view.urlTextBox.Text)
.DisposeWith(disposables);


DataContext = new ServerSharingViewModel();
this.BindCommand(ViewModel,
viewModel => viewModel.CopyLink,
view => view.copyLinkButton)
.DisposeWith(disposables);
});
} }


private void urlTextBox_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) private void urlTextBox_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)


+ 43
- 0
shadowsocks-csharp/Views/VersionUpdatePromptView.xaml View File

@@ -0,0 +1,43 @@
<reactiveui:ReactiveUserControl
x:Class="Shadowsocks.Views.VersionUpdatePromptView"
x:TypeArguments="vms:VersionUpdatePromptViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shadowsocks.Views"
xmlns:vms="clr-namespace:Shadowsocks.ViewModels"
xmlns:reactiveui="http://reactiveui.net"
xmlns:mdxam="clr-namespace:MdXaml;assembly=MdXaml"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
lex:LocalizeDictionary.DesignCulture="en"
lex:ResxLocalizationProvider.DefaultAssembly="Shadowsocks"
lex:ResxLocalizationProvider.DefaultDictionary="Strings"
mc:Ignorable="d"
d:DesignHeight="480" d:DesignWidth="640">
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Margin="8 8 8 4" Grid.Row="0"
FontSize="16"
Text="{lex:Loc updatePromptTitle}" />
<TextBlock Margin="8 4 8 8" Grid.Row="1"
Text="{lex:Loc updatePromptBody}" />
<mdxam:MarkdownScrollViewer x:Name="releaseNotesMarkdownScrollViewer"
Margin="8"
Grid.Row="2"
Markdown="{Binding ReleaseNotes}"
MarkdownStyle="{x:Static mdxam:MarkdownStyle.GithubLike}"/>
<StackPanel Orientation="Horizontal" Grid.Row="3">
<Button x:Name="updateButton" Margin="8 8 4 4" Width="75" Height="23" Content="{lex:Loc}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Row="3" HorizontalAlignment="Right">
<Button x:Name="skipVersionButton" Margin="4 8 4 4" Width="75" Height="23" Content="{lex:Loc}"/>
<Button x:Name="notNowButton" Margin="4 8 8 4" Width="75" Height="23" Content="{lex:Loc}"/>
</StackPanel>
</Grid>
</reactiveui:ReactiveUserControl>

+ 40
- 0
shadowsocks-csharp/Views/VersionUpdatePromptView.xaml.cs View File

@@ -0,0 +1,40 @@
using Newtonsoft.Json.Linq;
using ReactiveUI;
using Shadowsocks.ViewModels;
using System.Reactive.Disposables;

namespace Shadowsocks.Views
{
/// <summary>
/// Interaction logic for VersionUpdatePromptView.xaml
/// </summary>
public partial class VersionUpdatePromptView : ReactiveUserControl<VersionUpdatePromptViewModel>
{
public VersionUpdatePromptView(JToken releaseObject)
{
InitializeComponent();
ViewModel = new VersionUpdatePromptViewModel(releaseObject);
DataContext = ViewModel; // for compatibility with MdXaml
this.WhenActivated(disposables =>
{
/*this.OneWayBind(ViewModel,
viewModel => viewModel.ReleaseNotes,
view => releaseNotesMarkdownScrollViewer.Markdown)
.DisposeWith(disposables);*/

this.BindCommand(ViewModel,
viewModel => viewModel.Update,
view => view.updateButton)
.DisposeWith(disposables);
this.BindCommand(ViewModel,
viewModel => viewModel.SkipVersion,
view => view.skipVersionButton)
.DisposeWith(disposables);
this.BindCommand(ViewModel,
viewModel => viewModel.NotNow,
view => view.notNowButton)
.DisposeWith(disposables);
});
}
}
}

+ 4
- 0
shadowsocks-csharp/app.config View File

@@ -26,6 +26,10 @@
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" /> <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly> </dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.AvalonEdit" publicKeyToken="9cc39be672370310" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.1.278" newVersion="6.0.1.278" />
</dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
<userSettings> <userSettings>


+ 10
- 2
shadowsocks-csharp/packages.config View File

@@ -1,17 +1,23 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="AvalonEdit" version="6.0.1" targetFramework="net472" />
<package id="Caseless.Fody" version="1.9.0" targetFramework="net472" /> <package id="Caseless.Fody" version="1.9.0" targetFramework="net472" />
<package id="CommandLineParser" version="2.8.0" targetFramework="net472" /> <package id="CommandLineParser" version="2.8.0" targetFramework="net472" />
<package id="Costura.Fody" version="4.1.0" targetFramework="net472" /> <package id="Costura.Fody" version="4.1.0" targetFramework="net472" />
<package id="DynamicData" version="6.17.14" targetFramework="net472" /> <package id="DynamicData" version="6.17.14" targetFramework="net472" />
<package id="Fody" version="6.2.6" targetFramework="net472" developmentDependency="true" />
<package id="Fody" version="6.3.0" targetFramework="net472" developmentDependency="true" />
<package id="GlobalHotKey" version="1.1.0" targetFramework="net472" /> <package id="GlobalHotKey" version="1.1.0" targetFramework="net472" />
<package id="Google.Protobuf" version="3.13.0" targetFramework="net472" /> <package id="Google.Protobuf" version="3.13.0" targetFramework="net472" />
<package id="MdXaml" version="1.6.0" targetFramework="net472" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" /> <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" />
<package id="NLog" version="4.7.5" targetFramework="net472" /> <package id="NLog" version="4.7.5" targetFramework="net472" />
<package id="Pharmacist.Common" version="1.8.1" targetFramework="net472" />
<package id="ReactiveUI" version="11.5.35" targetFramework="net472" /> <package id="ReactiveUI" version="11.5.35" targetFramework="net472" />
<package id="ReactiveUI.Events.WPF" version="11.5.35" targetFramework="net472" />
<package id="ReactiveUI.Fody" version="11.5.35" targetFramework="net472" />
<package id="ReactiveUI.Validation" version="1.7.1" targetFramework="net472" />
<package id="ReactiveUI.WPF" version="11.5.35" targetFramework="net472" /> <package id="ReactiveUI.WPF" version="11.5.35" targetFramework="net472" />
<package id="Splat" version="9.5.49" targetFramework="net472" />
<package id="Splat" version="9.6.1" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" /> <package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="System.IO" version="4.3.0" targetFramework="net472" /> <package id="System.IO" version="4.3.0" targetFramework="net472" />
<package id="System.Memory" version="4.5.4" targetFramework="net472" /> <package id="System.Memory" version="4.5.4" targetFramework="net472" />
@@ -26,5 +32,7 @@
<package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net472" /> <package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" /> <package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" /> <package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
<package id="WPFLocalizeExtension" version="3.8.0" targetFramework="net472" />
<package id="XAMLMarkupExtensions" version="2.0.0" targetFramework="net472" />
<package id="ZXing.Net" version="0.16.6" targetFramework="net472" /> <package id="ZXing.Net" version="0.16.6" targetFramework="net472" />
</packages> </packages>

+ 81
- 33
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\ReactiveUI.Fody.11.5.35\build\ReactiveUI.Fody.props" Condition="Exists('..\packages\ReactiveUI.Fody.11.5.35\build\ReactiveUI.Fody.props')" />
<Import Project="..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" /> <Import Project="..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" />
<Import Project="..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props" Condition="Exists('..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props')" /> <Import Project="..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props" Condition="Exists('..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props')" />
<PropertyGroup> <PropertyGroup>
@@ -87,6 +88,12 @@
<Reference Include="Google.Protobuf, Version=3.13.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> <Reference Include="Google.Protobuf, Version=3.13.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.13.0\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.13.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference> </Reference>
<Reference Include="ICSharpCode.AvalonEdit, Version=6.0.1.278, Culture=neutral, PublicKeyToken=9cc39be672370310, processorArchitecture=MSIL">
<HintPath>..\packages\AvalonEdit.6.0.1\lib\net45\ICSharpCode.AvalonEdit.dll</HintPath>
</Reference>
<Reference Include="MdXaml, Version=1.6.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MdXaml.1.6.0\lib\net45\MdXaml.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.VisualBasic" /> <Reference Include="Microsoft.VisualBasic" />
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
@@ -95,16 +102,29 @@
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.7.5\lib\net45\NLog.dll</HintPath> <HintPath>..\packages\NLog.4.7.5\lib\net45\NLog.dll</HintPath>
</Reference> </Reference>
<Reference Include="Pharmacist.Common, Version=1.8.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Pharmacist.Common.1.8.1\lib\netstandard2.0\Pharmacist.Common.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" /> <Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" /> <Reference Include="PresentationFramework" />
<Reference Include="PresentationFramework.Aero" />
<Reference Include="ReactiveUI, Version=11.5.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="ReactiveUI, Version=11.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ReactiveUI.11.5.35\lib\net461\ReactiveUI.dll</HintPath> <HintPath>..\packages\ReactiveUI.11.5.35\lib\net461\ReactiveUI.dll</HintPath>
</Reference> </Reference>
<Reference Include="ReactiveUI.Events.WPF, Version=11.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ReactiveUI.Events.WPF.11.5.35\lib\net472\ReactiveUI.Events.WPF.dll</HintPath>
</Reference>
<Reference Include="ReactiveUI.Fody.Helpers, Version=11.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ReactiveUI.Fody.11.5.35\lib\net461\ReactiveUI.Fody.Helpers.dll</HintPath>
</Reference>
<Reference Include="ReactiveUI.Validation, Version=1.7.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ReactiveUI.Validation.1.7.1\lib\net461\ReactiveUI.Validation.dll</HintPath>
</Reference>
<Reference Include="ReactiveUI.WPF, Version=11.5.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="ReactiveUI.WPF, Version=11.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ReactiveUI.WPF.11.5.35\lib\net472\ReactiveUI.WPF.dll</HintPath> <HintPath>..\packages\ReactiveUI.WPF.11.5.35\lib\net472\ReactiveUI.WPF.dll</HintPath>
</Reference> </Reference>
<Reference Include="Splat, Version=9.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Splat.9.5.49\lib\net461\Splat.dll</HintPath>
<Reference Include="Splat, Version=9.6.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Splat.9.6.1\lib\net461\Splat.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
@@ -184,6 +204,12 @@
<Reference Include="UIAutomationProvider" /> <Reference Include="UIAutomationProvider" />
<Reference Include="WindowsBase" /> <Reference Include="WindowsBase" />
<Reference Include="WindowsFormsIntegration" /> <Reference Include="WindowsFormsIntegration" />
<Reference Include="WPFLocalizeExtension, Version=3.8.0.0, Culture=neutral, PublicKeyToken=c726e0262981a1eb, processorArchitecture=MSIL">
<HintPath>..\packages\WPFLocalizeExtension.3.8.0\lib\net452\WPFLocalizeExtension.dll</HintPath>
</Reference>
<Reference Include="XAMLMarkupExtensions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c726e0262981a1eb, processorArchitecture=MSIL">
<HintPath>..\packages\XAMLMarkupExtensions.2.0.0\lib\net472\XAMLMarkupExtensions.dll</HintPath>
</Reference>
<Reference Include="zxing, Version=0.16.6.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL"> <Reference Include="zxing, Version=0.16.6.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
<HintPath>..\packages\ZXing.Net.0.16.6\lib\net47\zxing.dll</HintPath> <HintPath>..\packages\ZXing.Net.0.16.6\lib\net47\zxing.dll</HintPath>
</Reference> </Reference>
@@ -218,10 +244,16 @@
<Compile Include="Encryption\Stream\StreamMbedTLSEncryptor.cs" /> <Compile Include="Encryption\Stream\StreamMbedTLSEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamOpenSSLEncryptor.cs" /> <Compile Include="Encryption\Stream\StreamOpenSSLEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" /> <Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" />
<Compile Include="Localization\LocalizationProvider.cs" />
<Compile Include="Localization\Strings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Strings.resx</DependentUpon>
</Compile>
<Compile Include="Model\Geosite\Geosite.cs" /> <Compile Include="Model\Geosite\Geosite.cs" />
<Compile Include="Model\HotKeyConfig.cs" /> <Compile Include="Model\HotKeyConfig.cs" />
<Compile Include="Model\NLogConfig.cs" /> <Compile Include="Model\NLogConfig.cs" />
<Compile Include="Model\ProxyConfig.cs" />
<Compile Include="Model\ForwardProxyConfig.cs" />
<Compile Include="Model\SysproxyConfig.cs" /> <Compile Include="Model\SysproxyConfig.cs" />
<Compile Include="Properties\Resources.Designer.cs"> <Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
@@ -268,7 +300,23 @@
<Compile Include="Util\SystemProxy\Sysproxy.cs" /> <Compile Include="Util\SystemProxy\Sysproxy.cs" />
<Compile Include="Util\Util.cs" /> <Compile Include="Util\Util.cs" />
<Compile Include="Util\ViewUtils.cs" /> <Compile Include="Util\ViewUtils.cs" />
<Compile Include="ViewModels\ForwardProxyViewModel.cs" />
<Compile Include="ViewModels\HotkeysViewModel.cs" />
<Compile Include="ViewModels\OnlineConfigViewModel.cs" />
<Compile Include="ViewModels\ServerSharingViewModel.cs" /> <Compile Include="ViewModels\ServerSharingViewModel.cs" />
<Compile Include="ViewModels\VersionUpdatePromptViewModel.cs" />
<Compile Include="Views\ForwardProxyView.xaml.cs">
<DependentUpon>ForwardProxyView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\HotkeysView.xaml.cs">
<DependentUpon>HotkeysView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\OnlineConfigView.xaml.cs">
<DependentUpon>OnlineConfigView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\VersionUpdatePromptView.xaml.cs">
<DependentUpon>VersionUpdatePromptView.xaml</DependentUpon>
</Compile>
<Compile Include="View\ConfigForm.cs"> <Compile Include="View\ConfigForm.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@@ -287,12 +335,6 @@
<Compile Include="View\CalculationControl.Designer.cs"> <Compile Include="View\CalculationControl.Designer.cs">
<DependentUpon>CalculationControl.cs</DependentUpon> <DependentUpon>CalculationControl.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="View\HotkeySettingsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\HotkeySettingsForm.designer.cs">
<DependentUpon>HotkeySettingsForm.cs</DependentUpon>
</Compile>
<Compile Include="View\LogForm.cs"> <Compile Include="View\LogForm.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@@ -300,18 +342,6 @@
<DependentUpon>LogForm.cs</DependentUpon> <DependentUpon>LogForm.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="View\MenuViewController.cs" /> <Compile Include="View\MenuViewController.cs" />
<Compile Include="View\OnlineConfigForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\OnlineConfigForm.Designer.cs">
<DependentUpon>OnlineConfigForm.cs</DependentUpon>
</Compile>
<Compile Include="View\ProxyForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\ProxyForm.Designer.cs">
<DependentUpon>ProxyForm.cs</DependentUpon>
</Compile>
<Compile Include="View\QRCodeSplashForm.cs"> <Compile Include="View\QRCodeSplashForm.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@@ -324,30 +354,31 @@
<Compile Include="View\StatisticsStrategyConfigurationForm.Designer.cs"> <Compile Include="View\StatisticsStrategyConfigurationForm.Designer.cs">
<DependentUpon>StatisticsStrategyConfigurationForm.cs</DependentUpon> <DependentUpon>StatisticsStrategyConfigurationForm.cs</DependentUpon>
</Compile> </Compile>
<EmbeddedResource Include="Localization\Strings.fr.resx" />
<EmbeddedResource Include="Localization\Strings.ja.resx" />
<EmbeddedResource Include="Localization\Strings.ko.resx" />
<EmbeddedResource Include="Localization\Strings.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Strings.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Localization\Strings.ru.resx" />
<EmbeddedResource Include="Localization\Strings.zh-Hans.resx" />
<EmbeddedResource Include="Localization\Strings.zh-Hant.resx" />
<EmbeddedResource Include="View\ConfigForm.resx"> <EmbeddedResource Include="View\ConfigForm.resx">
<DependentUpon>ConfigForm.cs</DependentUpon> <DependentUpon>ConfigForm.cs</DependentUpon>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<Generator>PublicResXFileCodeGenerator</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="View\CalculationControl.resx"> <EmbeddedResource Include="View\CalculationControl.resx">
<DependentUpon>CalculationControl.cs</DependentUpon> <DependentUpon>CalculationControl.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="View\HotkeySettingsForm.resx">
<DependentUpon>HotkeySettingsForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\LogForm.resx"> <EmbeddedResource Include="View\LogForm.resx">
<DependentUpon>LogForm.cs</DependentUpon> <DependentUpon>LogForm.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="View\OnlineConfigForm.resx">
<DependentUpon>OnlineConfigForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\ProxyForm.resx">
<DependentUpon>ProxyForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\StatisticsStrategyConfigurationForm.resx"> <EmbeddedResource Include="View\StatisticsStrategyConfigurationForm.resx">
<DependentUpon>StatisticsStrategyConfigurationForm.cs</DependentUpon> <DependentUpon>StatisticsStrategyConfigurationForm.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
@@ -412,22 +443,39 @@
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Include="Views\ForwardProxyView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\HotkeysView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\OnlineConfigView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ServerSharingView.xaml"> <Page Include="Views\ServerSharingView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Views\VersionUpdatePromptView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Fody.6.2.6\build\Fody.targets" Condition="Exists('..\packages\Fody.6.2.6\build\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\packages\Fody.6.2.6\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.6.2.6\build\Fody.targets'))" />
<Error Condition="!Exists('..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props'))" /> <Error Condition="!Exists('..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props'))" />
<Error Condition="!Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" /> <Error Condition="!Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" />
<Error Condition="!Exists('..\packages\Fody.6.3.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.6.3.0\build\Fody.targets'))" />
<Error Condition="!Exists('..\packages\ReactiveUI.Fody.11.5.35\build\ReactiveUI.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ReactiveUI.Fody.11.5.35\build\ReactiveUI.Fody.props'))" />
</Target> </Target>
<Import Project="..\packages\Fody.6.3.0\build\Fody.targets" Condition="Exists('..\packages\Fody.6.3.0\build\Fody.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">


+ 4
- 0
test/app.config View File

@@ -10,6 +10,10 @@
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" /> <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly> </dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.AvalonEdit" publicKeyToken="9cc39be672370310" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.1.278" newVersion="6.0.1.278" />
</dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
</configuration> </configuration>

Loading…
Cancel
Save