diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index d59b8bd7..f2323521 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,13 +1,26 @@
Changelog
=========
+v1.0.16
+-------
+
+ - Installer recommends Syncthing 0.11 (#64)
+ - Fix bad browser zoom after restart (#57)
+ - Fix display of folders which contain an underscore (#58)
+ - Handle duplicate devices/folders in Syncthing config (#61)
+ - Fix bad character encoding in Syncthing console (#62)
+ - Fix installer's handling of Syncthing version changes (#63)
+ - Clarify some UI wording/typos (#60, others)
+ - Remember size of Syncthing console (#56)
+ - Updated translations
+
v1.0.15
-------
- Fix crash on startup if Syncthing is slow to start (#55)
- - Remember window size-position (#51)
- - Zoom built-in borwser (#52)
- - Add support for aribtrary environmental variables for Syncthing
+ - Remember window size/position (#51)
+ - Zoom built-in browser (#52)
+ - Add support for arbitrary environmental variables for Syncthing
v1.0.14
-------
diff --git a/Rakefile b/Rakefile
index f6d20bfb..763838a3 100644
--- a/Rakefile
+++ b/Rakefile
@@ -43,6 +43,8 @@ class ArchDirConfig
end
end
+SYNCTHING_VERSIONS_TO_UPDATE = ['0.11']
+
ARCH_CONFIG = [ArchDirConfig.new('x64'), ArchDirConfig.new('x86')]
ASSEMBLY_INFOS = FileList['**/AssemblyInfo.cs']
@@ -166,7 +168,7 @@ namespace :"update-syncthing" do
ARCH_CONFIG.each do |arch_config|
desc "Update syncthing binaries (#{arch_config.arch}"
task arch_config.arch do
- arch_config.syncthing_binaries.values.each do |bin|
+ arch_config.syncthing_binaries.values_at(*SYNCTHING_VERSIONS_TO_UPDATE).each do |bin|
path = File.join(arch_config.installer_dir, bin)
raise "Could not find #{path}" unless File.exist?(path)
sh path, '-upgrade' do; end
diff --git a/installer/x64/installer-x64.iss b/installer/x64/installer-x64.iss
index dbb63a3c..627eabc8 100644
--- a/installer/x64/installer-x64.iss
+++ b/installer/x64/installer-x64.iss
@@ -43,12 +43,13 @@ TouchDate=current
Name: "english"; MessagesFile: "compiler:Default.isl"
[CustomMessages]
-SyncthingVersion=%nPlease select the Syncthing version.%n%n!! IMPORTANT !!%n%nv0.10 and v0.11 (beta) are incompatible. All of your devices must either use v0.10 or v0.11 (beta).
+SyncthingVersion=%nPlease select the Syncthing version.%n%nv0.11 and v0.10 are incompatible. All of your devices must either use v0.11 or v0.10.%n
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
-Name: "syncthing0p10"; Description: "Syncthing v0.10 (recommended)"; GroupDescription: "{cm:SyncthingVersion}"; Flags: exclusive
-Name: "syncthing0p11"; Description: "Syncthing v0.11 (beta)"; GroupDescription: "{cm:SyncthingVersion}"; Flags: exclusive unchecked
+Name: "syncthing0p11"; Description: "Syncthing v0.11 (recommended)"; GroupDescription: "{cm:SyncthingVersion}"; Flags: exclusive
+Name: "syncthing0p10"; Description: "Syncthing v0.10"; GroupDescription: "{cm:SyncthingVersion}"; Flags: exclusive unchecked
+
[Dirs]
Name: "{userappdata}\{#AppDataFolder}"
@@ -86,12 +87,32 @@ begin
result := not exists or (release < 378758);
end;
+procedure BumpInstallCount;
+var
+ fileContents: AnsiString;
+ installCount: integer;
+begin
+ { Increment the install count in InstallCount.txt if it exists, or create it with the contents '1' if it doesn't }
+ if LoadStringFromFile(ExpandConstant('{app}\InstallCount.txt'), fileContents) then
+ begin
+ installCount := StrTointDef(Trim(string(fileContents)), 0) + 1;
+ end
+ else
+ begin
+ installCount := 1;
+ end;
+
+ SaveStringToFile(ExpandConstant('{app}\InstallCount.txt'), IntToStr(installCount), False);
+end;
+
procedure CurStepChanged(CurStep: TSetupStep);
var
ResultCode: integer;
begin
if CurStep = ssInstall then
begin
+ BumpInstallCount();
+
{ We might be being run from ProcessRunner.exe, *and* we might be trying to update it. Funsies. Let's rename it (which Windows lets us do) }
DeleteFile(ExpandConstant('{app}\ProcessRunner.exe.old'));
RenameFile(ExpandConstant('{app}\ProcessRunner.exe'), ExpandConstant('{app}\ProcessRunner.exe.old'));
@@ -114,5 +135,6 @@ end;
[UninstallDelete]
Type: files; Name: "{app}\ProcessRunner.exe.old"
+Type: files; Name: "{app}\InstallCount.txt"
Type: filesandordirs; Name: "{userappdata}\{#AppDataFolder}"
Type: filesandordirs; Name: "{userappdata}\{#AppDataFolder}"
\ No newline at end of file
diff --git a/installer/x86/installer-x86.iss b/installer/x86/installer-x86.iss
index f1859c78..99755da6 100644
--- a/installer/x86/installer-x86.iss
+++ b/installer/x86/installer-x86.iss
@@ -41,12 +41,12 @@ TouchDate=current
Name: "english"; MessagesFile: "compiler:Default.isl"
[CustomMessages]
-SyncthingVersion=%nPlease select the Syncthing version.%n%n!! IMPORTANT !!%n%nv0.10 and v0.11 (beta) are incompatible. All of your devices must either use v0.10 or v0.11 (beta).
+SyncthingVersion=%nPlease select the Syncthing version.%n%nv0.11 and v0.10 are incompatible. All of your devices must either use v0.11 or v0.10.%n
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
-Name: "syncthing0p10"; Description: "Syncthing v0.10 (recommended)"; GroupDescription: "{cm:SyncthingVersion}"; Flags: exclusive
-Name: "syncthing0p11"; Description: "Syncthing v0.11 (beta)"; GroupDescription: "{cm:SyncthingVersion}"; Flags: exclusive unchecked
+Name: "syncthing0p11"; Description: "Syncthing v0.11 (recommended)"; GroupDescription: "{cm:SyncthingVersion}"; Flags: exclusive
+Name: "syncthing0p10"; Description: "Syncthing v0.10"; GroupDescription: "{cm:SyncthingVersion}"; Flags: exclusive unchecked
[Dirs]
Name: "{userappdata}\{#AppDataFolder}"
@@ -84,12 +84,32 @@ begin
result := not exists or (release < 378758);
end;
+procedure BumpInstallCount;
+var
+ fileContents: AnsiString;
+ installCount: integer;
+begin
+ { Increment the install count in InstallCount.txt if it exists, or create it with the contents '1' if it doesn't }
+ if LoadStringFromFile(ExpandConstant('{app}\InstallCount.txt'), fileContents) then
+ begin
+ installCount := StrTointDef(Trim(string(fileContents)), 0) + 1;
+ end
+ else
+ begin
+ installCount := 1;
+ end;
+
+ SaveStringToFile(ExpandConstant('{app}\InstallCount.txt'), IntToStr(installCount), False);
+end;
+
procedure CurStepChanged(CurStep: TSetupStep);
var
ResultCode: integer;
begin
if CurStep = ssInstall then
begin
+ BumpInstallCount();
+
{ We might be being run from ProcessRunner.exe, *and* we might be trying to update it. Funsies. Let's rename it (which Windows lets us do) }
DeleteFile(ExpandConstant('{app}\ProcessRunner.exe.old'));
RenameFile(ExpandConstant('{app}\ProcessRunner.exe'), ExpandConstant('{app}\ProcessRunner.exe.old'));
@@ -112,5 +132,6 @@ end;
[UninstallDelete]
Type: files; Name: "{app}\ProcessRunner.exe.old"
+Type: files; Name: "{app}\InstallCount.txt"
Type: filesandordirs; Name: "{userappdata}\{#AppDataFolder}"
Type: filesandordirs; Name: "{userappdata}\{#AppDataFolder}"
\ No newline at end of file
diff --git a/server/version_check.php b/server/version_check.php
index 3c433519..73da4fdf 100644
--- a/server/version_check.php
+++ b/server/version_check.php
@@ -65,6 +65,16 @@ function get_with_wildcard($src, $value, $default = null)
}
$versions = [
+ '1.0.16' => [
+ 'installed' => [
+ 'direct_download_url' => [
+ 'x64' => 'https://github.com/canton7/SyncTrayzor/releases/download/v1.0.16/SyncTrayzorSetup-x64.exe',
+ 'x86' => 'https://github.com/canton7/SyncTrayzor/releases/download/v1.0.16/SyncTrayzorSetup-x86.exe',
+ ],
+ ],
+ 'release_page_url' => 'https://github.com/canton7/SyncTrayzor/releases/tag/v1.0.16',
+ 'release_notes' => "- Installer recommends Syncthing 0.11 (#64)\n- Fix bad browser zoom after restart (#57)\n- Fix display of folders which contain an underscore (#58)\n- Handle duplicate devices/folders in Syncthing config (#61)\n- Fix bad character encoding in Syncthing console (#62)\n- Fix installer's handling of Syncthing version changes (#63)\n- Clarify some UI wording/typos (#60, others)\n- Remember size of Syncthing console (#56)\n- Updated translations",
+ ],
'1.0.15' => [
'installed' => [
'direct_download_url' => [
@@ -73,14 +83,14 @@ function get_with_wildcard($src, $value, $default = null)
],
],
'release_page_url' => 'https://github.com/canton7/SyncTrayzor/releases/tag/v1.0.15',
- 'release_notes' => "- Fix crash on startup if Syncthing is slow to start (#55)\n- Remember window size-position (#51)\n- Zoom built-in borwser (#52)\n- Add support for aribtrary environmental variables for Syncthing\n",
+ 'release_notes' => "- Fix crash on startup if Syncthing is slow to start (#55)\n- Remember window size/position (#51)\n- Zoom built-in browser (#52)\n- Add support for arbitrary environmental variables for Syncthing",
],
'1.0.14' => [
'installed' => [
'direct_download_url' => []
],
'release_page_url' => 'https://github.com/canton7/SyncTrayzor/releases/tag/v1.0.14',
- 'release_notes' => "- Give Syncthing more than 10 seconds to start, fixing crash (#47, #48, #50)\n- Better Syncthing API management in general\n- Add support for 150% and 200% DPI to tray icon\n- Slightly improve UI\n",
+ 'release_notes' => "- Give Syncthing more than 10 seconds to start, fixing crash (#47, #48, #50)\n- Better Syncthing API management in general\n- Add support for 150% and 200% DPI to tray icon\n- Slightly improve UI",
],
'1.0.13' => [
'installed' => [
@@ -92,6 +102,7 @@ function get_with_wildcard($src, $value, $default = null)
];
$upgrades = [
+ '1.0.15' => ['to' => 'latest', 'formatter' => '2'],
'1.0.14' => ['to' => 'latest', 'formatter' => '2'],
'1.0.13' => ['to' => 'latest', 'formatter' => '1'],
'1.0.12' => ['to' => 'latest', 'formatter' => '1'],
diff --git a/src/ProcessRunner/Properties/AssemblyInfo.cs b/src/ProcessRunner/Properties/AssemblyInfo.cs
index acc6002f..5d39ad3e 100644
--- a/src/ProcessRunner/Properties/AssemblyInfo.cs
+++ b/src/ProcessRunner/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.15.0")]
-[assembly: AssemblyFileVersion("1.0.15.0")]
+[assembly: AssemblyVersion("1.0.16.0")]
+[assembly: AssemblyFileVersion("1.0.16.0")]
diff --git a/src/SyncTrayzor/App.config b/src/SyncTrayzor/App.config
index 16a10987..a5adc2eb 100644
--- a/src/SyncTrayzor/App.config
+++ b/src/SyncTrayzor/App.config
@@ -46,7 +46,7 @@
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="3">
false
false
true
@@ -62,8 +62,9 @@
true
true
true
- true
+ 100
0
+ 0
diff --git a/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml b/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml
index 82e8ed8d..fe27e759 100644
--- a/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml
+++ b/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml
@@ -3,7 +3,8 @@
xmlns:s="https://github.com/canton7/Stylet"
xmlns:l="clr-namespace:SyncTrayzor.Localization"
xmlns:ni="clr-namespace:SyncTrayzor.NotifyIcon"
- xmlns:tb="http://www.hardcodet.net/taskbar">
+ xmlns:tb="http://www.hardcodet.net/taskbar"
+ xmlns:xaml="clr-namespace:SyncTrayzor.Xaml">
@@ -79,7 +80,7 @@
Visibility="{Binding Folders, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
diff --git a/src/SyncTrayzor/Pages/SettingsView.xaml b/src/SyncTrayzor/Pages/SettingsView.xaml
index 68695d4b..74cea72d 100644
--- a/src/SyncTrayzor/Pages/SettingsView.xaml
+++ b/src/SyncTrayzor/Pages/SettingsView.xaml
@@ -119,7 +119,10 @@
-
+
+
+
+
diff --git a/src/SyncTrayzor/Pages/ShellView.xaml b/src/SyncTrayzor/Pages/ShellView.xaml
index 96fd9ce2..1b318d3a 100644
--- a/src/SyncTrayzor/Pages/ShellView.xaml
+++ b/src/SyncTrayzor/Pages/ShellView.xaml
@@ -53,22 +53,23 @@
-
+
-
+
-
+
-
+
diff --git a/src/SyncTrayzor/Pages/ShellViewModel.cs b/src/SyncTrayzor/Pages/ShellViewModel.cs
index bec55f82..5db48bee 100644
--- a/src/SyncTrayzor/Pages/ShellViewModel.cs
+++ b/src/SyncTrayzor/Pages/ShellViewModel.cs
@@ -27,6 +27,7 @@ public class ShellViewModel : Screen
public bool WindowActivated { get; set; }
public bool ShowConsole { get; set; }
+ public double ConsoleHeight { get; set; }
public WindowPlacement Placement { get; set; }
public ConsoleViewModel Console { get; private set; }
public ViewerViewModel Viewer { get; private set; }
@@ -62,8 +63,14 @@ public ShellViewModel(
this.syncThingManager.StateChanged += (o, e) => this.SyncThingState = e.NewState;
this.syncThingManager.ProcessExitedWithError += (o, e) => this.ShowExitedWithError();
- this.ShowConsole = configuration.ShowSyncthingConsole;
- this.Bind(s => s.ShowConsole, (o, e) => this.configurationProvider.AtomicLoadAndSave(c => c.ShowSyncthingConsole = e.NewValue));
+ this.ConsoleHeight = configuration.SyncthingConsoleHeight;
+ this.Bind(s => s.ConsoleHeight, (o, e) => this.configurationProvider.AtomicLoadAndSave(c => c.SyncthingConsoleHeight = e.NewValue));
+
+ this.ShowConsole = configuration.SyncthingConsoleHeight > 0;
+ this.Bind(s => s.ShowConsole, (o, e) =>
+ {
+ this.ConsoleHeight = e.NewValue ? Configuration.DefaultSyncthingConsoleHeight : 0.0;
+ });
this.Placement = configuration.WindowPlacement;
this.Bind(s => s.Placement, (o, e) => this.configurationProvider.AtomicLoadAndSave(c => c.WindowPlacement = e.NewValue));
diff --git a/src/SyncTrayzor/Pages/ViewerViewModel.cs b/src/SyncTrayzor/Pages/ViewerViewModel.cs
index 4d0aac60..39e49711 100644
--- a/src/SyncTrayzor/Pages/ViewerViewModel.cs
+++ b/src/SyncTrayzor/Pages/ViewerViewModel.cs
@@ -29,6 +29,7 @@ public class ViewerViewModel : Screen, IRequestHandler, ILifeSpanHandler
private readonly object cultureLock = new object(); // This can be read from many threads
private CultureInfo culture;
+ private double zoomLevel;
public string Location { get; private set; }
@@ -36,7 +37,7 @@ public class ViewerViewModel : Screen, IRequestHandler, ILifeSpanHandler
public bool ShowSyncThingStarting { get { return this.syncThingState == SyncThingState.Starting; } }
public bool ShowSyncThingStopped { get { return this.syncThingState == SyncThingState.Stopped; ; } }
- public IWpfWebBrowser WebBrowser { get; set; }
+ public ChromiumWebBrowser WebBrowser { get; set; }
private JavascriptCallbackObject callback;
@@ -51,6 +52,9 @@ public ViewerViewModel(
this.processStartProvider = processStartProvider;
this.configurationProvider = configurationProvider;
+ var configuration = this.configurationProvider.Load();
+ this.zoomLevel = configuration.SyncthingWebBrowserZoomLevel;
+
this.syncThingManager.StateChanged += (o, e) =>
{
this.syncThingState = e.NewState;
@@ -65,7 +69,7 @@ public ViewerViewModel(
this.InitializeBrowser(e.NewValue);
});
- this.SetCulture(configurationProvider.Load());
+ this.SetCulture(configuration);
configurationProvider.ConfigurationChanged += (o, e) => this.SetCulture(e.NewConfiguration);
}
@@ -85,11 +89,25 @@ protected override void OnInitialActivate()
});
}
- private void InitializeBrowser(IWpfWebBrowser webBrowser)
+ private void InitializeBrowser(ChromiumWebBrowser webBrowser)
{
webBrowser.RequestHandler = this;
webBrowser.LifeSpanHandler = this;
webBrowser.RegisterJsObject("callbackObject", this.callback);
+
+ // So. Fun story. From https://github.com/cefsharp/CefSharp/issues/738#issuecomment-91099199, we need to set the zoom level
+ // in the FrameLoadStart event. However, the IWpfWebBrowser's ZoomLevel is a DependencyProperty, and it wraps
+ // the SetZoomLevel method on the unmanaged browser (which is exposed directly by ChromiumWebBrowser, but not by IWpfWebBrowser).
+ // Now, FrameLoadState and FrameLoadEnd are called on a background thread, and since ZoomLevel is a DP, it can only be changed
+ // from the UI thread (it's "helpful" and does a dispatcher check for us). But, if we dispatch back to the UI thread to call
+ // ZoomLevel = xxx, then CEF seems to hit threading issues, and can sometimes render things entirely badly (massive icons, no
+ // localization, bad spacing, no JavaScript at all, etc).
+ // So, in this case, we need to call SetZoomLevel directly, as we can do that from the thread on which FrameLoadStart is called,
+ // and everything's happy.
+ // However, this means that the DP value isn't updated... Which means we can't use the DP at all. We have to call SetZoomLevel
+ // *everywhere*, and that means keeping a local field zoomLevel to track the current zoom level. Such is life
+
+ webBrowser.FrameLoadStart += (o, e) => webBrowser.SetZoomLevel(this.zoomLevel);
webBrowser.FrameLoadEnd += (o, e) =>
{
if (e.IsMainFrame && e.Url != "about:blank")
@@ -103,7 +121,6 @@ private void InitializeBrowser(IWpfWebBrowser webBrowser)
webBrowser.ExecuteScriptAsync(script);
}
};
- WebBrowser.ZoomLevel = this.configurationProvider.Load().SyncthingWebBrowserZoomLevel;
}
public void RefreshBrowser()
@@ -115,30 +132,27 @@ public void RefreshBrowser()
public void ZoomIn()
{
- this.ZoomBy(0.2);
+ this.ZoomTo(this.zoomLevel + 0.2);
}
public void ZoomOut()
{
- this.ZoomBy(-0.2);
+ this.ZoomTo(this.zoomLevel - 0.2);
}
- private void ZoomBy(double amount)
+ public void ZoomReset()
{
- if (this.WebBrowser == null || this.syncThingState != SyncThingState.Running)
- return;
-
- this.WebBrowser.ZoomLevel += amount;
- this.configurationProvider.AtomicLoadAndSave(c => c.SyncthingWebBrowserZoomLevel = this.WebBrowser.ZoomLevel);
+ this.ZoomTo(0.0);
}
- public void ZoomReset()
+ private void ZoomTo(double zoomLevel)
{
if (this.WebBrowser == null || this.syncThingState != SyncThingState.Running)
return;
- this.WebBrowser.ZoomLevel = 0;
- this.configurationProvider.AtomicLoadAndSave(c => c.SyncthingWebBrowserZoomLevel = this.WebBrowser.ZoomLevel);
+ this.zoomLevel = zoomLevel;
+ this.WebBrowser.SetZoomLevel(zoomLevel);
+ this.configurationProvider.AtomicLoadAndSave(c => c.SyncthingWebBrowserZoomLevel = zoomLevel);
}
private void OpenFolder(string folderId)
diff --git a/src/SyncTrayzor/Properties/AssemblyInfo.cs b/src/SyncTrayzor/Properties/AssemblyInfo.cs
index e47065ae..28a54390 100644
--- a/src/SyncTrayzor/Properties/AssemblyInfo.cs
+++ b/src/SyncTrayzor/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.15.0")]
-[assembly: AssemblyFileVersion("1.0.15.0")]
+[assembly: AssemblyVersion("1.0.16.0")]
+[assembly: AssemblyFileVersion("1.0.16.0")]
diff --git a/src/SyncTrayzor/Properties/Settings.Designer.cs b/src/SyncTrayzor/Properties/Settings.Designer.cs
index 972455ff..0bf7d81e 100644
--- a/src/SyncTrayzor/Properties/Settings.Designer.cs
+++ b/src/SyncTrayzor/Properties/Settings.Designer.cs
@@ -116,7 +116,7 @@ public int SyncthingConnectTimeoutSeconds {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute(@"
-
+
false
false
true
@@ -132,8 +132,9 @@ public int SyncthingConnectTimeoutSeconds {
true
true
true
- true
+ 100
0
+ 0
")]
public global::SyncTrayzor.Services.Config.Configuration DefaultUserConfiguration {
get {
diff --git a/src/SyncTrayzor/Properties/Settings.settings b/src/SyncTrayzor/Properties/Settings.settings
index c90e592e..bacafcd3 100644
--- a/src/SyncTrayzor/Properties/Settings.settings
+++ b/src/SyncTrayzor/Properties/Settings.settings
@@ -34,7 +34,7 @@
<?xml version="1.0" encoding="utf-16"?>
-<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="2">
+<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="3">
<ShowTrayIconOnlyOnClose>false</ShowTrayIconOnlyOnClose>
<MinimizeToTray>false</MinimizeToTray>
<CloseToTray>true</CloseToTray>
@@ -50,8 +50,9 @@
<NotifyOfNewVersions>true</NotifyOfNewVersions>
<ObfuscateDeviceIDs>true</ObfuscateDeviceIDs>
<UseComputerCulture>true</UseComputerCulture>
- <ShowSyncthingConsole>true</ShowSyncthingConsole>
+ <SyncthingConsoleHeight>100</SyncthingConsoleHeight>
<SyncthingWebBrowserZoomLevel>0</SyncthingWebBrowserZoomLevel>
+ <LastSeenInstallCount>0</LastSeenInstallCount>
</Configuration>
diff --git a/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs b/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs
index 68cd8f6f..67e85a9f 100644
--- a/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs
+++ b/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.18444
+// Runtime Version:4.0.30319.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -636,7 +636,7 @@ public static string SettingsView_Validation_NotShouldBeEmpty {
}
///
- /// Looks up a localized string similar to Must be in the format 'VAR=value VAR2="val1 vla2"'.
+ /// Looks up a localized string similar to Must be in the format 'VAR=value VAR2="val1 val2"'.
///
public static string SettingsView_Validation_SyncthingEnvironmentalVariablesMustHaveFormat {
get {
@@ -645,7 +645,7 @@ public static string SettingsView_Validation_SyncthingEnvironmentalVariablesMust
}
///
- /// Looks up a localized string similar to The following folders will be watched for changes, which avoids polling..
+ /// Looks up a localized string similar to The following folders will be watched for changes, which means you can set a longer polling interval..
///
public static string SettingsView_WatchedFolders_Explanation {
get {
diff --git a/src/SyncTrayzor/Properties/Strings/Resources.cs.resx b/src/SyncTrayzor/Properties/Strings/Resources.cs.resx
index 8b3a016b..e9357053 100644
--- a/src/SyncTrayzor/Properties/Strings/Resources.cs.resx
+++ b/src/SyncTrayzor/Properties/Strings/Resources.cs.resx
@@ -167,7 +167,7 @@
_Nastavení
- P_omoc
+ _Pomoc
_O programu
@@ -305,11 +305,11 @@
Nastavení
Title of the 'settings' dialog
-
- Proměnné sledování Syncthing:
+
+ Proměnné prostředí Syncthing:
- V následujících adresářích budou sledovány změny, což zabrání opakovanému skenování.
+ V následujících adresářích budou sledovány změny, tudíž pro ně můžete nastavit delší interval opakování skenování.
Adresáře nejsou dostupné. Spusťte prosím Syncthing
@@ -557,4 +557,7 @@ Je nám líto, ale SyncTrayzor se musí ukončit.
_Resetovat
+
+ Musí být ve formátu 'PROM=hodnota PROM2="hodnota1 hodnota2"'
+
diff --git a/src/SyncTrayzor/Properties/Strings/Resources.de.resx b/src/SyncTrayzor/Properties/Strings/Resources.de.resx
index 0df903ea..2fac1059 100644
--- a/src/SyncTrayzor/Properties/Strings/Resources.de.resx
+++ b/src/SyncTrayzor/Properties/Strings/Resources.de.resx
@@ -121,7 +121,7 @@
Erstellt von Antony Male.
- Herunterladen
+ Herunterladen Seite öffnen
Clickable link allowing the user to download the latest version of SyncTrayzor
@@ -198,7 +198,7 @@
When a new version is available, the user receives a prompt. This button allows the user to say they want want to be prompted to upgrade to this particular version again
- Jetzt herunterladen
+ Herunterladen Seite öffnen
When a new version is available, the user receives a prompt. This button allows them to download the new version
@@ -305,11 +305,11 @@
Einstellungen
Title of the 'settings' dialog
-
- Syncthing Trace-Variablen:
+
+ Syncthing Umgebungsvariablen:
- Die folgenden Ordner werden auf Änderungen überwacht. Dies wiederum verhindert unnötige Abfragen.
+ The following folders will be watched for changes, which means you can set a longer polling interval.
Ordner nicht verfügbar, bitte Syncthing starten.
@@ -545,4 +545,19 @@ SyncTrayzor wird nun geschlossen.
Änderungshistorie anzeigen
+
+ _Zoom Browser
+
+
+ Hineinzoomen
+
+
+ Herauszoomen
+
+
+ Zurücksetzen
+
+
+ Muss im folgenden Format sein 'VAR=value VAR2="val1 val2"'
+
diff --git a/src/SyncTrayzor/Properties/Strings/Resources.el.resx b/src/SyncTrayzor/Properties/Strings/Resources.el.resx
index d709a8ad..2f7c1c91 100644
--- a/src/SyncTrayzor/Properties/Strings/Resources.el.resx
+++ b/src/SyncTrayzor/Properties/Strings/Resources.el.resx
@@ -121,7 +121,7 @@
Δημιουργήθηκε από τον Antony Male.
- Λήψη
+ Άνοιγμα σελίδας λήψης
Clickable link allowing the user to download the latest version of SyncTrayzor
@@ -198,7 +198,7 @@
When a new version is available, the user receives a prompt. This button allows the user to say they want want to be prompted to upgrade to this particular version again
- Λήψη τώρα
+ Άνοιγμα σελίδας λήψης
When a new version is available, the user receives a prompt. This button allows them to download the new version
@@ -305,11 +305,11 @@
Ρυθμίσεις
Title of the 'settings' dialog
-
- Syncthing ανίχνευση μεταβλητών:
+
+ Syncthing περιβαλλοντικές μεταβλητές:
- Οι ακόλουθοι φάκελοι θα πρέπει να παρακολουθούνται για αλλαγές, πράγμα που αποτρέπει την ψηφοφορία.
+ The following folders will be watched for changes, which means you can set a longer polling interval.
Φάκελοι μη διαθέσιμη. Παρακαλούμε ξεκινήστε το Syncthing
@@ -545,4 +545,19 @@ The menu option "Syncthing ->Kill all Syncthing processes" corresponds to She
Εμφάνιση αρχείου καταγραφής αλλαγών
+
+ _Zoom Browser
+
+
+ Μεγέθυνση
+
+
+ Σμίκρυνση
+
+
+ Eπαναφορά
+
+
+ Πρέπει να είναι στη μορφή 'VAR=value VAR2="val1 val2"'
+
diff --git a/src/SyncTrayzor/Properties/Strings/Resources.es.resx b/src/SyncTrayzor/Properties/Strings/Resources.es.resx
index a0992408..1ec58bb7 100644
--- a/src/SyncTrayzor/Properties/Strings/Resources.es.resx
+++ b/src/SyncTrayzor/Properties/Strings/Resources.es.resx
@@ -121,7 +121,7 @@
Creado por Antony Male.
- Open Download Page
+ Abrir la página de descargas
Clickable link allowing the user to download the latest version of SyncTrayzor
@@ -185,7 +185,7 @@
_Abrir en navegador externo
- _Refrescar navegador
+ Re_frescar navegador
_Comenzar
@@ -198,7 +198,7 @@
When a new version is available, the user receives a prompt. This button allows the user to say they want want to be prompted to upgrade to this particular version again
- Open Download Page
+ Abrir la página de descargas
When a new version is available, the user receives a prompt. This button allows them to download the new version
@@ -213,7 +213,7 @@
When a new version is available, the user receives a prompt. This message tells the user how to permanently disable new version prompts. 'The Settings page' corresponds to ShellView_Menu_File. 'Help ->About' corresponds to ShellView_Menu_Help_About.
- SyncTrayzor version {0} is available!
+ ¡La versión {0} de SyncTrayzor está disponible!
When a new version is available, the user receives a prompt. This text appears at the top of that prompt
@@ -239,7 +239,7 @@
Setting allowing the user to indicate that the 'minimize' button on the top right of the window should put Syncthing down into the tray, rather than minimizing the application
- Debes reiniciar Syncthing para que los nuevos cambios surtan efecto.
+ Debes reiniciar Syncthing para que los nuevos cambios surtan efecto
Ofuscar el ID de dispositivo en la ventana de log
@@ -252,7 +252,7 @@
Section header for advanced settings
- iniciar al hacer login
+ Iniciar al hacer login
Section header for settings to do with automatically starting SyncTrayzor when the user logs in
@@ -264,7 +264,7 @@
Section header for settings to do with configuring SyncTrayzor
- Carpetas Vigiladas
+ Carpetas Supervisadas
Section header for settings to do with configuring SyncTrayzor's ability to watch folders for changes
@@ -295,7 +295,7 @@
ToolTip shown when a user hovers over the SettingsView_SyncthingAddress text input. This shows more information on the input.
- Usar el directorio principal para Syncthing.
+ Usar el directorio principal para Syncthing
Esto significa que SyncTrayzor verá un conjunto diferente de carpetas configuradas con respecto a cualquier otra instancia de Syncthing en tu ordenador.
@@ -305,11 +305,11 @@
Preferencias
Title of the 'settings' dialog
-
- Variables de trazado de Syncthing:
+
+ Variables de Entorno de Syncthing:
- Las siguiente carpetas estarán vigiladas durante los cambios, lo cual evita el muestreo.
+ Las siguientes carpetas estarán supervisadas por si cambian, lo que significa que puedes configurar un intervalo de consulta más largo.
Carpetas no disponibles. Por favor inicia Syncthing
@@ -531,30 +531,33 @@ SyncTrayzor se va a cerrar. Lo sentimos.
Link show in the centre of the screen when Syncthing is stopped, allowing the user to start syncthing
- Usar el idioma de mi ordenador, si está disponible. Es necesario reiniciar SyncTrayzor para que el cambio surta efecto.
+ Usar el idioma de mi ordenador si está disponible. Es necesario reiniciar SyncTrayzor para que el cambio surta efecto
- _View
+ _Ver
- Syncthing Console
+ _Mostrar la consola de Syncthing
- Install Now
+ Instalar ahora
- View Changelog
+ Ver lista de cambios
- _Zoom Browser
+ _Zoom del navegador
- Zoom _In
+ _Acercar
- Zoom _Out
+ Al_ejar
- _Reset
+ _Restaurar
+
+
+ Debe estar en el formato 'VAR=valor VAR2="val1 val2"'
diff --git a/src/SyncTrayzor/Properties/Strings/Resources.fr.resx b/src/SyncTrayzor/Properties/Strings/Resources.fr.resx
index 6dbcab3b..61468788 100644
--- a/src/SyncTrayzor/Properties/Strings/Resources.fr.resx
+++ b/src/SyncTrayzor/Properties/Strings/Resources.fr.resx
@@ -179,7 +179,7 @@
_Arrêter
- Arrêter _tous les processus Syncthing
+ Arrêter _tous les processus Syncthing
_Ouvrir dans le navigateur externe
@@ -305,11 +305,11 @@
Paramètres
Title of the 'settings' dialog
-
- Syncthing Trace Variables:
+
+ Variables d’environnement de Syncthing :
- The following folders will be watched for changes, which avoids polling.
+ The following folders will be watched for changes, which means you can set a longer polling interval.
Dossiers indisponibles. Veuillez démarrer Syncthing
@@ -537,7 +537,7 @@ SyncTrayzor doit se fermer. Veuillez nous excuser.
_Vue
- Syncthing Console
+ Afficher la console de Syncthing
Installer maintenant
@@ -546,15 +546,18 @@ SyncTrayzor doit se fermer. Veuillez nous excuser.
View Changelog
- _Zoom Browser
+ Zoom
- Zoom _In
+ Zoom _avant
- Zoom _Out
+ Zoom _arrière
- _Reset
+ _Normal
+
+
+ Doit être dans le format suivant : 'VAR=value VAR2="val1 val2"'
diff --git a/src/SyncTrayzor/Properties/Strings/Resources.nl.resx b/src/SyncTrayzor/Properties/Strings/Resources.nl.resx
index 0e67914d..f017e9aa 100644
--- a/src/SyncTrayzor/Properties/Strings/Resources.nl.resx
+++ b/src/SyncTrayzor/Properties/Strings/Resources.nl.resx
@@ -305,11 +305,11 @@
Instellingen
Title of the 'settings' dialog
-
- Syncthing-opsporingsvariabelen:
+
+ Syncthing Environmental Variables:
- De volgende mappen zullen in de gaten worden gehouden op wijzigingen:
+ The following folders will be watched for changes, which means you can set a longer polling interval.
Geen mappen beschikbaar. Start Syncthing.
@@ -557,4 +557,7 @@ SyncTrayzor gaat nu afsluiten. Onze excuses.
_Reset
+
+ Must be in the format 'VAR=value VAR2="val1 val2"'
+
diff --git a/src/SyncTrayzor/Properties/Strings/Resources.resx b/src/SyncTrayzor/Properties/Strings/Resources.resx
index d619aa7f..29ead54e 100644
--- a/src/SyncTrayzor/Properties/Strings/Resources.resx
+++ b/src/SyncTrayzor/Properties/Strings/Resources.resx
@@ -309,7 +309,7 @@
Syncthing Environmental Variables:
- The following folders will be watched for changes, which avoids polling.
+ The following folders will be watched for changes, which means you can set a longer polling interval.
Folders unavailable. Please start Syncthing
@@ -558,6 +558,6 @@ SyncTrayzor is going to have to close. Sorry about that
_Reset
- Must be in the format 'VAR=value VAR2="val1 vla2"'
+ Must be in the format 'VAR=value VAR2="val1 val2"'
\ No newline at end of file
diff --git a/src/SyncTrayzor/Properties/Strings/Resources.ru.resx b/src/SyncTrayzor/Properties/Strings/Resources.ru.resx
index 03f7e27c..46ccd167 100644
--- a/src/SyncTrayzor/Properties/Strings/Resources.ru.resx
+++ b/src/SyncTrayzor/Properties/Strings/Resources.ru.resx
@@ -121,7 +121,7 @@
Создано Antony Male.
- Загрузить
+ Open Download Page
Clickable link allowing the user to download the latest version of SyncTrayzor
@@ -198,7 +198,7 @@
When a new version is available, the user receives a prompt. This button allows the user to say they want want to be prompted to upgrade to this particular version again
- Загрузить сейчас
+ Open Download Page
When a new version is available, the user receives a prompt. This button allows them to download the new version
@@ -305,11 +305,11 @@
Настройки
Title of the 'settings' dialog
-
- Отслеживаемые переменные Syncthing:
+
+ Syncthing Environmental Variables:
- Изменения будут отслеживаться в следующих папках.
+ The following folders will be watched for changes, which means you can set a longer polling interval.
Папки недоступны. Запустите Syncthing
@@ -545,4 +545,19 @@ SyncTrayzor закрывается. Извините.
Посмотреть список изменений
+
+ _Zoom Browser
+
+
+ Zoom _In
+
+
+ Zoom _Out
+
+
+ _Reset
+
+
+ Must be in the format 'VAR=value VAR2="val1 val2"'
+
diff --git a/src/SyncTrayzor/Properties/Strings/Resources.sk.resx b/src/SyncTrayzor/Properties/Strings/Resources.sk.resx
index 3876063e..e70e3e7c 100644
--- a/src/SyncTrayzor/Properties/Strings/Resources.sk.resx
+++ b/src/SyncTrayzor/Properties/Strings/Resources.sk.resx
@@ -121,7 +121,7 @@
Vytvoril Anthony Male.
- Open Download Page
+ Otvoriť stránku na stiahnutie
Clickable link allowing the user to download the latest version of SyncTrayzor
@@ -198,7 +198,7 @@
When a new version is available, the user receives a prompt. This button allows the user to say they want want to be prompted to upgrade to this particular version again
- Open Download Page
+ Otvoriť stránku na stiahnutie
When a new version is available, the user receives a prompt. This button allows them to download the new version
@@ -305,11 +305,11 @@
Nastavenia
Title of the 'settings' dialog
-
- Stopové premenné Syncthing:
+
+ Premenné prostredia Syncthing:
- Nasledovné priečinky budú sledované kvôli zmenám, čo predchádza dopytovaniu.
+ The following folders will be watched for changes, which means you can set a longer polling interval.
Priečinky nie sú dostupné. Prosím zapnite Syncthing
@@ -546,15 +546,18 @@ SyncTrayzor sa musí zavrieť. Ospravedlňujeme sa
Zobraziť zoznam zmien
- _Zoom Browser
+ _Priblížiť prehliadač
- Zoom _In
+ Pr_iblížiť
- Zoom _Out
+ _Oddialiť
_Reset
+
+ Musí byť vo formáte 'VAR=hodnota VAR2="premenná1 premenná2"'
+
diff --git a/src/SyncTrayzor/Services/Config/ApplicationPathsProvider.cs b/src/SyncTrayzor/Services/Config/ApplicationPathsProvider.cs
index a5c30a89..02501ed8 100644
--- a/src/SyncTrayzor/Services/Config/ApplicationPathsProvider.cs
+++ b/src/SyncTrayzor/Services/Config/ApplicationPathsProvider.cs
@@ -17,6 +17,7 @@ public interface IApplicationPathsProvider
string ConfigurationFilePath { get; }
string ConfigurationFileBackupPath { get; }
string UpdatesDownloadPath { get; }
+ string InstallCountFilePath { get; }
void Initialize(PathConfiguration pathConfiguration);
}
@@ -84,5 +85,10 @@ public string UpdatesDownloadPath
{
get { return Path.Combine(Path.GetTempPath(), "SyncTrayzor"); }
}
+
+ public string InstallCountFilePath
+ {
+ get { return Path.Combine(this.ExePath, "InstallCount.txt"); }
+ }
}
}
diff --git a/src/SyncTrayzor/Services/Config/Configuration.cs b/src/SyncTrayzor/Services/Config/Configuration.cs
index a750b870..1815a999 100644
--- a/src/SyncTrayzor/Services/Config/Configuration.cs
+++ b/src/SyncTrayzor/Services/Config/Configuration.cs
@@ -74,7 +74,8 @@ public void WriteXml(XmlWriter writer)
[XmlRoot("Configuration")]
public class Configuration
{
- public const int CurrentVersion = 2;
+ public const int CurrentVersion = 3;
+ public const double DefaultSyncthingConsoleHeight = 100;
[XmlAttribute("Version")]
public int Version
@@ -116,9 +117,10 @@ public string LatestNotifiedVersionRaw
}
public bool UseComputerCulture { get; set; }
- public bool ShowSyncthingConsole { get; set; }
+ public double SyncthingConsoleHeight { get; set; }
public WindowPlacement WindowPlacement { get; set; }
public double SyncthingWebBrowserZoomLevel { get; set; }
+ public int LastSeenInstallCount { get; set; }
public Configuration()
{
@@ -141,9 +143,10 @@ public Configuration()
this.ObfuscateDeviceIDs = true;
this.LatestNotifiedVersion = null;
this.UseComputerCulture = true;
- this.ShowSyncthingConsole = true;
+ this.SyncthingConsoleHeight = Configuration.DefaultSyncthingConsoleHeight;
this.WindowPlacement = null;
this.SyncthingWebBrowserZoomLevel = 0;
+ this.LastSeenInstallCount = 0;
}
public Configuration(Configuration other)
@@ -165,9 +168,10 @@ public Configuration(Configuration other)
this.ObfuscateDeviceIDs = other.ObfuscateDeviceIDs;
this.LatestNotifiedVersion = other.LatestNotifiedVersion;
this.UseComputerCulture = other.UseComputerCulture;
- this.ShowSyncthingConsole = other.ShowSyncthingConsole;
+ this.SyncthingConsoleHeight = other.SyncthingConsoleHeight;
this.WindowPlacement = other.WindowPlacement;
this.SyncthingWebBrowserZoomLevel = other.SyncthingWebBrowserZoomLevel;
+ this.LastSeenInstallCount = other.LastSeenInstallCount;
}
public override string ToString()
@@ -175,13 +179,13 @@ public override string ToString()
return String.Format("",
+ "LastNotifiedVersion={14} ObfuscateDeviceIDs={15} UseComputerCulture={16} SyncthingConsoleHeight={17} WindowPlacement={18} " +
+ "SyncthingWebBrowserZoomLevel={19} LastSeenInstallCount={20}>",
this.ShowTrayIconOnlyOnClose, this.MinimizeToTray, this.CloseToTray, this.ShowSynchronizedBalloon, this.ShowDeviceConnectivityBalloons,
this.SyncthingAddress, this.StartSyncthingAutomatically, this.SyncthingApiKey, String.Join(" ", this.SyncthingEnvironmentalVariables.Select(x => String.Format("{0}={1}", x.Key, x.Value))),
this.SyncthingUseCustomHome, this.SyncthingDenyUpgrade, this.SyncthingRunLowPriority, String.Join(", ", this.Folders), this.NotifyOfNewVersions,
- this.LatestNotifiedVersion, this.ObfuscateDeviceIDs, this.UseComputerCulture, this.ShowSyncthingConsole, this.WindowPlacement,
- this.SyncthingWebBrowserZoomLevel);
+ this.LatestNotifiedVersion, this.ObfuscateDeviceIDs, this.UseComputerCulture, this.SyncthingConsoleHeight, this.WindowPlacement,
+ this.SyncthingWebBrowserZoomLevel, this.LastSeenInstallCount);
}
}
}
diff --git a/src/SyncTrayzor/Services/Config/ConfigurationProvider.cs b/src/SyncTrayzor/Services/Config/ConfigurationProvider.cs
index 8efaa234..144e8c0b 100644
--- a/src/SyncTrayzor/Services/Config/ConfigurationProvider.cs
+++ b/src/SyncTrayzor/Services/Config/ConfigurationProvider.cs
@@ -67,7 +67,8 @@ public ConfigurationProvider(IApplicationPathsProvider paths)
this.migrations = new Func[]
{
- this.MigrateV1ToV2
+ this.MigrateV1ToV2,
+ this.MigrateV2ToV3,
};
}
@@ -79,25 +80,60 @@ public void Initialize(Configuration defaultConfiguration)
if (!File.Exists(Path.GetDirectoryName(this.paths.ConfigurationFilePath)))
Directory.CreateDirectory(Path.GetDirectoryName(this.paths.ConfigurationFilePath));
- if (!File.Exists(this.paths.SyncthingPath))
+ this.currentConfig = this.LoadFromDisk(defaultConfiguration);
+
+ bool installCountChanged = false;
+ bool updateConfigInstallCount = false;
+ int latestInstallCount = 0;
+ // Might be portable, in which case this file won't exist
+ if (File.Exists(this.paths.InstallCountFilePath))
{
- if (File.Exists(this.paths.SyncthingBackupPath))
+ latestInstallCount = Int32.Parse(File.ReadAllText(this.paths.InstallCountFilePath).Trim());
+ if (latestInstallCount != this.currentConfig.LastSeenInstallCount)
{
- logger.Info("Syncthing doesn't exist at {0}, so copying from {1}", this.paths.SyncthingPath, this.paths.SyncthingBackupPath);
- File.Copy(this.paths.SyncthingBackupPath, this.paths.SyncthingPath);
+ logger.Debug("InstallCount changed from {0} to {1}", this.currentConfig.LastSeenInstallCount, latestInstallCount);
+ installCountChanged = true;
+ updateConfigInstallCount = true;
}
- else
- throw new Exception(String.Format("Unable to find Syncthing at {0} or {1}", this.paths.SyncthingPath, this.paths.SyncthingBackupPath));
}
- else if (this.paths.SyncthingPath != this.paths.SyncthingBackupPath && File.Exists(this.paths.SyncthingBackupPath) &&
- File.GetLastWriteTimeUtc(this.paths.SyncthingPath) < File.GetLastWriteTimeUtc(this.paths.SyncthingBackupPath))
+
+ // They're the same if we're portable, in which case, nothing to do
+ if (this.paths.SyncthingPath != this.paths.SyncthingBackupPath)
{
- logger.Info("Syncthing at {0} is older ({1}) than at {2} ({3}, so overwriting from backup",
- this.paths.SyncthingPath, File.GetLastWriteTimeUtc(this.paths.SyncthingPath), this.paths.SyncthingBackupPath, File.GetLastWriteTimeUtc(this.paths.SyncthingBackupPath));
- File.Copy(this.paths.SyncthingBackupPath, this.paths.SyncthingPath, true);
+ if (!File.Exists(this.paths.SyncthingPath))
+ {
+ if (File.Exists(this.paths.SyncthingBackupPath))
+ {
+ logger.Info("Syncthing doesn't exist at {0}, so copying from {1}", this.paths.SyncthingPath, this.paths.SyncthingBackupPath);
+ File.Copy(this.paths.SyncthingBackupPath, this.paths.SyncthingPath);
+ }
+ else
+ {
+ throw new Exception(String.Format("Unable to find Syncthing at {0} or {1}", this.paths.SyncthingPath, this.paths.SyncthingBackupPath));
+ }
+ }
+ else if (installCountChanged)
+ {
+ // If we hit this, then latestInstallCount is set to a real value
+ logger.Info("Install Count changed, so updating Syncthing at {0} from {1}", this.paths.SyncthingPath, this.paths.SyncthingBackupPath);
+ try
+ {
+ File.Copy(this.paths.SyncthingBackupPath, this.paths.SyncthingPath, true);
+ }
+ catch (IOException e)
+ {
+ // Syncthing.exe was probably running. We'll try again next time
+ updateConfigInstallCount = false;
+ logger.Error(String.Format("Failed to copy Syncthing from {0} to {1}", this.paths.SyncthingBackupPath, this.paths.SyncthingPath), e);
+ }
+ }
}
- this.currentConfig = this.LoadFromDisk(defaultConfiguration);
+ if (updateConfigInstallCount)
+ {
+ this.currentConfig.LastSeenInstallCount = latestInstallCount;
+ this.SaveToFile(this.currentConfig);
+ }
}
private Configuration LoadFromDisk(Configuration defaultConfiguration)
@@ -189,6 +225,13 @@ private XDocument MigrateV1ToV2(XDocument configuration)
return configuration;
}
+ private XDocument MigrateV2ToV3(XDocument configuration)
+ {
+ bool? visible = (bool?)configuration.Root.Element("ShowSyncthingConsole");
+ configuration.Root.Add(new XElement("SyncthingConsoleHeight", visible == true ? Configuration.DefaultSyncthingConsoleHeight : 0.0));
+ return configuration;
+ }
+
private XDocument LegacyMigrationConfiguration(XDocument configuration)
{
var address = configuration.Root.Element("SyncthingAddress").Value;
diff --git a/src/SyncTrayzor/SyncThing/ApiClient/Config.cs b/src/SyncTrayzor/SyncThing/ApiClient/Config.cs
index 5ec1b791..9568e4b6 100644
--- a/src/SyncTrayzor/SyncThing/ApiClient/Config.cs
+++ b/src/SyncTrayzor/SyncThing/ApiClient/Config.cs
@@ -41,9 +41,13 @@ public TimeSpan RescanInterval
set { this.RescanIntervalSeconds = (long)value.TotalSeconds; }
}
+ [JsonProperty("invalid")]
+ public string Invalid { get; set; }
+
public override string ToString()
{
- return String.Format("", this.ID, this.Path, String.Join(", ", this.Devices), this.ReadOnly, this.RescanInterval);
+ return String.Format("",
+ this.ID, this.Path, String.Join(", ", this.Devices), this.ReadOnly, this.RescanInterval, this.Invalid);
}
}
diff --git a/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiClient.cs b/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiClient.cs
index 1ae5bd0f..bd9e1f65 100644
--- a/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiClient.cs
+++ b/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiClient.cs
@@ -10,8 +10,8 @@ namespace SyncTrayzor.SyncThing.ApiClient
public interface ISyncThingApiClient
{
Task ShutdownAsync();
- Task> FetchEventsAsync(int since, int limit, CancellationToken cancellationToken);
- Task> FetchEventsAsync(int since, CancellationToken cancellationToken);
+ Task> FetchEventsAsync(int since, int limit);
+ Task> FetchEventsAsync(int since);
Task FetchConfigAsync();
Task ScanAsync(string folderId, string subPath);
Task FetchSystemInfoAsync();
diff --git a/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiV0p10.cs b/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiV0p10.cs
index b3ffe5c4..5f0e5955 100644
--- a/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiV0p10.cs
+++ b/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiV0p10.cs
@@ -11,10 +11,10 @@ namespace SyncTrayzor.SyncThing.ApiClient
public interface ISyncThingApiV0p10
{
[Get("/rest/events")]
- Task> FetchEventsAsync(int since, CancellationToken cancellationToken);
+ Task> FetchEventsAsync(int since);
[Get("/rest/events")]
- Task> FetchEventsLimitAsync(int since, int limit, CancellationToken cancellationToken);
+ Task> FetchEventsLimitAsync(int since, int limit);
[Get("/rest/config")]
Task FetchConfigAsync();
diff --git a/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiV0p11.cs b/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiV0p11.cs
index 01cbffaa..2a432148 100644
--- a/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiV0p11.cs
+++ b/src/SyncTrayzor/SyncThing/ApiClient/ISyncThingApiV0p11.cs
@@ -11,10 +11,10 @@ namespace SyncTrayzor.SyncThing.ApiClient
public interface ISyncThingApiV0p11
{
[Get("/rest/events")]
- Task> FetchEventsAsync(int since, CancellationToken cancellationToken);
+ Task> FetchEventsAsync(int since);
[Get("/rest/events")]
- Task> FetchEventsLimitAsync(int since, int limit, CancellationToken cancellationToken);
+ Task> FetchEventsLimitAsync(int since, int limit);
[Get("/rest/system/config")]
Task FetchConfigAsync();
diff --git a/src/SyncTrayzor/SyncThing/ApiClient/SyncThingApiClientV0p10.cs b/src/SyncTrayzor/SyncThing/ApiClient/SyncThingApiClientV0p10.cs
index c84255e8..bd200986 100644
--- a/src/SyncTrayzor/SyncThing/ApiClient/SyncThingApiClientV0p10.cs
+++ b/src/SyncTrayzor/SyncThing/ApiClient/SyncThingApiClientV0p10.cs
@@ -40,14 +40,14 @@ public Task ShutdownAsync()
return this.api.ShutdownAsync();
}
- public Task> FetchEventsAsync(int since, int limit, CancellationToken cancellationToken)
+ public Task> FetchEventsAsync(int since, int limit)
{
- return this.api.FetchEventsLimitAsync(since, limit, cancellationToken);
+ return this.api.FetchEventsLimitAsync(since, limit);
}
- public Task> FetchEventsAsync(int since, CancellationToken cancellationToken)
+ public Task> FetchEventsAsync(int since)
{
- return this.api.FetchEventsAsync(since, cancellationToken);
+ return this.api.FetchEventsAsync(since);
}
public async Task FetchConfigAsync()
diff --git a/src/SyncTrayzor/SyncThing/ApiClient/SyncThingApiClientV0p11.cs b/src/SyncTrayzor/SyncThing/ApiClient/SyncThingApiClientV0p11.cs
index b420b1a2..f7dd6669 100644
--- a/src/SyncTrayzor/SyncThing/ApiClient/SyncThingApiClientV0p11.cs
+++ b/src/SyncTrayzor/SyncThing/ApiClient/SyncThingApiClientV0p11.cs
@@ -40,14 +40,14 @@ public Task ShutdownAsync()
return this.api.ShutdownAsync();
}
- public Task> FetchEventsAsync(int since, int limit, CancellationToken cancellationToken)
+ public Task> FetchEventsAsync(int since, int limit)
{
- return this.api.FetchEventsLimitAsync(since, limit, cancellationToken);
+ return this.api.FetchEventsLimitAsync(since, limit);
}
- public Task> FetchEventsAsync(int since, CancellationToken cancellationToken)
+ public Task> FetchEventsAsync(int since)
{
- return this.api.FetchEventsAsync(since, cancellationToken);
+ return this.api.FetchEventsAsync(since);
}
public async Task FetchConfigAsync()
diff --git a/src/SyncTrayzor/SyncThing/EventWatcher/SyncThingEventWatcher.cs b/src/SyncTrayzor/SyncThing/EventWatcher/SyncThingEventWatcher.cs
index d0647893..fe18c94f 100644
--- a/src/SyncTrayzor/SyncThing/EventWatcher/SyncThingEventWatcher.cs
+++ b/src/SyncTrayzor/SyncThing/EventWatcher/SyncThingEventWatcher.cs
@@ -52,9 +52,9 @@ protected override async Task PollAsync(CancellationToken cancellationToken)
List events;
// If this is the first poll, don't fetch the history
if (this.lastEventId == 0)
- events = await this.apiClient.FetchEventsAsync(0, 1, cancellationToken);
+ events = await this.apiClient.FetchEventsAsync(0, 1);
else
- events = await this.apiClient.FetchEventsAsync(this.lastEventId, cancellationToken);
+ events = await this.apiClient.FetchEventsAsync(this.lastEventId);
// We can be aborted in the time it takes to fetch the events
cancellationToken.ThrowIfCancellationRequested();
diff --git a/src/SyncTrayzor/SyncThing/SyncThingManager.cs b/src/SyncTrayzor/SyncThing/SyncThingManager.cs
index 56082d17..9506b1bd 100644
--- a/src/SyncTrayzor/SyncThing/SyncThingManager.cs
+++ b/src/SyncTrayzor/SyncThing/SyncThingManager.cs
@@ -423,27 +423,36 @@ private async Task LoadStartupDataAsync(CancellationToken cancellationToken)
cancellationToken.ThrowIfCancellationRequested();
await Task.WhenAll(configTask, systemTask, versionTask, connectionsTask);
- this.devices = new ConcurrentDictionary(configTask.Result.Devices.Select(device =>
+ // We can potentially see duplicate devices (if the user set their config file that way). Ignore them.
+ var devices = configTask.Result.Devices.DistinctBy(x => x.DeviceID).Select(device =>
{
var deviceObj = new Device(device.DeviceID, device.Name);
ItemConnectionData connectionData;
if (connectionsTask.Result.DeviceConnections.TryGetValue(device.DeviceID, out connectionData))
deviceObj.SetConnected(connectionData.Address);
- return new KeyValuePair(device.DeviceID, deviceObj);
- }));
+ return deviceObj;
+ });
+ this.devices = new ConcurrentDictionary(devices.Select(x => new KeyValuePair(x.DeviceId, x)));
var tilde = systemTask.Result.Tilde;
- var folderConstructionTasks = configTask.Result.Folders.Select(async folder =>
- {
- var ignores = await this.FetchFolderIgnoresAsync(folder.ID, cancellationToken);
- var path = folder.Path;
- if (path.StartsWith("~"))
- path = Path.Combine(tilde, path.Substring(1).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
- return new Folder(folder.ID, path, new FolderIgnores(ignores.IgnorePatterns, ignores.RegexPatterns));
- });
+ // If the folder is invalid for any reason, we'll ignore it.
+ // Again, there's the potential for duplicate folder IDs (if the user's been fiddling their config).
+ // In this case, there's nothing really sensible we can do. Just pick one of them :)
+ var folderConstructionTasks = configTask.Result.Folders
+ .Where(x => String.IsNullOrWhiteSpace(x.Invalid))
+ .DistinctBy(x => x.ID)
+ .Select(async folder =>
+ {
+ var ignores = await this.FetchFolderIgnoresAsync(folder.ID, cancellationToken);
+ var path = folder.Path;
+ if (path.StartsWith("~"))
+ path = Path.Combine(tilde, path.Substring(1).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
+ return new Folder(folder.ID, path, new FolderIgnores(ignores.IgnorePatterns, ignores.RegexPatterns));
+ });
cancellationToken.ThrowIfCancellationRequested();
+
var folders = await Task.WhenAll(folderConstructionTasks);
this.folders = new ConcurrentDictionary(folders.Select(x => new KeyValuePair(x.FolderId, x)));
diff --git a/src/SyncTrayzor/SyncThing/SyncThingProcessRunner.cs b/src/SyncTrayzor/SyncThing/SyncThingProcessRunner.cs
index b371dd0d..4f0686f0 100644
--- a/src/SyncTrayzor/SyncThing/SyncThingProcessRunner.cs
+++ b/src/SyncTrayzor/SyncThing/SyncThingProcessRunner.cs
@@ -102,6 +102,8 @@ public void Start()
RedirectStandardInput = true,
RedirectStandardError = true,
RedirectStandardOutput = true,
+ StandardOutputEncoding = Encoding.UTF8,
+ StandardErrorEncoding = Encoding.UTF8,
};
foreach (var kvp in this.EnvironmentalVariables)
diff --git a/src/SyncTrayzor/SyncTrayzor.csproj b/src/SyncTrayzor/SyncTrayzor.csproj
index 2a9d8148..f83b72d4 100644
--- a/src/SyncTrayzor/SyncTrayzor.csproj
+++ b/src/SyncTrayzor/SyncTrayzor.csproj
@@ -265,6 +265,8 @@
+
+
@@ -273,7 +275,9 @@
+
+
diff --git a/src/SyncTrayzor/Utils/ChromiumWebBrowserExtensions.cs b/src/SyncTrayzor/Utils/ChromiumWebBrowserExtensions.cs
new file mode 100644
index 00000000..b6d6192b
--- /dev/null
+++ b/src/SyncTrayzor/Utils/ChromiumWebBrowserExtensions.cs
@@ -0,0 +1,22 @@
+using CefSharp.Wpf;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SyncTrayzor.Utils
+{
+ public static class ChromiumWebBrowserExtensions
+ {
+ private static MethodInfo setZoomLevelMethod = typeof(ChromiumWebBrowser).GetMethod("OnZoomLevelChanged", BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, new[] { typeof(double), typeof(double) }, null);
+
+ public static void SetZoomLevel(this ChromiumWebBrowser browser, double zoomLevel)
+ {
+ // Yuck yuck yuck. This is fixed in CefSharp 39, but that breaks other things (I'm not entirely sure what, but things like
+ // the device ID become broken).
+ setZoomLevelMethod.Invoke(browser, new object[] { 0.0, zoomLevel });
+ }
+ }
+}
diff --git a/src/SyncTrayzor/Utils/EnumerableExtensions.cs b/src/SyncTrayzor/Utils/EnumerableExtensions.cs
new file mode 100644
index 00000000..6b31c960
--- /dev/null
+++ b/src/SyncTrayzor/Utils/EnumerableExtensions.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SyncTrayzor.Utils
+{
+ public static class EnumerableExtensions
+ {
+ public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector)
+ {
+ var knownKeys = new HashSet();
+ foreach (var element in source)
+ {
+ if (knownKeys.Add(keySelector(element)))
+ yield return element;
+ }
+ }
+ }
+}
diff --git a/src/SyncTrayzor/Utils/SafeSyncthingExtensions.cs b/src/SyncTrayzor/Utils/SafeSyncthingExtensions.cs
index a921fcee..55e31e0e 100644
--- a/src/SyncTrayzor/Utils/SafeSyncthingExtensions.cs
+++ b/src/SyncTrayzor/Utils/SafeSyncthingExtensions.cs
@@ -35,8 +35,8 @@ public static async Task StartWithErrorDialogAsync(this ISyncThingManager syncTh
{
// Haven't translated yet - still debugging
windowManager.ShowMessageBox(
- "Syncthing didn't start correctly",
"Syncthing started running, but we were enable to connect to it. Please report this as a bug",
+ "Syncthing didn't start correctly",
MessageBoxButton.OK, icon: MessageBoxImage.Error);
}
}
diff --git a/src/SyncTrayzor/Xaml/CollapsingRowDefinitionBehaviour.cs b/src/SyncTrayzor/Xaml/CollapsingRowDefinitionBehaviour.cs
index 1b865114..e6a4ff0e 100644
--- a/src/SyncTrayzor/Xaml/CollapsingRowDefinitionBehaviour.cs
+++ b/src/SyncTrayzor/Xaml/CollapsingRowDefinitionBehaviour.cs
@@ -5,6 +5,7 @@
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Data;
using System.Windows.Interactivity;
namespace SyncTrayzor.Xaml
@@ -43,8 +44,15 @@ protected override void OnAttached()
this.Refresh();
}
+ protected override void OnDetaching()
+ {
+ BindingOperations.ClearBinding(this.AssociatedObject, RowDefinition.HeightProperty);
+ }
+
private void Refresh()
{
+ BindingOperations.ClearBinding(this.AssociatedObject, RowDefinition.HeightProperty);
+
if (this.RowVisibility == Visibility.Collapsed)
{
this.AssociatedObject.Height = new GridLength(0);
@@ -52,7 +60,13 @@ private void Refresh()
}
else
{
- this.AssociatedObject.Height = this.Height;
+ var heightBinding = new Binding("Height")
+ {
+ Source = this,
+ Mode = BindingMode.TwoWay,
+ };
+ BindingOperations.SetBinding(this.AssociatedObject, RowDefinition.HeightProperty, heightBinding);
+
this.AssociatedObject.MinHeight = this.MinHeight;
}
}
diff --git a/src/SyncTrayzor/Xaml/GridLengthToAbsoluteConverter.cs b/src/SyncTrayzor/Xaml/GridLengthToAbsoluteConverter.cs
new file mode 100644
index 00000000..1fdafecf
--- /dev/null
+++ b/src/SyncTrayzor/Xaml/GridLengthToAbsoluteConverter.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Data;
+
+namespace SyncTrayzor.Xaml
+{
+ public class GridLengthToAbsoluteConverter : IValueConverter
+ {
+ public static readonly GridLengthToAbsoluteConverter Instance = new GridLengthToAbsoluteConverter();
+
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (value == null)
+ return null;
+
+ try
+ {
+ return new GridLength(System.Convert.ToDouble(value));
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (!(value is GridLength))
+ return null;
+
+ return ((GridLength)value).Value;
+ }
+ }
+}
diff --git a/src/SyncTrayzor/Xaml/RemoveMnemonicsConverter.cs b/src/SyncTrayzor/Xaml/RemoveMnemonicsConverter.cs
new file mode 100644
index 00000000..2cd388d8
--- /dev/null
+++ b/src/SyncTrayzor/Xaml/RemoveMnemonicsConverter.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace SyncTrayzor.Xaml
+{
+ public class RemoveMnemonicsConverter : IValueConverter
+ {
+ public static RemoveMnemonicsConverter Instance = new RemoveMnemonicsConverter();
+
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ var val = value as string;
+ if (val == null)
+ return null;
+
+ return val.Replace("_", "__");
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ var val = value as string;
+ if (val == null)
+ return null;
+
+ return val.Replace("__", "_");
+ }
+ }
+}