diff --git a/src/Greenshot.Addons/Core/CoreConfigurationExtensions.cs b/src/Greenshot.Addons/Core/CoreConfigurationExtensions.cs
index 12c449554..d9bbec239 100644
--- a/src/Greenshot.Addons/Core/CoreConfigurationExtensions.cs
+++ b/src/Greenshot.Addons/Core/CoreConfigurationExtensions.cs
@@ -103,6 +103,7 @@ namespace Greenshot.Addons.Core
///
/// Supply values we can't put as defaults
///
+ /// ICoreConfiguration
/// The property to return a default for
/// object with the default value for the supplied property
public static object GetDefault(this ICoreConfiguration coreConfiguration, string property)
diff --git a/src/Greenshot.Addons/Core/RssHelper.cs b/src/Greenshot.Addons/Core/RssHelper.cs
deleted file mode 100644
index 675f4e2fe..000000000
--- a/src/Greenshot.Addons/Core/RssHelper.cs
+++ /dev/null
@@ -1,235 +0,0 @@
-#region Greenshot GNU General Public License
-
-// Greenshot - a free and open source screenshot tool
-// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom
-//
-// For more information see: http://getgreenshot.org/
-// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 1 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-#endregion
-
-#region Usings
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Text.RegularExpressions;
-using System.Xml;
-using Dapplo.Log;
-
-#endregion
-
-namespace Greenshot.Addons.Core
-{
- public class RssFile
- {
- private readonly DateTime _pubdate;
-
- public RssFile(string file, string pubdate, string link)
- {
- File = file;
- if (!DateTime.TryParse(pubdate, out _pubdate))
- {
- DateTime.TryParseExact(pubdate.Replace(" UT", ""), "ddd, dd MMM yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out _pubdate);
- }
- Link = link;
- }
-
- public string File { get; }
- public DateTime Pubdate => _pubdate;
-
- public string Link { get; }
- public Version Version { get; set; }
-
- public string Language { get; set; }
-
- public bool IsExe
- {
- get
- {
- if (File != null)
- {
- return File.ToLower().EndsWith(".exe");
- }
- return false;
- }
- }
-
- public bool IsAlpha => File?.ToLowerInvariant().Contains("alpha") == true;
-
- public bool IsBeta => File?.ToLowerInvariant().Contains("beta") == true;
-
- public bool IsReleaseCandidate
- {
- get
- {
- if (File != null)
- {
- return Regex.IsMatch(File.ToLower(), "rc[0-9]+");
- }
- return false;
- }
- }
- }
-
- ///
- /// Description of RssHelper.
- ///
- public class RssHelper
- {
- private const string Rssfeed = "http://getgreenshot.org/project-feed/";
- private static readonly LogSource Log = new LogSource();
-
- ///
- /// This is using the HTTP HEAD Method to check if the RSS Feed is modified after the supplied date
- ///
- /// DateTime
- /// true if the feed is newer
- public static bool IsRssModifiedAfter(DateTime updateTime)
- {
- var lastModified = NetworkHelper.GetLastModified(new Uri(Rssfeed));
- if (lastModified == DateTime.MinValue)
- {
- // Time could not be read, just take now and add one hour to it.
- // This assist BUG-1850
- lastModified = DateTime.Now.AddHours(1);
- }
- return updateTime.CompareTo(lastModified) < 0;
- }
-
- ///
- /// Read the Greenshot RSS feed, so we can use this information to check for updates
- ///
- /// List with RssFile(s)
- public static IList ReadRss()
- {
- var rssDoc = new XmlDocument();
- try
- {
- var webRequest = NetworkHelper.CreateWebRequest(Rssfeed);
- var rssReader = new XmlTextReader(webRequest.GetResponse().GetResponseStream());
-
- // Load the XML content into a XmlDocument
- rssDoc.Load(rssReader);
- }
- catch (Exception wE)
- {
- Log.Warn().WriteLine("Problem reading RSS from {0}", Rssfeed);
- Log.Warn().WriteLine(wE.Message);
- return null;
- }
-
- // Loop for the tag
- XmlNode nodeRss = null;
- for (var i = 0; i < rssDoc.ChildNodes.Count; i++)
- {
- // If it is the rss tag
- if (rssDoc.ChildNodes[i].Name == "rss")
- {
- // tag found
- nodeRss = rssDoc.ChildNodes[i];
- }
- }
-
- if (nodeRss == null)
- {
- Log.Debug().WriteLine("No RSS Feed!");
- return null;
- }
-
- // Loop for the tag
- XmlNode nodeChannel = null;
- for (var i = 0; i < nodeRss.ChildNodes.Count; i++)
- {
- // If it is the channel tag
- if (nodeRss.ChildNodes[i].Name == "channel")
- {
- // tag found
- nodeChannel = nodeRss.ChildNodes[i];
- }
- }
-
- if (nodeChannel == null)
- {
- Log.Debug().WriteLine("No channel in RSS feed!");
- return null;
- }
-
- IList rssFiles = new List();
-
- // Loop for the , , and all the other tags
- for (var i = 0; i < nodeChannel.ChildNodes.Count; i++)
- {
- // If it is the item tag, then it has children tags which we will add as items to the ListView
-
- if (nodeChannel.ChildNodes[i].Name != "item")
- {
- continue;
- }
- var nodeItem = nodeChannel.ChildNodes[i];
- var link = nodeItem["link"]?.InnerText;
- var pubdate = nodeItem["pubDate"]?.InnerText;
- try
- {
- if (link == null)
- {
- continue;
- }
- var match = Regex.Match(Uri.UnescapeDataString(link), @"^.*\/(Greenshot.+)\/download$");
- if (!match.Success)
- {
- continue;
- }
- var file = match.Groups[1].Value;
-
- var rssFile = new RssFile(file, pubdate, link);
- if (file.EndsWith(".exe") || file.EndsWith(".zip"))
- {
- var version = Regex.Replace(file, @".*[a-zA-Z_]\-", "");
- version = version.Replace(@"\-[a-zA-Z]+.*", "");
- version = Regex.Replace(version, @"\.exe$", "");
- version = Regex.Replace(version, @"\.zip$", "");
- version = Regex.Replace(version, @"RC[0-9]+", "");
- if (version.Trim().Length > 0)
- {
- version = version.Replace('-', '.');
- version = version.Replace(',', '.');
- version = Regex.Replace(version, @"^[a-zA-Z_]*\.", "");
- version = Regex.Replace(version, @"\.[a-zA-Z_]*$", "");
-
- try
- {
- rssFile.Version = new Version(version);
- }
- catch (Exception)
- {
- Log.Debug().WriteLine("Found invalid version {0} in file {1}", version, file);
- }
- }
- rssFiles.Add(rssFile);
- }
- }
- catch (Exception ex)
- {
- Log.Warn().WriteLine("Couldn't read RSS entry for: {0}", nodeChannel["title"]?.InnerText);
- Log.Warn().WriteLine(ex, "Reason: ");
- }
- }
-
- return rssFiles;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Greenshot.Addons/Greenshot.Addons.csproj b/src/Greenshot.Addons/Greenshot.Addons.csproj
index e22c8ed1e..0150e00ce 100644
--- a/src/Greenshot.Addons/Greenshot.Addons.csproj
+++ b/src/Greenshot.Addons/Greenshot.Addons.csproj
@@ -363,7 +363,6 @@
-
diff --git a/src/Greenshot.Tests/Greenshot.Tests.csproj b/src/Greenshot.Tests/Greenshot.Tests.csproj
index 1bf980274..57cba32f0 100644
--- a/src/Greenshot.Tests/Greenshot.Tests.csproj
+++ b/src/Greenshot.Tests/Greenshot.Tests.csproj
@@ -83,6 +83,9 @@
..\packages\Dapplo.CaliburnMicro.Translations.1.0.46\lib\net46\Dapplo.CaliburnMicro.Translations.dll
+
+ ..\packages\Dapplo.HttpExtensions.0.8.35\lib\net46\Dapplo.HttpExtensions.dll
+
..\packages\Dapplo.Ini.0.5.28\lib\net45\Dapplo.Ini.dll
@@ -173,6 +176,7 @@
..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll
+
..\packages\System.Reactive.4.0.0\lib\net46\System.Reactive.dll
@@ -200,6 +204,7 @@
..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net46\System.Security.Cryptography.X509Certificates.dll
+
..\packages\System.Text.Encoding.CodePages.4.5.0\lib\net46\System.Text.Encoding.CodePages.dll
@@ -262,11 +267,13 @@
+
-
-
-
+
+ {5b924697-4dcd-4f98-85f1-105cb84b7341}
+ Greenshot.Addons
+
{14894a45-aa2c-4bc3-85a3-e388d0bdc1ca}
Greenshot.Gfx.Experimental
@@ -306,6 +313,12 @@
+
+
+ PreserveNewest
+ Designer
+
+
diff --git a/src/Greenshot.Tests/TestFiles/project-feed.xml b/src/Greenshot.Tests/TestFiles/project-feed.xml
new file mode 100644
index 000000000..a36a74ef1
--- /dev/null
+++ b/src/Greenshot.Tests/TestFiles/project-feed.xml
@@ -0,0 +1,75 @@
+
+
+
+ Greenshot
+ https://getgreenshot.org
+ Greenshot update feed
+ -
+ Greenshot-INSTALLER-1.2.9.129-RELEASE.exe
+ http://sourceforge/projects/greenshot/files/release/Greenshot/Greenshot-INSTALLER-1.2.9.129-RELEASE.exe/download
+ Sat, 28 Jan 2017 15:59:07 +0000
+
+
+ -
+ Greenshot-INSTALLER-1.2.10.6-RELEASE.exe
+ http://sourceforge/projects/greenshot/files/release/Greenshot/Greenshot-INSTALLER-1.2.10.6-RELEASE.exe/download
+ Wed, 09 Aug 2017 15:35:30 +0000
+
+
+ -
+ Greenshot-INSTALLER-1.2.9.112-RELEASE.exe
+ http://sourceforge/projects/greenshot/files/release/Greenshot/Greenshot-INSTALLER-1.2.9.112-RELEASE.exe/download
+ Fri, 30 Dec 2016 21:39:18 +0000
+
+
+ -
+ Greenshot-INSTALLER-1.2.9.104-RELEASE.exe
+ http://sourceforge/projects/greenshot/files/release/Greenshot/Greenshot-INSTALLER-1.2.9.104-RELEASE.exe/download
+ Thu, 15 Dec 2016 19:35:59 +0000
+
+
+ -
+ Greenshot-INSTALLER-1.3.0.14-BETA.exe
+ http://sourceforge/projects/greenshot/files/release/Greenshot/Greenshot-INSTALLER-1.3.0.0-BETA.exe/download
+ Thu, 03 Nov 2016 20:59:15 +0000
+
+
+ -
+ Greenshot-INSTALLER-1.2.8.12-RELEASE.exe
+ http://sourceforge/projects/greenshot/files/release/Greenshot/Greenshot-INSTALLER-1.2.8.12-RELEASE.exe/download
+ Tue, 10 Nov 2015 10:58:37 +0000
+
+
+ -
+ Greenshot-INSTALLER-1.2.10.6-RELEASE.exe
+ https://github.com/greenshot/greenshot/releases/download/Greenshot-RELEASE-1.2.10.6/Greenshot-INSTALLER-1.2.10.6-RELEASE.exe
+ Wed, 09 Aug 2017 15:35:30 +0000
+
+
-
+ Greenshot-INSTALLER-1.2.9.129-RELEASE.exe
+ https://github.com/greenshot/greenshot/releases/download/Greenshot-RELEASE-1.2.9.129/Greenshot-INSTALLER-1.2.9.129-RELEASE.exe
+ Sat, 28 Jan 2017 15:59:07 +0000
+
+
-
+ Greenshot-INSTALLER-1.2.9.112-RELEASE.exe
+ https://github.com/greenshot/greenshot/releases/download/Greenshot-RELEASE-1.2.9.112/Greenshot-INSTALLER-1.2.9.112-RELEASE.exe
+ Fri, 30 Dec 2016 21:39:18 +0000
+
+
-
+ Greenshot-INSTALLER-1.2.9.104-RELEASE.exe
+ https://github.com/greenshot/greenshot/releases/download/Greenshot-RELEASE-1.2.9.104/Greenshot-INSTALLER-1.2.9.104-RELEASE.exe
+ Thu, 15 Dec 2016 19:35:59 +0000
+
+
-
+ Greenshot-INSTALLER-1.2.20.99-RC1.exe
+ https://github.com/greenshot/greenshot/releases/download/Greenshot-RC1-1.2.20.99/Greenshot-INSTALLER-1.2.20.99-RC1.exe
+ Thu, 03 Nov 2016 20:59:15 +0000
+
+
-
+ Greenshot-INSTALLER-1.2.8.12-RELEASE.exe
+ https://github.com/greenshot/greenshot/releases/download/Greenshot-RELEASE-1.2.8.12/Greenshot-INSTALLER-1.2.8.12-RELEASE.exe
+ Tue, 10 Nov 2015 10:58:37 +0000
+
+
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Tests/UpdateTests.cs b/src/Greenshot.Tests/UpdateTests.cs
new file mode 100644
index 000000000..382d220da
--- /dev/null
+++ b/src/Greenshot.Tests/UpdateTests.cs
@@ -0,0 +1,35 @@
+using System;
+using System.ServiceModel.Syndication;
+using System.Threading.Tasks;
+using System.Xml;
+using Dapplo.HttpExtensions;
+using Dapplo.Log;
+using Greenshot.Components;
+using Xunit;
+
+namespace Greenshot.Tests
+{
+ public class UpdateTests
+ {
+ [Fact]
+ public async Task UpdateTest_GetFeed()
+ {
+ var updateFeed = await new Uri("http://getgreenshot.org/project-feed/").GetAsAsync();
+ Assert.True(updateFeed.Links.Count >0);
+ }
+
+ [Fact]
+ public void UpdateTest()
+ {
+ var updateService = new UpdateService(null, null);
+ using (var reader = XmlReader.Create(@"TestFiles\project-feed.xml"))
+ {
+ var feed = SyndicationFeed.Load(reader);
+ updateService.ProcessFeed(feed);
+ Assert.Equal(new Version("1.2.10.6"), updateService.LatestVersion);
+ Assert.Equal(new Version("1.3.0.0"), updateService.BetaVersion);
+ Assert.Equal(new Version("1.2.20.99"), updateService.ReleaseCandidateVersion);
+ }
+ }
+ }
+}
diff --git a/src/Greenshot.Tests/app.config b/src/Greenshot.Tests/app.config
deleted file mode 100644
index 4a3bb809c..000000000
--- a/src/Greenshot.Tests/app.config
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Greenshot.Tests/packages.config b/src/Greenshot.Tests/packages.config
index 67c7225c8..2a90c7987 100644
--- a/src/Greenshot.Tests/packages.config
+++ b/src/Greenshot.Tests/packages.config
@@ -14,6 +14,7 @@
+
diff --git a/src/Greenshot/Components/GreenshotClient.cs b/src/Greenshot/Components/GreenshotClient.cs
index 7bca346c5..da6ce4ad8 100644
--- a/src/Greenshot/Components/GreenshotClient.cs
+++ b/src/Greenshot/Components/GreenshotClient.cs
@@ -36,7 +36,6 @@ namespace Greenshot.Components
public static void Capture(string parameters)
{
-
using (var factory = ChannelFactory)
{
var client = factory.CreateChannel();
diff --git a/src/Greenshot/Components/GreenshotStartupOrder.cs b/src/Greenshot/Components/GreenshotStartupOrder.cs
index 14d026489..b0025826a 100644
--- a/src/Greenshot/Components/GreenshotStartupOrder.cs
+++ b/src/Greenshot/Components/GreenshotStartupOrder.cs
@@ -34,6 +34,7 @@ namespace Greenshot.Components
/// Start the forms initialization before the shell is initialized!
///
Forms = CaliburnStartOrder.Shell-1,
+ User = CaliburnStartOrder.User,
Server = CaliburnStartOrder.User + 100,
Sound = CaliburnStartOrder.User + 200
}
diff --git a/src/Greenshot/Components/GreenshotUiStartupOrder.cs b/src/Greenshot/Components/GreenshotUiStartupOrder.cs
index 0919e07a7..fc2b58c8d 100644
--- a/src/Greenshot/Components/GreenshotUiStartupOrder.cs
+++ b/src/Greenshot/Components/GreenshotUiStartupOrder.cs
@@ -29,7 +29,7 @@ namespace Greenshot.Components
public enum GreenshotUiStartupOrder
{
TrayIcon = 100,
- Plugins = 200,
+ Addons = 200,
Hotkeys = 300
}
}
diff --git a/src/Greenshot/Components/MainFormStartup.cs b/src/Greenshot/Components/MainFormStartup.cs
index b85c438d3..38e5cc3f1 100644
--- a/src/Greenshot/Components/MainFormStartup.cs
+++ b/src/Greenshot/Components/MainFormStartup.cs
@@ -25,6 +25,7 @@
using System;
using System.Linq;
using System.Windows.Forms;
+using Autofac.Features.OwnedInstances;
using Dapplo.Addons;
using Dapplo.CaliburnMicro;
using Dapplo.Log;
@@ -45,12 +46,18 @@ namespace Greenshot.Components
private static readonly LogSource Log = new LogSource();
private readonly ICoreConfiguration _coreConfiguration;
private readonly MainForm _mainForm;
+ private readonly Func> _languageDialogFactory;
private readonly WindowHandle _windowHandle;
- public MainFormStartup(ICoreConfiguration coreConfiguration, MainForm mainForm, WindowHandle windowHandle)
+ public MainFormStartup(
+ ICoreConfiguration coreConfiguration,
+ MainForm mainForm,
+ Func> languageDialogFactory,
+ WindowHandle windowHandle)
{
_coreConfiguration = coreConfiguration;
_mainForm = mainForm;
+ _languageDialogFactory = languageDialogFactory;
_windowHandle = windowHandle;
}
@@ -61,9 +68,11 @@ namespace Greenshot.Components
// if language is not set, show language dialog
if (string.IsNullOrEmpty(_coreConfiguration.Language))
{
- var languageDialog = LanguageDialog.GetInstance();
- languageDialog.ShowDialog();
- _coreConfiguration.Language = languageDialog.SelectedLanguage;
+ using (var ownedLanguageDialog = _languageDialogFactory())
+ {
+ ownedLanguageDialog.Value.ShowDialog();
+ _coreConfiguration.Language = ownedLanguageDialog.Value.SelectedLanguage;
+ }
}
// This makes sure the MainForm can initialize, calling show first would create the "Handle" and causing e.g. the DPI Handler to be to late.
diff --git a/src/Greenshot/Components/UpdateService.cs b/src/Greenshot/Components/UpdateService.cs
new file mode 100644
index 000000000..ed071e7ee
--- /dev/null
+++ b/src/Greenshot/Components/UpdateService.cs
@@ -0,0 +1,233 @@
+#region Greenshot GNU General Public License
+
+// Greenshot - a free and open source screenshot tool
+// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom
+//
+// For more information see: http://getgreenshot.org/
+// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 1 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#endregion
+
+#region Usings
+
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.ServiceModel.Syndication;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Dapplo.Addons;
+using Dapplo.CaliburnMicro;
+using Dapplo.HttpExtensions;
+using Dapplo.Log;
+using Dapplo.Utils;
+using Greenshot.Addons;
+using Greenshot.Addons.Core;
+using Greenshot.Forms;
+
+#endregion
+
+namespace Greenshot.Components
+{
+ ///
+ /// This processes the information, if there are updates available.
+ ///
+ [ServiceOrder(GreenshotStartupOrder.User)]
+ public class UpdateService : IStartup, IShutdown, IVersionProvider
+ {
+ private static readonly LogSource Log = new LogSource();
+ private static readonly Regex VersionRegex = new Regex(@"^.*[^-]-(?[0-9\.]+)\-(?(release|beta|rc[0-9]+))\.exe.*", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+ private const string StableDownloadLink = "https://getgreenshot.org/downloads/";
+ private static readonly Uri UpdateFeed = new Uri("http://getgreenshot.org/project-feed/");
+ private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
+
+ private readonly ICoreConfiguration _coreConfiguration;
+ private readonly IGreenshotLanguage _greenshotLanguage;
+
+ ///
+ public Version CurrentVersion { get; }
+
+ ///
+ public Version LatestVersion { get; private set; }
+
+ ///
+ /// The latest beta version
+ ///
+ public Version BetaVersion { get; private set; }
+
+ ///
+ /// The latest RC version
+ ///
+ public Version ReleaseCandidateVersion { get; private set; }
+
+ ///
+ public bool IsUpdateAvailable => LatestVersion > CurrentVersion;
+
+ ///
+ /// Constructor with dependencies
+ ///
+ /// ICoreConfiguration
+ /// IGreenshotLanguage
+ public UpdateService(
+ ICoreConfiguration coreConfiguration,
+ IGreenshotLanguage greenshotLanguage)
+ {
+ _coreConfiguration = coreConfiguration;
+ _greenshotLanguage = greenshotLanguage;
+ LatestVersion = CurrentVersion = GetType().Assembly.GetName().Version;
+ _coreConfiguration.LastSaveWithVersion = CurrentVersion.ToString();
+
+ }
+
+ ///
+ public void Start()
+ {
+ var ignore = BackgroundTask(() => TimeSpan.FromDays(_coreConfiguration.UpdateCheckInterval), UpdateCheck, _cancellationTokenSource.Token);
+ }
+
+ ///
+ public void Shutdown()
+ {
+ _cancellationTokenSource.Cancel();
+ }
+
+ ///
+ /// This runs a periodic task in the background
+ ///
+ /// Func which returns a TimeSpan
+ /// Func which returns a task
+ /// CancellationToken
+ /// Task
+ private async Task BackgroundTask(Func intervalFactory, Func reoccurringTask, CancellationToken cancellationToken = default)
+ {
+ Log.Info().WriteLine("Starting background task");
+ await Task.Run(async () =>
+ {
+ while (true)
+ {
+ var interval = intervalFactory();
+ var task = reoccurringTask;
+ if (TimeSpan.Zero == interval)
+ {
+ interval = TimeSpan.FromMinutes(10);
+ task = c => Task.FromResult(true);
+ }
+ try
+ {
+ await Task.WhenAll(Task.Delay(interval, cancellationToken), task(cancellationToken));
+ }
+ catch (Exception ex)
+ {
+ Log.Error().WriteLine(ex, "Error occured when trying to check for updates.");
+ }
+ if (cancellationToken.IsCancellationRequested)
+ {
+ break;
+ }
+ }
+ }, cancellationToken);
+ Log.Info().WriteLine("Finished background task");
+ }
+
+ private async Task UpdateCheck(CancellationToken cancellationToken = default)
+ {
+ Log.Info().WriteLine("Checking for updates");
+ var updateFeed = await UpdateFeed.GetAsAsync(cancellationToken);
+ if (updateFeed == null)
+ {
+ return;
+ }
+ _coreConfiguration.LastUpdateCheck = DateTime.Now;
+
+ ProcessFeed(updateFeed);
+
+ if (IsUpdateAvailable)
+ {
+ await UiContext.RunOn(() =>
+ {
+ // TODO: Show update
+ MainForm.Instance.NotifyIcon.BalloonTipClicked += HandleBalloonTipClick;
+ MainForm.Instance.NotifyIcon.BalloonTipClosed += CleanupBalloonTipClick;
+ MainForm.Instance.NotifyIcon.ShowBalloonTip(10000, "Greenshot", string.Format(_greenshotLanguage.UpdateFound, LatestVersion), ToolTipIcon.Info);
+ }, cancellationToken);
+ }
+ }
+
+ ///
+ /// Process the update feed to get the latest version
+ ///
+ ///
+ public void ProcessFeed(SyndicationFeed updateFeed)
+ {
+ var versions =
+ from link in updateFeed.Items.SelectMany(i => i.Links)
+ select VersionRegex.Match(link.Uri.AbsoluteUri) into match
+ where match.Success
+ group match by Regex.Replace(match.Groups["type"].Value, @"[\d-]", string.Empty) into groupedVersions
+ select groupedVersions.OrderByDescending(m => new Version(m.Groups["version"].Value)).First();
+
+ foreach (var versionMatch in versions)
+ {
+ var version = new Version(versionMatch.Groups["version"].Value);
+ var type = versionMatch.Groups["type"].Value;
+ if (string.IsNullOrEmpty(type))
+ {
+ continue;
+ }
+ Log.Debug().WriteLine("Got {0} {1}", type, version);
+ if ("release".Equals(type, StringComparison.OrdinalIgnoreCase))
+ {
+ LatestVersion = version;
+ }
+ if ("beta".Equals(type, StringComparison.OrdinalIgnoreCase))
+ {
+ BetaVersion = version;
+ }
+ if ("rc".Equals(type, StringComparison.OrdinalIgnoreCase))
+ {
+ ReleaseCandidateVersion = version;
+ }
+ }
+ }
+
+ private void CleanupBalloonTipClick(object sender, EventArgs e)
+ {
+ MainForm.Instance.NotifyIcon.BalloonTipClicked -= HandleBalloonTipClick;
+ MainForm.Instance.NotifyIcon.BalloonTipClosed -= CleanupBalloonTipClick;
+ }
+
+ private void HandleBalloonTipClick(object sender, EventArgs e)
+ {
+ try
+ {
+ // "Direct" download link
+ // Process.Start(latestGreenshot.Link);
+ // Go to getgreenshot.org
+ Process.Start(StableDownloadLink);
+ }
+ catch (Exception)
+ {
+ MessageBox.Show(string.Format(_greenshotLanguage.ErrorOpenlink, StableDownloadLink), _greenshotLanguage.Error);
+ }
+ finally
+ {
+ CleanupBalloonTipClick(sender, e);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot/Destinations/PrinterDestination.cs b/src/Greenshot/Destinations/PrinterDestination.cs
index 3065afbfc..cd8219080 100644
--- a/src/Greenshot/Destinations/PrinterDestination.cs
+++ b/src/Greenshot/Destinations/PrinterDestination.cs
@@ -28,11 +28,11 @@ using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
+using Autofac.Features.OwnedInstances;
using Greenshot.Addons;
using Greenshot.Addons.Components;
using Greenshot.Addons.Core;
using Greenshot.Addons.Interfaces;
-using Greenshot.Configuration;
using Greenshot.Helpers;
#endregion
@@ -46,19 +46,23 @@ namespace Greenshot.Destinations
public class PrinterDestination : AbstractDestination
{
private readonly IGreenshotLanguage _greenshotLanguage;
+ private readonly Func> _printHelperFactory;
private readonly string _printerName;
public PrinterDestination(ICoreConfiguration coreConfiguration,
- IGreenshotLanguage greenshotLanguage
- ): base(coreConfiguration, greenshotLanguage)
+ IGreenshotLanguage greenshotLanguage,
+ Func> printHelperFactory
+ ) : base(coreConfiguration, greenshotLanguage)
{
_greenshotLanguage = greenshotLanguage;
+ _printHelperFactory = printHelperFactory;
}
protected PrinterDestination(
ICoreConfiguration coreConfiguration,
IGreenshotLanguage greenshotLanguage,
- string printerName) : this(coreConfiguration, greenshotLanguage)
+ Func> printHelperFactory,
+ string printerName) : this(coreConfiguration, greenshotLanguage, printHelperFactory)
{
_printerName = printerName;
}
@@ -110,7 +114,7 @@ namespace Greenshot.Destinations
});
foreach (var printer in printers)
{
- yield return new PrinterDestination(CoreConfiguration, GreenshotLanguage, printer);
+ yield return new PrinterDestination(CoreConfiguration, GreenshotLanguage, _printHelperFactory, printer);
}
}
@@ -127,25 +131,26 @@ namespace Greenshot.Destinations
PrinterSettings printerSettings;
if (!string.IsNullOrEmpty(_printerName))
{
- using (var printHelper = new PrintHelper(CoreConfiguration, GreenshotLanguage,surface, captureDetails))
+ using (var ownedPrintHelper = _printHelperFactory(surface, captureDetails))
{
- printerSettings = printHelper.PrintTo(_printerName);
+ printerSettings = ownedPrintHelper.Value.PrintTo(_printerName);
}
}
else if (!manuallyInitiated)
{
var settings = new PrinterSettings();
- using (var printHelper = new PrintHelper(CoreConfiguration, GreenshotLanguage, surface, captureDetails))
- {
- printerSettings = printHelper.PrintTo(settings.PrinterName);
- }
+
+ using (var ownedPrintHelper = _printHelperFactory(surface, captureDetails))
+ {
+ printerSettings = ownedPrintHelper.Value.PrintTo(settings.PrinterName);
+ }
}
else
{
- using (var printHelper = new PrintHelper(CoreConfiguration, GreenshotLanguage, surface, captureDetails))
- {
- printerSettings = printHelper.PrintWithDialog();
- }
+ using (var ownedPrintHelper = _printHelperFactory(surface, captureDetails))
+ {
+ printerSettings = ownedPrintHelper.Value.PrintWithDialog();
+ }
}
if (printerSettings != null)
{
diff --git a/src/Greenshot/Forms/LanguageDialog.cs b/src/Greenshot/Forms/LanguageDialog.cs
index 68ecafbde..285cd8b23 100644
--- a/src/Greenshot/Forms/LanguageDialog.cs
+++ b/src/Greenshot/Forms/LanguageDialog.cs
@@ -41,7 +41,6 @@ namespace Greenshot.Forms
public partial class LanguageDialog : Form
{
private static readonly LogSource Log = new LogSource();
- private static LanguageDialog _uniqueInstance;
private bool _properOkPressed;
private LanguageDialog()
@@ -108,10 +107,5 @@ namespace Greenshot.Forms
Language.CurrentLanguage = SelectedLanguage;
Close();
}
-
- public static LanguageDialog GetInstance()
- {
- return _uniqueInstance ?? (_uniqueInstance = new LanguageDialog());
- }
}
}
\ No newline at end of file
diff --git a/src/Greenshot/Forms/MainForm.cs b/src/Greenshot/Forms/MainForm.cs
index 08111c417..86a76992c 100644
--- a/src/Greenshot/Forms/MainForm.cs
+++ b/src/Greenshot/Forms/MainForm.cs
@@ -74,11 +74,11 @@ namespace Greenshot.Forms
private static readonly LogSource Log = new LogSource();
private readonly ICoreConfiguration _coreConfiguration;
private readonly IWindowManager _windowManager;
- private readonly ConfigViewModel _configViewModel;
+ private readonly Func> _configViewModelFactory;
+ private readonly Func> _aboutFormFactory;
// Timer for the double click test
private readonly Timer _doubleClickTimer = new Timer();
- private readonly Func> _aboutFormFactory;
private readonly DestinationHolder _destinationHolder;
// Thumbnail preview
@@ -89,13 +89,13 @@ namespace Greenshot.Forms
public MainForm(ICoreConfiguration coreConfiguration,
IWindowManager windowManager,
IGreenshotLanguage greenshotLanguage,
- ConfigViewModel configViewModel,
+ Func> configViewModelFactory,
Func> aboutFormFactory,
DestinationHolder destinationHolder) : base(greenshotLanguage)
{
_coreConfiguration = coreConfiguration;
_windowManager = windowManager;
- _configViewModel = configViewModel;
+ _configViewModelFactory = configViewModelFactory;
_aboutFormFactory = aboutFormFactory;
_destinationHolder = destinationHolder;
Instance = this;
@@ -365,17 +365,7 @@ namespace Greenshot.Forms
{
PsApi.EmptyWorkingSet();
}
- if (UpdateHelper.IsUpdateCheckNeeded())
- {
- Log.Debug().WriteLine("BackgroundWorkerTimerTick checking for update");
- // Start update check in the background
- var backgroundTask = new Thread(UpdateHelper.CheckAndAskForUpdate)
- {
- Name = "Update check",
- IsBackground = true
- };
- backgroundTask.Start();
- }
+
}
@@ -841,10 +831,9 @@ namespace Greenshot.Forms
///
public void ShowSetting()
{
- // The new MVVM Configuration
- if (!_configViewModel.IsActive)
+ using(var ownedConfigViewModel = _configViewModelFactory())
{
- _windowManager.ShowDialog(_configViewModel);
+ _windowManager.ShowDialog(ownedConfigViewModel.Value);
}
InitializeQuickSettingsMenu();
}
diff --git a/src/Greenshot/Greenshot.csproj b/src/Greenshot/Greenshot.csproj
index 47a1ebaf8..610568f8c 100644
--- a/src/Greenshot/Greenshot.csproj
+++ b/src/Greenshot/Greenshot.csproj
@@ -289,7 +289,7 @@
-
+
diff --git a/src/Greenshot/GreenshotAutofacModule.cs b/src/Greenshot/GreenshotAutofacModule.cs
index 53dfe62ac..05933161d 100644
--- a/src/Greenshot/GreenshotAutofacModule.cs
+++ b/src/Greenshot/GreenshotAutofacModule.cs
@@ -29,6 +29,7 @@ using Dapplo.CaliburnMicro.Security;
using Greenshot.Addons.Components;
using Greenshot.Components;
using Greenshot.Forms;
+using Greenshot.Helpers;
using Greenshot.Ui.Configuration.ViewModels;
using Greenshot.Ui.Misc.ViewModels;
@@ -41,8 +42,8 @@ namespace Greenshot
{
builder
.RegisterType()
- .AsSelf()
- .SingleInstance();
+ .AsSelf();
+
builder
.RegisterType()
.As()
@@ -53,6 +54,18 @@ namespace Greenshot
.AsSelf()
.SingleInstance();
+ builder
+ .RegisterType()
+ .AsSelf();
+
+ builder
+ .RegisterType()
+ .AsSelf();
+
+ builder
+ .RegisterType()
+ .AsSelf();
+
builder
.RegisterType()
.As()
@@ -83,7 +96,7 @@ namespace Greenshot
.AssignableTo()
.As()
.SingleInstance();
-
+
builder
.RegisterType()
.AsSelf();
diff --git a/src/Greenshot/Helpers/PrintHelper.cs b/src/Greenshot/Helpers/PrintHelper.cs
index b39d5a1b6..2d3b5c411 100644
--- a/src/Greenshot/Helpers/PrintHelper.cs
+++ b/src/Greenshot/Helpers/PrintHelper.cs
@@ -27,6 +27,7 @@ using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
+using Autofac.Features.OwnedInstances;
using Greenshot.Forms;
using Dapplo.Log;
using Dapplo.Windows.Common.Extensions;
@@ -52,6 +53,7 @@ namespace Greenshot.Helpers
private static readonly LogSource Log = new LogSource();
private readonly ICoreConfiguration _coreConfig;
private readonly IGreenshotLanguage _greenshotLanguage;
+ private readonly Func> _printOptionsDialogFactory;
private readonly ICaptureDetails _captureDetails;
private PrintDialog _printDialog = new PrintDialog();
private PrintDocument _printDocument = new PrintDocument();
@@ -61,11 +63,13 @@ namespace Greenshot.Helpers
public PrintHelper(
ICoreConfiguration coreConfiguration,
IGreenshotLanguage greenshotLanguage,
+ Func> printOptionsDialogFactory,
ISurface surface,
ICaptureDetails captureDetails)
{
_coreConfig = coreConfiguration;
_greenshotLanguage = greenshotLanguage;
+ _printOptionsDialogFactory = printOptionsDialogFactory;
_surface = surface;
_captureDetails = captureDetails;
@@ -83,16 +87,6 @@ namespace Greenshot.Helpers
public void Dispose()
{
Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /**
- * Destructor
- */
-
- ~PrintHelper()
- {
- Dispose(false);
}
/**
@@ -149,29 +143,30 @@ namespace Greenshot.Helpers
/// printer settings if actually printed, or null if print was cancelled or has failed
public PrinterSettings PrintWithDialog()
{
- PrinterSettings returnPrinterSettings = null;
- if (_printDialog.ShowDialog() == DialogResult.OK)
- {
- var printOptionsResult = ShowPrintOptionsDialog();
- try
- {
- if (printOptionsResult == null || printOptionsResult == DialogResult.OK)
- {
- if (!IsColorPrint())
- {
- _printDocument.DefaultPageSettings.Color = false;
- }
- _printDocument.Print();
- returnPrinterSettings = _printDialog.PrinterSettings;
- }
- }
- catch (Exception e)
- {
- Log.Error().WriteLine(e, "An error ocurred while trying to print");
- MessageBox.Show(Language.GetString(LangKey.print_error), Language.GetString(LangKey.error));
- }
- }
- return returnPrinterSettings;
+ if (_printDialog.ShowDialog() != DialogResult.OK)
+ {
+ return null;
+ }
+ PrinterSettings returnPrinterSettings = null;
+ var printOptionsResult = ShowPrintOptionsDialog();
+ try
+ {
+ if (printOptionsResult == null || printOptionsResult == DialogResult.OK)
+ {
+ if (!IsColorPrint())
+ {
+ _printDocument.DefaultPageSettings.Color = false;
+ }
+ _printDocument.Print();
+ returnPrinterSettings = _printDialog.PrinterSettings;
+ }
+ }
+ catch (Exception e)
+ {
+ Log.Error().WriteLine(e, "An error ocurred while trying to print");
+ MessageBox.Show(Language.GetString(LangKey.print_error), Language.GetString(LangKey.error));
+ }
+ return returnPrinterSettings;
}
private bool IsColorPrint()
@@ -190,9 +185,9 @@ namespace Greenshot.Helpers
return null;
}
- using (var printOptionsDialog = new PrintOptionsDialog(_coreConfig, _greenshotLanguage))
+ using (var ownedPrintOptionsDialog = _printOptionsDialogFactory())
{
- return printOptionsDialog.ShowDialog();
+ return ownedPrintOptionsDialog.Value.ShowDialog();
}
}
diff --git a/src/Greenshot/Helpers/UpdateHelper.cs b/src/Greenshot/Helpers/UpdateHelper.cs
deleted file mode 100644
index 0f11f79b4..000000000
--- a/src/Greenshot/Helpers/UpdateHelper.cs
+++ /dev/null
@@ -1,223 +0,0 @@
-#region Greenshot GNU General Public License
-
-// Greenshot - a free and open source screenshot tool
-// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom
-//
-// For more information see: http://getgreenshot.org/
-// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 1 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-#endregion
-
-#region Usings
-
-using System;
-using System.Diagnostics;
-using System.Reflection;
-using System.Windows.Forms;
-using Dapplo.Ini;
-using Dapplo.Log;
-using Greenshot.Addons.Core;
-using Greenshot.Addons.Core.Enums;
-using Greenshot.Configuration;
-using Greenshot.Forms;
-
-#endregion
-
-namespace Greenshot.Helpers
-{
- ///
- /// Description of RssFeedHelper.
- ///
- public static class UpdateHelper
- {
- private const string StableDownloadLink = "https://getgreenshot.org/downloads/";
- private const string VersionHistoryLink = "https://getgreenshot.org/version-history/";
- private static readonly LogSource Log = new LogSource();
- private static readonly ICoreConfiguration CoreConfig = IniConfig.Current.Get();
- private static readonly object LockObject = new object();
- private static RssFile _latestGreenshot;
- private static string _downloadLink = StableDownloadLink;
-
- ///
- /// Is an update check needed?
- ///
- /// bool true if yes
- public static bool IsUpdateCheckNeeded()
- {
- lock (LockObject)
- {
- if (CoreConfig.UpdateCheckInterval == 0)
- {
- return false;
- }
- var checkTime = CoreConfig.LastUpdateCheck;
- checkTime = checkTime.AddDays(CoreConfig.UpdateCheckInterval);
- if (DateTime.Now.CompareTo(checkTime) < 0)
- {
- Log.Debug().WriteLine("No need to check RSS feed for updates, feed check will be after {0}", checkTime);
- return false;
- }
- Log.Debug().WriteLine("Update check is due, last check was {0} check needs to be made after {1} (which is one {2} later)", CoreConfig.LastUpdateCheck, checkTime,
- CoreConfig.UpdateCheckInterval);
- if (!RssHelper.IsRssModifiedAfter(CoreConfig.LastUpdateCheck))
- {
- Log.Debug().WriteLine("RSS feed has not been updated since after {0}", CoreConfig.LastUpdateCheck);
- return false;
- }
- }
- return true;
- }
-
- ///
- /// Read the RSS feed to see if there is a Greenshot update
- ///
- public static void CheckAndAskForUpdate()
- {
- lock (LockObject)
- {
- var currentVersion = Assembly.GetExecutingAssembly().GetName().Version;
- // Test like this:
- // currentVersion = new Version("0.8.1.1198");
-
- try
- {
- _latestGreenshot = null;
- ProcessRssInfo(currentVersion);
- if (_latestGreenshot != null)
- {
- MainForm.Instance.NotifyIcon.BalloonTipClicked += HandleBalloonTipClick;
- MainForm.Instance.NotifyIcon.BalloonTipClosed += CleanupBalloonTipClick;
- MainForm.Instance.NotifyIcon.ShowBalloonTip(10000, "Greenshot", Language.GetFormattedString(LangKey.update_found, "'" + _latestGreenshot.File + "'"),
- ToolTipIcon.Info);
- }
- CoreConfig.LastUpdateCheck = DateTime.Now;
- }
- catch (Exception e)
- {
- Log.Error().WriteLine(e, "An error occured while checking for updates, the error will be ignored: ");
- }
- }
- }
-
- private static void CleanupBalloonTipClick(object sender, EventArgs e)
- {
- MainForm.Instance.NotifyIcon.BalloonTipClicked -= HandleBalloonTipClick;
- MainForm.Instance.NotifyIcon.BalloonTipClosed -= CleanupBalloonTipClick;
- }
-
- private static void HandleBalloonTipClick(object sender, EventArgs e)
- {
- try
- {
- if (_latestGreenshot != null)
- {
- // "Direct" download link
- // Process.Start(latestGreenshot.Link);
- // Go to getgreenshot.org
- Process.Start(_downloadLink);
- }
- }
- catch (Exception)
- {
- MessageBox.Show(Language.GetFormattedString(LangKey.error_openlink, _downloadLink), Language.GetString(LangKey.error));
- }
- finally
- {
- CleanupBalloonTipClick(sender, e);
- }
- }
-
- private static void ProcessRssInfo(Version currentVersion)
- {
- // Reset latest Greenshot
- var rssFiles = RssHelper.ReadRss();
-
- if (rssFiles == null)
- {
- return;
- }
-
- // Retrieve the current and latest greenshot
- foreach (var rssFile in rssFiles)
- {
- if (rssFile.File.StartsWith("Greenshot"))
- {
- // check for exe
- if (!rssFile.IsExe)
- {
- continue;
- }
-
- // do we have a version?
- if (rssFile.Version == null)
- {
- Log.Debug().WriteLine("Skipping unversioned exe {0} which is published at {1} : {2}", rssFile.File, rssFile.Pubdate.ToLocalTime(), rssFile.Link);
- continue;
- }
-
- // if the file is unstable, we will skip it when:
- // the current version is a release or release candidate AND check unstable is turned off.
- if (rssFile.IsAlpha)
- {
- // Skip if we shouldn't check unstables
- if (CoreConfigurationExtensions.BuildState == BuildStates.RELEASE && !CoreConfig.CheckForUnstable)
- {
- continue;
- }
- }
-
- // if the file is a release candidate, we will skip it when:
- // the current version is a release AND check unstable is turned off.
- if (rssFile.IsReleaseCandidate)
- {
- if (CoreConfigurationExtensions.BuildState == BuildStates.RELEASE && !CoreConfig.CheckForUnstable)
- {
- continue;
- }
- }
-
- // Compare versions
- var versionCompare = rssFile.Version.CompareTo(currentVersion);
- if (versionCompare > 0)
- {
- Log.Debug().WriteLine("Found newer Greenshot '{0}' with version {1} published at {2} : {3}", rssFile.File, rssFile.Version, rssFile.Pubdate.ToLocalTime(), rssFile.Link);
- if (_latestGreenshot == null || rssFile.Version.CompareTo(_latestGreenshot.Version) > 0)
- {
- _latestGreenshot = rssFile;
- if (rssFile.IsReleaseCandidate || rssFile.IsAlpha)
- {
- _downloadLink = VersionHistoryLink;
- }
- else
- {
- _downloadLink = StableDownloadLink;
- }
- }
- }
- else if (versionCompare < 0)
- {
- Log.Debug().WriteLine("Skipping older greenshot with version {0}", rssFile.Version);
- }
- else if (versionCompare == 0)
- {
- Log.Debug().WriteLine("Found current version as exe {0} with version {1} published at {2} : {3}", rssFile.File, rssFile.Version, rssFile.Pubdate.ToLocalTime(),
- rssFile.Link);
- }
- }
- }
- }
- }
-}
\ No newline at end of file