mirror of
https://github.com/greenshot/greenshot
synced 2025-08-23 14:46:19 -07:00
Merge pull request #1 from greenshot/release/1.2.9BF2
Release/1.2.9 bf2
This commit is contained in:
commit
f65b86f165
34 changed files with 357 additions and 361 deletions
|
@ -116,6 +116,7 @@ namespace Greenshot.Destinations {
|
|||
pattern = "greenshot ${capturetime}";
|
||||
}
|
||||
string filename = FilenameHelper.GetFilenameFromPattern(pattern, CoreConfig.OutputFileFormat, captureDetails);
|
||||
CoreConfig.ValidateAndCorrectOutputFilePath();
|
||||
string filepath = FilenameHelper.FillVariables(CoreConfig.OutputFilePath, false);
|
||||
try {
|
||||
fullPath = Path.Combine(filepath, filename);
|
||||
|
|
|
@ -27,6 +27,7 @@ using Greenshot.Plugin.Drawing;
|
|||
using GreenshotPlugin.Interfaces.Drawing;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Greenshot.Drawing.Fields
|
||||
{
|
||||
|
@ -203,7 +204,7 @@ namespace Greenshot.Drawing.Fields
|
|||
{
|
||||
return;
|
||||
}
|
||||
foreach (var drawableContainer1 in _boundContainers)
|
||||
foreach (var drawableContainer1 in _boundContainers.ToList())
|
||||
{
|
||||
var drawableContainer = (DrawableContainer) drawableContainer1;
|
||||
if (!drawableContainer.HasField(field.FieldType))
|
||||
|
|
|
@ -56,9 +56,10 @@ namespace Greenshot.Drawing
|
|||
/// <summary>
|
||||
/// Restore the target gripper
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
protected override void OnDeserialized(StreamingContext context)
|
||||
/// <param name="streamingContext">StreamingContext</param>
|
||||
protected override void OnDeserialized(StreamingContext streamingContext)
|
||||
{
|
||||
base.OnDeserialized(streamingContext);
|
||||
InitAdorner(Color.Green, _storedTargetGripperLocation);
|
||||
}
|
||||
#endregion
|
||||
|
@ -303,7 +304,6 @@ namespace Greenshot.Drawing
|
|||
tail.Dispose();
|
||||
|
||||
// Draw the text
|
||||
UpdateFormat();
|
||||
DrawText(graphics, rect, lineThickness, lineColor, shadow, StringFormat, Text, Font);
|
||||
}
|
||||
|
||||
|
|
|
@ -272,8 +272,11 @@ namespace Greenshot.Drawing
|
|||
_parent.Controls.Add(_textBox);
|
||||
}
|
||||
EnsureTextBoxContrast();
|
||||
_textBox.Show();
|
||||
_textBox.Focus();
|
||||
if (_textBox != null)
|
||||
{
|
||||
_textBox.Show();
|
||||
_textBox.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -281,6 +284,10 @@ namespace Greenshot.Drawing
|
|||
/// </summary>
|
||||
private void EnsureTextBoxContrast()
|
||||
{
|
||||
if (_textBox == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Color lc = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
if (lc.R > 203 && lc.G > 203 && lc.B > 203)
|
||||
{
|
||||
|
@ -295,7 +302,7 @@ namespace Greenshot.Drawing
|
|||
private void HideTextBox()
|
||||
{
|
||||
_parent.Focus();
|
||||
_textBox.Hide();
|
||||
_textBox?.Hide();
|
||||
_parent.KeysLocked = false;
|
||||
_parent.Controls.Remove(_textBox);
|
||||
}
|
||||
|
@ -424,6 +431,10 @@ namespace Greenshot.Drawing
|
|||
/// </summary>
|
||||
private void UpdateTextBoxPosition()
|
||||
{
|
||||
if (_textBox == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
|
||||
int lineWidth = (int)Math.Floor(lineThickness / 2d);
|
||||
|
|
|
@ -860,13 +860,15 @@ namespace Greenshot {
|
|||
case Keys.Oemcomma: // Rotate CCW Ctrl + ,
|
||||
RotateCcwToolstripButtonClick(sender, e);
|
||||
break;
|
||||
case Keys.OemPeriod: // Rotate CW Ctrl + .
|
||||
case Keys.OemPeriod: // Rotate CW Ctrl + .
|
||||
RotateCwToolstripButtonClick(sender, e);
|
||||
break;
|
||||
case Keys.Add: // Ctrl + +
|
||||
case Keys.Oemplus: // Ctrl + +
|
||||
EnlargeCanvasToolStripMenuItemClick(sender, e);
|
||||
break;
|
||||
case Keys.Subtract: // Ctrl + -
|
||||
case Keys.OemMinus: // Ctrl + -
|
||||
ShrinkCanvasToolStripMenuItemClick(sender, e);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1307,46 +1307,11 @@ namespace Greenshot {
|
|||
private void NotifyIconClick(ClickActions clickAction) {
|
||||
switch (clickAction) {
|
||||
case ClickActions.OPEN_LAST_IN_EXPLORER:
|
||||
string path = _conf.OutputFileAsFullpath;
|
||||
if (!File.Exists(path)) {
|
||||
string lastFilePath = Path.GetDirectoryName(_conf.OutputFileAsFullpath);
|
||||
if (!string.IsNullOrEmpty(lastFilePath) && Directory.Exists(lastFilePath)) {
|
||||
path = lastFilePath;
|
||||
}
|
||||
}
|
||||
if (path == null) {
|
||||
string configPath = FilenameHelper.FillVariables(_conf.OutputFilePath, false);
|
||||
if (Directory.Exists(configPath)) {
|
||||
path = configPath;
|
||||
}
|
||||
}
|
||||
|
||||
if (path != null) {
|
||||
try {
|
||||
// Check if path is a directory
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
using (Process.Start(path))
|
||||
{
|
||||
}
|
||||
}
|
||||
// Check if path is a file
|
||||
else if (File.Exists(path))
|
||||
{
|
||||
// Start the explorer process and select the file
|
||||
using (var explorer = Process.Start("explorer.exe", $"/select,\"{path}\""))
|
||||
{
|
||||
explorer?.WaitForInputIdle(500);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// Make sure we show what we tried to open in the exception
|
||||
ex.Data.Add("path", path);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
Contextmenu_OpenRecent(this, null);
|
||||
break;
|
||||
case ClickActions.OPEN_LAST_IN_EDITOR:
|
||||
_conf.ValidateAndCorrectOutputFileAsFullpath();
|
||||
|
||||
if (File.Exists(_conf.OutputFileAsFullpath)) {
|
||||
CaptureHelper.CaptureFile(_conf.OutputFileAsFullpath, DestinationHelper.GetDestination(EditorDestination.DESIGNATION));
|
||||
}
|
||||
|
@ -1364,25 +1329,40 @@ namespace Greenshot {
|
|||
/// <summary>
|
||||
/// The Contextmenu_OpenRecent currently opens the last know save location
|
||||
/// </summary>
|
||||
private void Contextmenu_OpenRecent(object sender, EventArgs eventArgs) {
|
||||
string path = FilenameHelper.FillVariables(_conf.OutputFilePath, false);
|
||||
// Fix for #1470, problems with a drive which is no longer available
|
||||
try {
|
||||
string lastFilePath = Path.GetDirectoryName(_conf.OutputFileAsFullpath);
|
||||
private void Contextmenu_OpenRecent(object sender, EventArgs eventArgs)
|
||||
{
|
||||
_conf.ValidateAndCorrectOutputFilePath();
|
||||
_conf.ValidateAndCorrectOutputFileAsFullpath();
|
||||
string path = _conf.OutputFileAsFullpath;
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
path = FilenameHelper.FillVariables(_conf.OutputFilePath, false);
|
||||
// Fix for #1470, problems with a drive which is no longer available
|
||||
try
|
||||
{
|
||||
string lastFilePath = Path.GetDirectoryName(_conf.OutputFileAsFullpath);
|
||||
|
||||
if (lastFilePath != null && Directory.Exists(lastFilePath)) {
|
||||
path = lastFilePath;
|
||||
} else if (!Directory.Exists(path)) {
|
||||
// What do I open when nothing can be found? Right, nothing...
|
||||
return;
|
||||
if (lastFilePath != null && Directory.Exists(lastFilePath))
|
||||
{
|
||||
path = lastFilePath;
|
||||
}
|
||||
else if (!Directory.Exists(path))
|
||||
{
|
||||
// What do I open when nothing can be found? Right, nothing...
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Warn("Couldn't open the path to the last exported file, taking default.", ex);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.Warn("Couldn't open the path to the last exported file, taking default.", ex);
|
||||
}
|
||||
LOG.Debug("DoubleClick was called! Starting: " + path);
|
||||
try {
|
||||
Process.Start(path);
|
||||
} catch (Exception ex) {
|
||||
try
|
||||
{
|
||||
ExplorerHelper.OpenInExplorer(path);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Make sure we show what we tried to open in the exception
|
||||
ex.Data.Add("path", path);
|
||||
LOG.Warn("Couldn't open the path to the last exported file", ex);
|
||||
|
|
|
@ -512,22 +512,14 @@ namespace Greenshot.Helpers {
|
|||
string errorMessage = null;
|
||||
var path = Path.GetDirectoryName(surface.LastSaveFullPath);
|
||||
try {
|
||||
if (path != null)
|
||||
{
|
||||
var processStartInfo = new ProcessStartInfo("explorer.exe")
|
||||
{
|
||||
Arguments = path,
|
||||
UseShellExecute = false
|
||||
};
|
||||
using (var process = new Process()) {
|
||||
process.StartInfo = processStartInfo;
|
||||
process.Start();
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ExplorerHelper.OpenInExplorer(path);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorMessage = ex.Message;
|
||||
}
|
||||
// Added fallback for when the explorer can't be found
|
||||
// TODO: Check if this makes sense
|
||||
if (errorMessage != null) {
|
||||
try {
|
||||
string windowsPath = Environment.GetEnvironmentVariable("SYSTEMROOT");
|
||||
|
@ -852,7 +844,7 @@ namespace Greenshot.Helpers {
|
|||
// Restore the window making sure it's visible!
|
||||
windowToCapture.Restore();
|
||||
} else {
|
||||
windowToCapture.ToForeground();
|
||||
windowToCapture.ToForeground(false);
|
||||
}
|
||||
tmpCapture = windowToCapture.CaptureGdiWindow(captureForWindow);
|
||||
if (tmpCapture != null) {
|
||||
|
@ -954,7 +946,7 @@ namespace Greenshot.Helpers {
|
|||
_capture.CaptureDetails.DpiY = graphics.DpiY;
|
||||
}
|
||||
// Set previouslyActiveWindow as foreground window
|
||||
previouslyActiveWindow?.ToForeground();
|
||||
previouslyActiveWindow?.ToForeground(false);
|
||||
if (_capture.CaptureDetails != null) {
|
||||
((Bitmap) _capture.Image)?.SetResolution(_capture.CaptureDetails.DpiX, _capture.CaptureDetails.DpiY);
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@ namespace Greenshot.Experimental {
|
|||
public static class UpdateHelper {
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(UpdateHelper));
|
||||
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
|
||||
private const string StableDownloadLink = "http://getgreenshot.org/downloads/";
|
||||
private const string VersionHistoryLink = "http://getgreenshot.org/version-history/";
|
||||
private const string StableDownloadLink = "https://getgreenshot.org/downloads/";
|
||||
private const string VersionHistoryLink = "https://getgreenshot.org/version-history/";
|
||||
private static readonly object LockObject = new object();
|
||||
private static RssFile _latestGreenshot;
|
||||
private static string _downloadLink = StableDownloadLink;
|
||||
|
|
|
@ -9,6 +9,36 @@ All details to our tickets can be found here: https://greenshot.atlassian.net
|
|||
|
||||
@DETAILVERSION@
|
||||
|
||||
This is Greenshot 1.2.9BF2, the second bugfix release for Greenshot 1.2.9
|
||||
|
||||
The following tickets are on the list for the bugfix release, the current state is not represented in UNSTABLE builds:
|
||||
* BUG-2051 Scroll-lock button not usable as hotkey
|
||||
* BUG-2055 Cannot paste Greenshot capture to Skype
|
||||
* BUG-2056 Cannot export to external command Paint.NET if .greenshot format is used
|
||||
* BUG-2068 Export to Confluence caused System.NullReferenceException
|
||||
* BUG-2081 Canvas resize (Ctrl + / Ctrl -) only works via numpad keys
|
||||
* BUG-2093 Shadow effects not renderingWindows 10 window border frame is not capture correctly on Windows 10
|
||||
* BUG-2095 'Save as' doesn't remember last saved directory (after restart)
|
||||
* BUG-2097 Window border is not captured on Windows 10
|
||||
* BUG-2098 Greenshot opens Explorer when clicking tray while notification is still showing
|
||||
* BUG-2100 ArgumentException when changing the icon size from 16 to 32
|
||||
* BUG-2101 Update to version 1.2.9.112 release -> Error 5 Access is denied
|
||||
* BUG-2102 InvalidOperationException when selecting a color
|
||||
* BUG-2103 ArgumentException when changing the icon size from 16 to 32
|
||||
* BUG-2104 Speechbubble can't be used after copy/paste
|
||||
* BUG-2105 Window border is not captured on Windows 10
|
||||
* BUG-2108 Capture last region doesn't work
|
||||
* BUG-2109 Double-click on textbox causes NullReferenceException
|
||||
* BUG-2110 Missing annotations when opening .greenshot files
|
||||
* BUG-2111 Drag and Drop image file on editor doesn't work
|
||||
* BUG-2114 Storage location reset to default if not available during start
|
||||
* BUG-2115 Error while trying to upload screenshot to Jira
|
||||
* FEATURE-998 The feature "Opening last capture in explorer should select/jump to the file" wasn't available everywhere
|
||||
|
||||
|
||||
1.2.9.112-9bc62ac RELEASE
|
||||
|
||||
|
||||
This is a bugfix release for the Greenshot 1.2.9.104-3721c10 RELEASE
|
||||
|
||||
Bugs fixed:
|
||||
|
|
|
@ -43,33 +43,21 @@ namespace ExternalCommand {
|
|||
_presetCommand = commando;
|
||||
}
|
||||
|
||||
public override string Designation {
|
||||
get {
|
||||
return "External " + _presetCommand.Replace(',','_');
|
||||
}
|
||||
}
|
||||
public override string Designation => "External " + _presetCommand.Replace(',','_');
|
||||
|
||||
public override string Description {
|
||||
get {
|
||||
return _presetCommand;
|
||||
}
|
||||
}
|
||||
public override string Description => _presetCommand;
|
||||
|
||||
public override IEnumerable<IDestination> DynamicDestinations() {
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override Image DisplayIcon {
|
||||
get {
|
||||
return IconCache.IconForCommand(_presetCommand);
|
||||
}
|
||||
}
|
||||
public override Image DisplayIcon => IconCache.IconForCommand(_presetCommand);
|
||||
|
||||
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
|
||||
ExportInformation exportInformation = new ExportInformation(Designation, Description);
|
||||
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings();
|
||||
outputSettings.PreventGreenshotFormat();
|
||||
|
||||
|
||||
if (_presetCommand != null) {
|
||||
if (!config.RunInbackground.ContainsKey(_presetCommand)) {
|
||||
config.RunInbackground.Add(_presetCommand, true);
|
||||
|
@ -154,12 +142,12 @@ namespace ExternalCommand {
|
|||
private int CallExternalCommand(string commando, string fullPath, out string output, out string error) {
|
||||
try {
|
||||
return CallExternalCommand(commando, fullPath, null, out output, out error);
|
||||
} catch (Win32Exception w32ex) {
|
||||
} catch (Win32Exception w32Ex) {
|
||||
try {
|
||||
return CallExternalCommand(commando, fullPath, "runas", out output, out error);
|
||||
} catch {
|
||||
w32ex.Data.Add("commandline", config.Commandline[_presetCommand]);
|
||||
w32ex.Data.Add("arguments", config.Argument[_presetCommand]);
|
||||
w32Ex.Data.Add("commandline", config.Commandline[_presetCommand]);
|
||||
w32Ex.Data.Add("arguments", config.Argument[_presetCommand]);
|
||||
throw;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace GreenshotFlickrPlugin {
|
|||
private const string FLICKR_ACCESS_TOKEN_URL = FLICKR_OAUTH_BASE_URL + "access_token";
|
||||
private const string FLICKR_AUTHORIZE_URL = FLICKR_OAUTH_BASE_URL + "authorize";
|
||||
private const string FLICKR_REQUEST_TOKEN_URL = FLICKR_OAUTH_BASE_URL + "request_token";
|
||||
private const string FLICKR_FARM_URL = "https://farm{0}.staticflickr.com/{1}/{2}_{3}.jpg";
|
||||
private const string FLICKR_FARM_URL = "https://farm{0}.staticflickr.com/{1}/{2}_{3}_o.{4}";
|
||||
// REST
|
||||
private const string FLICKR_REST_URL = FLICKR_API_BASE_URL + "rest/";
|
||||
private const string FLICKR_GET_INFO_URL = FLICKR_REST_URL + "?method=flickr.photos.getInfo";
|
||||
|
@ -131,8 +131,9 @@ namespace GreenshotFlickrPlugin {
|
|||
string farmId = item.Attributes["farm"].Value;
|
||||
string serverId = item.Attributes["server"].Value;
|
||||
string photoId = item.Attributes["id"].Value;
|
||||
string secret = item.Attributes["secret"].Value;
|
||||
return string.Format(FLICKR_FARM_URL, farmId, serverId, photoId, secret);
|
||||
string originalsecret = item.Attributes["originalsecret"].Value;
|
||||
string originalFormat = item.Attributes["originalformat"].Value;
|
||||
return string.Format(FLICKR_FARM_URL, farmId, serverId, photoId, originalsecret, originalFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ using System;
|
|||
using System.Runtime.Caching;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Dapplo.Log.Facade;
|
||||
using Dapplo.Log;
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ namespace GreenshotJiraPlugin.Forms {
|
|||
private readonly JiraConnector _jiraConnector;
|
||||
private Issue _selectedIssue;
|
||||
private readonly GreenshotColumnSorter _columnSorter;
|
||||
private static readonly JiraConfiguration JiraConfig = IniConfig.GetIniSection<JiraConfiguration>();
|
||||
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
|
||||
|
||||
public JiraForm(JiraConnector jiraConnector) {
|
||||
|
@ -161,14 +160,21 @@ namespace GreenshotJiraPlugin.Forms {
|
|||
jiraListView.LargeImageList = imageList;
|
||||
|
||||
foreach (var issue in issues) {
|
||||
var issueIcon = await _jiraConnector.GetIssueTypeBitmapAsync(issue);
|
||||
imageList.Images.Add(issueIcon);
|
||||
|
||||
var item = new ListViewItem
|
||||
{
|
||||
Tag = issue,
|
||||
ImageIndex = imageList.Images.Count - 1
|
||||
Tag = issue
|
||||
};
|
||||
try
|
||||
{
|
||||
var issueIcon = await _jiraConnector.GetIssueTypeBitmapAsync(issue);
|
||||
imageList.Images.Add(issueIcon);
|
||||
item.ImageIndex = imageList.Images.Count - 1;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn("Problem loading issue type, ignoring", ex);
|
||||
}
|
||||
|
||||
item.SubItems.Add(issue.Key);
|
||||
item.SubItems.Add(issue.Fields.Created.ToString("d", DateTimeFormatInfo.InvariantInfo));
|
||||
item.SubItems.Add(issue.Fields.Assignee?.DisplayName);
|
||||
|
|
|
@ -34,32 +34,42 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
|
||||
<ItemGroup>
|
||||
<Reference Include="Dapplo.HttpExtensions, Version=0.5.43.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dapplo.HttpExtensions.0.5.43\lib\net45\Dapplo.HttpExtensions.dll</HintPath>
|
||||
<Reference Include="Dapplo.HttpExtensions, Version=0.6.17.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dapplo.HttpExtensions.0.6.17\lib\net45\Dapplo.HttpExtensions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Dapplo.Jira, Version=0.1.65.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dapplo.Jira.0.1.65\lib\net45\Dapplo.Jira.dll</HintPath>
|
||||
<Reference Include="Dapplo.Jira, Version=0.5.8.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dapplo.Jira.0.5.8\lib\net45\Dapplo.Jira.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Dapplo.Log.Facade, Version=0.5.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dapplo.Log.Facade.0.5.4\lib\net45\Dapplo.Log.Facade.dll</HintPath>
|
||||
<Reference Include="Dapplo.Log, Version=1.0.23.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dapplo.Log.1.0.23\lib\net45\Dapplo.Log.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="log4net">
|
||||
<HintPath>..\Greenshot\Lib\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Svg, Version=2.2.1.38382, Culture=neutral, PublicKeyToken=12a0bac221edeae2, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Svg.2.2.2\lib\net35\Svg.dll</HintPath>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="Svg, Version=2.2.1.39233, Culture=neutral, PublicKeyToken=12a0bac221edeae2, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Svg.2.3.0\lib\net35\Svg.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Runtime.Caching" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Web.Services" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AsyncMemoryCache.cs" />
|
||||
|
@ -94,7 +104,6 @@
|
|||
<Compile Include="LanguageKeys.cs" />
|
||||
<Compile Include="Log4NetLogger.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SvgBitmapHttpContentConverter.cs" />
|
||||
<Compile Include="SvgImage.cs" />
|
||||
<None Include="Languages\language_jiraplugin-de-DE.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
|
|
|
@ -33,11 +33,11 @@ namespace GreenshotJiraPlugin
|
|||
/// </summary>
|
||||
public class IssueTypeBitmapCache : AsyncMemoryCache<IssueType, Bitmap>
|
||||
{
|
||||
private readonly JiraApi _jiraApi;
|
||||
private readonly IJiraClient _jiraClient;
|
||||
|
||||
public IssueTypeBitmapCache(JiraApi jiraApi)
|
||||
public IssueTypeBitmapCache(IJiraClient jiraClient)
|
||||
{
|
||||
_jiraApi = jiraApi;
|
||||
_jiraClient = jiraClient;
|
||||
// Set the expire timeout to an hour
|
||||
ExpireTimeSpan = TimeSpan.FromHours(4);
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ namespace GreenshotJiraPlugin
|
|||
|
||||
protected override async Task<Bitmap> CreateAsync(IssueType issueType, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
return await _jiraApi.GetUriContentAsync<Bitmap>(issueType.IconUri, cancellationToken).ConfigureAwait(false);
|
||||
return await _jiraClient.Server.GetUriContentAsync<Bitmap>(issueType.IconUri, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,19 +24,20 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Dapplo.HttpExtensions;
|
||||
using Dapplo.HttpExtensions.Extensions;
|
||||
using Dapplo.Jira;
|
||||
using Dapplo.Jira.Converters;
|
||||
using Dapplo.Jira.Entities;
|
||||
using Greenshot.IniFile;
|
||||
using GreenshotPlugin.Core;
|
||||
|
||||
namespace GreenshotJiraPlugin {
|
||||
/// <summary>
|
||||
/// This encapsulates the JiraApi to make it possible to change as less old Greenshot code as needed
|
||||
/// This encapsulates the JiraClient to make it possible to change as less old Greenshot code as needed
|
||||
/// </summary>
|
||||
public class JiraConnector : IDisposable {
|
||||
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraConnector));
|
||||
|
@ -47,27 +48,19 @@ namespace GreenshotJiraPlugin {
|
|||
private DateTimeOffset _loggedInTime = DateTimeOffset.MinValue;
|
||||
private bool _loggedIn;
|
||||
private readonly int _timeout;
|
||||
private JiraApi _jiraApi;
|
||||
private IJiraClient _jiraClient;
|
||||
private IssueTypeBitmapCache _issueTypeBitmapCache;
|
||||
private static readonly SvgBitmapHttpContentConverter SvgBitmapHttpContentConverterInstance = new SvgBitmapHttpContentConverter();
|
||||
|
||||
/// <summary>
|
||||
/// Initialize some basic stuff, in the case the SVG to bitmap converter
|
||||
/// </summary>
|
||||
static JiraConnector()
|
||||
{
|
||||
if (HttpExtensionsGlobals.HttpContentConverters.All(x => x.GetType() != typeof(SvgBitmapHttpContentConverter)))
|
||||
{
|
||||
HttpExtensionsGlobals.HttpContentConverters.Add(SvgBitmapHttpContentConverterInstance);
|
||||
}
|
||||
SvgBitmapHttpContentConverterInstance.Width = CoreConfig.IconSize.Width;
|
||||
SvgBitmapHttpContentConverterInstance.Height = CoreConfig.IconSize.Height;
|
||||
CoreConfig.PropertyChanged += (sender, args) =>
|
||||
{
|
||||
if (args.PropertyName == nameof(CoreConfig.IconSize))
|
||||
{
|
||||
SvgBitmapHttpContentConverterInstance.Width = CoreConfig.IconSize.Width;
|
||||
SvgBitmapHttpContentConverterInstance.Height = CoreConfig.IconSize.Height;
|
||||
JiraPlugin.Instance.JiraConnector._jiraClient?.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.IconSize.Width, Height = CoreConfig.IconSize.Height });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -77,7 +70,7 @@ namespace GreenshotJiraPlugin {
|
|||
/// Dispose, logout the users
|
||||
/// </summary>
|
||||
public void Dispose() {
|
||||
if (_jiraApi != null)
|
||||
if (_jiraClient != null)
|
||||
{
|
||||
Task.Run(async () => await LogoutAsync()).Wait();
|
||||
}
|
||||
|
@ -104,25 +97,27 @@ namespace GreenshotJiraPlugin {
|
|||
/// Internal login which catches the exceptions
|
||||
/// </summary>
|
||||
/// <returns>true if login was done sucessfully</returns>
|
||||
private async Task<bool> DoLoginAsync(string user, string password)
|
||||
private async Task<bool> DoLoginAsync(string user, string password, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(password))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_jiraApi = new JiraApi(new Uri(JiraConfig.Url));
|
||||
_issueTypeBitmapCache = new IssueTypeBitmapCache(_jiraApi);
|
||||
_jiraClient = JiraClient.Create(new Uri(JiraConfig.Url));
|
||||
_jiraClient.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.IconSize.Width, Height = CoreConfig.IconSize.Height });
|
||||
|
||||
_issueTypeBitmapCache = new IssueTypeBitmapCache(_jiraClient);
|
||||
LoginInfo loginInfo;
|
||||
try
|
||||
{
|
||||
loginInfo = await _jiraApi.StartSessionAsync(user, password);
|
||||
loginInfo = await _jiraClient.Session.StartAsync(user, password, cancellationToken);
|
||||
Monitor = new JiraMonitor();
|
||||
await Monitor.AddJiraInstanceAsync(_jiraApi);
|
||||
await Monitor.AddJiraInstanceAsync(_jiraClient, cancellationToken);
|
||||
|
||||
var favIconUri = _jiraApi.JiraBaseUri.AppendSegments("favicon.ico");
|
||||
var favIconUri = _jiraClient.JiraBaseUri.AppendSegments("favicon.ico");
|
||||
try
|
||||
{
|
||||
FavIcon = await _jiraApi.GetUriContentAsync<Bitmap>(favIconUri);
|
||||
FavIcon = await _jiraClient.Server.GetUriContentAsync<Bitmap>(favIconUri, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -142,8 +137,8 @@ namespace GreenshotJiraPlugin {
|
|||
/// If there are credentials, call the real login.
|
||||
/// </summary>
|
||||
/// <returns>Task</returns>
|
||||
public async Task LoginAsync() {
|
||||
await LogoutAsync();
|
||||
public async Task LoginAsync(CancellationToken cancellationToken = default(CancellationToken)) {
|
||||
await LogoutAsync(cancellationToken);
|
||||
try {
|
||||
// Get the system name, so the user knows where to login to
|
||||
var credentialsDialog = new CredentialsDialog(JiraConfig.Url)
|
||||
|
@ -151,7 +146,7 @@ namespace GreenshotJiraPlugin {
|
|||
Name = null
|
||||
};
|
||||
while (credentialsDialog.Show(credentialsDialog.Name) == DialogResult.OK) {
|
||||
if (await DoLoginAsync(credentialsDialog.Name, credentialsDialog.Password)) {
|
||||
if (await DoLoginAsync(credentialsDialog.Name, credentialsDialog.Password, cancellationToken)) {
|
||||
if (credentialsDialog.SaveChecked) {
|
||||
credentialsDialog.Confirm(true);
|
||||
}
|
||||
|
@ -181,11 +176,11 @@ namespace GreenshotJiraPlugin {
|
|||
/// <summary>
|
||||
/// End the session, if there was one
|
||||
/// </summary>
|
||||
public async Task LogoutAsync() {
|
||||
if (_jiraApi != null && _loggedIn)
|
||||
public async Task LogoutAsync(CancellationToken cancellationToken = default(CancellationToken)) {
|
||||
if (_jiraClient != null && _loggedIn)
|
||||
{
|
||||
Monitor.Dispose();
|
||||
await _jiraApi.EndSessionAsync();
|
||||
await _jiraClient.Session.EndAsync(cancellationToken);
|
||||
_loggedIn = false;
|
||||
}
|
||||
}
|
||||
|
@ -195,14 +190,14 @@ namespace GreenshotJiraPlugin {
|
|||
/// Do not use ConfigureAwait to call this, as it will move await from the UI thread.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task CheckCredentialsAsync() {
|
||||
private async Task CheckCredentialsAsync(CancellationToken cancellationToken = default(CancellationToken)) {
|
||||
if (_loggedIn) {
|
||||
if (_loggedInTime.AddMinutes(_timeout-1).CompareTo(DateTime.Now) < 0) {
|
||||
await LogoutAsync();
|
||||
await LoginAsync();
|
||||
await LogoutAsync(cancellationToken);
|
||||
await LoginAsync(cancellationToken);
|
||||
}
|
||||
} else {
|
||||
await LoginAsync();
|
||||
await LoginAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,23 +205,24 @@ namespace GreenshotJiraPlugin {
|
|||
/// Get the favourite filters
|
||||
/// </summary>
|
||||
/// <returns>List with filters</returns>
|
||||
public async Task<IList<Filter>> GetFavoriteFiltersAsync()
|
||||
public async Task<IList<Filter>> GetFavoriteFiltersAsync(CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
await CheckCredentialsAsync();
|
||||
return await _jiraApi.GetFavoriteFiltersAsync().ConfigureAwait(false);
|
||||
await CheckCredentialsAsync(cancellationToken);
|
||||
return await _jiraClient.Filter.GetFavoritesAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the issue for a key
|
||||
/// </summary>
|
||||
/// <param name="issueKey">Jira issue key</param>
|
||||
/// <param name="cancellationToken">CancellationToken</param>
|
||||
/// <returns>Issue</returns>
|
||||
public async Task<Issue> GetIssueAsync(string issueKey)
|
||||
public async Task<Issue> GetIssueAsync(string issueKey, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
await CheckCredentialsAsync();
|
||||
await CheckCredentialsAsync(cancellationToken);
|
||||
try
|
||||
{
|
||||
return await _jiraApi.GetIssueAsync(issueKey).ConfigureAwait(false);
|
||||
return await _jiraClient.Issue.GetAsync(issueKey, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -243,12 +239,12 @@ namespace GreenshotJiraPlugin {
|
|||
/// <returns></returns>
|
||||
public async Task AttachAsync(string issueKey, IBinaryContainer content, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
await CheckCredentialsAsync();
|
||||
await CheckCredentialsAsync(cancellationToken);
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
content.WriteToStream(memoryStream);
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
await _jiraApi.AttachAsync(issueKey, memoryStream, content.Filename, content.ContentType, cancellationToken).ConfigureAwait(false);
|
||||
await _jiraClient.Attachment.AttachAsync(issueKey, memoryStream, content.Filename, content.ContentType, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,8 +257,8 @@ namespace GreenshotJiraPlugin {
|
|||
/// <param name="cancellationToken">CancellationToken</param>
|
||||
public async Task AddCommentAsync(string issueKey, string body, string visibility = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
await CheckCredentialsAsync();
|
||||
await _jiraApi.AddCommentAsync(issueKey, body, visibility, cancellationToken).ConfigureAwait(false);
|
||||
await CheckCredentialsAsync(cancellationToken);
|
||||
await _jiraClient.Issue.AddCommentAsync(issueKey, body, visibility, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -273,8 +269,8 @@ namespace GreenshotJiraPlugin {
|
|||
/// <returns></returns>
|
||||
public async Task<IList<Issue>> SearchAsync(Filter filter, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
await CheckCredentialsAsync();
|
||||
var searchResult = await _jiraApi.SearchAsync(filter.Jql, 20, new[] { "summary", "reporter", "assignee", "created", "issuetype" }, cancellationToken).ConfigureAwait(false);
|
||||
await CheckCredentialsAsync(cancellationToken);
|
||||
var searchResult = await _jiraClient.Issue.SearchAsync(filter.Jql, 20, new[] { "summary", "reporter", "assignee", "created", "issuetype" }, cancellationToken).ConfigureAwait(false);
|
||||
return searchResult.Issues;
|
||||
}
|
||||
|
||||
|
@ -292,7 +288,7 @@ namespace GreenshotJiraPlugin {
|
|||
/// <summary>
|
||||
/// Get the base uri
|
||||
/// </summary>
|
||||
public Uri JiraBaseUri => _jiraApi.JiraBaseUri;
|
||||
public Uri JiraBaseUri => _jiraClient.JiraBaseUri;
|
||||
|
||||
/// <summary>
|
||||
/// Is the user "logged in?
|
||||
|
|
|
@ -78,9 +78,17 @@ namespace GreenshotJiraPlugin {
|
|||
{
|
||||
if (_jiraIssue != null)
|
||||
{
|
||||
displayIcon = jiraConnector.GetIssueTypeBitmapAsync(_jiraIssue).Result;
|
||||
// Try to get the issue type as icon
|
||||
try
|
||||
{
|
||||
displayIcon = jiraConnector.GetIssueTypeBitmapAsync(_jiraIssue).Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"Problem loading issue type for {_jiraIssue.Key}, ignoring", ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (displayIcon == null)
|
||||
{
|
||||
displayIcon = jiraConnector.FavIcon;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ using System.Text.RegularExpressions;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Dapplo.Jira;
|
||||
using Dapplo.Log.Facade;
|
||||
using Dapplo.Log;
|
||||
using GreenshotJiraPlugin.Hooking;
|
||||
|
||||
namespace GreenshotJiraPlugin
|
||||
|
@ -42,9 +42,10 @@ namespace GreenshotJiraPlugin
|
|||
private static readonly LogSource Log = new LogSource();
|
||||
private readonly Regex _jiraKeyPattern = new Regex(@"[A-Z][A-Z0-9]+\-[0-9]+");
|
||||
private readonly WindowsTitleMonitor _monitor;
|
||||
private readonly IList<JiraApi> _jiraInstances = new List<JiraApi>();
|
||||
private readonly IDictionary<string, JiraApi> _projectJiraApiMap = new Dictionary<string, JiraApi>();
|
||||
private readonly IList<IJiraClient> _jiraInstances = new List<IJiraClient>();
|
||||
private readonly IDictionary<string, IJiraClient> _projectJiraClientMap = new Dictionary<string, IJiraClient>();
|
||||
private readonly int _maxEntries;
|
||||
// TODO: Add issues from issueHistory (JQL -> Where.IssueKey.InIssueHistory())
|
||||
private IDictionary<string, JiraDetails> _recentJiras = new Dictionary<string, JiraDetails>();
|
||||
|
||||
/// <summary>
|
||||
|
@ -92,10 +93,10 @@ namespace GreenshotJiraPlugin
|
|||
/// Retrieve the API belonging to a JiraDetails
|
||||
/// </summary>
|
||||
/// <param name="jiraDetails"></param>
|
||||
/// <returns>JiraAPI</returns>
|
||||
public JiraApi GetJiraApiForKey(JiraDetails jiraDetails)
|
||||
/// <returns>IJiraClient</returns>
|
||||
public IJiraClient GetJiraClientForKey(JiraDetails jiraDetails)
|
||||
{
|
||||
return _projectJiraApiMap[jiraDetails.ProjectKey];
|
||||
return _projectJiraClientMap[jiraDetails.ProjectKey];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -116,17 +117,17 @@ namespace GreenshotJiraPlugin
|
|||
/// </summary>
|
||||
/// <param name="jiraInstance"></param>
|
||||
/// <param name="token"></param>
|
||||
public async Task AddJiraInstanceAsync(JiraApi jiraInstance, CancellationToken token = default(CancellationToken))
|
||||
public async Task AddJiraInstanceAsync(IJiraClient jiraInstance, CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
_jiraInstances.Add(jiraInstance);
|
||||
var projects = await jiraInstance.GetProjectsAsync(token).ConfigureAwait(false);
|
||||
var projects = await jiraInstance.Project.GetAllAsync(cancellationToken: token).ConfigureAwait(false);
|
||||
if (projects != null)
|
||||
{
|
||||
foreach (var project in projects)
|
||||
{
|
||||
if (!_projectJiraApiMap.ContainsKey(project.Key))
|
||||
if (!_projectJiraClientMap.ContainsKey(project.Key))
|
||||
{
|
||||
_projectJiraApiMap.Add(project.Key, jiraInstance);
|
||||
_projectJiraClientMap.Add(project.Key, jiraInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,10 +142,10 @@ namespace GreenshotJiraPlugin
|
|||
{
|
||||
try
|
||||
{
|
||||
JiraApi jiraApi;
|
||||
if (_projectJiraApiMap.TryGetValue(jiraDetails.ProjectKey, out jiraApi))
|
||||
IJiraClient jiraClient;
|
||||
if (_projectJiraClientMap.TryGetValue(jiraDetails.ProjectKey, out jiraClient))
|
||||
{
|
||||
var issue = await jiraApi.GetIssueAsync(jiraDetails.JiraKey).ConfigureAwait(false);
|
||||
var issue = await jiraClient.Issue.GetAsync(jiraDetails.JiraKey).ConfigureAwait(false);
|
||||
jiraDetails.JiraIssue = issue;
|
||||
}
|
||||
// Send event
|
||||
|
@ -178,9 +179,9 @@ namespace GreenshotJiraPlugin
|
|||
var projectKey = jiraKeyParts[0];
|
||||
var jiraId = jiraKeyParts[1];
|
||||
|
||||
JiraApi jiraApi;
|
||||
IJiraClient jiraClient;
|
||||
// Check if we have a JIRA instance with a project for this key
|
||||
if (_projectJiraApiMap.TryGetValue(projectKey, out jiraApi))
|
||||
if (_projectJiraClientMap.TryGetValue(projectKey, out jiraClient))
|
||||
{
|
||||
// We have found a project for this _jira key, so it must be a valid & known JIRA
|
||||
JiraDetails currentJiraDetails;
|
||||
|
@ -207,8 +208,7 @@ namespace GreenshotJiraPlugin
|
|||
if (_recentJiras.Count > _maxEntries)
|
||||
{
|
||||
// Add it to the list of recent Jiras
|
||||
IList<JiraDetails> clonedList = new List<JiraDetails>(_recentJiras.Values);
|
||||
_recentJiras = (from jiraDetails in clonedList
|
||||
_recentJiras = (from jiraDetails in _recentJiras.Values.ToList()
|
||||
orderby jiraDetails.SeenAt descending
|
||||
select jiraDetails).Take(_maxEntries).ToDictionary(jd => jd.JiraKey, jd => jd);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ using Greenshot.IniFile;
|
|||
using Greenshot.Plugin;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Dapplo.Log.Facade;
|
||||
using Dapplo.Log;
|
||||
using Greenshot.Forms;
|
||||
using Greenshot.Helpers;
|
||||
using GreenshotJiraPlugin.Forms;
|
||||
using GreenshotPlugin.Core;
|
||||
using log4net;
|
||||
|
@ -57,6 +59,22 @@ namespace GreenshotJiraPlugin {
|
|||
|
||||
public JiraPlugin() {
|
||||
_instance = this;
|
||||
// Added to prevent Greenshot from shutting down when there was an exception in a Task
|
||||
TaskScheduler.UnobservedTaskException += (sender, args) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Exception exceptionToLog = args.Exception;
|
||||
string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
|
||||
Log.Error("Exception caught in the UnobservedTaskException handler.");
|
||||
Log.Error(exceptionText);
|
||||
new BugReportForm(exceptionText).ShowDialog();
|
||||
}
|
||||
finally
|
||||
{
|
||||
args.SetObserved();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public IEnumerable<IDestination> Destinations() {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Dapplo.Log.Facade;
|
||||
using Dapplo.Log;
|
||||
using log4net;
|
||||
|
||||
namespace GreenshotJiraPlugin
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2016 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Dapplo.HttpExtensions;
|
||||
using Dapplo.HttpExtensions.ContentConverter;
|
||||
using Dapplo.HttpExtensions.Extensions;
|
||||
using Dapplo.HttpExtensions.Support;
|
||||
using Dapplo.Log.Facade;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace GreenshotJiraPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// This adds SVG image support for the Jira Plugin
|
||||
/// </summary>
|
||||
public class SvgBitmapHttpContentConverter : IHttpContentConverter
|
||||
{
|
||||
private static readonly LogSource Log = new LogSource();
|
||||
private static readonly IList<string> SupportedContentTypes = new List<string>();
|
||||
|
||||
static SvgBitmapHttpContentConverter()
|
||||
{
|
||||
SupportedContentTypes.Add(MediaTypes.Svg.EnumValueOf());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Order => 0;
|
||||
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This checks if the HttpContent can be converted to a Bitmap and is assignable to the specified Type
|
||||
/// </summary>
|
||||
/// <param name="typeToConvertTo">This should be something we can assign Bitmap to</param>
|
||||
/// <param name="httpContent">HttpContent to process</param>
|
||||
/// <returns>true if it can convert</returns>
|
||||
public bool CanConvertFromHttpContent(Type typeToConvertTo, HttpContent httpContent)
|
||||
{
|
||||
if (typeToConvertTo == typeof(object) || !typeToConvertTo.IsAssignableFrom(typeof(Bitmap)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var httpBehaviour = HttpBehaviour.Current;
|
||||
return !httpBehaviour.ValidateResponseContentType || SupportedContentTypes.Contains(httpContent.GetContentType());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<object> ConvertFromHttpContentAsync(Type resultType, HttpContent httpContent, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (!CanConvertFromHttpContent(resultType, httpContent))
|
||||
{
|
||||
var exMessage = "CanConvertFromHttpContent resulted in false, ConvertFromHttpContentAsync is not supposed to be called.";
|
||||
Log.Error().WriteLine(exMessage);
|
||||
throw new NotSupportedException(exMessage);
|
||||
}
|
||||
using (var memoryStream = (MemoryStream) await StreamHttpContentConverter.Instance.ConvertFromHttpContentAsync(typeof(MemoryStream), httpContent, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
Log.Debug().WriteLine("Creating a Bitmap from the SVG.");
|
||||
var svgImage = new SvgImage(memoryStream)
|
||||
{
|
||||
Height = Height,
|
||||
Width = Width
|
||||
};
|
||||
return svgImage.Image;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanConvertToHttpContent(Type typeToConvert, object content)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public HttpContent ConvertToHttpContent(Type typeToConvert, object content)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddAcceptHeadersForType(Type resultType, HttpRequestMessage httpRequestMessage)
|
||||
{
|
||||
if (resultType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(resultType));
|
||||
}
|
||||
if (httpRequestMessage == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpRequestMessage));
|
||||
}
|
||||
if (resultType == typeof(object) || !resultType.IsAssignableFrom(typeof(Bitmap)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
httpRequestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypes.Svg.EnumValueOf()));
|
||||
Log.Debug().WriteLine("Modified the header(s) of the HttpRequestMessage: Accept: {0}", httpRequestMessage.Headers.Accept);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Dapplo.HttpExtensions" version="0.5.43" targetFramework="net45" />
|
||||
<package id="Dapplo.Jira" version="0.1.65" targetFramework="net45" />
|
||||
<package id="Dapplo.Log.Facade" version="0.5.4" targetFramework="net45" />
|
||||
<package id="Dapplo.HttpExtensions" version="0.6.17" targetFramework="net45" />
|
||||
<package id="Dapplo.Jira" version="0.5.8" targetFramework="net45" />
|
||||
<package id="Dapplo.Log" version="1.0.23" targetFramework="net45" />
|
||||
<package id="LibZ.Tool" version="1.2.0.0" targetFramework="net45" />
|
||||
<package id="Svg" version="2.2.2" targetFramework="net45" />
|
||||
<package id="Svg" version="2.3.0" targetFramework="net45" />
|
||||
</packages>
|
|
@ -20,7 +20,6 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
|
@ -48,15 +47,6 @@ namespace GreenshotPlugin.Controls {
|
|||
private static int _hotKeyCounter = 1;
|
||||
private const uint WM_HOTKEY = 0x312;
|
||||
private static IntPtr _hotkeyHwnd;
|
||||
|
||||
// static HotkeyControl() {
|
||||
// StringBuilder keyName = new StringBuilder();
|
||||
// for(uint sc = 0; sc < 500; sc++) {
|
||||
// if (GetKeyNameText(sc << 16, keyName, 100) != 0) {
|
||||
// LOG.DebugFormat("SC {0} = {1}", sc, keyName);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum Modifiers : uint {
|
||||
|
@ -96,8 +86,8 @@ namespace GreenshotPlugin.Controls {
|
|||
|
||||
// ArrayLists used to enforce the use of proper modifiers.
|
||||
// Shift+A isn't a valid hotkey, for instance, as it would screw up when the user is typing.
|
||||
private readonly ArrayList _needNonShiftModifier;
|
||||
private readonly ArrayList _needNonAltGrModifier;
|
||||
private readonly IList<int> _needNonShiftModifier = new List<int>();
|
||||
private readonly IList<int> _needNonAltGrModifier = new List<int>();
|
||||
|
||||
private readonly ContextMenu _dummy = new ContextMenu();
|
||||
|
||||
|
@ -138,9 +128,6 @@ namespace GreenshotPlugin.Controls {
|
|||
KeyUp += HotkeyControl_KeyUp;
|
||||
KeyDown += HotkeyControl_KeyDown;
|
||||
|
||||
// Fill the ArrayLists that contain all invalid hotkey combinations
|
||||
_needNonShiftModifier = new ArrayList();
|
||||
_needNonAltGrModifier = new ArrayList();
|
||||
PopulateModifierLists();
|
||||
}
|
||||
|
||||
|
@ -180,8 +167,6 @@ namespace GreenshotPlugin.Controls {
|
|||
_needNonShiftModifier.Add((int)Keys.Return);
|
||||
_needNonShiftModifier.Add((int)Keys.Escape);
|
||||
_needNonShiftModifier.Add((int)Keys.NumLock);
|
||||
_needNonShiftModifier.Add((int)Keys.Scroll);
|
||||
_needNonShiftModifier.Add((int)Keys.Pause);
|
||||
|
||||
// Ctrl+Alt + 0 - 9
|
||||
for (Keys k = Keys.D0; k <= Keys.D9; k++) {
|
||||
|
|
|
@ -68,6 +68,7 @@ namespace GreenshotPlugin.Controls {
|
|||
ApplyFilterOptions();
|
||||
string initialDirectory = null;
|
||||
try {
|
||||
conf.ValidateAndCorrectOutputFileAsFullpath();
|
||||
initialDirectory = Path.GetDirectoryName(conf.OutputFileAsFullpath);
|
||||
} catch {
|
||||
LOG.WarnFormat("OutputFileAsFullpath was set to {0}, ignoring due to problem in path.", conf.OutputFileAsFullpath);
|
||||
|
@ -90,12 +91,12 @@ namespace GreenshotPlugin.Controls {
|
|||
PrepareFilterOptions();
|
||||
string fdf = "";
|
||||
int preselect = 0;
|
||||
var outputFileFormatAsString = Enum.GetName(typeof(OutputFormat), conf.OutputFileFormat);
|
||||
var outputFileFormatAsString = Enum.GetName(typeof(OutputFormat), conf.OutputFileFormat);
|
||||
for(int i=0; i<_filterOptions.Length; i++){
|
||||
FilterOption fo = _filterOptions[i];
|
||||
fdf += fo.Label + "|*." + fo.Extension + "|";
|
||||
if(outputFileFormatAsString == fo.Extension)
|
||||
preselect = i;
|
||||
if(outputFileFormatAsString == fo.Extension)
|
||||
preselect = i;
|
||||
}
|
||||
fdf = fdf.Substring(0, fdf.Length-1);
|
||||
SaveFileDialog.Filter = fdf;
|
||||
|
|
|
@ -813,10 +813,10 @@ EndSelection:<<<<<<<4
|
|||
string[] dropFileNames = (string[]) dataObject.GetData(DataFormats.FileDrop);
|
||||
if (dropFileNames != null && dropFileNames.Length > 0)
|
||||
{
|
||||
return dropFileNames.Where(filename => !string.IsNullOrEmpty(filename))
|
||||
return dropFileNames
|
||||
.Where(filename => !string.IsNullOrEmpty(filename))
|
||||
.Where(Path.HasExtension)
|
||||
.Select(filename => Path.GetExtension(filename).ToLowerInvariant())
|
||||
.Where(ext => ImageHelper.StreamConverters.Keys.Contains(ext));
|
||||
.Where(filename => ImageHelper.StreamConverters.Keys.Contains(Path.GetExtension(filename).ToLowerInvariant().Substring(1)));
|
||||
}
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
|
|
@ -274,6 +274,9 @@ namespace GreenshotPlugin.Core {
|
|||
[IniProperty("LastCapturedRegion", Description = "The last used region, for reuse in the capture last region")]
|
||||
public Rectangle LastCapturedRegion { get; set; }
|
||||
|
||||
[IniProperty("Win10BorderCrop", Description = "The capture is cropped with these settings, e.g. when you don't want to color around it -1,-1"), DefaultValue("0,0")]
|
||||
public Size Win10BorderCrop { get; set; }
|
||||
|
||||
private Size _iconSize;
|
||||
[IniProperty("IconSize", Description = "Defines the size of the icons (e.g. for the buttons in the editor), default value 16,16 anything bigger will cause scaling", DefaultValue = "16,16")]
|
||||
public Size IconSize {
|
||||
|
@ -350,9 +353,8 @@ namespace GreenshotPlugin.Core {
|
|||
case "OutputFileAsFullpath":
|
||||
if (IniConfig.IsPortable) {
|
||||
return Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots\dummy.png");
|
||||
} else {
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),"dummy.png");
|
||||
}
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),"dummy.png");
|
||||
case "OutputFilePath":
|
||||
if (IniConfig.IsPortable) {
|
||||
string pafOutputFilePath = Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots");
|
||||
|
@ -523,13 +525,27 @@ namespace GreenshotPlugin.Core {
|
|||
if (WebRequestReadWriteTimeout < 1) {
|
||||
WebRequestReadWriteTimeout = 100;
|
||||
}
|
||||
}
|
||||
|
||||
// Added for BUG-1992, reset the OutputFilePath / OutputFileAsFullpath if they don't exist (e.g. the configuration is used on a different PC)
|
||||
/// <summary>
|
||||
/// Validate the OutputFilePath, and if this is not correct it will be set to the default
|
||||
/// Added for BUG-1992, reset the OutputFilePath / OutputFileAsFullpath if they don't exist (e.g. the configuration is used on a different PC)
|
||||
/// </summary>
|
||||
public void ValidateAndCorrectOutputFilePath()
|
||||
{
|
||||
if (!Directory.Exists(OutputFilePath))
|
||||
{
|
||||
OutputFilePath = GetDefault(nameof(OutputFilePath)) as string;
|
||||
}
|
||||
if (!File.Exists(OutputFileAsFullpath))
|
||||
}
|
||||
/// <summary>
|
||||
/// Validate the OutputFileAsFullpath, and if this is not correct it will be set to the default
|
||||
/// Added for BUG-1992, reset the OutputFilePath / OutputFileAsFullpath if they don't exist (e.g. the configuration is used on a different PC)
|
||||
/// </summary>
|
||||
public void ValidateAndCorrectOutputFileAsFullpath()
|
||||
{
|
||||
var outputFilePath = Path.GetDirectoryName(OutputFileAsFullpath);
|
||||
if (outputFilePath == null || (!File.Exists(OutputFileAsFullpath) && !Directory.Exists(outputFilePath)))
|
||||
{
|
||||
OutputFileAsFullpath = GetDefault(nameof(OutputFileAsFullpath)) as string;
|
||||
}
|
||||
|
|
54
GreenshotPlugin/Core/ExplorerHelper.cs
Normal file
54
GreenshotPlugin/Core/ExplorerHelper.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple utility for the explorer
|
||||
/// </summary>
|
||||
public static class ExplorerHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Open the path in the windows explorer.
|
||||
/// If the path is a directory, it will just open the explorer with that directory.
|
||||
/// If the path is a file, the explorer is opened with the directory and the file is selected.
|
||||
/// </summary>
|
||||
/// <param name="path">Path to file or directory</param>
|
||||
public static bool OpenInExplorer(string path)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
// Check if path is a directory
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
using (Process.Start(path))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Check if path is a file
|
||||
else if (File.Exists(path))
|
||||
{
|
||||
// Start the explorer process and select the file
|
||||
using (var explorer = Process.Start("explorer.exe", $"/select,\"{path}\""))
|
||||
{
|
||||
explorer?.WaitForInputIdle(500);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Make sure we show what we tried to open in the exception
|
||||
ex.Data.Add("path", path);
|
||||
throw;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,7 +105,7 @@ namespace GreenshotPlugin.Core {
|
|||
bool useMemoryStream = false;
|
||||
MemoryStream memoryStream = null;
|
||||
if (outputSettings.Format == OutputFormat.greenshot && surface == null) {
|
||||
throw new ArgumentException("Surface needs to be se when using OutputFormat.Greenshot");
|
||||
throw new ArgumentException("Surface needs to be set when using OutputFormat.Greenshot");
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -770,7 +770,7 @@ namespace GreenshotPlugin.Core {
|
|||
{
|
||||
// Somehow DWM doesn't calculate it corectly, there is a 1 pixel border around the capture
|
||||
// Remove this border, currently it's fixed but TODO: Make it depend on the OS?
|
||||
windowRect.Inflate(-1, -1);
|
||||
windowRect.Inflate(Conf.Win10BorderCrop);
|
||||
_previousWindowRectangle = windowRect;
|
||||
_lastWindowRectangleRetrieveTime = now;
|
||||
return windowRect;
|
||||
|
@ -1001,7 +1001,7 @@ namespace GreenshotPlugin.Core {
|
|||
// TODO: Also 8.x?
|
||||
if (Environment.OSVersion.IsWindows10())
|
||||
{
|
||||
captureRectangle.Inflate(-1, -1);
|
||||
captureRectangle.Inflate(Conf.Win10BorderCrop);
|
||||
}
|
||||
|
||||
if (autoMode) {
|
||||
|
@ -1250,11 +1250,13 @@ namespace GreenshotPlugin.Core {
|
|||
size = result ? new Size((int)windowInfo.cxWindowBorders, (int)windowInfo.cyWindowBorders) : Size.Empty;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the window as foreground window
|
||||
/// </summary>
|
||||
public static void ToForeground(IntPtr handle)
|
||||
/// <param name="handle">hWnd of the window to bring to the foreground</param>
|
||||
/// <param name="workaround">bool with true to use a trick to really bring the window to the foreground</param>
|
||||
public static void ToForeground(IntPtr handle, bool workaround = true)
|
||||
{
|
||||
// Do nothing if the window is already in the foreground
|
||||
if (User32.GetForegroundWindow() == handle)
|
||||
|
@ -1266,10 +1268,14 @@ namespace GreenshotPlugin.Core {
|
|||
const int EXTENDEDKEY = 0x1;
|
||||
const int KEYUP = 0x2;
|
||||
|
||||
// Simulate an "ALT" key press.
|
||||
User32.keybd_event(ALT, 0x45, EXTENDEDKEY | 0, 0);
|
||||
// Simulate an "ALT" key release.
|
||||
User32.keybd_event(ALT, 0x45, EXTENDEDKEY | KEYUP, 0);
|
||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms633539(v=vs.85).aspx
|
||||
if (workaround)
|
||||
{
|
||||
// Simulate an "ALT" key press.
|
||||
User32.keybd_event(ALT, 0x45, EXTENDEDKEY | 0, 0);
|
||||
// Simulate an "ALT" key release.
|
||||
User32.keybd_event(ALT, 0x45, EXTENDEDKEY | KEYUP, 0);
|
||||
}
|
||||
|
||||
// Show window in forground.
|
||||
User32.SetForegroundWindow(handle);
|
||||
|
@ -1278,8 +1284,9 @@ namespace GreenshotPlugin.Core {
|
|||
/// <summary>
|
||||
/// Set the window as foreground window
|
||||
/// </summary>
|
||||
public void ToForeground() {
|
||||
ToForeground(Handle);
|
||||
/// <param name="workaround">true to use a workaround, otherwise the window might only flash</param>
|
||||
public void ToForeground(bool workaround = true) {
|
||||
ToForeground(Handle, workaround);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
<Compile Include="Controls\GreenshotRadioButton.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Core\ExplorerHelper.cs" />
|
||||
<Compile Include="Effects\AdjustEffect.cs" />
|
||||
<Compile Include="Effects\BorderEffect.cs" />
|
||||
<Compile Include="Core\CaptureHandler.cs" />
|
||||
|
|
|
@ -98,8 +98,15 @@ namespace Greenshot.Plugin {
|
|||
ReduceColors = reduceColors;
|
||||
}
|
||||
|
||||
public SurfaceOutputSettings PreventGreenshotFormat() {
|
||||
if (Format == OutputFormat.greenshot) {
|
||||
/// <summary>
|
||||
/// BUG-2056 reported a logical issue, using greenshot format as the default causes issues with the external commands.
|
||||
/// </summary>
|
||||
/// <returns>this for fluent API usage</returns>
|
||||
public SurfaceOutputSettings PreventGreenshotFormat()
|
||||
{
|
||||
// If OutputFormat is Greenshot, use PNG instead.
|
||||
if (Format == OutputFormat.greenshot)
|
||||
{
|
||||
Format = OutputFormat.png;
|
||||
}
|
||||
return this;
|
||||
|
|
|
@ -171,11 +171,16 @@ namespace GreenshotPlugin.UnmanagedHelpers {
|
|||
/// </summary>
|
||||
/// <param name="radius"></param>
|
||||
/// <returns>false if blur is not possible</returns>
|
||||
public static bool IsBlurPossible(int radius) {
|
||||
public static bool IsBlurPossible(int radius)
|
||||
{
|
||||
if (!_isBlurEnabled) {
|
||||
return false;
|
||||
}
|
||||
return Environment.OSVersion.Version.Minor < 2 || radius >= 20;
|
||||
if (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor < 2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return Environment.OSVersion.Version.Major > 6 && radius >= 20;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -70,8 +70,11 @@ namespace GreenshotWin10Plugin
|
|||
using (var logoStream = new MemoryRandomAccessStream())
|
||||
using (var thumbnailStream = new MemoryRandomAccessStream())
|
||||
{
|
||||
var outputSettings = new SurfaceOutputSettings();
|
||||
outputSettings.PreventGreenshotFormat();
|
||||
|
||||
// Create capture for export
|
||||
ImageOutput.SaveToStream(surface, imageStream, new SurfaceOutputSettings());
|
||||
ImageOutput.SaveToStream(surface, imageStream, outputSettings);
|
||||
imageStream.Position = 0;
|
||||
Log.Info("Created RandomAccessStreamReference for the image");
|
||||
var imageRandomAccessStreamReference = RandomAccessStreamReference.CreateFromStream(imageStream);
|
||||
|
@ -83,7 +86,7 @@ namespace GreenshotWin10Plugin
|
|||
{
|
||||
using (var thumbnail = ImageHelper.CreateThumbnail(tmpImageForThumbnail, 240, 160))
|
||||
{
|
||||
ImageOutput.SaveToStream(thumbnail, null, thumbnailStream, new SurfaceOutputSettings());
|
||||
ImageOutput.SaveToStream(thumbnail, null, thumbnailStream, outputSettings);
|
||||
thumbnailStream.Position = 0;
|
||||
thumbnailRandomAccessStreamReference = RandomAccessStreamReference.CreateFromStream(thumbnailStream);
|
||||
Log.Info("Created RandomAccessStreamReference for the thumbnail");
|
||||
|
@ -94,7 +97,7 @@ namespace GreenshotWin10Plugin
|
|||
{
|
||||
using (var logoThumbnail = ImageHelper.CreateThumbnail(logo, 30, 30))
|
||||
{
|
||||
ImageOutput.SaveToStream(logoThumbnail, null, logoStream, new SurfaceOutputSettings());
|
||||
ImageOutput.SaveToStream(logoThumbnail, null, logoStream, outputSettings);
|
||||
logoStream.Position = 0;
|
||||
logoRandomAccessStreamReference = RandomAccessStreamReference.CreateFromStream(logoStream);
|
||||
Log.Info("Created RandomAccessStreamReference for the logo");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
version: 1.2.9.{build}
|
||||
branches:
|
||||
only:
|
||||
- release/1.2.9
|
||||
- release/1.2.9BF2
|
||||
skip_tags: true
|
||||
configuration: Release
|
||||
platform: Any CPU
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue