Sfoglia il codice sorgente

Re-instate the donation drive, but towards charity this time

Antony Male 8 anni fa
parent
commit
27d475ab02

+ 12 - 1
README.md

@@ -7,7 +7,7 @@ Quick Links
 
  - [Download and install SyncTrayzor now](#installation)
  - [Something went wrong](#something-went-wrong)
- - [Buy me a beer!](#buy-me-a-beer)
+ - [Donate to my charity fundraiser](#donate-to-my-charity-fundraiser)
 
 
 Introduction
@@ -85,6 +85,17 @@ Multi-lingual? SyncTrayzor needs you! Please read [Localization](https://github.
 Want to make a contribution? Fantastic, and thank you! Please read [Contributing](https://github.com/canton7/SyncTrayzor/wiki/Contributing) first.
 
 
+Donate to my charity fundraiser
+-------------------------------
+
+I develop SyncTrayzor in my free time because I enjoy it.
+SyncTrayzor will never become paid-for.
+
+However, if you find SyncTrayzor useful and want to say thanks, please consider [donating to my charity fundraiser](https://synctrayzor.antonymale.co.uk/donate).
+I'm currently raising money for Médecins Sans Frontières (Doctors Without Borders).
+Thanks!
+
+
 Will SyncTrayzor phone home / give away my secrets / etc?
 ---------------------------------------------------------
 

+ 1 - 0
src/SyncTrayzor/Bootstrapper.cs

@@ -76,6 +76,7 @@ namespace SyncTrayzor
             builder.Bind<IMeteredNetworkManager>().To<MeteredNetworkManager>().InSingletonScope();
             builder.Bind<IPathTransformer>().To<PathTransformer>().InSingletonScope();
             builder.Bind<IConnectedEventDebouncer>().To<ConnectedEventDebouncer>();
+            builder.Bind<IDonationManager>().To<DonationManager>().InSingletonScope();
 
             if (AppSettings.Instance.Variant == SyncTrayzorVariant.Installed)
                 builder.Bind<IUpdateVariantHandler>().To<InstalledUpdateVariantHandler>();

+ 26 - 0
src/SyncTrayzor/Pages/AboutView.xaml

@@ -10,6 +10,11 @@
         FlowDirection="{x:Static l:Localizer.FlowDirection}">
     <Window.Resources>
         <s:BoolToVisibilityConverter x:Key="NoNewVersionVisibility" TrueVisibility="Collapsed" FalseVisibility="Visible"/>
+        <Style x:Key="DonateStyle" TargetType="TextBlock">
+            <Setter Property="TextAlignment" Value="Center"/>
+            <Setter Property="Margin" Value="0,25"/>
+            <Setter Property="TextWrapping" Value="Wrap"/>
+        </Style>
     </Window.Resources>
     <DockPanel LastChildFill="False" Margin="10">
         <TextBlock DockPanel.Dock="Top" FontWeight="Bold" FontSize="25" HorizontalAlignment="Center" Margin="0,0,0,20">SyncTrayzor</TextBlock>
@@ -33,6 +38,27 @@
                        Visibility="{Binding ShowTranslatorAttributation, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}}"/>
         </Grid>
 
+        <TextBlock DockPanel.Dock="Top"
+                   Visibility="{Binding DonationManager.HaveDonated, Converter={x:Static s:BoolToVisibilityConverter.Instance}}"
+                   Style="{StaticResource DonateStyle}"
+                   Width="{Binding Parent.ActualWidth, RelativeSource={RelativeSource Self}}">
+            <TextBlock Text="{l:Loc AboutView_DonateThanks}"/><LineBreak/>
+            <Hyperlink s:View.ActionTarget="{Binding DonationManager}" Command="{s:Action Donate}">
+                <TextBlock Text="{l:Loc AboutView_DonateAgain_Link}"/>
+            </Hyperlink>
+        </TextBlock>
+
+        <TextBlock DockPanel.Dock="Top"
+                   Visibility="{Binding DonationManager.HaveDonated, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}}"
+                   Style="{StaticResource DonateStyle}"
+                   FontSize="14"
+                   Width="{Binding Parent.ActualWidth, RelativeSource={RelativeSource Self}}">
+            <TextBlock Text="{l:Loc AboutView_Donate_Text}" TextWrapping="Wrap"/><LineBreak/>
+            <Hyperlink s:View.ActionTarget="{Binding DonationManager}" Command="{s:Action Donate}">
+                <TextBlock Text="{l:Loc AboutView_Donate_Link}"/>
+            </Hyperlink>
+        </TextBlock>
+        
         <TextBlock DockPanel.Dock="Top" Margin="0,5">
             <Hyperlink Command="{s:Action ShowHomepage}">
                 <TextBlock Text="{Binding HomepageUrl}"/>

+ 6 - 6
src/SyncTrayzor/Pages/AboutViewModel.cs

@@ -12,9 +12,9 @@ namespace SyncTrayzor.Pages
 {
     public class AboutViewModel : Screen
     {
+        // Not in the app.config, in case some sysadmin wants to change it
         private readonly IWindowManager windowManager;
         private readonly ISyncthingManager syncthingManager;
-        private readonly IConfigurationProvider configurationProvider;
         private readonly IUpdateManager updateManager;
         private readonly Func<ThirdPartyComponentsViewModel> thirdPartyComponentsViewModelFactory;
         private readonly IProcessStartProvider processStartProvider;
@@ -30,20 +30,22 @@ namespace SyncTrayzor.Pages
         }
         private string newerVersionDownloadUrl;
 
+        public IDonationManager DonationManager { get; }
+
         public AboutViewModel(
             IWindowManager windowManager,
             ISyncthingManager syncthingManager,
-            IConfigurationProvider configurationProvider,
             IUpdateManager updateManager,
             Func<ThirdPartyComponentsViewModel> thirdPartyComponentsViewModelFactory,
-            IProcessStartProvider processStartProvider)
+            IProcessStartProvider processStartProvider,
+            IDonationManager donationManager)
         {
             this.windowManager = windowManager;
             this.syncthingManager = syncthingManager;
-            this.configurationProvider = configurationProvider;
             this.updateManager = updateManager;
             this.thirdPartyComponentsViewModelFactory = thirdPartyComponentsViewModelFactory;
             this.processStartProvider = processStartProvider;
+            this.DonationManager = donationManager;
 
             this.Version = Assembly.GetExecutingAssembly().GetName().Version.ToString(3);
             this.HomepageUrl = AppSettings.Instance.HomepageUrl;
@@ -51,8 +53,6 @@ namespace SyncTrayzor.Pages
             this.syncthingManager.DataLoaded += this.SyncthingDataLoaded;
             this.LoadSyncthingVersion();
 
-            var configuration = this.configurationProvider.Load();
-
             this.CheckForNewerVersionAsync();
         }
 

+ 36 - 29
src/SyncTrayzor/Pages/ShellView.xaml

@@ -27,36 +27,43 @@
         <KeyBinding Key="F5" Command="{s:Action RefreshBrowser}"/>
     </Window.InputBindings>
     <DockPanel>
-        <Menu DockPanel.Dock="Top">
-            <MenuItem Header="{l:Loc ShellView_Menu_File}">
-                <MenuItem Header="{l:Loc ShellView_Menu_File_Settings}" Command="{s:Action ShowSettings}"/>
-                <MenuItem Header="{l:Loc ShellView_Menu_File_ConflictResolver}" Command="{s:Action ShowConflictResolver}"/>
-                <Separator/>
-                <MenuItem Header="{l:Loc ShellView_Menu_File_Exit}" Command="{s:Action Shutdown}"/>
-            </MenuItem>
-            <MenuItem Header="{l:Loc ShellView_Menu_Syncthing}">
-                <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_Start}" Command="{s:Action Start}"/>
-                <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_Stop}" Command="{s:Action Stop}"/>
-                <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_Restart}" Command="{s:Action Restart}"/>
-                <Separator/>
-                <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_Refresh}" InputGestureText="F5" Command="{s:Action RefreshBrowser}"/>
-                <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_OpenExternal}" Command="{s:Action OpenBrowser}"/>
-                <Separator/>
-                <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_KillAll}" Command="{s:Action KillAllSyncthingProcesses}"/>
-            </MenuItem>
-            <MenuItem Header="{l:Loc ShellView_Menu_View}">
-                <MenuItem Header="{l:Loc ShellView_Menu_View_SyncthingConsole}" IsCheckable="True" IsChecked="{Binding ShowConsole}"/>
-                <Separator/>
-                <MenuItem Header="{l:Loc ShellView_Menu_Zoom}" IsEnabled="{Binding CanZoomBrowser}">
-                    <MenuItem Header="{l:Loc ShellView_Menu_Zoom_In}" InputGestureText="Ctrl++" Command="{s:Action BrowserZoomIn}"/>
-                    <MenuItem Header="{l:Loc ShellView_Menu_Zoom_Out}" InputGestureText="Ctrl+-" Command="{s:Action BrowserZoomOut}"/>
-                    <MenuItem Header="{l:Loc ShellView_Menu_Zoom_Reset}" InputGestureText="Ctrl+0" Command="{s:Action BrowserZoomReset}"/>
+        <Grid DockPanel.Dock="Top">
+            <Menu>
+                <MenuItem Header="{l:Loc ShellView_Menu_File}">
+                    <MenuItem Header="{l:Loc ShellView_Menu_File_Settings}" Command="{s:Action ShowSettings}"/>
+                    <MenuItem Header="{l:Loc ShellView_Menu_File_ConflictResolver}" Command="{s:Action ShowConflictResolver}"/>
+                    <Separator/>
+                    <MenuItem Header="{l:Loc ShellView_Menu_File_Exit}" Command="{s:Action Shutdown}"/>
                 </MenuItem>
-            </MenuItem>
-            <MenuItem Header="{l:Loc ShellView_Menu_Help}">
-                <MenuItem Header="{l:Loc ShellView_Menu_Help_About}" Command="{s:Action ShowAbout}"/>
-            </MenuItem>
-        </Menu>
+                <MenuItem Header="{l:Loc ShellView_Menu_Syncthing}">
+                    <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_Start}" Command="{s:Action Start}"/>
+                    <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_Stop}" Command="{s:Action Stop}"/>
+                    <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_Restart}" Command="{s:Action Restart}"/>
+                    <Separator/>
+                    <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_Refresh}" InputGestureText="F5" Command="{s:Action RefreshBrowser}"/>
+                    <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_OpenExternal}" Command="{s:Action OpenBrowser}"/>
+                    <Separator/>
+                    <MenuItem Header="{l:Loc ShellView_Menu_Syncthing_KillAll}" Command="{s:Action KillAllSyncthingProcesses}"/>
+                </MenuItem>
+                <MenuItem Header="{l:Loc ShellView_Menu_View}">
+                    <MenuItem Header="{l:Loc ShellView_Menu_View_SyncthingConsole}" IsCheckable="True" IsChecked="{Binding ShowConsole}"/>
+                    <Separator/>
+                    <MenuItem Header="{l:Loc ShellView_Menu_Zoom}" IsEnabled="{Binding CanZoomBrowser}">
+                        <MenuItem Header="{l:Loc ShellView_Menu_Zoom_In}" InputGestureText="Ctrl++" Command="{s:Action BrowserZoomIn}"/>
+                        <MenuItem Header="{l:Loc ShellView_Menu_Zoom_Out}" InputGestureText="Ctrl+-" Command="{s:Action BrowserZoomOut}"/>
+                        <MenuItem Header="{l:Loc ShellView_Menu_Zoom_Reset}" InputGestureText="Ctrl+0" Command="{s:Action BrowserZoomReset}"/>
+                    </MenuItem>
+                </MenuItem>
+                <MenuItem Header="{l:Loc ShellView_Menu_Help}">
+                    <MenuItem Header="{l:Loc ShellView_Menu_Help_About}" Command="{s:Action ShowAbout}"/>
+                </MenuItem>
+            </Menu>
+            <TextBlock HorizontalAlignment="Right" Margin="0,0,5,0" Visibility="{Binding DonationManager.HaveDonated, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}}">
+                <Hyperlink s:View.ActionTarget="{Binding DonationManager}" Command="{s:Action Donate}" >
+                    <TextBlock Text="{l:Loc ShellView_Donate}"/>
+                </Hyperlink>
+            </TextBlock>
+        </Grid>
 
         <Grid>
             <Grid.RowDefinitions>

+ 4 - 1
src/SyncTrayzor/Pages/ShellViewModel.cs

@@ -27,6 +27,7 @@ namespace SyncTrayzor.Pages
         public bool ShowConsole { get; set; }
         public double ConsoleHeight { get; set; }
         public WindowPlacement Placement { get; set; }
+        public IDonationManager DonationManager { get; }
 
         private readonly Subject<bool> _activateObservable = new Subject<bool>();
         public IObservable<bool> ActivateObservable => this._activateObservable;
@@ -47,7 +48,8 @@ namespace SyncTrayzor.Pages
             Func<SettingsViewModel> settingsViewModelFactory,
             Func<AboutViewModel> aboutViewModelFactory,
             Func<ConflictResolutionViewModel> confictResolutionViewModelFactory,
-            IProcessStartProvider processStartProvider)
+            IProcessStartProvider processStartProvider,
+            IDonationManager donationManager)
         {
             this.windowManager = windowManager;
             this.syncthingManager = syncthingManager;
@@ -60,6 +62,7 @@ namespace SyncTrayzor.Pages
             this.aboutViewModelFactory = aboutViewModelFactory;
             this.confictResolutionViewModelFactory = confictResolutionViewModelFactory;
             this.processStartProvider = processStartProvider;
+            this.DonationManager = donationManager;
 
             var configuration = this.configurationProvider.Load();
 

+ 46 - 0
src/SyncTrayzor/Properties/Resources.Designer.cs

@@ -69,6 +69,43 @@ namespace SyncTrayzor.Properties {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Donate now.
+        /// </summary>
+        public static string AboutView_Donate_Link {
+            get {
+                return ResourceManager.GetString("AboutView_Donate_Link", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Find SyncTrayzor useful?
+        ///Please donate to my charity fundraising campaign..
+        /// </summary>
+        public static string AboutView_Donate_Text {
+            get {
+                return ResourceManager.GetString("AboutView_Donate_Text", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Donate again.
+        /// </summary>
+        public static string AboutView_DonateAgain_Link {
+            get {
+                return ResourceManager.GetString("AboutView_DonateAgain_Link", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Cheers! Thanks for donating..
+        /// </summary>
+        public static string AboutView_DonateThanks {
+            get {
+                return ResourceManager.GetString("AboutView_DonateThanks", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Open Download Page.
         /// </summary>
@@ -1445,6 +1482,15 @@ namespace SyncTrayzor.Properties {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Donate to my charity fundraiser.
+        /// </summary>
+        public static string ShellView_Donate {
+            get {
+                return ResourceManager.GetString("ShellView_Donate", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to _File.
         /// </summary>

+ 17 - 0
src/SyncTrayzor/Properties/Resources.resx

@@ -852,6 +852,13 @@ Do you want to restart SyncTrayzor now?</value>
   <data name="ConflictResolutionView_Button_ShowInFolder" xml:space="preserve">
     <value>Show in Folder</value>
   </data>
+  <data name="AboutView_Donate_Link" xml:space="preserve">
+    <value>Donate now</value>
+  </data>
+  <data name="AboutView_Donate_Text" xml:space="preserve">
+    <value>Find SyncTrayzor useful?
+Please donate to my charity fundraising campaign.</value>
+  </data>
   <data name="ConflictResolutionView_DeleteToRecycleBin" xml:space="preserve">
     <value>Move deleted files to the recycle bin, rather than deleting permanently</value>
   </data>
@@ -884,6 +891,9 @@ Do you want to restart SyncTrayzor now?</value>
   <data name="ConsoleView_ResumeButton" xml:space="preserve">
     <value>Resume</value>
   </data>
+  <data name="AboutView_DonateThanks" xml:space="preserve">
+    <value>Cheers! Thanks for donating.</value>
+  </data>
   <data name="SettingsView_ShowDeviceOrFolderRejectedBalloons" xml:space="preserve">
     <value>Show "Add New Device / Folder" balloon messages</value>
   </data>
@@ -947,4 +957,11 @@ Do you want to restart SyncTrayzor now?</value>
   <data name="ConfliectResolutionView_ChooseMultipleDescription" xml:space="preserve">
     <value>You have selected {0} conflicts. Choose how you want to resolve them. The other versions will be deleted.</value>
   </data>
+  <data name="AboutView_DonateAgain_Link" xml:space="preserve">
+    <value>Donate again</value>
+  </data>
+  <data name="ShellView_Donate" xml:space="preserve">
+    <value>Donate to my charity fundraiser</value>
+    <comment>Shown in the top right of the menu bar, if the user hasn't yet donated</comment>
+  </data>
 </root>

+ 55 - 0
src/SyncTrayzor/Services/DonationManager.cs

@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Stylet;
+using SyncTrayzor.Services.Config;
+
+namespace SyncTrayzor.Services
+{
+    // Implementing INPC is hacky, but convenient
+    public interface IDonationManager : INotifyPropertyChanged, IDisposable
+    {
+        bool HaveDonated { get; }
+
+        void Donate();
+    }
+
+    public class DonationManager : PropertyChangedBase, IDonationManager
+    {
+        // Not in the app.config, in case some sysadmin wants to change it
+        private const string donateUrl = "https://synctrayzor.antonymale.co.uk/donate";
+
+        private readonly IConfigurationProvider configurationProvider;
+        private readonly IProcessStartProvider processStartProvider;
+
+        public bool HaveDonated { get; private set; }
+
+        public DonationManager(IConfigurationProvider configurationProvider, IProcessStartProvider processStartProvider)
+        {
+            this.configurationProvider = configurationProvider;
+            this.processStartProvider = processStartProvider;
+
+            this.HaveDonated = this.configurationProvider.Load().HaveDonated;
+            this.configurationProvider.ConfigurationChanged += this.ConfigurationChanged;
+        }
+
+        private void ConfigurationChanged(object sender, ConfigurationChangedEventArgs e)
+        {
+            this.HaveDonated = e.NewConfiguration.HaveDonated;
+        }
+
+        public void Donate()
+        {
+            this.processStartProvider.StartDetached(donateUrl);
+            this.configurationProvider.AtomicLoadAndSave(x => x.HaveDonated = true);
+        }
+
+        public void Dispose()
+        {
+            this.configurationProvider.ConfigurationChanged -= this.ConfigurationChanged;
+        }
+    }
+}

+ 1 - 0
src/SyncTrayzor/SyncTrayzor.csproj

@@ -234,6 +234,7 @@
     <Compile Include="Services\Config\WindowPlacement.cs" />
     <Compile Include="Services\Conflicts\ConflictFileManager.cs" />
     <Compile Include="Services\Conflicts\ConflictFileWatcher.cs" />
+    <Compile Include="Services\DonationManager.cs" />
     <Compile Include="Services\FilesystemProvider.cs" />
     <Compile Include="Services\FileWatcher.cs" />
     <Compile Include="Services\IpcCommsClient.cs" />