Small fixes, mainly to make the TfsDestination work better.

This commit is contained in:
Robin 2018-04-26 16:00:40 +02:00
commit 62811016ce
9 changed files with 94 additions and 31 deletions

View file

@ -190,6 +190,7 @@
<Compile Include="ViewModels\JiraViewModel.cs" />
<Compile Include="ViewModels\JiraConfigViewModel.cs" />
<None Include="app.config" />
<EmbeddedResource Include="jira.svgz" />
<None Include="Languages\language_jiraplugin-de-DE.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>

View file

@ -126,7 +126,7 @@ namespace Greenshot.Addon.Jira
}
}
IEnumerable<IDestination> DynamicDestinations()
public override IEnumerable<IDestination> DynamicDestinations()
{
if (_jiraConnector == null || !_jiraConnector.IsLoggedIn)
{

Binary file not shown.

View file

@ -34,5 +34,8 @@ namespace Greenshot.Addon.Tfs.Entities
[JsonProperty("System.WorkItemType")]
public string WorkItemType { get; set; }
[JsonProperty("System.State")]
public string State { get; set; }
}
}

View file

@ -23,13 +23,13 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Dapplo.HttpExtensions;
using Dapplo.HttpExtensions.ContentConverter;
using Dapplo.HttpExtensions.Factory;
using Dapplo.HttpExtensions.JsonNet;
using Greenshot.Addon.Tfs.Entities;
@ -59,11 +59,16 @@ namespace Greenshot.Addon.Tfs
_coreConfiguration = coreConfiguration;
_tfsConfiguration = tfsConfiguration;
#if DEBUG
// Set json log threshold high
DefaultJsonHttpContentConverter.Instance.Value.LogThreshold = 0;
#endif
_tfsHttpBehaviour = new HttpBehaviour
{
HttpSettings = networkConfiguration,
JsonSerializer = new JsonNetJsonSerializer()
};
}
public bool CanUpdate => _tfsConfiguration.TfsUri != null && !string.IsNullOrEmpty(_tfsConfiguration.ApiKey);
@ -75,7 +80,7 @@ namespace Greenshot.Addon.Tfs
{
return;
}
var workItems = await GetOwnWorkitems();
var workItems = await GetOwnWorkitems().ConfigureAwait(false);
foreach (var workItem in workItems.Items)
{
WorkItems[workItem.Id] = workItem;
@ -95,14 +100,14 @@ namespace Greenshot.Addon.Tfs
var wiql = new JObject { { "query", "Select [System.Id] FROM WorkItems WHERE [System.AssignedTo] = @me" } };
var queryResult = await client.PostAsync<HttpResponse<WorkItemQueryResult, string>>(workitemsQueryUri, wiql);
var queryResult = await client.PostAsync<HttpResponse<WorkItemQueryResult, string>>(workitemsQueryUri, wiql).ConfigureAwait(false);
if (queryResult.HasError)
{
throw new Exception(queryResult.ErrorResponse);
}
var workItemsUri = apiUri.AppendSegments("wit", "workItems").ExtendQuery("ids", string.Join(",",queryResult.Response.Items.Select(item => item.Id)));
var result = await client.GetAsAsync<HttpResponse<WorkItemList, string>>(workItemsUri);
var result = await client.GetAsAsync<HttpResponse<WorkItemList, string>>(workItemsUri).ConfigureAwait(false);
if (result.HasError)
{
throw new Exception(result.ErrorResponse);
@ -132,7 +137,7 @@ namespace Greenshot.Addon.Tfs
using (var content = new StreamContent(imageStream))
{
content.SetContentType("application/octet-stream");
var createAttachmentresult = await client.PostAsync<HttpResponse<CreateAttachmentResult, string>>(attachmentUri, content);
var createAttachmentresult = await client.PostAsync<HttpResponse<CreateAttachmentResult, string>>(attachmentUri, content).ConfigureAwait(false);
if (createAttachmentresult.HasError)
{
throw new Exception(createAttachmentresult.ErrorResponse);
@ -176,7 +181,7 @@ namespace Greenshot.Addon.Tfs
var content = HttpContentFactory.Create(linkAttachmentRequest);
content.SetContentType("application/json-patch+json");
var result = await client.PatchAsync<HttpResponse<string, string>>(linkAttachmentUri, content);
var result = await client.PatchAsync<HttpResponse<string, string>>(linkAttachmentUri, content).ConfigureAwait(false);
if (result.HasError)
{
throw new Exception(result.ErrorResponse);

View file

@ -65,20 +65,36 @@ namespace Greenshot.Addon.Tfs
_tfsConfiguration = tfsConfiguration;
_tfsLanguage = tfsLanguage;
_tfsClient = tfsClient;
var ignoreTask = _tfsClient.UpdateWorkItems();
}
public TfsDestination(
ITfsConfiguration tfsConfiguration,
ITfsLanguage tfsLanguage,
TfsClient tfsClient, WorkItem workItem) : this(tfsConfiguration, tfsLanguage, tfsClient)
TfsClient tfsClient, WorkItem workItem)
{
_tfsConfiguration = tfsConfiguration;
_tfsLanguage = tfsLanguage;
_tfsClient = tfsClient;
_workItem = workItem;
}
public override bool IsActive => base.IsActive && _tfsClient.CanUpdate;
public override bool UseDynamicsOnly => true;
public override bool IsDynamic => true;
protected override async Task PrepareDynamicDestinations(ToolStripMenuItem destinationToolStripMenuItem)
{
if (!destinationToolStripMenuItem.HasDropDownItems)
{
var oldColor = destinationToolStripMenuItem.BackColor;
destinationToolStripMenuItem.BackColor = Color.DarkGray;
await _tfsClient.UpdateWorkItems();
destinationToolStripMenuItem.BackColor = oldColor;
}
}
public override IEnumerable<IDestination> DynamicDestinations()
{
var workitems = _tfsClient.WorkItems.Values;
@ -96,7 +112,6 @@ namespace Greenshot.Addon.Tfs
}
}
public override string Description
{
get
@ -106,7 +121,8 @@ namespace Greenshot.Addon.Tfs
return _tfsLanguage.UploadMenuItem;
}
// Format the title of this destination
return _workItem.Id + ": " + _workItem.Fields.Title.Substring(0, Math.Min(20, _workItem.Fields.Title.Length));
// TODO: substring?
return $"{_workItem.Fields.WorkItemType} {_workItem.Id}: {_workItem.Fields.Title}";
}
}
@ -123,8 +139,7 @@ namespace Greenshot.Addon.Tfs
}
}
public override async Task<ExportInformation> ExportCaptureAsync(bool manuallyInitiated, ISurface surface,
ICaptureDetails captureDetails)
public override async Task<ExportInformation> ExportCaptureAsync(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
if (_workItem == null)
{
@ -157,7 +172,7 @@ namespace Greenshot.Addon.Tfs
Uri response;
var cancellationTokenSource = new CancellationTokenSource();
using (var pleaseWaitForm = new PleaseWaitForm("OneDrive plug-in", _tfsLanguage.CommunicationWait,
using (var pleaseWaitForm = new PleaseWaitForm("TFS plug-in", _tfsLanguage.CommunicationWait,
cancellationTokenSource))
{
pleaseWaitForm.Show();

View file

@ -4,6 +4,8 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:Greenshot.Addon.Tfs.ViewModels"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:behaviours="http://metro.mahapps.com/winfx/xaml/shared"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance viewModels:TfsConfigViewModel,IsDesignTimeCreatable=False}"
>
@ -13,12 +15,12 @@
<ContentControl x:Name="FileConfigPartViewModel"/>
<CheckBox IsChecked="{Binding TfsConfiguration.AfterUploadLinkToClipBoard}" Content="{Binding TfsLanguage.UsePageLink}"/>
<DockPanel LastChildFill="True">
<Label Content="{Binding TfsLanguage.LabelUrl}" Width="100" />
<TextBox Text="{Binding TfsConfiguration.TfsUri}" />
<Label Content="{Binding TfsLanguage.LabelUrl}" Width="100"/>
<TextBox Text="{Binding TfsConfiguration.TfsUri}" mah:TextBoxHelper.ClearTextButton="True" mah:TextBoxHelper.Watermark="TFS Url"/>
</DockPanel>
<DockPanel LastChildFill="True">
<Label Content="{Binding TfsLanguage.LabelApiKey}" Width="100" />
<TextBox Text="{Binding TfsConfiguration.ApiKey}" />
<PasswordBox behaviours:PasswordBoxBindingBehavior.Password="{Binding TfsConfiguration.ApiKey}" mah:PasswordBoxHelper.RevealButtonContent="{Binding TfsConfiguration.ApiKey}" />
</DockPanel>
</StackPanel>
</GroupBox>

View file

@ -27,6 +27,7 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
@ -64,12 +65,16 @@ namespace Greenshot.Addons.Core
Designation = GetType().GetDesignation();
}
/// <inheritdoc />
public virtual string Designation { get; }
/// <inheritdoc />
public abstract string Description { get; }
/// <inheritdoc />
public virtual Bitmap DisplayIcon { get; set; }
/// <inheritdoc />
public virtual BitmapSource DisplayIconWpf => DisplayIcon?.ToBitmapSource() ?? GetDisplayIcon(DpiHandler.DefaultScreenDpi).ToBitmapSource();
public virtual Bitmap GetDisplayIcon(double dpi)
@ -81,9 +86,33 @@ namespace Greenshot.Addons.Core
public virtual Keys EditorShortcutKeys => Keys.None;
/// <summary>
/// Give a destination a preparation possibility before showing the toolstrip items
/// </summary>
/// <param name="destinationToolStripMenuItem">ToolStripMenuItem</param>
/// <returns>Task</returns>
protected virtual Task PrepareDynamicDestinations(ToolStripMenuItem destinationToolStripMenuItem)
{
return Task.FromResult(true);
}
/// <summary>
/// Get the Dynamic destinations
/// </summary>
/// <returns>IEnumerable of IDestination</returns>
public virtual IEnumerable<IDestination> DynamicDestinations()
{
yield break;
return Enumerable.Empty<IDestination>();
}
/// <summary>
/// Give a destination the possibility to clean up after showing the toolstrip item
/// </summary>
/// <param name="destinationToolStripMenuItem">ToolStripMenuItem</param>
/// <returns>Task</returns>
protected virtual Task AfterDynamicDestinations(ToolStripMenuItem destinationToolStripMenuItem)
{
return Task.FromResult(true);
}
public void Dispose()
@ -91,12 +120,16 @@ namespace Greenshot.Addons.Core
Dispose(true);
}
/// <inheritdoc />
public virtual bool IsDynamic => false;
/// <inheritdoc />
public virtual bool UseDynamicsOnly => false;
/// <inheritdoc />
public virtual bool IsLinkable => false;
/// <inheritdoc />
public virtual bool IsActive => true;
protected virtual ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
@ -140,13 +173,16 @@ namespace Greenshot.Addons.Core
if (IsDynamic && addDynamics)
{
basisMenuItem.DropDownOpening += (sender, args) =>
basisMenuItem.DropDownOpening += async (sender, args) =>
{
if (basisMenuItem.DropDownItems.Count != 0)
{
return;
}
// Give the destination a chance to prepare for the destinations
await PrepareDynamicDestinations(basisMenuItem).ConfigureAwait(true);
var subDestinations = new List<IDestination>();
// Fixing Bug #3536968 by catching the COMException (every exception) and not displaying the "subDestinations"
try
@ -157,7 +193,7 @@ namespace Greenshot.Addons.Core
{
Log.Error().WriteLine("Skipping {0}, due to the following error: {1}", Description, ex.Message);
}
await AfterDynamicDestinations(basisMenuItem).ConfigureAwait(true);
if (subDestinations.Count <= 0)
{
return;
@ -184,6 +220,7 @@ namespace Greenshot.Addons.Core
AddTagEvents(destinationMenuItem, menu, subDestination.Description);
basisMenuItem.DropDownItems.Add(destinationMenuItem);
}
basisMenuItem.ShowDropDown();
}
};
}

View file

@ -29,28 +29,28 @@
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBox x:Name="Filter" />
<TreeView x:Name="TreeItems"
cal:Message.Attach="[Event SelectedItemChanged] = [Action ActivateChildView($this.SelectedItem)]">
<Grid Grid.Column="0" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox x:Name="Filter" Grid.Row="0" mah:TextBoxHelper.ClearTextButton="True" />
<TreeView x:Name="TreeItems" Grid.Row="1" cal:Message.Attach="[Event SelectedItemChanged] = [Action ActivateChildView($this.SelectedItem)]">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
<Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
<Setter Property="Visibility" Value="{Binding IsVisible, Converter={StaticResource BooleanToVisibility}}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Converter={StaticResource AuthenticationTargetPropertyConverter}}"
Value="{x:Static security:AuthenticationTargetProperties.Visibility}">
<DataTrigger Binding="{Binding Converter={StaticResource AuthenticationTargetPropertyConverter}}" Value="{x:Static security:AuthenticationTargetProperties.Visibility}">
<Setter Property="security:AuthenticationVisibility.Permissions" Value="{Binding Permissions}" />
<Setter Property="security:AuthenticationVisibility.WhenPermissions" Value="{Binding WhenPermission}" />
<Setter Property="security:AuthenticationVisibility.WhenPermissionsMissing"
Value="{Binding WhenPermissionMissing}" />
<Setter Property="security:AuthenticationVisibility.WhenPermissionsMissing" Value="{Binding WhenPermissionMissing}" />
</DataTrigger>
<DataTrigger Binding="{Binding Converter={StaticResource AuthenticationTargetPropertyConverter}}"
Value="{x:Static security:AuthenticationTargetProperties.IsEnabled}">
<Setter Property="security:AuthenticationEnabled.Permissions" Value="{Binding Permissions}" />
<Setter Property="security:AuthenticationEnabled.WhenPermissions" Value="{Binding WhenPermission}" />
<Setter Property="security:AuthenticationEnabled.WhenPermissionsMissing"
Value="{Binding WhenPermissionMissing}" />
<Setter Property="security:AuthenticationEnabled.WhenPermissionsMissing" Value="{Binding WhenPermissionMissing}" />
</DataTrigger>
</Style.Triggers>
</Style>
@ -61,7 +61,7 @@
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
</Grid>
<ContentControl x:Name="ActiveItem" Grid.Column="1" Grid.Row="0"/>
<UniformGrid Grid.Column="1" Grid.Row="1" Rows="1" Columns="2">
<Button x:Name="Cancel" Content="{Binding GreenshotLanguage.Cancel}" />