diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to .github/CONTRIBUTING.md diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..07d6479e --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +custom: ['https://github.com/canton7/synctrayzor/blob/develop/DONATING.md#donating'] \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 25c333a4..1e7ea0a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ Changelog ========= +v1.1.28 +------- + + - Work around Intel X2 Graphics driver bug which causes Syncthing's UI to appear blank (#606) + - Fix chocolatey package (#614) + v1.1.27 ------- diff --git a/DONATING.md b/DONATING.md new file mode 100644 index 00000000..32b61cb7 --- /dev/null +++ b/DONATING.md @@ -0,0 +1,38 @@ +Donating +======== + +Syncthing and SyncTrayzor are free software, and you don't need to pay a penny to use them. +However, if you find them useful, please consider giving a small amount to one of the causes below. + +Syncthing +--------- + +SyncTrayzor is just the wrapper around [Syncthing](https://syncthing.net), which makes it look and behave like a native Windows application. +The heavy lifting is being done by Syncthing. + +While development is done for free by a fantastic team, running the infrastructure which lets your devices find and talk to each other costs money, as does hosting things like the [website](https://syncthing.net) and [forum](https://forum.syncthing.net). +If you make use of these, I kindly ask that you consider sending a small amount towards funding Syncthing's running costs and future development. +Donations are handled by the Syncthing Foundation, whose accounts are public. + +[Donate to Syncthing](https://syncthing.net/donations/). + + +SyncTrayzor Charity Fundraiser +------------------------------ + +I've put a lot of my free time into writing and maintaining SyncTrayzor. +If you use it and appreciate it, I'd be very grateful if you could show your thanks by +donating a small amount (the price of a beer) to charity. + +I've been running charity fundraisers for many years, and very kind people from all over the world have helped raise thousands for people who really need it, which is absolutely amazing. + +Please consider [donating to the current appeal](https://synctrayzor.antonymale.co.uk/fundraiser). + + +Buy me a beer +------------- + +If you want to buy me a coffee (or beer!), you'll absolutely make my day. +Thank you! + +I'm on [Ko-fi](https://ko-fi.com/canton7) or [PayPal](https://www.paypal.com/donate?hosted_button_id=92FADFBYS42MU). diff --git a/README.md b/README.md index aa046519..9d13b8df 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Quick Links - [Download and install SyncTrayzor now](#installation) - [Something went wrong](#something-went-wrong) - - [Find SyncTrayzor useful? Please donate!](#find-synctrayzor-useful-please-donate) + - [Find Syncthing/SyncTrayzor useful? Please donate!](DONATING.md#donating) Introduction @@ -80,15 +80,10 @@ 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. -Find SyncTrayzor useful? Please donate! ---------------------------------------- +Find Syncthing/SyncTrayzor useful? Please donate! +------------------------------------------------- -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! +Please see [DONATING](DONATING.md#donating). Will SyncTrayzor phone home / give away my secrets / etc? diff --git a/chocolatey/synctrayzor.nuspec b/chocolatey/synctrayzor.nuspec index ba956d89..2f3767fb 100644 --- a/chocolatey/synctrayzor.nuspec +++ b/chocolatey/synctrayzor.nuspec @@ -44,6 +44,8 @@ Features include: + + https://github.com/canton7/SyncTrayzor/blob/master/CHANGELOG.md diff --git a/chocolatey/tools/chocolateyinstall.ps1 b/chocolatey/tools/chocolateyinstall.ps1 index cc86fd40..b960eb28 100644 --- a/chocolatey/tools/chocolateyinstall.ps1 +++ b/chocolatey/tools/chocolateyinstall.ps1 @@ -4,7 +4,7 @@ $toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definitio $packageName= 'SyncTrayzor' $file = (Join-Path $toolsDir 'SyncTrayzorSetup-x86.exe') $file64 = (Join-Path $toolsDir 'SyncTrayzorSetup-x64.exe') -$silentArgs = '/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-' +$silentArgs = '/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- /SkipDotNetInstall' $fileType = 'exe' $validExitCodes = @(0) diff --git a/installer/common.iss b/installer/common.iss index c94e122d..f814315e 100644 --- a/installer/common.iss +++ b/installer/common.iss @@ -250,13 +250,27 @@ begin end end; +function CmdLineParamGiven(const Value: String): Boolean; +var + I: Integer; +begin + // Can't use {param}, as it doesn't match flags with no value + Result := False; + for I := 1 to ParamCount do + if CompareText(ParamStr(I), Value) = 0 then + begin + Result := True; + Exit; + end; +end; + function PrepareToInstall(var NeedsRestart: Boolean): String; begin // 'NeedsRestart' only has an effect if we return a non-empty string, thus aborting the installation. // If the installers indicate that they want a restart, this should be done at the end of installation. // Therefore we set the global 'restartRequired' if a restart is needed, and return this from NeedRestart() - if DotNetIsMissing() then + if not CmdLineParamGiven('/SkipDotNetInstall') and DotNetIsMissing() then begin Result := InstallDotNet(); end; @@ -268,19 +282,8 @@ begin end; function ShouldStartSyncTrayzor(): Boolean; -var - flagPassed: Boolean; - i: Integer; begin - // Can't use {param}, as it doesn't match flags with no value - flagPassed := False; - for i := 0 to ParamCount do begin - if ParamStr(i) = '/StartSyncTrayzor' then begin - flagPassed := True; - break; - end; - end; - Result := (not WizardSilent()) or flagPassed; + Result := (not WizardSilent()) or CmdLineParamGiven('/StartSyncTrayzor'); end; function SyncTrayzorStartFlags(param: String): String; diff --git a/server/version_check.php b/server/version_check.php index 1460a52b..abceccb9 100644 --- a/server/version_check.php +++ b/server/version_check.php @@ -65,7 +65,7 @@ function get_with_wildcard($src, $value, $default = null) } $versions = [ - '1.1.27' => [ + '1.1.28' => [ 'base_url' => 'https://github.com/canton7/SyncTrayzor/releases/download', 'installed' => [ 'direct_download_url' => [ @@ -82,7 +82,7 @@ function get_with_wildcard($src, $value, $default = null) 'sha1sum_download_url' => "{base_url}/v{version}/sha1sum.txt.asc", 'sha512sum_download_url' => "{base_url}/v{version}/sha512sum.txt.asc", 'release_page_url' => 'https://github.com/canton7/SyncTrayzor/releases/tag/v{version}', - 'release_notes' => "- Add touch support\n- Minor UI updates (#538, #540, #541, #543)\n- Wrap text on Settings screen (#540)\n- Improve appearance on high-DPI displays (#559)\n- Uninstaller tries to remove autostart registry keys (#586)", + 'release_notes' => "Add a workaround for an Intel Xe graphics driver bug which causes Syncthing's UI to appear blank.\n\nIf you are not affected by this, you do not need to upgrade.", ], '1.1.21' => [ 'base_url' => 'https://synctrayzor.antonymale.co.uk/download', @@ -106,9 +106,10 @@ function get_with_wildcard($src, $value, $default = null) ]; $upgrades = [ - '1.1.26' => ['to' => 'latest', 'formatter' => '5', 'overrides' => ['release_notes' => "- Fix crashes on a small number of machines (#602, #603)\n- Wrap text on Settings screen (#540)\n- Improve appearance on high-DPI displays (#559)"]], - '1.1.25' => ['to' => 'latest', 'formatter' => '5', 'overrides' => ['release_notes' => "- Fix the problems in v1.1.25 (#594, #595, #596, #597, #602, #603)\n- Wrap text on Settings screen (#540)\n- Improve appearance on high-DPI displays (#559)\n- Uninstaller tries to remove autostart registry keys (#586)"]], - '1.1.24' => ['to' => 'latest', 'formatter' => '5', 'overrides' => ['release_notes' => "- Add touch support\n- Wrap text on Settings screen (#540)\n- Improve appearance on high-DPI displays (#559)\n- Uninstaller tries to remove autostart registry keys (#586)"]], + '1.1.27' => ['to' => 'latest', 'formatter' => '5'], + '1.1.26' => ['to' => 'latest', 'formatter' => '5'], + '1.1.25' => ['to' => 'latest', 'formatter' => '5'], + '1.1.24' => ['to' => 'latest', 'formatter' => '5'], '1.1.23' => ['to' => 'latest', 'formatter' => '5'], '1.1.22' => ['to' => 'latest', 'formatter' => '5'], '1.1.21' => ['to' => 'latest', 'formatter' => '5'], diff --git a/src/SyncTrayzor/Bootstrapper.cs b/src/SyncTrayzor/Bootstrapper.cs index 2ef8eab3..fb07af52 100644 --- a/src/SyncTrayzor/Bootstrapper.cs +++ b/src/SyncTrayzor/Bootstrapper.cs @@ -27,6 +27,8 @@ using SyncTrayzor.Localization; using SyncTrayzor.Services.Ipc; using System.Net; +using System.Windows.Media; +using System.Windows.Interop; namespace SyncTrayzor { @@ -195,6 +197,13 @@ protected override void Configure() MessageBoxViewModel.DefaultFlowDirection = Localizer.FlowDirection; RecycleBinDeleter.Logger = s => LogManager.GetLogger(typeof(RecycleBinDeleter).FullName).Error(s); + + // Workaround for Intel Xe processors, which mess up CefSharp unless we disable hardware + // rendering for WPF. See #606. + if (configuration.DisableHardwareRendering) + { + RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly; + } } protected override void Launch() diff --git a/src/SyncTrayzor/Pages/BarAlerts/BarAlertsViewModel.cs b/src/SyncTrayzor/Pages/BarAlerts/BarAlertsViewModel.cs index 16aeed50..c7e02c82 100644 --- a/src/SyncTrayzor/Pages/BarAlerts/BarAlertsViewModel.cs +++ b/src/SyncTrayzor/Pages/BarAlerts/BarAlertsViewModel.cs @@ -1,6 +1,7 @@ using Stylet; using SyncTrayzor.Pages.ConflictResolution; using SyncTrayzor.Services; +using SyncTrayzor.Services.Config; using SyncTrayzor.Syncthing; using System; using System.Collections.Generic; @@ -12,23 +13,33 @@ public class BarAlertsViewModel : Conductor.Collection.AllActive private readonly IAlertsManager alertsManager; private readonly ISyncthingManager syncthingManager; private readonly Func conflictResolutionViewModelFactory; + private readonly Func intelXeGraphicsAlertViewModelFactory; private readonly IWindowManager windowManager; + private readonly IConfigurationProvider configurationProvider; + private readonly GraphicsCardDetector graphicsCardDetector; public BarAlertsViewModel( IAlertsManager alertsManager, ISyncthingManager syncthingManager, Func conflictResolutionViewModelFactory, - IWindowManager windowManager) + Func intelXeGraphicsAlertViewModelFactory, + IWindowManager windowManager, + IConfigurationProvider configurationProvider, + GraphicsCardDetector graphicsCardDetector) { this.alertsManager = alertsManager; this.syncthingManager = syncthingManager; this.conflictResolutionViewModelFactory = conflictResolutionViewModelFactory; + this.intelXeGraphicsAlertViewModelFactory = intelXeGraphicsAlertViewModelFactory; this.windowManager = windowManager; + this.configurationProvider = configurationProvider; + this.graphicsCardDetector = graphicsCardDetector; } protected override void OnInitialActivate() { this.alertsManager.AlertsStateChanged += this.AlertsStateChanged; + this.configurationProvider.ConfigurationChanged += this.AlertsStateChanged; this.Load(); } @@ -69,6 +80,12 @@ private void Load() var vm = new PausedDevicesFromMeteringViewModel(pausedDeviceNames); this.Items.Add(vm); } + + var configuration = this.configurationProvider.Load(); + if (!configuration.DisableHardwareRendering && !configuration.HideIntelXeWarningMessage && this.graphicsCardDetector.IsIntelXe) + { + this.Items.Add(this.intelXeGraphicsAlertViewModelFactory()); + } } private void OpenConflictResolver() @@ -80,6 +97,7 @@ private void OpenConflictResolver() protected override void OnClose() { this.alertsManager.AlertsStateChanged -= this.AlertsStateChanged; + this.configurationProvider.ConfigurationChanged -= this.AlertsStateChanged; } } } diff --git a/src/SyncTrayzor/Pages/BarAlerts/IntelXeGraphicsAlertView.xaml b/src/SyncTrayzor/Pages/BarAlerts/IntelXeGraphicsAlertView.xaml new file mode 100644 index 00000000..6025b741 --- /dev/null +++ b/src/SyncTrayzor/Pages/BarAlerts/IntelXeGraphicsAlertView.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/src/SyncTrayzor/Pages/BarAlerts/IntelXeGraphicsAlertViewModel.cs b/src/SyncTrayzor/Pages/BarAlerts/IntelXeGraphicsAlertViewModel.cs new file mode 100644 index 00000000..0ab58a72 --- /dev/null +++ b/src/SyncTrayzor/Pages/BarAlerts/IntelXeGraphicsAlertViewModel.cs @@ -0,0 +1,22 @@ +using Stylet; +using SyncTrayzor.Services.Config; + +namespace SyncTrayzor.Pages.BarAlerts +{ + public class IntelXeGraphicsAlertViewModel : Screen, IBarAlert + { + private readonly IConfigurationProvider configurationProvider; + + public AlertSeverity Severity => AlertSeverity.Info; + + public IntelXeGraphicsAlertViewModel(IConfigurationProvider configurationProvider) + { + this.configurationProvider = configurationProvider; + } + + public void Dismiss() + { + this.configurationProvider.AtomicLoadAndSave(config => config.HideIntelXeWarningMessage = true); + } + } +} diff --git a/src/SyncTrayzor/Pages/ViewerViewModel.cs b/src/SyncTrayzor/Pages/ViewerViewModel.cs index 3fc5d3b5..d86e5b12 100644 --- a/src/SyncTrayzor/Pages/ViewerViewModel.cs +++ b/src/SyncTrayzor/Pages/ViewerViewModel.cs @@ -113,9 +113,10 @@ protected override void OnInitialActivate() if (configuration.DisableHardwareRendering) { - settings.CefCommandLineArgs.Add("disable-gpu", "1"); - settings.CefCommandLineArgs.Add("disable-gpu-vsync", "1"); - settings.CefCommandLineArgs.Add("disable-application-cache", "1"); + settings.CefCommandLineArgs.Add("disable-gpu"); + settings.CefCommandLineArgs.Add("disable-gpu-vsync"); + settings.CefCommandLineArgs.Add("disable-gpu-compositing"); + settings.CefCommandLineArgs.Add("disable-application-cache"); } Cef.Initialize(settings); diff --git a/src/SyncTrayzor/Properties/Resources.Designer.cs b/src/SyncTrayzor/Properties/Resources.Designer.cs index 62a5b1dc..fa430820 100644 --- a/src/SyncTrayzor/Properties/Resources.Designer.cs +++ b/src/SyncTrayzor/Properties/Resources.Designer.cs @@ -205,6 +205,24 @@ public static string BarAlertsView_FailedTransfer_Details { } } + /// + /// Looks up a localized string similar to The area below may be blank when using Intel Xe graphics cards. Please disable hardware rendering under File -⁠> Settings if you encounter this.. + /// + public static string BarAlertsView_IntelXeGraphics_AlertText { + get { + return ResourceManager.GetString("BarAlertsView_IntelXeGraphics_AlertText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Dismiss. + /// + public static string BarAlertsView_IntelXeGraphics_DismissLink { + get { + return ResourceManager.GetString("BarAlertsView_IntelXeGraphics_DismissLink", resourceCulture); + } + } + /// /// Looks up a localized string similar to The following {0:p:device has|devices have} been paused because {0:p:it|they} connected using a metered network: {0:l:{}|, }.. /// diff --git a/src/SyncTrayzor/Properties/Resources.resx b/src/SyncTrayzor/Properties/Resources.resx index 415b6c18..5b30fd0e 100644 --- a/src/SyncTrayzor/Properties/Resources.resx +++ b/src/SyncTrayzor/Properties/Resources.resx @@ -995,4 +995,11 @@ Please donate to my charity fundraising campaign. _Rescan All Folders Menu option available when right-clicking the tray icon. Allows the user to re-scan all folders + + The area below may be blank when using Intel Xe graphics cards. Please disable hardware rendering under File -⁠> Settings if you encounter this. + Warning shown at the top of a page if Intel Xe graphics are detected + + + Dismiss + \ No newline at end of file diff --git a/src/SyncTrayzor/Services/Config/Configuration.cs b/src/SyncTrayzor/Services/Config/Configuration.cs index 814ec363..e5a8eb62 100644 --- a/src/SyncTrayzor/Services/Config/Configuration.cs +++ b/src/SyncTrayzor/Services/Config/Configuration.cs @@ -61,6 +61,7 @@ public string LatestNotifiedVersionRaw public string SyncthingCustomPath { get; set; } public string SyncthingCustomHomePath { get; set; } public bool DisableHardwareRendering { get; set; } + public bool HideIntelXeWarningMessage { get; set; } public bool EnableFailedTransferAlerts { get; set; } public bool EnableConflictFileMonitoring { get; set; } @@ -100,6 +101,7 @@ public Configuration() this.SyncthingCustomPath = null; this.SyncthingCustomHomePath = null; this.DisableHardwareRendering = false; + this.HideIntelXeWarningMessage = false; this.EnableFailedTransferAlerts = true; this.EnableConflictFileMonitoring = true; this.ConflictResolverDeletesToRecycleBin = true; @@ -137,6 +139,7 @@ public Configuration(Configuration other) this.SyncthingCustomPath = other.SyncthingCustomPath; this.SyncthingCustomHomePath = other.SyncthingCustomHomePath; this.DisableHardwareRendering = other.DisableHardwareRendering; + this.HideIntelXeWarningMessage = other.HideIntelXeWarningMessage; this.EnableFailedTransferAlerts = other.EnableFailedTransferAlerts; this.EnableConflictFileMonitoring = other.EnableConflictFileMonitoring; this.ConflictResolverDeletesToRecycleBin = other.ConflictResolverDeletesToRecycleBin; @@ -160,7 +163,7 @@ public override string ToString() $"ObfuscateDeviceIDs={this.ObfuscateDeviceIDs} UseComputerCulture={this.UseComputerCulture} SyncthingConsoleHeight={this.SyncthingConsoleHeight} WindowPlacement={this.WindowPlacement} " + $"SyncthingWebBrowserZoomLevel={this.SyncthingWebBrowserZoomLevel} LastSeenInstallCount={this.LastSeenInstallCount} SyncthingCustomPath={this.SyncthingCustomPath} " + $"SyncthingCustomHomePath={this.SyncthingCustomHomePath} ShowSynchronizedBalloonEvenIfNothingDownloaded={this.ShowSynchronizedBalloonEvenIfNothingDownloaded} " + - $"DisableHardwareRendering={this.DisableHardwareRendering} EnableFailedTransferAlerts={this.EnableFailedTransferAlerts} " + + $"DisableHardwareRendering={this.DisableHardwareRendering} HideIntelXeWarningMessage={this.HideIntelXeWarningMessage} EnableFailedTransferAlerts={this.EnableFailedTransferAlerts} " + $"EnableConflictFileMonitoring={this.EnableConflictFileMonitoring} " + $"ConflictResolverDeletesToRecycleBin={this.ConflictResolverDeletesToRecycleBin} PauseDevicesOnMeteredNetworks={this.PauseDevicesOnMeteredNetworks} " + $"HaveDonated={this.HaveDonated} IconAnimationMode={this.IconAnimationMode} OpenFolderCommand={this.OpenFolderCommand} ShowFileInFolderCommand={this.ShowFileInFolderCommand}" + diff --git a/src/SyncTrayzor/Services/GraphicsCardDetector.cs b/src/SyncTrayzor/Services/GraphicsCardDetector.cs new file mode 100644 index 00000000..0790ce6c --- /dev/null +++ b/src/SyncTrayzor/Services/GraphicsCardDetector.cs @@ -0,0 +1,42 @@ +using NLog; +using System; +using System.Management; + +namespace SyncTrayzor.Services +{ + public class GraphicsCardDetector + { + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + private bool? _isIntelXe; + public bool IsIntelXe + { + get + { + if (this._isIntelXe == null) + this._isIntelXe = GetIsIntelXe(); + return this._isIntelXe.Value; + } + } + + private static bool GetIsIntelXe() + { + var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_VideoController"); + foreach (ManagementObject obj in searcher.Get()) + { + if (obj["CurrentBitsPerPixel"] != null && obj["CurrentHorizontalResolution"] != null) + { + string name = obj["Name"]?.ToString(); + if (name.IndexOf("Intel", StringComparison.OrdinalIgnoreCase) >= 0 && + name.IndexOf(" Xe ", StringComparison.OrdinalIgnoreCase) >= 0) + { + logger.Info($"Graphics card: {name}"); + return true; + } + } + } + + return false; + } + } +} diff --git a/src/SyncTrayzor/SyncTrayzor.csproj b/src/SyncTrayzor/SyncTrayzor.csproj index 9859bf15..dee2adca 100644 --- a/src/SyncTrayzor/SyncTrayzor.csproj +++ b/src/SyncTrayzor/SyncTrayzor.csproj @@ -101,6 +101,7 @@ + @@ -140,6 +141,7 @@ + PausedDevicesFromMeteringView.xaml @@ -183,6 +185,7 @@ + @@ -392,6 +395,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile