From bfed942387e1c3dbe7c757d7b517568f8cc90411 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Thu, 12 Mar 2015 18:15:48 +0000 Subject: [PATCH 01/16] Remove window icon Windows was using the window icon when not pinned, and the Assembly icon when pinned. The window icon was 16x16; the Assembly icon had the full resolution set. Removing the window icon causes it to fall back to the Assembly icon, which is fine. Fixes #20 --- src/SyncTrayzor/Pages/ShellView.xaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/SyncTrayzor/Pages/ShellView.xaml b/src/SyncTrayzor/Pages/ShellView.xaml index 0acf8626..da979080 100644 --- a/src/SyncTrayzor/Pages/ShellView.xaml +++ b/src/SyncTrayzor/Pages/ShellView.xaml @@ -6,8 +6,7 @@ xmlns:xaml="clr-namespace:SyncTrayzor.Xaml" xmlns:l="clr-namespace:SyncTrayzor.Localization" Height="700" Width="1100" - Title="SyncTrayzor" - Icon="..\Icons\default_tray.ico"> + Title="SyncTrayzor"> From fb5bd85d13107b4eadfb8bfc47aae460bc0b8cdb Mon Sep 17 00:00:00 2001 From: Antony Male Date: Fri, 13 Mar 2015 13:39:50 +0000 Subject: [PATCH 02/16] Add message to the README directing people with Syncthing problems to Syncthing --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1181f17a..fa83371b 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,20 @@ Grab the latest standalone .zip from the [releases](https://github.com/canton7/S Unzip, and run `SyncTrayzor.exe`. If you're updating, you'll need to copy the `data` folder across from your previous standalone installation. +Something went wrong! +--------------------- + +First, what went wrong? Remember that SyncTrayzor is a wrapper around [Syncthing](http://github.com/syncthing/syncthing). +Syncthing is the file synchronization program, which has a web interface. +SyncTrayzor is the tray utilty, looks like a normal Windows program, and has menus and suchlike, and a big area where Syncthing's web interface is displayed. + + - If you're having problems connection to other devices, your files aren't synchronizing, or you're getting error messages in the console area, [raise an issue with Syncthing](http://github.com/syncthing/syncthing) or [post on the Syncthing forums](http://discourse.syncthing.net). + - If SyncTrayzor isn't talking to Syncthing, you're getting error dialogs, it's not auto-starting, etc, [raise an issue with SyncTrayzor](http://github.com/canton7/SyncTrayzor). + - If you're not sure, raise an issue here and I'll redirect you if appropriate. + Contributing ------------ -Got a bug? [Raise an issue](https://github.com/canton7/SyncTrayzor/issues), providing as much detail as you can. - Multi-lingual? SyncTrayzor needs you! Please read [Localization](https://github.com/canton7/SyncTrayzor/wiki/Localization). Want to make a contribution? Fantastic, and thank you! Please read [Contributing](https://github.com/canton7/SyncTrayzor/wiki/Contributing) first. From 1fd6fd93863c6900897bceb2bf9aca35be10f670 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Fri, 13 Mar 2015 16:56:55 +0000 Subject: [PATCH 03/16] Add 'TranslatorAttributation' field to allow translators to credit themselves Show on the About view, if changed from the default --- src/SyncTrayzor/Localization/Localizer.cs | 6 ++ src/SyncTrayzor/Pages/AboutView.xaml | 9 ++- src/SyncTrayzor/Pages/AboutViewModel.cs | 4 ++ .../Properties/Strings/Resources.Designer.cs | 9 +++ .../Properties/Strings/Resources.resx | 59 ++++++++++--------- 5 files changed, 59 insertions(+), 28 deletions(-) diff --git a/src/SyncTrayzor/Localization/Localizer.cs b/src/SyncTrayzor/Localization/Localizer.cs index 2354f481..60e324bc 100644 --- a/src/SyncTrayzor/Localization/Localizer.cs +++ b/src/SyncTrayzor/Localization/Localizer.cs @@ -1,6 +1,7 @@ using SyncTrayzor.Properties.Strings; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -18,5 +19,10 @@ public static string Translate(string key, params object[] parameters) return String.Format(format, parameters); } + + public static string OriginalTranslation(string key) + { + return Resources.ResourceManager.GetString(key, new CultureInfo("en-US", false)); + } } } diff --git a/src/SyncTrayzor/Pages/AboutView.xaml b/src/SyncTrayzor/Pages/AboutView.xaml index 961c5c13..76a5cb84 100644 --- a/src/SyncTrayzor/Pages/AboutView.xaml +++ b/src/SyncTrayzor/Pages/AboutView.xaml @@ -4,7 +4,7 @@ xmlns:s="https://github.com/canton7/Stylet" xmlns:l="clr-namespace:SyncTrayzor.Localization" Height="300" Width="250" - WindowStyle="None" SizeToContent="WidthAndHeight" + WindowStyle="None" SizeToContent="Height" ShowInTaskbar="False"> @@ -29,6 +29,13 @@ + + + + + diff --git a/src/SyncTrayzor/Pages/AboutViewModel.cs b/src/SyncTrayzor/Pages/AboutViewModel.cs index ce0bfdbb..bc326cf9 100644 --- a/src/SyncTrayzor/Pages/AboutViewModel.cs +++ b/src/SyncTrayzor/Pages/AboutViewModel.cs @@ -27,6 +27,10 @@ public class AboutViewModel : Screen public string HomepageUrl { get; set; } public string NewerVersion { get; set; } + public bool ShowTranslatorAttributation + { + get { return Localizer.Translate("TranslatorAttributation") == Localizer.OriginalTranslation("TranslatorAttributation"); } + } private string newerVersionDownloadUrl; public AboutViewModel( diff --git a/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs b/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs index 70a40638..a6c7449e 100644 --- a/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs +++ b/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs @@ -721,6 +721,15 @@ public static string ThirdPartyComponentsView_Title { } } + /// + /// Looks up a localized string similar to Dummy text ignored by the UI. + /// + public static string TranslatorAttributation { + get { + return ResourceManager.GetString("TranslatorAttributation", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0}: Finished Syncing. /// diff --git a/src/SyncTrayzor/Properties/Strings/Resources.resx b/src/SyncTrayzor/Properties/Strings/Resources.resx index aac9ce51..710331e2 100644 --- a/src/SyncTrayzor/Properties/Strings/Resources.resx +++ b/src/SyncTrayzor/Properties/Strings/Resources.resx @@ -1,4 +1,4 @@ - + - - + + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - + @@ -184,7 +184,7 @@ S_top - Don't Remind Me Again + Don't Remind Me Again Download Now @@ -196,7 +196,7 @@ Changelog: - 'Don't Remind Me Again' will silence reminders for this version. You can permanently disable new version alerts from the Settings page. Visit Help -> About to manually check for a new version. + 'Don't Remind Me Again' will silence reminders for this version. You can permanently disable new version alerts from the Settings page. Visit Help -> About to manually check for a new version. A new version of SyncTrayzor is available! @@ -215,7 +215,7 @@ Do you want to download it now? API Key: - SyncTrayzor overrides the API key specified in Syncthing's configuration. However, you can set it to whatever value you like here. + SyncTrayzor overrides the API key specified in Syncthing's configuration. However, you can set it to whatever value you like here. Close to tray @@ -248,7 +248,8 @@ Do you want to download it now? Watched Folders - Show 'Synchronized' balloon messages + Show 'Synchronized' balloon messages + Setting allowing the user to specify that a balloon message (white area down by the tray icon, linked to the tray icon) should be shown whenever a folder finishes synchronizing Start Minimized @@ -266,7 +267,7 @@ Do you want to download it now? GUI Listen Address: - SyncTrayzor overrides the "GUI Listen Address" specified in Syncthing's configuration. However, you can set it to whatever value you like here. + SyncTrayzor overrides the "GUI Listen Address" specified in Syncthing's configuration. However, you can set it to whatever value you like here. Use custom home directory for Syncthing. @@ -300,7 +301,7 @@ Do you want to download it now? Please read the log to determine the cause. -If "FATAL: Cannot open database" appears, please close any other open instances of Syncthing. If SyncTrayzor crashed previously, there may still be zombine Syncthing processes alive. Please use the menu option "Syncthing -> Kill all Syncthing processes" to stop them, then use "Syncthing -> Start" to start Syncthing again. +If "FATAL: Cannot open database" appears, please close any other open instances of Syncthing. If SyncTrayzor crashed previously, there may still be zombine Syncthing processes alive. Please use the menu option "Syncthing -> Kill all Syncthing processes" to stop them, then use "Syncthing -> Start" to start Syncthing again. "FATAL: Cannot Open Database" should remain in English @@ -311,7 +312,7 @@ If "FATAL: Cannot open database" appears, please close any other open This could be because Windows if set up to forbid executing files in AppData, or because you have anti-malware installed (e.g. CryptoPrevent ) which prevents executing files in AppData. -Please adjust your settings / whitelists to allow '{1}' to execute +Please adjust your settings / whitelists to allow '{1}' to execute {0}: Exception message {1}: Path to Syncthing @@ -378,7 +379,7 @@ Details on each component, and its license text, are shown below. SyncTrayzor is going to have to close. Sorry about that - + Appears after the log path @@ -402,4 +403,8 @@ SyncTrayzor is going to have to close. Sorry about that Syncthing Stopped - + + Dummy text ignored by the UI + Shown on the 'about' page, this is space for you to attribute yourself. E.g. your local language equivalent of "Kingon translation by My Name". Add yourself to this field if you contribute to the translation for this language. + + \ No newline at end of file From 58b964d2df85de9b371aa3f186c50ed73b663c47 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Fri, 13 Mar 2015 17:22:09 +0000 Subject: [PATCH 04/16] Localize dialog buttons, and add comments to many strings --- .gitattributes | 1 + src/SyncTrayzor/Bootstrapper.cs | 9 +++ .../Properties/Strings/Resources.Designer.cs | 27 +++++++ .../Properties/Strings/Resources.resx | 81 +++++++++++++++++-- 4 files changed, 111 insertions(+), 7 deletions(-) diff --git a/.gitattributes b/.gitattributes index e82616f3..222d9b0a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,3 +2,4 @@ *.xaml eol=crlf *.sln eol=crlf *.csproj eol=crlf +*.resx eol=crlf diff --git a/src/SyncTrayzor/Bootstrapper.cs b/src/SyncTrayzor/Bootstrapper.cs index 6fc7a6ed..04f96292 100644 --- a/src/SyncTrayzor/Bootstrapper.cs +++ b/src/SyncTrayzor/Bootstrapper.cs @@ -3,6 +3,7 @@ using NLog; using Stylet; using StyletIoC; +using SyncTrayzor.Localization; using SyncTrayzor.NotifyIcon; using SyncTrayzor.Pages; using SyncTrayzor.Properties; @@ -82,6 +83,14 @@ protected override void Configure() // Horrible workaround for a CefSharp crash on logout/shutdown // https://github.com/cefsharp/CefSharp/issues/800#issuecomment-75058534 this.Application.SessionEnding += (o, e) => Process.GetCurrentProcess().Kill(); + + MessageBoxViewModel.ButtonLabels = new Dictionary() + { + { MessageBoxResult.Cancel, Localizer.Translate("Generic_Dialog_Cancel") }, + { MessageBoxResult.No, Localizer.Translate("Generic_Dialog_No") }, + { MessageBoxResult.OK, Localizer.Translate("Generic_Dialog_OK") }, + { MessageBoxResult.Yes, Localizer.Translate("Generic_Dialog_Yes") }, + }; } protected override void OnStart() diff --git a/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs b/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs index a6c7449e..89ad899a 100644 --- a/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs +++ b/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs @@ -212,6 +212,24 @@ public static string Generic_Dialog_Close { } } + /// + /// Looks up a localized string similar to No. + /// + public static string Generic_Dialog_No { + get { + return ResourceManager.GetString("Generic_Dialog_No", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to OK. + /// + public static string Generic_Dialog_OK { + get { + return ResourceManager.GetString("Generic_Dialog_OK", resourceCulture); + } + } + /// /// Looks up a localized string similar to Save. /// @@ -221,6 +239,15 @@ public static string Generic_Dialog_Save { } } + /// + /// Looks up a localized string similar to Yes. + /// + public static string Generic_Dialog_Yes { + get { + return ResourceManager.GetString("Generic_Dialog_Yes", resourceCulture); + } + } + /// /// Looks up a localized string similar to Don't Remind Me Again. /// diff --git a/src/SyncTrayzor/Properties/Strings/Resources.resx b/src/SyncTrayzor/Properties/Strings/Resources.resx index 710331e2..5e7442eb 100644 --- a/src/SyncTrayzor/Properties/Strings/Resources.resx +++ b/src/SyncTrayzor/Properties/Strings/Resources.resx @@ -122,9 +122,12 @@ Download + Clickable link allowing the user to download the latest version of SyncTrayzor New version available: {0} + Prompt showing the user that a new version of SynTrayzor is available +{0}: Latest version of SyncTrayzor Released under the MIT license. @@ -134,18 +137,25 @@ Syncthing Version: {0} + Information showing the user the current version of Syncthing +{0}: Current Syncthing version Version: {0} + Information showing the user the current version of SyncTrayzor +{0}: Current SyncTrayzor version Cancel + 'Cancel' button shown in various dialogs Close + 'Close' button shown on various dialogs Save + 'Save' button shown on various dialogs _File @@ -185,18 +195,22 @@ Don't Remind Me Again + 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 Download Now + When a new version is available, the user receives a prompt. This button allows them to download the new version Remind Me Later + When a new version is available, the user receives a prompt. This button allows them to say they want to be prompted the next time they start SyncTrayzor Changelog: 'Don't Remind Me Again' will silence reminders for this version. You can permanently disable new version alerts from the Settings page. Visit Help -> About to manually check for a new version. + 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. A new version of SyncTrayzor is available! @@ -204,9 +218,11 @@ Version: {0} Do you want to download it now? + When a new version is available, the user receives a prompt. This text appears at the top of that prompt SyncTrayzor Update Available + When a new version is available, the user receives a prompt. This is the title of that prompt. Alert if a new version of SyncTrayzor is available @@ -216,12 +232,15 @@ Do you want to download it now? SyncTrayzor overrides the API key specified in Syncthing's configuration. However, you can set it to whatever value you like here. + ToolTip shown when a user hovers over the SettingsView_ApiKey text input. This shows more information on the input. Close to tray + Setting allowing the user to indicate that the 'close' button on the top right of the window should put Syncthing down into the tray, rather than closing the application Minimize to tray + 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 You must restart Syncthing for changes in these settings to take effect @@ -234,18 +253,23 @@ Do you want to download it now? Advanced + Section header for advanced settings Start on Login + Section header for settings to do with automatically starting SyncTrayzor when the user logs in Syncthing + Section header for settings to do with configuring Syncthing SyncTrayzor + Section header for settings to do with configuring SyncTrayzor Watched Folders + Section header for settings to do with configuring SyncTrayzor's ability to watch folders for changes Show 'Synchronized' balloon messages @@ -253,30 +277,37 @@ Do you want to download it now? Start Minimized + Setting allowing the user to specify that, when SyncTrayzor is started automatically on login, it should start in the tray, rather than being visible to the user Automatically start on login + Setting allowing the user to specify that SyncTrayzor should be started when the user logs in Permission denied. Please start SyncTrayzor as an Administrator to change these settings. + Message displayed instead of SettingsView_StartOnLogin SettingsView_StartMinimized when the user doesn't have permission to edit the registry Start Syncthing when SyncTrayzor starts + Setting allowing the user to specify that Syncthing should be start automatically when SyncTrayzor starts GUI Listen Address: SyncTrayzor overrides the "GUI Listen Address" specified in Syncthing's configuration. However, you can set it to whatever value you like here. + ToolTip shown when a user hovers over the SettingsView_SyncthingAddress text input. This shows more information on the input. Use custom home directory for Syncthing. This will mean that SyncTrayzor will see a different set of configured folders to any other Syncthing instances on your computer. + ToolTip shown when a user hovers over the SettingsView_SyncthingUseCustomHome text input. This shows more information on the input. Settings + Title of the 'settings' dialog Syncthing Trace Variables: @@ -289,12 +320,15 @@ Do you want to download it now? Unknown + Shown within AboutView_SyncthingVersion if Syncthing's version couldn't be determined Are you sure you want to kill all Syncthing processes, even those not managed by SyncTrayzor? + Body for the dialog show when the user clicks on ShellView_Menu_Syncthing_KillAll Really? + Title for the dialog shown when the user clicks on ShellView_Menu_Syncthing_KillAll Failed to start Syncthing. @@ -302,10 +336,15 @@ Do you want to download it now? Please read the log to determine the cause. If "FATAL: Cannot open database" appears, please close any other open instances of Syncthing. If SyncTrayzor crashed previously, there may still be zombine Syncthing processes alive. Please use the menu option "Syncthing -> Kill all Syncthing processes" to stop them, then use "Syncthing -> Start" to start Syncthing again. - "FATAL: Cannot Open Database" should remain in English + Content of the dialog shown when Syncthing couldn't be started (and exited with an error). Instructs the user on how to proceed. + +"FATAL: Cannot Open Database" should remain in English + +The menu option "Syncthing ->Kill all Syncthing processes" corresponds to ShellView_Menu_Syncthing_KillAll, while "Syncthing ->Start" corresponds to ShellView_Menu_Syncthing_Start Syncthing failed to start + Title of the dialog shown when Syncthing couldn't be started (and exited with an error) Unable to start Syncthing: {0} @@ -313,17 +352,21 @@ If "FATAL: Cannot open database" appears, please close any other open instances This could be because Windows if set up to forbid executing files in AppData, or because you have anti-malware installed (e.g. CryptoPrevent ) which prevents executing files in AppData. Please adjust your settings / whitelists to allow '{1}' to execute - {0}: Exception message -{1}: Path to Syncthing + Content of dialog shown when Syncthing couldn't start because of group policy settings (probably) +{0}: Exact exception message +{1}: Path to Syncthing executable Error starting Syncthing + Title of dialog shown when Syncthing couldn't start because of group policy settings (probably) Must be a valid URL + Validation message (shown in red) below the SettingsView_SyncthingAddress field when the user enters a value which is not a value URL Should not be empty + Validation message (shown in red) below the SettingsView_SyncthingAddress or SettingsView_ApiKey fields when the user makes this field empty Description: @@ -352,27 +395,36 @@ Details on each component, and its license text, are shown below. {0}: Finished Syncing + Content of the balloon message shown when a folder finished synchronization + +{0}:The name of the folder which finished synchronizing Finished Syncing Close to Tray + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to minimize itself to the tray _Exit + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to exit _Restore + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to restore itself from the tray, and be visible to the user Sett_ings + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to show the Settings dialog _Start + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to start Syncthing. Only available if Syncthing isn't running S_top + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to stop Syncthing. Only available if Syncthing is running Oops! Something went badly wrong. @@ -380,28 +432,43 @@ SyncTrayzor is going to have to close. Sorry about that - Appears after the log path + When an unhandled exception occurs, the user is informed that they may have to provide a log file, and gives the path. This text appears immediately after the log path You may be asked to provide a log file. You can find this in: - Appears before the log path + When an unhandled exception occurs, the user is informed that they may have to provide a log file, and gives the path. This text appears immediately before the log path and include the following information: - Appers after the hyperlink to the Github issues page + When an unhandled exception occurs, the user is prompted to visit the Github issues page. This text appears immediately after the link to github, and also prompts the user to include the stack trace shown directly below this text Please open an issue at - Appears before a hyperlink to the Github issues page + When an unhandled exception occurs, the user is prompted to visit the Github issues page. This text appears immediately before the link to github Error! + Title of the dialog shown when an unhandled excepotion occurs Syncthing Starting... + Text shown in the centre of the screen when Syncthing is starting, but there's no UI to display yet Syncthing Stopped + Text shown in the centre of the screen when Syncthing is stopped + + + No + 'No' button shown on various dialogs + + + OK + 'OK' button shown on various dialogs + + + Yes + 'Yes' button shown on various dialogs Dummy text ignored by the UI From a885811e2296dd6e90df25317c5166f7ad90b4ed Mon Sep 17 00:00:00 2001 From: Antony Male Date: Sat, 14 Mar 2015 12:22:31 +0000 Subject: [PATCH 05/16] Small changes to possibly help small memory leaks --- .../NotifyIcon/TaskbarIconResources.xaml | 2 +- src/SyncTrayzor/Pages/ConsoleView.xaml | 6 +- src/SyncTrayzor/SyncTrayzor.csproj | 2 +- src/SyncTrayzor/Xaml/ScrollToEndBehaviour.cs | 41 ++++++++++ src/SyncTrayzor/Xaml/ScrollViewerUtilities.cs | 76 ------------------- 5 files changed, 48 insertions(+), 79 deletions(-) create mode 100644 src/SyncTrayzor/Xaml/ScrollToEndBehaviour.cs delete mode 100644 src/SyncTrayzor/Xaml/ScrollViewerUtilities.cs diff --git a/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml b/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml index 1d3a6764..3bf73c6c 100644 --- a/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml +++ b/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml @@ -55,7 +55,7 @@ - + diff --git a/src/SyncTrayzor/Pages/ConsoleView.xaml b/src/SyncTrayzor/Pages/ConsoleView.xaml index d3a616ac..a3d69e55 100644 --- a/src/SyncTrayzor/Pages/ConsoleView.xaml +++ b/src/SyncTrayzor/Pages/ConsoleView.xaml @@ -3,12 +3,16 @@ 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:i="http://schemas.microsoft.com/expression/2010/interactivity" mc:Ignorable="d" xmlns:s="https://github.com/canton7/Stylet" xmlns:xaml="clr-namespace:SyncTrayzor.Xaml" d:DesignHeight="300" d:DesignWidth="300"> - + + + + diff --git a/src/SyncTrayzor/SyncTrayzor.csproj b/src/SyncTrayzor/SyncTrayzor.csproj index 39dca36f..2bf69a4b 100644 --- a/src/SyncTrayzor/SyncTrayzor.csproj +++ b/src/SyncTrayzor/SyncTrayzor.csproj @@ -206,7 +206,7 @@ - + diff --git a/src/SyncTrayzor/Xaml/ScrollToEndBehaviour.cs b/src/SyncTrayzor/Xaml/ScrollToEndBehaviour.cs new file mode 100644 index 00000000..c756e1e7 --- /dev/null +++ b/src/SyncTrayzor/Xaml/ScrollToEndBehaviour.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; + +namespace SyncTrayzor.Xaml +{ + public class ScrollToEndBehaviour : DetachingBehaviour + { + public INotifyCollectionChanged Source + { + get { return (INotifyCollectionChanged)GetValue(SourceProperty); } + set { SetValue(SourceProperty, value); } + } + + public static readonly DependencyProperty SourceProperty = + DependencyProperty.Register("Source", typeof(INotifyCollectionChanged), typeof(ScrollToEndBehaviour), new PropertyMetadata(null, (d, e) => + { + ((ScrollToEndBehaviour)d).InccSubject(e.NewValue as INotifyCollectionChanged, e.OldValue as INotifyCollectionChanged); + })); + + private void InccSubject(INotifyCollectionChanged newValue, INotifyCollectionChanged oldValue) + { + if (oldValue != null) + oldValue.CollectionChanged -= this.OnCollectionChanged; + + if (newValue != null) + newValue.CollectionChanged += this.OnCollectionChanged; + } + + private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Reset) + this.AssociatedObject.ScrollToEnd(); + } + } +} diff --git a/src/SyncTrayzor/Xaml/ScrollViewerUtilities.cs b/src/SyncTrayzor/Xaml/ScrollViewerUtilities.cs deleted file mode 100644 index 3044b17a..00000000 --- a/src/SyncTrayzor/Xaml/ScrollViewerUtilities.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; - -namespace SyncTrayzor.Xaml -{ - public static class ScrollViewerUtilities - { - - - public static NotifyCollectionChangedEventHandler GetScrollToEndSourceHandler(DependencyObject obj) - { - return (NotifyCollectionChangedEventHandler)obj.GetValue(ScrollToEndSourceHandlerProperty); - } - - public static void SetScrollToEndSourceHandler(DependencyObject obj, NotifyCollectionChangedEventHandler value) - { - obj.SetValue(ScrollToEndSourceHandlerProperty, value); - } - - // Using a DependencyProperty as the backing store for ScrollToEndSourceHandler. This enables animation, styling, binding, etc... - public static readonly DependencyProperty ScrollToEndSourceHandlerProperty = - DependencyProperty.RegisterAttached("ScrollToEndSourceHandler", typeof(NotifyCollectionChangedEventHandler), typeof(ScrollViewerUtilities), new PropertyMetadata(null)); - - - - public static INotifyCollectionChanged GetScrollToEndSource(DependencyObject obj) - { - return (INotifyCollectionChanged)obj.GetValue(ScrollToEndSourceProperty); - } - - public static void SetScrollToEndSource(DependencyObject obj, INotifyCollectionChanged value) - { - obj.SetValue(ScrollToEndSourceProperty, value); - } - - // Using a DependencyProperty as the backing store for ScrollToEndSource. This enables animation, styling, binding, etc... - public static readonly DependencyProperty ScrollToEndSourceProperty = - DependencyProperty.RegisterAttached("ScrollToEndSource", typeof(INotifyCollectionChanged), typeof(ScrollViewerUtilities), new PropertyMetadata(null, (d, e) => - { - var scrollViewer = d as ScrollViewer; - if (scrollViewer == null) - return; - - var newValue = e.NewValue as INotifyCollectionChanged; - var oldValue = e.OldValue as INotifyCollectionChanged; - - if (oldValue != null) - { - var oldHandler = GetScrollToEndSourceHandler(scrollViewer); - if (oldHandler != null) - oldValue.CollectionChanged -= oldHandler; - } - - if (newValue != null) - { - NotifyCollectionChangedEventHandler handler = (no, ne) => - { - if (ne.Action == NotifyCollectionChangedAction.Add || ne.Action == NotifyCollectionChangedAction.Reset) - scrollViewer.ScrollToEnd(); - }; - - SetScrollToEndSourceHandler(scrollViewer, handler); - newValue.CollectionChanged += handler; - } - - scrollViewer.ScrollToEnd(); - })); - } -} From 5a252c81b7524f3dcd65985a12d626770f2d2ed9 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Sun, 15 Mar 2015 10:14:00 +0000 Subject: [PATCH 06/16] Fix tilde substitution when resolving folders --- src/SyncTrayzor/SyncThing/SyncThingManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SyncTrayzor/SyncThing/SyncThingManager.cs b/src/SyncTrayzor/SyncThing/SyncThingManager.cs index 85f8cd0e..4133a79e 100644 --- a/src/SyncTrayzor/SyncThing/SyncThingManager.cs +++ b/src/SyncTrayzor/SyncThing/SyncThingManager.cs @@ -257,7 +257,7 @@ private async Task StartupCompleteAsync() var ignores = await this.apiClient.FetchIgnoresAsync(folder.ID); var path = folder.Path; if (path.StartsWith("~")) - path = Path.Combine(tilde, path.Substring(1)); + path = Path.Combine(tilde, path.Substring(1).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)); return new Folder(folder.ID, path, new FolderIgnores(ignores.IgnorePatterns, ignores.RegexPatterns)); }); From 477bd1ae6479c075e8639a5c71f5d3b02af9284c Mon Sep 17 00:00:00 2001 From: Antony Male Date: Sun, 15 Mar 2015 10:37:39 +0000 Subject: [PATCH 07/16] Add memory usage logging --- src/SyncTrayzor/Bootstrapper.cs | 2 + src/SyncTrayzor/Services/MemoryUsageLogger.cs | 56 +++++++++++++++++++ src/SyncTrayzor/SyncTrayzor.csproj | 1 + 3 files changed, 59 insertions(+) create mode 100644 src/SyncTrayzor/Services/MemoryUsageLogger.cs diff --git a/src/SyncTrayzor/Bootstrapper.cs b/src/SyncTrayzor/Bootstrapper.cs index 04f96292..67c2b097 100644 --- a/src/SyncTrayzor/Bootstrapper.cs +++ b/src/SyncTrayzor/Bootstrapper.cs @@ -80,6 +80,8 @@ protected override void Configure() notifyIconManager.Setup((INotifyIconDelegate)this.RootViewModel); this.Container.Get().ApplyConfiguration(); + this.Container.Get().Enabled = true; + // Horrible workaround for a CefSharp crash on logout/shutdown // https://github.com/cefsharp/CefSharp/issues/800#issuecomment-75058534 this.Application.SessionEnding += (o, e) => Process.GetCurrentProcess().Kill(); diff --git a/src/SyncTrayzor/Services/MemoryUsageLogger.cs b/src/SyncTrayzor/Services/MemoryUsageLogger.cs new file mode 100644 index 00000000..02079a18 --- /dev/null +++ b/src/SyncTrayzor/Services/MemoryUsageLogger.cs @@ -0,0 +1,56 @@ +using NLog; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Timers; + +namespace SyncTrayzor.Services +{ + public class MemoryUsageLogger + { + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + private static readonly string[] sizes = { "B", "KB", "MB", "GB" }; + private static readonly TimeSpan pollInterval = TimeSpan.FromSeconds(30); + + private readonly Timer timer; + private readonly Process process; + + public bool Enabled + { + get { return this.timer.Enabled; } + set { this.timer.Enabled = value; } + } + + public MemoryUsageLogger() + { + this.process = Process.GetCurrentProcess(); + + this.timer = new Timer() + { + AutoReset = true, + Interval = pollInterval.TotalMilliseconds, + }; + this.timer.Elapsed += (o, e) => + { + logger.Debug("Working Set: {0}. Private Memory Size: {1}. GC Total Memory: {2}", + this.BytesToHuman(this.process.WorkingSet64), this.BytesToHuman(this.process.PrivateMemorySize64), + this.BytesToHuman(GC.GetTotalMemory(false))); + }; + } + + private string BytesToHuman(long bytes) + { + // http://stackoverflow.com/a/281679/1086121 + int order = 0; + while (bytes >= 1024 && order + 1 < sizes.Length) + { + order++; + bytes = bytes / 1024; + } + return String.Format("{0:0.#}{1}", bytes, sizes[order]); + } + } +} diff --git a/src/SyncTrayzor/SyncTrayzor.csproj b/src/SyncTrayzor/SyncTrayzor.csproj index 2bf69a4b..02154dd6 100644 --- a/src/SyncTrayzor/SyncTrayzor.csproj +++ b/src/SyncTrayzor/SyncTrayzor.csproj @@ -159,6 +159,7 @@ + From 399714f6f569b7e57d0852b19c51f8b39d5f83bd Mon Sep 17 00:00:00 2001 From: Antony Male Date: Sun, 15 Mar 2015 11:14:42 +0000 Subject: [PATCH 08/16] Move back to the old way of handling console messages This uses a lot less memory if there are many messages --- src/SyncTrayzor/Pages/ConsoleView.xaml | 29 +++++---------- src/SyncTrayzor/Pages/ConsoleViewModel.cs | 5 +-- src/SyncTrayzor/SyncTrayzor.csproj | 1 + .../Xaml/LogMessageListToStringConverter.cs | 35 +++++++++++++++++++ src/SyncTrayzor/Xaml/ScrollToEndBehaviour.cs | 28 +++++---------- 5 files changed, 57 insertions(+), 41 deletions(-) create mode 100644 src/SyncTrayzor/Xaml/LogMessageListToStringConverter.cs diff --git a/src/SyncTrayzor/Pages/ConsoleView.xaml b/src/SyncTrayzor/Pages/ConsoleView.xaml index a3d69e55..0665fb02 100644 --- a/src/SyncTrayzor/Pages/ConsoleView.xaml +++ b/src/SyncTrayzor/Pages/ConsoleView.xaml @@ -8,31 +8,20 @@ xmlns:s="https://github.com/canton7/Stylet" xmlns:xaml="clr-namespace:SyncTrayzor.Xaml" d:DesignHeight="300" d:DesignWidth="300"> + + + - - - - - - - - - - - - - - + Text="{Binding LogMessages, Converter={StaticResource LogMessagesConverter}}"> + + + + diff --git a/src/SyncTrayzor/Pages/ConsoleViewModel.cs b/src/SyncTrayzor/Pages/ConsoleViewModel.cs index 56b04e86..5648ac10 100644 --- a/src/SyncTrayzor/Pages/ConsoleViewModel.cs +++ b/src/SyncTrayzor/Pages/ConsoleViewModel.cs @@ -21,7 +21,7 @@ public class ConsoleViewModel : Screen private readonly ISyncThingManager syncThingManager; private readonly IConfigurationProvider configurationProvider; - public ObservableQueue LogMessages { get; private set; } + public Queue LogMessages { get; private set; } public ConsoleViewModel( ISyncThingManager syncThingManager, @@ -29,7 +29,7 @@ public ConsoleViewModel( { this.syncThingManager = syncThingManager; this.configurationProvider = configurationProvider; - this.LogMessages = new ObservableQueue(); + this.LogMessages = new Queue(); var configuration = this.configurationProvider.Load(); this.configurationProvider.ConfigurationChanged += (o, e) => configuration = e.NewConfiguration; @@ -45,6 +45,7 @@ public ConsoleViewModel( this.LogMessages.Enqueue(message); if (this.LogMessages.Count > maxLogMessages) this.LogMessages.Dequeue(); + this.NotifyOfPropertyChange(() => this.LogMessages); }; } } diff --git a/src/SyncTrayzor/SyncTrayzor.csproj b/src/SyncTrayzor/SyncTrayzor.csproj index 02154dd6..99b4becf 100644 --- a/src/SyncTrayzor/SyncTrayzor.csproj +++ b/src/SyncTrayzor/SyncTrayzor.csproj @@ -207,6 +207,7 @@ + diff --git a/src/SyncTrayzor/Xaml/LogMessageListToStringConverter.cs b/src/SyncTrayzor/Xaml/LogMessageListToStringConverter.cs new file mode 100644 index 00000000..7eeeae5a --- /dev/null +++ b/src/SyncTrayzor/Xaml/LogMessageListToStringConverter.cs @@ -0,0 +1,35 @@ +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 LogMessageListToStringConverter : IValueConverter + { + private readonly StringBuilder sb = new StringBuilder(); + + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + var list = value as IEnumerable; + if (list == null) + return null; + + foreach (var elem in list) + { + this.sb.AppendLine(elem); + } + + var str = this.sb.ToString(); + this.sb.Clear(); + return str; + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/SyncTrayzor/Xaml/ScrollToEndBehaviour.cs b/src/SyncTrayzor/Xaml/ScrollToEndBehaviour.cs index c756e1e7..202ff314 100644 --- a/src/SyncTrayzor/Xaml/ScrollToEndBehaviour.cs +++ b/src/SyncTrayzor/Xaml/ScrollToEndBehaviour.cs @@ -9,33 +9,23 @@ namespace SyncTrayzor.Xaml { - public class ScrollToEndBehaviour : DetachingBehaviour + public class ScrollToEndBehaviour : DetachingBehaviour { - public INotifyCollectionChanged Source + protected override void AttachHandlers() { - get { return (INotifyCollectionChanged)GetValue(SourceProperty); } - set { SetValue(SourceProperty, value); } - } + this.AssociatedObject.TextChanged += TextChanged; - public static readonly DependencyProperty SourceProperty = - DependencyProperty.Register("Source", typeof(INotifyCollectionChanged), typeof(ScrollToEndBehaviour), new PropertyMetadata(null, (d, e) => - { - ((ScrollToEndBehaviour)d).InccSubject(e.NewValue as INotifyCollectionChanged, e.OldValue as INotifyCollectionChanged); - })); + this.AssociatedObject.ScrollToEnd(); + } - private void InccSubject(INotifyCollectionChanged newValue, INotifyCollectionChanged oldValue) + protected override void DetachHandlers() { - if (oldValue != null) - oldValue.CollectionChanged -= this.OnCollectionChanged; - - if (newValue != null) - newValue.CollectionChanged += this.OnCollectionChanged; + this.AssociatedObject.TextChanged -= TextChanged; } - private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + private void TextChanged(object sender, TextChangedEventArgs e) { - if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Reset) - this.AssociatedObject.ScrollToEnd(); + this.AssociatedObject.ScrollToEnd(); } } } From 22d7dc1a696742edc53e617238beb1007273fca7 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 16 Mar 2015 13:15:10 +0000 Subject: [PATCH 09/16] Remove some unused references --- src/SyncTrayzor/SyncTrayzor.csproj | 28 +++----------------- src/SyncTrayzor/Utils/CefSharpHelper.cs | 35 ------------------------- 2 files changed, 3 insertions(+), 60 deletions(-) delete mode 100644 src/SyncTrayzor/Utils/CefSharpHelper.cs diff --git a/src/SyncTrayzor/SyncTrayzor.csproj b/src/SyncTrayzor/SyncTrayzor.csproj index 99b4becf..13eda003 100644 --- a/src/SyncTrayzor/SyncTrayzor.csproj +++ b/src/SyncTrayzor/SyncTrayzor.csproj @@ -90,10 +90,7 @@ ..\packages\NLog.3.2.0.0\lib\net45\NLog.dll - - ..\packages\PropertyChanged.Fody.1.49.0\Lib\portable-net4+sl4+wp8+win8+wpa81+MonoAndroid16+MonoTouch40\PropertyChanged.dll - False - + ..\packages\refit.2.2.0\lib\Net45\Refit.dll @@ -104,21 +101,14 @@ - + - - - - - 4.0 - - - + @@ -199,7 +189,6 @@ - @@ -283,17 +272,6 @@ - - - {EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B} - 1 - 1 - 0 - tlbimp - False - True - - False diff --git a/src/SyncTrayzor/Utils/CefSharpHelper.cs b/src/SyncTrayzor/Utils/CefSharpHelper.cs deleted file mode 100644 index 1ce07468..00000000 --- a/src/SyncTrayzor/Utils/CefSharpHelper.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Management; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace SyncTrayzor.Utils -{ - public static class CefSharpHelper - { - public static void TerminateCefSharpProcess() - { - var executablePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "CefSharp.BrowserSubprocess.exe"); - foreach (var process in new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + Process.GetCurrentProcess().Id).Get()) - { - if ((string)process["ExecutablePath"] == executablePath) - { - try - { - Process proc = Process.GetProcessById(Convert.ToInt32(process["ProcessId"])); - proc.Kill(); - } - catch (ArgumentException) - { - // Process already exited. - } - } - } - } - } -} From b2794d5f29e3a6e1f47fb04581ef19007eeed3f8 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Fri, 13 Mar 2015 18:07:53 +0000 Subject: [PATCH 10/16] Groundwork for device connected / disconnected alerts from tray --- src/SyncTrayzor/Bootstrapper.cs | 1 + src/SyncTrayzor/SyncThing/Device.cs | 52 +++++++++++++ .../SyncThing/DeviceConnectedEventArgs.cs | 18 +++++ .../SyncThing/DeviceDisconnectedEventArgs.cs | 18 +++++ .../EventWatcher/DeviceConnectedEventArgs.cs | 20 +++++ .../DeviceDisconnectedEventArgs.cs | 20 +++++ .../EventWatcher/ItemStateChangedEventArgs.cs | 20 +++++ .../SyncThingEventWatcher.cs | 34 +++----- src/SyncTrayzor/SyncThing/SyncThingManager.cs | 78 +++++++++++++++++-- src/SyncTrayzor/SyncTrayzor.csproj | 8 +- 10 files changed, 237 insertions(+), 32 deletions(-) create mode 100644 src/SyncTrayzor/SyncThing/Device.cs create mode 100644 src/SyncTrayzor/SyncThing/DeviceConnectedEventArgs.cs create mode 100644 src/SyncTrayzor/SyncThing/DeviceDisconnectedEventArgs.cs create mode 100644 src/SyncTrayzor/SyncThing/EventWatcher/DeviceConnectedEventArgs.cs create mode 100644 src/SyncTrayzor/SyncThing/EventWatcher/DeviceDisconnectedEventArgs.cs create mode 100644 src/SyncTrayzor/SyncThing/EventWatcher/ItemStateChangedEventArgs.cs rename src/SyncTrayzor/SyncThing/{ => EventWatcher}/SyncThingEventWatcher.cs (84%) diff --git a/src/SyncTrayzor/Bootstrapper.cs b/src/SyncTrayzor/Bootstrapper.cs index 67c2b097..c72c2669 100644 --- a/src/SyncTrayzor/Bootstrapper.cs +++ b/src/SyncTrayzor/Bootstrapper.cs @@ -10,6 +10,7 @@ using SyncTrayzor.Services; using SyncTrayzor.Services.UpdateChecker; using SyncTrayzor.SyncThing; +using SyncTrayzor.SyncThing.EventWatcher; using SyncTrayzor.Utils; using System; using System.Collections.Generic; diff --git a/src/SyncTrayzor/SyncThing/Device.cs b/src/SyncTrayzor/SyncThing/Device.cs new file mode 100644 index 00000000..41d7f0c2 --- /dev/null +++ b/src/SyncTrayzor/SyncThing/Device.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SyncTrayzor.SyncThing +{ + public class Device + { + public string DeviceId { get; private set; } + public string Name { get; private set; } + + private readonly object connectivityLock = new object(); + + private bool _isConnected; + public bool IsConnected + { + get { lock (this.connectivityLock) { return this._isConnected; } } + } + + private string _address; + public string Address + { + get { lock (this.connectivityLock) { return this._address; } } + } + + public Device(string deviceId, string name) + { + this.DeviceId = deviceId; + this.Name = name; + } + + public void SetConnected(string address) + { + lock (this.connectivityLock) + { + this._isConnected = true; + this._address = address; + } + } + + public void SetDisconnected() + { + lock (this.connectivityLock) + { + this._isConnected = false; + this._address = null; + } + } + } +} diff --git a/src/SyncTrayzor/SyncThing/DeviceConnectedEventArgs.cs b/src/SyncTrayzor/SyncThing/DeviceConnectedEventArgs.cs new file mode 100644 index 00000000..d65e6175 --- /dev/null +++ b/src/SyncTrayzor/SyncThing/DeviceConnectedEventArgs.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SyncTrayzor.SyncThing +{ + public class DeviceConnectedEventArgs : EventArgs + { + public Device Device { get; private set; } + + public DeviceConnectedEventArgs(Device device) + { + this.Device = device; + } + } +} diff --git a/src/SyncTrayzor/SyncThing/DeviceDisconnectedEventArgs.cs b/src/SyncTrayzor/SyncThing/DeviceDisconnectedEventArgs.cs new file mode 100644 index 00000000..e0334108 --- /dev/null +++ b/src/SyncTrayzor/SyncThing/DeviceDisconnectedEventArgs.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SyncTrayzor.SyncThing +{ + public class DeviceDisconnectedEventArgs : EventArgs + { + public Device Device { get; private set; } + + public DeviceDisconnectedEventArgs(Device device) + { + this.Device = device; + } + } +} diff --git a/src/SyncTrayzor/SyncThing/EventWatcher/DeviceConnectedEventArgs.cs b/src/SyncTrayzor/SyncThing/EventWatcher/DeviceConnectedEventArgs.cs new file mode 100644 index 00000000..47e8d011 --- /dev/null +++ b/src/SyncTrayzor/SyncThing/EventWatcher/DeviceConnectedEventArgs.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SyncTrayzor.SyncThing.EventWatcher +{ + public class DeviceConnectedEventArgs : EventArgs + { + public string DeviceId { get; private set; } + public string Address { get; private set; } + + public DeviceConnectedEventArgs(string deviceId, string address) + { + this.DeviceId = deviceId; + this.Address = address; + } + } +} diff --git a/src/SyncTrayzor/SyncThing/EventWatcher/DeviceDisconnectedEventArgs.cs b/src/SyncTrayzor/SyncThing/EventWatcher/DeviceDisconnectedEventArgs.cs new file mode 100644 index 00000000..c213cbf2 --- /dev/null +++ b/src/SyncTrayzor/SyncThing/EventWatcher/DeviceDisconnectedEventArgs.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SyncTrayzor.SyncThing.EventWatcher +{ + public class DeviceDisconnectedEventArgs : EventArgs + { + public string DeviceId { get; private set; } + public string Error { get; private set; } + + public DeviceDisconnectedEventArgs(string deviceId, string error) + { + this.DeviceId = deviceId; + this.Error = error; + } + } +} diff --git a/src/SyncTrayzor/SyncThing/EventWatcher/ItemStateChangedEventArgs.cs b/src/SyncTrayzor/SyncThing/EventWatcher/ItemStateChangedEventArgs.cs new file mode 100644 index 00000000..2693a431 --- /dev/null +++ b/src/SyncTrayzor/SyncThing/EventWatcher/ItemStateChangedEventArgs.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SyncTrayzor.SyncThing.EventWatcher +{ + public class ItemStateChangedEventArgs : EventArgs + { + public string Folder { get; private set; } + public string Item { get; private set; } + + public ItemStateChangedEventArgs(string folder, string item) + { + this.Folder = folder; + this.Item = item; + } + } +} diff --git a/src/SyncTrayzor/SyncThing/SyncThingEventWatcher.cs b/src/SyncTrayzor/SyncThing/EventWatcher/SyncThingEventWatcher.cs similarity index 84% rename from src/SyncTrayzor/SyncThing/SyncThingEventWatcher.cs rename to src/SyncTrayzor/SyncThing/EventWatcher/SyncThingEventWatcher.cs index 602749de..62e220b3 100644 --- a/src/SyncTrayzor/SyncThing/SyncThingEventWatcher.cs +++ b/src/SyncTrayzor/SyncThing/EventWatcher/SyncThingEventWatcher.cs @@ -8,28 +8,16 @@ using System.Text; using System.Threading.Tasks; -namespace SyncTrayzor.SyncThing +namespace SyncTrayzor.SyncThing.EventWatcher { - public class ItemStateChangedEventArgs : EventArgs - { - public string Folder { get; private set; } - public string Item { get; private set; } - - public ItemStateChangedEventArgs(string folder, string item) - { - this.Folder = folder; - this.Item = item; - } - } - public interface ISyncThingEventWatcher : ISyncThingPoller { event EventHandler SyncStateChanged; event EventHandler StartupComplete; event EventHandler ItemStarted; event EventHandler ItemFinished; - event EventHandler DeviceConnected; - event EventHandler DeviceDisconnected; + event EventHandler DeviceConnected; + event EventHandler DeviceDisconnected; } public class SyncThingEventWatcher : SyncThingPoller, ISyncThingEventWatcher, IEventVisitor @@ -43,8 +31,8 @@ public class SyncThingEventWatcher : SyncThingPoller, ISyncThingEventWatcher, IE public event EventHandler StartupComplete; public event EventHandler ItemStarted; public event EventHandler ItemFinished; - public event EventHandler DeviceConnected; - public event EventHandler DeviceDisconnected; + public event EventHandler DeviceConnected; + public event EventHandler DeviceDisconnected; public SyncThingEventWatcher(ISyncThingApiClient apiClient) : base(TimeSpan.Zero) @@ -113,18 +101,18 @@ private void OnItemFinished(string folder, string item) handler(this, new ItemStateChangedEventArgs(folder, item)); } - private void OnDeviceConnected() + private void OnDeviceConnected(string deviceId, string address) { var handler = this.DeviceConnected; if (handler != null) - handler(this, EventArgs.Empty); + handler(this, new DeviceConnectedEventArgs(deviceId, address)); } - private void OnDeviceDisconnected() + private void OnDeviceDisconnected(string deviceId, string error) { var handler = this.DeviceDisconnected; if (handler != null) - handler(this, EventArgs.Empty); + handler(this, new DeviceDisconnectedEventArgs(deviceId, error)); } #region IEventVisitor @@ -165,12 +153,12 @@ public void Accept(StartupCompleteEvent evt) public void Accept(DeviceConnectedEvent evt) { - this.OnDeviceConnected(); + this.OnDeviceConnected(evt.Data.Id, evt.Data.Address); } public void Accept(DeviceDisconnectedEvent evt) { - this.OnDeviceDisconnected(); + this.OnDeviceDisconnected(evt.Data.Id, evt.Data.Error); } #endregion diff --git a/src/SyncTrayzor/SyncThing/SyncThingManager.cs b/src/SyncTrayzor/SyncThing/SyncThingManager.cs index 4133a79e..1cf005ca 100644 --- a/src/SyncTrayzor/SyncThing/SyncThingManager.cs +++ b/src/SyncTrayzor/SyncThing/SyncThingManager.cs @@ -1,5 +1,6 @@ using NLog; using SyncTrayzor.SyncThing.Api; +using SyncTrayzor.SyncThing.EventWatcher; using SyncTrayzor.Utils; using System; using System.Collections.Concurrent; @@ -10,6 +11,8 @@ using System.Threading; using System.Threading.Tasks; +using EventWatcher = SyncTrayzor.SyncThing.EventWatcher; + namespace SyncTrayzor.SyncThing { public interface ISyncThingManager : IDisposable @@ -23,6 +26,8 @@ public interface ISyncThingManager : IDisposable SyncThingConnectionStats TotalConnectionStats { get; } event EventHandler TotalConnectionStatsChanged; event EventHandler ProcessExitedWithError; + event EventHandler DeviceConnected; + event EventHandler DeviceDisconnected; string ExecutablePath { get; set; } string ApiKey { get; set; } @@ -40,6 +45,9 @@ public interface ISyncThingManager : IDisposable bool TryFetchFolderById(string folderId, out Folder folder); IReadOnlyCollection FetchAllFolders(); + bool TryFetchDeviceById(string deviceId, out Device device); + IReadOnlyCollection FetchAllDevices(); + Task ScanAsync(string folderId, string subPath); Task ReloadIgnoresAsync(string folderId); } @@ -75,6 +83,8 @@ public SyncThingState State public event EventHandler StateChanged; public event EventHandler MessageLogged; public event EventHandler FolderSyncStateChanged; + public event EventHandler DeviceConnected; + public event EventHandler DeviceDisconnected; private readonly object totalConnectionStatsLock = new object(); private SyncThingConnectionStats _totalConnectionStats; @@ -98,13 +108,21 @@ public SyncThingConnectionStats TotalConnectionStats // to create a memory barrier. The lock is only used when setting/fetching the field, not when accessing the // Folders dictionary itself. private readonly object foldersLock = new object(); - private ConcurrentDictionary _folders; + private ConcurrentDictionary _folders = new ConcurrentDictionary(); private ConcurrentDictionary folders { get { lock (this.foldersLock) { return this._folders; } } set { lock (this.foldersLock) { this._folders = value; } } } + private readonly object devicesLock = new object(); + private ConcurrentDictionary _devices = new ConcurrentDictionary(); + public ConcurrentDictionary devices + { + get { lock (this.devicesLock) { return this._devices; } } + set { lock (this.devicesLock) this._devices = value; } + } + public SyncthingVersion Version { get; private set; } public SyncThingManager( @@ -113,7 +131,6 @@ public SyncThingManager( ISyncThingEventWatcher eventWatcher, ISyncThingConnectionsWatcher connectionsWatcher) { - this.folders = new ConcurrentDictionary(); this.LastConnectivityEventTime = DateTime.UtcNow; this.eventDispatcher = new SynchronizedEventDispatcher(this); @@ -126,11 +143,11 @@ public SyncThingManager( this.processRunner.MessageLogged += (o, e) => this.OnMessageLogged(e.LogMessage); this.eventWatcher.StartupComplete += (o, e) => { var t = this.StartupCompleteAsync(); }; - this.eventWatcher.SyncStateChanged += (o, e) => this.OnSyncStateChanged(e); + this.eventWatcher.SyncStateChanged += (o, e) => this.OnFolderSyncStateChanged(e); this.eventWatcher.ItemStarted += (o, e) => this.ItemStarted(e.Folder, e.Item); this.eventWatcher.ItemFinished += (o, e) => this.ItemFinished(e.Folder, e.Item); - this.eventWatcher.DeviceConnected += (o, e) => this.DeviceConnectedOrDisconnected(); - this.eventWatcher.DeviceDisconnected += (o, e) => this.DeviceConnectedOrDisconnected(); + this.eventWatcher.DeviceConnected += (o, e) => this.OnDeviceConnected(e); + this.eventWatcher.DeviceDisconnected += (o, e) => this.OnDeviceDisconnected(e); this.connectionsWatcher.TotalConnectionStatsChanged += (o, e) => this.OnTotalConnectionStatsChanged(e.TotalConnectionStats); } @@ -186,6 +203,16 @@ public IReadOnlyCollection FetchAllFolders() return new List(this.folders.Values).AsReadOnly(); } + public bool TryFetchDeviceById(string deviceId, out Device device) + { + return this.devices.TryGetValue(deviceId, out device); + } + + public IReadOnlyCollection FetchAllDevices() + { + return new List(this.devices.Values).AsReadOnly(); + } + public Task ScanAsync(string folderId, string subPath) { return this.apiClient.ScanAsync(folderId, subPath); @@ -248,7 +275,17 @@ private async Task StartupCompleteAsync() var configTask = this.apiClient.FetchConfigAsync(); var systemTask = this.apiClient.FetchSystemInfoAsync(); var versionTask = this.apiClient.FetchVersionAsync(); - await Task.WhenAll(configTask, systemTask, versionTask); + var connectionsTask = this.apiClient.FetchConnectionsAsync(); + await Task.WhenAll(configTask, systemTask, versionTask, connectionsTask); + + this.devices = new ConcurrentDictionary(configTask.Result.Devices.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); + })); var tilde = systemTask.Result.Tilde; @@ -288,9 +325,34 @@ private void ItemFinished(string folderId, string item) folder.RemoveSyncingPath(item); } - private void DeviceConnectedOrDisconnected() + private void OnDeviceConnected(EventWatcher.DeviceConnectedEventArgs e) { + Device device; + if (!this.devices.TryGetValue(e.DeviceId, out device)) + { + logger.Warn("Unexpected device connected: {0}, address {1}. It wasn't fetched when we fetched our config", e.DeviceId, e.Address); + return; // Not expecting this device! It wasn't in the config... + } + + device.SetConnected(e.Address); + this.LastConnectivityEventTime = DateTime.UtcNow; + + this.eventDispatcher.Raise(this.DeviceConnected, new DeviceConnectedEventArgs(device)); + } + + private void OnDeviceDisconnected(EventWatcher.DeviceDisconnectedEventArgs e) + { + Device device; + if (!this.devices.TryGetValue(e.DeviceId, out device)) + { + logger.Warn("Unexpected device connected: {0}, error {1}. It wasn't fetched when we fetched our config", e.DeviceId, e.Error); + return; // Not expecting this device! It wasn't in the config... + } + + device.SetDisconnected(); this.LastConnectivityEventTime = DateTime.UtcNow; + + this.eventDispatcher.Raise(this.DeviceDisconnected, new DeviceDisconnectedEventArgs(device)); } private void OnMessageLogged(string logMessage) @@ -298,7 +360,7 @@ private void OnMessageLogged(string logMessage) this.eventDispatcher.Raise(this.MessageLogged, new MessageLoggedEventArgs(logMessage)); } - private void OnSyncStateChanged(SyncStateChangedEventArgs e) + private void OnFolderSyncStateChanged(SyncStateChangedEventArgs e) { Folder folder; if (!this.folders.TryGetValue(e.FolderId, out folder)) diff --git a/src/SyncTrayzor/SyncTrayzor.csproj b/src/SyncTrayzor/SyncTrayzor.csproj index 13eda003..a2f1191b 100644 --- a/src/SyncTrayzor/SyncTrayzor.csproj +++ b/src/SyncTrayzor/SyncTrayzor.csproj @@ -175,6 +175,12 @@ + + + + + + @@ -183,7 +189,7 @@ - + From 0d8f5438c8c26ce800a8f434b4e3dbbe01d3da08 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 16 Mar 2015 17:38:52 +0000 Subject: [PATCH 11/16] Finalize connectivity balloons --- .../NotifyIcon/NotifyIconManager.cs | 21 ++++++++ src/SyncTrayzor/Pages/SettingsView.xaml | 10 +++- src/SyncTrayzor/Pages/SettingsViewModel.cs | 18 ++++--- .../Properties/Strings/Resources.Designer.cs | 54 +++++++++++++++++++ .../Properties/Strings/Resources.resx | 24 +++++++++ src/SyncTrayzor/Services/Configuration.cs | 14 +++-- .../Services/ConfigurationApplicator.cs | 1 + src/SyncTrayzor/SyncThing/Api/Connections.cs | 9 +++- src/SyncTrayzor/SyncThing/SyncThingManager.cs | 14 ++++- src/SyncTrayzor/SyncTrayzor.csproj | 2 +- 10 files changed, 149 insertions(+), 18 deletions(-) diff --git a/src/SyncTrayzor/NotifyIcon/NotifyIconManager.cs b/src/SyncTrayzor/NotifyIcon/NotifyIconManager.cs index 4dfc8080..6a46e8a1 100644 --- a/src/SyncTrayzor/NotifyIcon/NotifyIconManager.cs +++ b/src/SyncTrayzor/NotifyIcon/NotifyIconManager.cs @@ -18,6 +18,7 @@ public interface INotifyIconManager bool MinimizeToTray { get; set; } bool CloseToTray { get; set; } bool ShowSynchronizedBalloon { get; set; } + bool ShowDeviceConnectivityBalloons { get; set; } void Setup(INotifyIconDelegate rootViewModel); @@ -58,6 +59,7 @@ public bool CloseToTray } public bool ShowSynchronizedBalloon { get; set; } + public bool ShowDeviceConnectivityBalloons { get; set; } public NotifyIconManager( IViewManager viewManager, @@ -81,12 +83,31 @@ public NotifyIconManager( { if (this.ShowSynchronizedBalloon && DateTime.UtcNow - this.syncThingManager.LastConnectivityEventTime > syncedDeadTime && + DateTime.UtcNow - this.syncThingManager.StartedTime > syncedDeadTime && e.SyncState == FolderSyncState.Idle && e.PrevSyncState == FolderSyncState.Syncing) { Application.Current.Dispatcher.CheckAccess(); // Double-check this.taskbarIcon.ShowBalloonTip(Localizer.Translate("TrayIcon_Balloon_FinishedSyncing_Title"), Localizer.Translate("TrayIcon_Balloon_FinishedSyncing_Message", e.Folder.FolderId), BalloonIcon.Info); } }; + + this.syncThingManager.DeviceConnected += (o, e) => + { + if (this.ShowDeviceConnectivityBalloons && + DateTime.UtcNow - this.syncThingManager.StartedTime > syncedDeadTime) + { + this.taskbarIcon.ShowBalloonTip(Localizer.Translate("TrayIcon_Balloon_DeviceConnected_Title"), Localizer.Translate("TrayIcon_Balloon_DeviceConnected_Message", e.Device.Name), BalloonIcon.Info); + } + }; + + this.syncThingManager.DeviceDisconnected += (o, e) => + { + if (this.ShowDeviceConnectivityBalloons && + DateTime.UtcNow - this.syncThingManager.StartedTime > syncedDeadTime) + { + this.taskbarIcon.ShowBalloonTip(Localizer.Translate("TrayIcon_Balloon_DeviceDisconnected_Title"), Localizer.Translate("TrayIcon_Balloon_DeviceDisconnected_Message", e.Device.Name), BalloonIcon.Info); + } + }; } private void SetShutdownMode() diff --git a/src/SyncTrayzor/Pages/SettingsView.xaml b/src/SyncTrayzor/Pages/SettingsView.xaml index 4217778b..fde75a85 100644 --- a/src/SyncTrayzor/Pages/SettingsView.xaml +++ b/src/SyncTrayzor/Pages/SettingsView.xaml @@ -29,13 +29,19 @@ - - + + + + + + + + diff --git a/src/SyncTrayzor/Pages/SettingsViewModel.cs b/src/SyncTrayzor/Pages/SettingsViewModel.cs index a603120d..6e7277f1 100644 --- a/src/SyncTrayzor/Pages/SettingsViewModel.cs +++ b/src/SyncTrayzor/Pages/SettingsViewModel.cs @@ -40,13 +40,15 @@ public class SettingsViewModel : Screen private readonly IConfigurationProvider configurationProvider; private readonly IAutostartProvider autostartProvider; - public bool ShowTrayIconOnlyOnClose { get; set;} public bool MinimizeToTray { get; set; } public bool CloseToTray { get; set; } - public bool ShowSynchronizedBalloon { get; set; } public bool NotifyOfNewVersions { get; set; } public bool ObfuscateDeviceIDs { get; set; } + public bool ShowTrayIconOnlyOnClose { get; set; } + public bool ShowSynchronizedBalloon { get; set; } + public bool ShowDeviceConnectivityBalloons { get; set; } + public bool StartSyncThingAutomatically { get; set; } public string SyncThingAddress { get; set; } public string SyncThingApiKey { get; set; } @@ -84,13 +86,15 @@ public SettingsViewModel( var configuration = this.configurationProvider.Load(); - this.ShowTrayIconOnlyOnClose = configuration.ShowTrayIconOnlyOnClose; this.MinimizeToTray = configuration.MinimizeToTray; this.CloseToTray = configuration.CloseToTray; - this.ShowSynchronizedBalloon = configuration.ShowSynchronizedBalloon; this.NotifyOfNewVersions = configuration.NotifyOfNewVersions; this.ObfuscateDeviceIDs = configuration.ObfuscateDeviceIDs; + this.ShowTrayIconOnlyOnClose = configuration.ShowTrayIconOnlyOnClose; + this.ShowSynchronizedBalloon = configuration.ShowSynchronizedBalloon; + this.ShowDeviceConnectivityBalloons = configuration.ShowDeviceConnectivityBalloons; + this.StartSyncThingAutomatically = configuration.StartSyncthingAutomatically; this.SyncThingAddress = configuration.SyncthingAddress; this.SyncThingApiKey = configuration.SyncthingApiKey; @@ -127,13 +131,15 @@ public void Save() { var configuration = this.configurationProvider.Load(); - configuration.ShowTrayIconOnlyOnClose = this.ShowTrayIconOnlyOnClose; configuration.MinimizeToTray = this.MinimizeToTray; configuration.CloseToTray = this.CloseToTray; - configuration.ShowSynchronizedBalloon = this.ShowSynchronizedBalloon; configuration.NotifyOfNewVersions = this.NotifyOfNewVersions; configuration.ObfuscateDeviceIDs = this.ObfuscateDeviceIDs; + configuration.ShowTrayIconOnlyOnClose = this.ShowTrayIconOnlyOnClose; + configuration.ShowSynchronizedBalloon = this.ShowSynchronizedBalloon; + configuration.ShowDeviceConnectivityBalloons = this.ShowDeviceConnectivityBalloons; + configuration.StartSyncthingAutomatically = this.StartSyncThingAutomatically; configuration.SyncthingAddress = this.SyncThingAddress; configuration.SyncthingApiKey = this.SyncThingApiKey; diff --git a/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs b/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs index 89ad899a..26a4e6ef 100644 --- a/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs +++ b/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs @@ -423,6 +423,15 @@ public static string SettingsView_Section_SyncTrayzor { } } + /// + /// Looks up a localized string similar to Tray Icon. + /// + public static string SettingsView_Section_TrayIcon { + get { + return ResourceManager.GetString("SettingsView_Section_TrayIcon", resourceCulture); + } + } + /// /// Looks up a localized string similar to Watched Folders. /// @@ -441,6 +450,15 @@ public static string SettingsView_ShowBalloonWhenSynchronized { } } + /// + /// Looks up a localized string similar to Show device Connected/Disconnected balloon messages. + /// + public static string SettingsView_ShowDeviceConnectivityBalloons { + get { + return ResourceManager.GetString("SettingsView_ShowDeviceConnectivityBalloons", resourceCulture); + } + } + /// /// Looks up a localized string similar to Start Minimized. /// @@ -757,6 +775,42 @@ public static string TranslatorAttributation { } } + /// + /// Looks up a localized string similar to {0} connected. + /// + public static string TrayIcon_Balloon_DeviceConnected_Message { + get { + return ResourceManager.GetString("TrayIcon_Balloon_DeviceConnected_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Device Connected. + /// + public static string TrayIcon_Balloon_DeviceConnected_Title { + get { + return ResourceManager.GetString("TrayIcon_Balloon_DeviceConnected_Title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} disconnected. + /// + public static string TrayIcon_Balloon_DeviceDisconnected_Message { + get { + return ResourceManager.GetString("TrayIcon_Balloon_DeviceDisconnected_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Device Disconnected. + /// + public static string TrayIcon_Balloon_DeviceDisconnected_Title { + get { + return ResourceManager.GetString("TrayIcon_Balloon_DeviceDisconnected_Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0}: Finished Syncing. /// diff --git a/src/SyncTrayzor/Properties/Strings/Resources.resx b/src/SyncTrayzor/Properties/Strings/Resources.resx index 5e7442eb..232f58cb 100644 --- a/src/SyncTrayzor/Properties/Strings/Resources.resx +++ b/src/SyncTrayzor/Properties/Strings/Resources.resx @@ -474,4 +474,28 @@ SyncTrayzor is going to have to close. Sorry about that Dummy text ignored by the UI Shown on the 'about' page, this is space for you to attribute yourself. E.g. your local language equivalent of "Kingon translation by My Name". Add yourself to this field if you contribute to the translation for this language. + + Tray Icon + + + Show device Connected/Disconnected balloon messages + + + {0} connected + Message of tray icon balloon show when another device connects +{0}: device name + + + Device Connected + Title of tray icon balloon when another device connected + + + {0} disconnected + Message of tray icon balloon show when another device disconnects +{0}: device name + + + Device Disconnected + Title of tray icon balloon when another device disconnected + \ No newline at end of file diff --git a/src/SyncTrayzor/Services/Configuration.cs b/src/SyncTrayzor/Services/Configuration.cs index 9921bd93..bbb78f8b 100644 --- a/src/SyncTrayzor/Services/Configuration.cs +++ b/src/SyncTrayzor/Services/Configuration.cs @@ -42,6 +42,7 @@ public class Configuration public bool MinimizeToTray { get; set; } public bool CloseToTray { get; set; } public bool ShowSynchronizedBalloon { get; set; } + public bool ShowDeviceConnectivityBalloons { get; set; } public string SyncthingAddress { get; set; } public bool StartSyncthingAutomatically { get; set; } public string SyncthingApiKey { get; set; } @@ -71,6 +72,7 @@ public Configuration(string syncThingApiKey, bool isPortableMode) this.MinimizeToTray = false; this.CloseToTray = true; this.ShowSynchronizedBalloon = true; + this.ShowDeviceConnectivityBalloons = true; this.SyncthingAddress = "http://localhost:8384"; this.StartSyncthingAutomatically = true; this.SyncthingApiKey = syncThingApiKey; @@ -88,6 +90,7 @@ public Configuration(Configuration other) this.MinimizeToTray = other.MinimizeToTray; this.CloseToTray = other.CloseToTray; this.ShowSynchronizedBalloon = other.ShowSynchronizedBalloon; + this.ShowDeviceConnectivityBalloons = other.ShowDeviceConnectivityBalloons; this.SyncthingAddress = other.SyncthingAddress; this.StartSyncthingAutomatically = other.StartSyncthingAutomatically; this.SyncthingApiKey = other.SyncthingApiKey; @@ -102,11 +105,12 @@ public Configuration(Configuration other) public override string ToString() { return String.Format("", - this.ShowTrayIconOnlyOnClose, this.MinimizeToTray, this.CloseToTray, this.ShowSynchronizedBalloon, this.SyncthingAddress, - this.StartSyncthingAutomatically, this.SyncthingApiKey, this.SyncthingTraceFacilities, this.SyncthingUseCustomHome, - String.Join(", ", this.Folders), this.NotifyOfNewVersions, this.LatestNotifiedVersion, this.ObfuscateDeviceIDs); + "ShowDeviceConnectivityBalloons={4} SyncthingAddress={5} StartSyncthingAutomatically={6} SyncthingApiKey={7} SyncthingTraceFacilities={8} " + + "SyncthingUseCustomHome={9} Folders=[{10}] NotifyOfNewVersions={11} LastNotifiedVersion={12} ObfuscateDeviceIDs={13}>", + this.ShowTrayIconOnlyOnClose, this.MinimizeToTray, this.CloseToTray, this.ShowSynchronizedBalloon, this.ShowDeviceConnectivityBalloons, + this.SyncthingAddress, this.StartSyncthingAutomatically, this.SyncthingApiKey, this.SyncthingTraceFacilities, + this.SyncthingUseCustomHome, String.Join(", ", this.Folders), this.NotifyOfNewVersions, this.LatestNotifiedVersion, + this.ObfuscateDeviceIDs); } } } diff --git a/src/SyncTrayzor/Services/ConfigurationApplicator.cs b/src/SyncTrayzor/Services/ConfigurationApplicator.cs index df265887..1d326210 100644 --- a/src/SyncTrayzor/Services/ConfigurationApplicator.cs +++ b/src/SyncTrayzor/Services/ConfigurationApplicator.cs @@ -65,6 +65,7 @@ private void ApplyNewConfiguration(Configuration configuration) this.notifyIconManager.CloseToTray = configuration.CloseToTray; this.notifyIconManager.ShowOnlyOnClose = configuration.ShowTrayIconOnlyOnClose; this.notifyIconManager.ShowSynchronizedBalloon = configuration.ShowSynchronizedBalloon; + this.notifyIconManager.ShowDeviceConnectivityBalloons = configuration.ShowDeviceConnectivityBalloons; this.syncThingManager.Address = new Uri(configuration.SyncthingAddress); this.syncThingManager.ApiKey = configuration.SyncthingApiKey; diff --git a/src/SyncTrayzor/SyncThing/Api/Connections.cs b/src/SyncTrayzor/SyncThing/Api/Connections.cs index 5e93208c..b3ca0a79 100644 --- a/src/SyncTrayzor/SyncThing/Api/Connections.cs +++ b/src/SyncTrayzor/SyncThing/Api/Connections.cs @@ -39,8 +39,13 @@ public Dictionary DeviceConnections { get { - return this._deviceConnections ?? - (this._deviceConnections = this.DeviceConnectionsRaw.ToDictionary(x => x.Key, x => x.Value.ToObject())); + if (this._deviceConnections == null) + { + this._deviceConnections = this.DeviceConnectionsRaw == null ? + new Dictionary() : + this.DeviceConnectionsRaw.ToDictionary(x => x.Key, x => x.Value.ToObject()); + } + return this._deviceConnections; } } } diff --git a/src/SyncTrayzor/SyncThing/SyncThingManager.cs b/src/SyncTrayzor/SyncThing/SyncThingManager.cs index 1cf005ca..a3c9f811 100644 --- a/src/SyncTrayzor/SyncThing/SyncThingManager.cs +++ b/src/SyncTrayzor/SyncThing/SyncThingManager.cs @@ -34,6 +34,7 @@ public interface ISyncThingManager : IDisposable Uri Address { get; set; } string SyncthingTraceFacilities { get; set; } string SyncthingCustomHomeDir { get; set; } + DateTime StartedTime { get; } DateTime LastConnectivityEventTime { get; } SyncthingVersion Version { get; } @@ -62,6 +63,14 @@ public class SyncThingManager : ISyncThingManager private readonly ISyncThingEventWatcher eventWatcher; private readonly ISyncThingConnectionsWatcher connectionsWatcher; + private DateTime _startedTime; + private readonly object startedTimeLock = new object(); + public DateTime StartedTime + { + get { lock (this.startedTimeLock) { return this._startedTime; } } + set { lock (this.startedTimeLock) { this._startedTime = value; } } + } + private DateTime _lastConnectivityEventTime; private readonly object lastConnectivityEventTimeLock = new object(); public DateTime LastConnectivityEventTime @@ -131,7 +140,8 @@ public SyncThingManager( ISyncThingEventWatcher eventWatcher, ISyncThingConnectionsWatcher connectionsWatcher) { - this.LastConnectivityEventTime = DateTime.UtcNow; + this.StartedTime = DateTime.MinValue; + this.LastConnectivityEventTime = DateTime.MinValue; this.eventDispatcher = new SynchronizedEventDispatcher(this); this.processRunner = processRunner; @@ -269,7 +279,6 @@ private void ProcessStopped(SyncThingExitStatus exitStatus) private async Task StartupCompleteAsync() { - this.LastConnectivityEventTime = DateTime.UtcNow; this.SetState(SyncThingState.Running); var configTask = this.apiClient.FetchConfigAsync(); @@ -304,6 +313,7 @@ private async Task StartupCompleteAsync() this.Version = versionTask.Result; this.OnDataLoaded(); + this.StartedTime = DateTime.UtcNow; this.IsDataLoaded = true; } diff --git a/src/SyncTrayzor/SyncTrayzor.csproj b/src/SyncTrayzor/SyncTrayzor.csproj index a2f1191b..c1ecaf22 100644 --- a/src/SyncTrayzor/SyncTrayzor.csproj +++ b/src/SyncTrayzor/SyncTrayzor.csproj @@ -305,8 +305,8 @@ PublicResXFileCodeGenerator - Resources.Designer.cs Designer + Resources.Designer.cs From b3e38cb590a9eb7569b912b4b8d41ff7776f8f5f Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 16 Mar 2015 19:25:19 +0000 Subject: [PATCH 12/16] Add option to restart Syncthing from the menu It was previously possible from Syncthing's built-in menu, but that was effort... --- .../NotifyIcon/NotifyIconViewModel.cs | 9 +++++++++ .../NotifyIcon/TaskbarIconResources.xaml | 1 + src/SyncTrayzor/Pages/ShellView.xaml | 1 + src/SyncTrayzor/Pages/ShellViewModel.cs | 9 +++++++++ .../Properties/Strings/Resources.Designer.cs | 20 ++++++++++++++++++- .../Properties/Strings/Resources.resx | 7 +++++++ .../SyncThing/Api/ISyncThingApi.cs | 3 +++ .../SyncThing/SyncThingApiClient.cs | 8 ++++++++ src/SyncTrayzor/SyncThing/SyncThingManager.cs | 9 +++++++++ 9 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/SyncTrayzor/NotifyIcon/NotifyIconViewModel.cs b/src/SyncTrayzor/NotifyIcon/NotifyIconViewModel.cs index 3a2ca045..690e925e 100644 --- a/src/SyncTrayzor/NotifyIcon/NotifyIconViewModel.cs +++ b/src/SyncTrayzor/NotifyIcon/NotifyIconViewModel.cs @@ -95,6 +95,15 @@ public void Stop() this.syncThingManager.StopAsync(); } + public bool CanRestart + { + get { return this.SyncThingState == SyncThingState.Running; } + } + public void Restart() + { + this.syncThingManager.RestartAsync(); + } + public void Exit() { this.OnExitRequested(); diff --git a/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml b/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml index 3bf73c6c..46c3b2e9 100644 --- a/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml +++ b/src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml @@ -76,6 +76,7 @@ + diff --git a/src/SyncTrayzor/Pages/ShellView.xaml b/src/SyncTrayzor/Pages/ShellView.xaml index da979080..db0faa12 100644 --- a/src/SyncTrayzor/Pages/ShellView.xaml +++ b/src/SyncTrayzor/Pages/ShellView.xaml @@ -19,6 +19,7 @@ + diff --git a/src/SyncTrayzor/Pages/ShellViewModel.cs b/src/SyncTrayzor/Pages/ShellViewModel.cs index 7cfac30a..9f925133 100644 --- a/src/SyncTrayzor/Pages/ShellViewModel.cs +++ b/src/SyncTrayzor/Pages/ShellViewModel.cs @@ -70,6 +70,15 @@ public void Stop() this.syncThingManager.StopAsync(); } + public bool CanRestart + { + get { return this.SyncThingState == SyncThing.SyncThingState.Running; } + } + public void Restart() + { + this.syncThingManager.RestartAsync(); + } + public bool CanKill { get { return this.SyncThingState != SyncThingState.Stopped; } diff --git a/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs b/src/SyncTrayzor/Properties/Strings/Resources.Designer.cs index 26a4e6ef..baf5b029 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.0 +// Runtime Version:4.0.30319.18444 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -675,6 +675,15 @@ public static string ShellView_Menu_Syncthing_Refresh { } } + /// + /// Looks up a localized string similar to R_estart. + /// + public static string ShellView_Menu_Syncthing_Restart { + get { + return ResourceManager.GetString("ShellView_Menu_Syncthing_Restart", resourceCulture); + } + } + /// /// Looks up a localized string similar to _Start. /// @@ -847,6 +856,15 @@ public static string TrayIcon_Menu_Exit { } } + /// + /// Looks up a localized string similar to R_estart. + /// + public static string TrayIcon_Menu_RestartSyncthing { + get { + return ResourceManager.GetString("TrayIcon_Menu_RestartSyncthing", resourceCulture); + } + } + /// /// Looks up a localized string similar to _Restore. /// diff --git a/src/SyncTrayzor/Properties/Strings/Resources.resx b/src/SyncTrayzor/Properties/Strings/Resources.resx index 232f58cb..5807933c 100644 --- a/src/SyncTrayzor/Properties/Strings/Resources.resx +++ b/src/SyncTrayzor/Properties/Strings/Resources.resx @@ -498,4 +498,11 @@ SyncTrayzor is going to have to close. Sorry about that Device Disconnected Title of tray icon balloon when another device disconnected + + R_estart + + + R_estart + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to restart + \ No newline at end of file diff --git a/src/SyncTrayzor/SyncThing/Api/ISyncThingApi.cs b/src/SyncTrayzor/SyncThing/Api/ISyncThingApi.cs index 8b0d1f36..df430bc5 100644 --- a/src/SyncTrayzor/SyncThing/Api/ISyncThingApi.cs +++ b/src/SyncTrayzor/SyncThing/Api/ISyncThingApi.cs @@ -35,5 +35,8 @@ public interface ISyncThingApi [Get("/rest/ignores")] Task FetchIgnoresAsync(string folder); + + [Post("/rest/restart")] + Task RestartAsync(); } } diff --git a/src/SyncTrayzor/SyncThing/SyncThingApiClient.cs b/src/SyncTrayzor/SyncThing/SyncThingApiClient.cs index 47210cd4..4287d80b 100644 --- a/src/SyncTrayzor/SyncThing/SyncThingApiClient.cs +++ b/src/SyncTrayzor/SyncThing/SyncThingApiClient.cs @@ -24,6 +24,7 @@ public interface ISyncThingApiClient Task FetchConnectionsAsync(); Task FetchVersionAsync(); Task FetchIgnoresAsync(string folderId); + Task RestartAsync(); } public class SyncThingApiClient : ISyncThingApiClient @@ -108,6 +109,13 @@ public async Task FetchIgnoresAsync(string folderId) return ignores; } + public Task RestartAsync() + { + this.EnsureSetup(); + logger.Debug("Restarting Syncthing"); + return this.api.RestartAsync(); + } + private void EnsureSetup() { if (this.api == null) diff --git a/src/SyncTrayzor/SyncThing/SyncThingManager.cs b/src/SyncTrayzor/SyncThing/SyncThingManager.cs index a3c9f811..76872dc3 100644 --- a/src/SyncTrayzor/SyncThing/SyncThingManager.cs +++ b/src/SyncTrayzor/SyncThing/SyncThingManager.cs @@ -40,6 +40,7 @@ public interface ISyncThingManager : IDisposable void Start(); Task StopAsync(); + Task RestartAsync(); void Kill(); void KillAllSyncthingProcesses(); @@ -192,6 +193,14 @@ public Task StopAsync() return this.apiClient.ShutdownAsync(); } + public Task RestartAsync() + { + if (this.State != SyncThingState.Running) + return Task.FromResult(false); + + return this.apiClient.RestartAsync(); + } + public void Kill() { this.processRunner.Kill(); From 4cbb885d2a30c65de952f92cd20882a673918203 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Tue, 17 Mar 2015 12:37:08 +0000 Subject: [PATCH 13/16] Update Stylet --- src/SyncTrayzor/packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SyncTrayzor/packages.config b/src/SyncTrayzor/packages.config index 0554c16a..9dde970c 100644 --- a/src/SyncTrayzor/packages.config +++ b/src/SyncTrayzor/packages.config @@ -11,5 +11,5 @@ - + \ No newline at end of file From cd462abca3a419a1f96511505a5747bcd30bc6d6 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Tue, 17 Mar 2015 12:39:26 +0000 Subject: [PATCH 14/16] Update 'de' translation, and add 'nl-NL' one --- .tx/config | 2 +- .../Properties/Strings/Resources.de.resx | 117 +++- .../Strings/Resources.nl-NL.Designer.cs | 0 .../Properties/Strings/Resources.nl-NL.resx | 508 ++++++++++++++++++ src/SyncTrayzor/SyncTrayzor.csproj | 9 + 5 files changed, 628 insertions(+), 8 deletions(-) create mode 100644 src/SyncTrayzor/Properties/Strings/Resources.nl-NL.Designer.cs create mode 100644 src/SyncTrayzor/Properties/Strings/Resources.nl-NL.resx diff --git a/.tx/config b/.tx/config index 431b2a2a..b3ef4410 100644 --- a/.tx/config +++ b/.tx/config @@ -9,4 +9,4 @@ type = RESX ; Irritatingly, Transifex likes xx_XX, .NET likes xx-XX and there's no way ; (that I can find) to map between them -lang_map = de_DE:de-DE +lang_map = nl_NL:nl-NL diff --git a/src/SyncTrayzor/Properties/Strings/Resources.de.resx b/src/SyncTrayzor/Properties/Strings/Resources.de.resx index d708ef9d..63647a8e 100644 --- a/src/SyncTrayzor/Properties/Strings/Resources.de.resx +++ b/src/SyncTrayzor/Properties/Strings/Resources.de.resx @@ -122,9 +122,12 @@ Herunterladen + Clickable link allowing the user to download the latest version of SyncTrayzor Neue Version verfügbar: {0} + Prompt showing the user that a new version of SynTrayzor is available +{0}: Latest version of SyncTrayzor Veröffentlicht unter MIT-Lizenz. @@ -134,18 +137,25 @@ SyncThing Version: {0} + Information showing the user the current version of Syncthing +{0}: Current Syncthing version Version: {0} + Information showing the user the current version of SyncTrayzor +{0}: Current SyncTrayzor version Abbrechen + 'Cancel' button shown in various dialogs Schließen + 'Close' button shown on various dialogs Speichern + 'Save' button shown on various dialogs _Datei @@ -185,18 +195,22 @@ Nicht erneut erinnern + 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 + When a new version is available, the user receives a prompt. This button allows them to download the new version Später erinnern + When a new version is available, the user receives a prompt. This button allows them to say they want to be prompted the next time they start SyncTrayzor Änderungshistorie: "Nicht erneut erinnern" wird keine weiteren Erinnerungen für diese Version anzeigen. Die Erinnerung kann auch permanent in den Einstellungen abgeschaltet werden. Im Hilfe-Menü können Sie die Version zudem manuell überprüfen. + 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. Eine neue Version von SyncTrayzor ist verfügbar! @@ -204,9 +218,11 @@ Version: {0} Wollen Sie diese nun herunterladen? + When a new version is available, the user receives a prompt. This text appears at the top of that prompt SyncTrayzor Update verfügbar + When a new version is available, the user receives a prompt. This is the title of that prompt. Benachrichtigen wenn eine neue SyncTrayzor-Version verfügbar ist @@ -216,12 +232,15 @@ Wollen Sie diese nun herunterladen? SyncTrayzor überschreibt den API-Schlüssel der in Syncthing konfiguriert wurde. Für einen eigenen Wert kann dieser jedoch hier hinterlegt werden. + ToolTip shown when a user hovers over the SettingsView_ApiKey text input. This shows more information on the input. Beim schließen in den Infobereich minimieren + Setting allowing the user to indicate that the 'close' button on the top right of the window should put Syncthing down into the tray, rather than closing the application Beim minieren im Infobereich anzeigen + 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 Syncthing muss neu gestartet werden damit die Änderungen wirksam werden. @@ -234,48 +253,61 @@ Wollen Sie diese nun herunterladen? Erweitert + Section header for advanced settings Bei Anmeldung starten + Section header for settings to do with automatically starting SyncTrayzor when the user logs in Syncthing + Section header for settings to do with configuring Syncthing SyncTrayzor + Section header for settings to do with configuring SyncTrayzor Überwachte Ordner + Section header for settings to do with configuring SyncTrayzor's ability to watch folders for changes Synchronieserungs-Benachrichtigungen im Infobereich anzeigen + Setting allowing the user to specify that a balloon message (white area down by the tray icon, linked to the tray icon) should be shown whenever a folder finishes synchronizing Minimiert starten + Setting allowing the user to specify that, when SyncTrayzor is started automatically on login, it should start in the tray, rather than being visible to the user Automatisch bei Anmeldung starten + Setting allowing the user to specify that SyncTrayzor should be started when the user logs in Zugriff verweigert. Bitte starten Sie SyncTrayzor als Administrator um diese Einstellungen anzupassen. + Message displayed instead of SettingsView_StartOnLogin SettingsView_StartMinimized when the user doesn't have permission to edit the registry Starte Syncthing wenn SyncTrayzor gestartet wird + Setting allowing the user to specify that Syncthing should be start automatically when SyncTrayzor starts Listen-Adresse der GUI: SyncTrayzor überschreibt die "Listen-Adresse der GUI" die in Syncthing konfiguriert wurde. Für einen eigenen Wert kann dieser jedoch hier hinterlegt werden. + ToolTip shown when a user hovers over the SettingsView_SyncthingAddress text input. This shows more information on the input. Eigenen Stammordner für Syncthing verwenden. Dies bedeutet das SyncTrayzor eine unterschiedliche Sammlung von eingestellten Ordnern sehen wird. + ToolTip shown when a user hovers over the SettingsView_SyncthingUseCustomHome text input. This shows more information on the input. Einstellungen + Title of the 'settings' dialog Syncthing Trace-Variablen: @@ -288,12 +320,15 @@ Wollen Sie diese nun herunterladen? Unbekannt + Shown within AboutView_SyncthingVersion if Syncthing's version couldn't be determined Sicher das Sie alle Syncthing-Prozesse beenden wollen, auch solche die nicht durch SyncTrayzor verwaltet werden? + Body for the dialog show when the user clicks on ShellView_Menu_Syncthing_KillAll Wirklich sicher? + Title for the dialog shown when the user clicks on ShellView_Menu_Syncthing_KillAll Syncthing konnte nicht gestartet werden. @@ -301,10 +336,15 @@ Wollen Sie diese nun herunterladen? Bitte das Logfile analysieren um den Grund festzustellen. Wenn eine Meldung "FATAL: Cannot open database" erscheint, bitte kontrollieren das keine anderen Instanzen von Syncthing auf diesem Computer laufen. Falls SyncTrayzor vorher abgestürzt ist, können noch unbeaufsichtigte Prozesse laufen, in diesem Fall bitte alle Prozesse über das Syncthing-Menü beenden. Danach Syncthing einfach wieder starten. - "FATAL: Cannot Open Database" should remain in English + Content of the dialog shown when Syncthing couldn't be started (and exited with an error). Instructs the user on how to proceed. + +"FATAL: Cannot Open Database" should remain in English + +The menu option "Syncthing ->Kill all Syncthing processes" corresponds to ShellView_Menu_Syncthing_KillAll, while "Syncthing ->Start" corresponds to ShellView_Menu_Syncthing_Start Beim starten von Syncthing trat ein Fehler auf + Title of the dialog shown when Syncthing couldn't be started (and exited with an error) Syncthing konnte nicht gestartet werden: {0} @@ -312,17 +352,21 @@ Wenn eine Meldung "FATAL: Cannot open database" erscheint, bitte kontr Dies kann passieren wenn keine Dateien aus dem %APPDATA%-Verzeichnis gestartet werden können. Mögliche Gründe können Viren- oder Malwareschutz-Programme sein (z.B. CryptoPrevent) welche dies gezielt verhindern. Bitte die Einstellung entsprechend anpassen bzw. '{1}' in die Whitelists eintragen. - {0}: Exception message -{1}: Path to Syncthing + Content of dialog shown when Syncthing couldn't start because of group policy settings (probably) +{0}: Exact exception message +{1}: Path to Syncthing executable Fehler beim starten von Syncthing + Title of dialog shown when Syncthing couldn't start because of group policy settings (probably) Gültige URL eingeben + Validation message (shown in red) below the SettingsView_SyncthingAddress field when the user enters a value which is not a value URL Darf nicht leer sein + Validation message (shown in red) below the SettingsView_SyncthingAddress or SettingsView_ApiKey fields when the user makes this field empty Beschreibung: @@ -351,27 +395,36 @@ Genaueres zu jeder Komponente, sowie die entsprechenden Lizenz-Texte, werden unt {0}: Synchronisation abgeschlossen + Content of the balloon message shown when a folder finished synchronization + +{0}:The name of the folder which finished synchronizing Synchronisation abgeschlossen Beim schließen in den Infobereich minimieren + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to minimize itself to the tray _Beenden + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to exit _Wiederherstellen + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to restore itself from the tray, and be visible to the user _Einstellungen + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to show the Settings dialog _Starten + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to start Syncthing. Only available if Syncthing isn't running _Anhalten + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to stop Syncthing. Only available if Syncthing is running Hoppla! Irgendwas ist schief gelaufen. @@ -379,27 +432,77 @@ SyncTrayzor wird nun geschlossen. - Appears after the log path + When an unhandled exception occurs, the user is informed that they may have to provide a log file, and gives the path. This text appears immediately after the log path Falls Sie gefragt nach einem Logfile gefragt werden finden Sie dies in: - Appears before the log path + When an unhandled exception occurs, the user is informed that they may have to provide a log file, and gives the path. This text appears immediately before the log path und fügen Sie die folgenden Informationen hinzu: - Appers after the hyperlink to the Github issues page + When an unhandled exception occurs, the user is prompted to visit the Github issues page. This text appears immediately after the link to github, and also prompts the user to include the stack trace shown directly below this text Bitte eröffnen Sie einen Support-Fall bei - Appears before a hyperlink to the Github issues page + When an unhandled exception occurs, the user is prompted to visit the Github issues page. This text appears immediately before the link to github Fehler! + Title of the dialog shown when an unhandled excepotion occurs Syncthing startet... + Text shown in the centre of the screen when Syncthing is starting, but there's no UI to display yet Syncthing angehalten + Text shown in the centre of the screen when Syncthing is stopped + + + No + 'No' button shown on various dialogs + + + OK + 'OK' button shown on various dialogs + + + Yes + 'Yes' button shown on various dialogs + + + Dummy text ignored by the UI + Shown on the 'about' page, this is space for you to attribute yourself. E.g. your local language equivalent of "Kingon translation by My Name". Add yourself to this field if you contribute to the translation for this language. + + + Tray Icon + + + Show device Connected/Disconnected balloon messages + + + {0} connected + Message of tray icon balloon show when another device connects +{0}: device name + + + Device Connected + Title of tray icon balloon when another device connected + + + {0} disconnected + Message of tray icon balloon show when another device disconnects +{0}: device name + + + Device Disconnected + Title of tray icon balloon when another device disconnected + + + R_estart + + + R_estart + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to restart diff --git a/src/SyncTrayzor/Properties/Strings/Resources.nl-NL.Designer.cs b/src/SyncTrayzor/Properties/Strings/Resources.nl-NL.Designer.cs new file mode 100644 index 00000000..e69de29b diff --git a/src/SyncTrayzor/Properties/Strings/Resources.nl-NL.resx b/src/SyncTrayzor/Properties/Strings/Resources.nl-NL.resx new file mode 100644 index 00000000..16d4c2c1 --- /dev/null +++ b/src/SyncTrayzor/Properties/Strings/Resources.nl-NL.resx @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Gecreëerd door Antony Male. + + + Downloaden + Clickable link allowing the user to download the latest version of SyncTrayzor + + + Er is een nieuwe versie beschikbaar: {0} + Prompt showing the user that a new version of SynTrayzor is available +{0}: Latest version of SyncTrayzor + + + Uitgebracht onder de MIT-licentie. + + + Open bron-licenties weergeven + + + Syncthing-versie: {0} + Information showing the user the current version of Syncthing +{0}: Current Syncthing version + + + Versie: {0} + Information showing the user the current version of SyncTrayzor +{0}: Current SyncTrayzor version + + + Annuleren + 'Cancel' button shown in various dialogs + + + Sluiten + 'Close' button shown on various dialogs + + + Opslaan + 'Save' button shown on various dialogs + + + _Bestand + + + _Afsluiten + + + _Instellingen + + + _Hulp + + + _Over + + + _Syncthing + + + _Vernietigen + + + _Alle Syncthing-processen vernietigen + + + _Openen in externe browser + + + Browser _verversen + + + _Starten + + + S_toppen + + + Herinner me hier niet nogmaals aan + 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 + + + Nu downloaden + When a new version is available, the user receives a prompt. This button allows them to download the new version + + + Herinner me hier later aan + When a new version is available, the user receives a prompt. This button allows them to say they want to be prompted the next time they start SyncTrayzor + + + Wijzigingslog: + + + 'Herinner me hier niet nogmaals aan' zal de herhaalmeldingen voor deze versie uitschakelen. U kunt meldingen over nieuwe versies permanent uitschakelen op de Instellingen-pagina. Ga naar Hulp -> Over om handmatig te controleren op een nieuwe versie. + 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. + + + Er is een nieuwe versie van SyncTrayzor beschikbaar! + +Versie: {0} + +Wilt u deze nu downloaden? + When a new version is available, the user receives a prompt. This text appears at the top of that prompt + + + SyncTrayzor-update beschikbaar + When a new version is available, the user receives a prompt. This is the title of that prompt. + + + Een melding weergeven zodra er een nieuwe versie van SyncTrayzor beschikbaar is + + + API-sleutel: + + + SyncTrayzor overschrijft de API-sleuten die in Syncthing opgegeven is. U kunt hier elke waarde die u wilt instellen. + ToolTip shown when a user hovers over the SettingsView_ApiKey text input. This shows more information on the input. + + + Sluiten naar systeemvak + Setting allowing the user to indicate that the 'close' button on the top right of the window should put Syncthing down into the tray, rather than closing the application + + + Minimalizeren naar systeemvak + 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 + + + U moet Syncthing herstarten om deze instellingswijzigingen toe te passen + + + Verberg apparaat-ID's in de logboekweergave + + + Systeemvakpictogram alleen weergeven bij sluiten + + + Geavanceerd + Section header for advanced settings + + + Automatisch opstarten bij inloggen + Section header for settings to do with automatically starting SyncTrayzor when the user logs in + + + Syncthing + Section header for settings to do with configuring Syncthing + + + SyncTrayzor + Section header for settings to do with configuring SyncTrayzor + + + Mappen die in de gaten worden gehouden + Section header for settings to do with configuring SyncTrayzor's ability to watch folders for changes + + + 'Gesynchroniseerd'-ballonmeldingen weergeven + Setting allowing the user to specify that a balloon message (white area down by the tray icon, linked to the tray icon) should be shown whenever a folder finishes synchronizing + + + Geminimaliseerd opstarten + Setting allowing the user to specify that, when SyncTrayzor is started automatically on login, it should start in the tray, rather than being visible to the user + + + Automatisch opstarten bij inloggen + Setting allowing the user to specify that SyncTrayzor should be started when the user logs in + + + De toegang is geweigerd. Start SyncTrayzor als een administrator om deze instellingen te wijzigen. + Message displayed instead of SettingsView_StartOnLogin SettingsView_StartMinimized when the user doesn't have permission to edit the registry + + + Syncthing starten wanneer SyncTrayzor wordt gestart + Setting allowing the user to specify that Syncthing should be start automatically when SyncTrayzor starts + + + GUI-luisteradres: + + + SyncTrayzor overrides the "GUI Listen Address" specified in Syncthing's configuration. However, you can set it to whatever value you like here. + ToolTip shown when a user hovers over the SettingsView_SyncthingAddress text input. This shows more information on the input. + + + Aangepaste persoonlijke map gebruiken voor Syncthing. + + + Dit betekent dat SyncTrayzor andere ingestelde mappen ziet in elk ander Syncthing-proces op uw computer. + ToolTip shown when a user hovers over the SettingsView_SyncthingUseCustomHome text input. This shows more information on the input. + + + Instellingen + Title of the 'settings' dialog + + + Syncthing-opsporingsvariabelen: + + + De volgende mappen zullen in de gaten worden gehouden op wijzigingen: + + + Geen mappen beschikbaar. Start Syncthing. + + + Onbekend + Shown within AboutView_SyncthingVersion if Syncthing's version couldn't be determined + + + Weet u zeker dat u alle Syncthing-processen wilt vernietigen, zelfs de niet door SyncTrayzor beheerde? + Body for the dialog show when the user clicks on ShellView_Menu_Syncthing_KillAll + + + Weet u het zeker? + Title for the dialog shown when the user clicks on ShellView_Menu_Syncthing_KillAll + + + Failed to start Syncthing. + +Please read the log to determine the cause. + +If "FATAL: Cannot open database" appears, please close any other open instances of Syncthing. If SyncTrayzor crashed previously, there may still be zombine Syncthing processes alive. Please use the menu option "Syncthing -> Kill all Syncthing processes" to stop them, then use "Syncthing -> Start" to start Syncthing again. + Content of the dialog shown when Syncthing couldn't be started (and exited with an error). Instructs the user on how to proceed. + +"FATAL: Cannot Open Database" should remain in English + +The menu option "Syncthing ->Kill all Syncthing processes" corresponds to ShellView_Menu_Syncthing_KillAll, while "Syncthing ->Start" corresponds to ShellView_Menu_Syncthing_Start + + + Het is niet gelukt om Syncthing te starten + Title of the dialog shown when Syncthing couldn't be started (and exited with an error) + + + Unable to start Syncthing: {0} + +This could be because Windows if set up to forbid executing files in AppData, or because you have anti-malware installed (e.g. CryptoPrevent ) which prevents executing files in AppData. + +Please adjust your settings / whitelists to allow '{1}' to execute + Content of dialog shown when Syncthing couldn't start because of group policy settings (probably) +{0}: Exact exception message +{1}: Path to Syncthing executable + + + Er is een fout opgetreden bij het starten van Syncthing + Title of dialog shown when Syncthing couldn't start because of group policy settings (probably) + + + Het moet een geldige URL zijn + Validation message (shown in red) below the SettingsView_SyncthingAddress field when the user enters a value which is not a value URL + + + Het mag niet leeg worden gelaten + Validation message (shown in red) below the SettingsView_SyncthingAddress or SettingsView_ApiKey fields when the user makes this field empty + + + Beschrijving: + + + Website: + + + Licentie: + + + Licentietekst: + + + Naam: + + + Notities: + + + SyncTrayzor is gebouwd met behulp van vele open bron-onderdelen en zou niet kunnen bestaan zonder ze. +De details van elk onderdeel, incl. licentietekst, worden hieronder weergegeven. + + + Onderdelen van derde partijen + + + {0}: Het synchroniseren is voltooid + Content of the balloon message shown when a folder finished synchronization + +{0}:The name of the folder which finished synchronizing + + + Het synchroniseren is voltooid + + + Sluiten naar systeemvak + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to minimize itself to the tray + + + _Afsluiten + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to exit + + + _Herstellen + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to restore itself from the tray, and be visible to the user + + + Inste_llingen + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to show the Settings dialog + + + _Starten + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to start Syncthing. Only available if Syncthing isn't running + + + S_toppen + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to stop Syncthing. Only available if Syncthing is running + + + Oeps, er ging iets grondig mis! +SyncTrayzor gaat nu afsluiten. Onze excuses. + + + + When an unhandled exception occurs, the user is informed that they may have to provide a log file, and gives the path. This text appears immediately after the log path + + + Het kan zijn dat u wordt gevraagd om een logbestand op te geven. U kunt dit bestand vinden in: + When an unhandled exception occurs, the user is informed that they may have to provide a log file, and gives the path. This text appears immediately before the log path + + + en geef de volgende informatie op: + When an unhandled exception occurs, the user is prompted to visit the Github issues page. This text appears immediately after the link to github, and also prompts the user to include the stack trace shown directly below this text + + + Open een probleemrapport op: + When an unhandled exception occurs, the user is prompted to visit the Github issues page. This text appears immediately before the link to github + + + Fout! + Title of the dialog shown when an unhandled excepotion occurs + + + Bezig met starten van Syncthing... + Text shown in the centre of the screen when Syncthing is starting, but there's no UI to display yet + + + Syncthing is gestopt + Text shown in the centre of the screen when Syncthing is stopped + + + No + 'No' button shown on various dialogs + + + OK + 'OK' button shown on various dialogs + + + Yes + 'Yes' button shown on various dialogs + + + Dummy text ignored by the UI + Shown on the 'about' page, this is space for you to attribute yourself. E.g. your local language equivalent of "Kingon translation by My Name". Add yourself to this field if you contribute to the translation for this language. + + + Tray Icon + + + Show device Connected/Disconnected balloon messages + + + {0} connected + Message of tray icon balloon show when another device connects +{0}: device name + + + Device Connected + Title of tray icon balloon when another device connected + + + {0} disconnected + Message of tray icon balloon show when another device disconnects +{0}: device name + + + Device Disconnected + Title of tray icon balloon when another device disconnected + + + R_estart + + + R_estart + Menu option available when right-clicking the tray icon. Instructs SyncTrayzor to restart + + diff --git a/src/SyncTrayzor/SyncTrayzor.csproj b/src/SyncTrayzor/SyncTrayzor.csproj index c1ecaf22..4092a347 100644 --- a/src/SyncTrayzor/SyncTrayzor.csproj +++ b/src/SyncTrayzor/SyncTrayzor.csproj @@ -138,6 +138,11 @@ True Resources.resx + + True + True + Resources.nl-NL.resx + @@ -303,6 +308,10 @@ PublicResXFileCodeGenerator Resources.de.Designer.cs + + PublicResXFileCodeGenerator + Resources.nl-NL.Designer.cs + PublicResXFileCodeGenerator Designer From 0ca2d2206cddee71577e961f6f36ed83847966f6 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Tue, 17 Mar 2015 12:41:39 +0000 Subject: [PATCH 15/16] Update changelog --- CHANGELOG.txt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index fa437602..ac01780f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,12 +1,22 @@ Changelog ========= +v1.0.9 +------ + + - Fix bug with directory watcher and paths containing a tilde (~) + - Fix resolution issue with taskbar icon + - Add 'device connected/disconnected' tray icon balloon messages + - Add Dutch transation (thanks Heimen Stoffels!) + - Small redution in memory usage + - Add menu item to restart Syncthing + v1.0.8 ------ - - Support HTTPS - - Add German translation (thanks Adrian Rudnik) - - Ensure SyncTrayzor is terminated properly when updating/uninstalling using the installer +- Support HTTPS +- Add German translation (thanks Adrian Rudnik) +- Ensure SyncTrayzor is terminated properly when updating/uninstalling using the installer v1.0.7 ------ From 85c9ba8ced5cf0ebda52a1e76e7e0d30e7fc2f58 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Tue, 17 Mar 2015 12:41:55 +0000 Subject: [PATCH 16/16] Bump version --- src/SyncTrayzor/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SyncTrayzor/Properties/AssemblyInfo.cs b/src/SyncTrayzor/Properties/AssemblyInfo.cs index d3796808..c50f8436 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.8.0")] -[assembly: AssemblyFileVersion("1.0.8.0")] +[assembly: AssemblyVersion("1.0.9.0")] +[assembly: AssemblyFileVersion("1.0.9.0")]