diff --git a/src/Greenshot.Addon.Tfs/Entities/Attributes.cs b/src/Greenshot.Addon.Tfs/Entities/Attributes.cs
new file mode 100644
index 000000000..3238f63f5
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Entities/Attributes.cs
@@ -0,0 +1,34 @@
+#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
+
+using Newtonsoft.Json;
+
+namespace Greenshot.Addon.Tfs.Entities
+{
+ [JsonObject]
+ public class Attributes
+ {
+ [JsonProperty("comment")]
+ public string Comment { get; set; }
+ }
+}
diff --git a/src/Greenshot.Addon.Tfs/Entities/Item.cs b/src/Greenshot.Addon.Tfs/Entities/Item.cs
new file mode 100644
index 000000000..f931b9c12
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Entities/Item.cs
@@ -0,0 +1,41 @@
+#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
+
+using System;
+using Newtonsoft.Json;
+
+namespace Greenshot.Addon.Tfs.Entities
+{
+ ///
+ /// Container for items returned from the api
+ ///
+ [JsonObject]
+ public class CreateAttachmentResult
+ {
+ [JsonProperty("id")]
+ public string id { get; set; }
+
+ [JsonProperty("url")]
+ public Uri Url { get; set; }
+ }
+}
diff --git a/src/Greenshot.Addon.Tfs/Entities/Operation.cs b/src/Greenshot.Addon.Tfs/Entities/Operation.cs
new file mode 100644
index 000000000..4a4de97c4
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Entities/Operation.cs
@@ -0,0 +1,42 @@
+#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
+
+using Newtonsoft.Json;
+
+namespace Greenshot.Addon.Tfs.Entities
+{
+ ///
+ /// Container for a test with Extension data
+ ///
+ [JsonObject]
+ public class Operation
+ {
+ [JsonProperty("op")]
+ public string OperationType { get; set; }
+
+ [JsonProperty("path")]
+ public string Path { get; set; }
+ [JsonProperty("value")]
+ public Value Value { get; set; }
+ }
+}
diff --git a/src/Greenshot.Addon.Tfs/Entities/Value.cs b/src/Greenshot.Addon.Tfs/Entities/Value.cs
new file mode 100644
index 000000000..e541bb75c
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Entities/Value.cs
@@ -0,0 +1,41 @@
+#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
+
+using System;
+using Newtonsoft.Json;
+
+namespace Greenshot.Addon.Tfs.Entities
+{
+ [JsonObject]
+ public class Value
+ {
+ [JsonProperty("rel")]
+ public string Relation { get; set; }
+
+ [JsonProperty("url")]
+ public Uri Url { get; set; }
+
+ [JsonProperty("attributes")]
+ public Attributes Attributes { get; set; }
+ }
+}
diff --git a/src/Greenshot.Addon.Tfs/Entities/WorkItemFields.cs b/src/Greenshot.Addon.Tfs/Entities/WorkItemFields.cs
new file mode 100644
index 000000000..b4650ee70
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Entities/WorkItemFields.cs
@@ -0,0 +1,38 @@
+#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
+
+using System;
+using Newtonsoft.Json;
+
+namespace Greenshot.Addon.Tfs.Entities
+{
+ [JsonObject]
+ public class WorkItemFields
+ {
+ [JsonProperty("System.Title")]
+ public string Title { get; set; }
+
+ [JsonProperty("System.WorkItemType")]
+ public string WorkItemType { get; set; }
+ }
+}
diff --git a/src/Greenshot.Addon.Tfs/Entities/WorkItemList.cs b/src/Greenshot.Addon.Tfs/Entities/WorkItemList.cs
new file mode 100644
index 000000000..ea99559dd
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Entities/WorkItemList.cs
@@ -0,0 +1,37 @@
+#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
+
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Greenshot.Addon.Tfs.Entities
+{
+ [JsonObject]
+ public class WorkItemList
+ {
+ [JsonProperty("count")]
+ public int Count { get; set; }
+ [JsonProperty("value")]
+ public IList Items { get; set; }
+ }
+}
diff --git a/src/Greenshot.Addon.Tfs/Entities/WorkItemQueryResult.cs b/src/Greenshot.Addon.Tfs/Entities/WorkItemQueryResult.cs
new file mode 100644
index 000000000..eaad31eb9
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Entities/WorkItemQueryResult.cs
@@ -0,0 +1,35 @@
+#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
+
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Greenshot.Addon.Tfs.Entities
+{
+ [JsonObject]
+ public class WorkItemQueryResult
+ {
+ [JsonProperty("workItems")]
+ public IList Items { get; set; }
+ }
+}
diff --git a/src/Greenshot.Addon.Tfs/Entities/Workitem.cs b/src/Greenshot.Addon.Tfs/Entities/Workitem.cs
new file mode 100644
index 000000000..62437aff5
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Entities/Workitem.cs
@@ -0,0 +1,44 @@
+#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
+
+using System;
+using Newtonsoft.Json;
+
+namespace Greenshot.Addon.Tfs.Entities
+{
+ [JsonObject]
+ public class WorkItem
+ {
+ [JsonProperty("id")]
+ public long Id { get; set; }
+
+ [JsonProperty("rev")]
+ public int Reversion { get; set; }
+
+ [JsonProperty("url")]
+ public Uri Url { get; set; }
+
+ [JsonProperty("fields")]
+ public WorkItemFields Fields { get; set; }
+ }
+}
diff --git a/src/Greenshot.Addon.Tfs/Greenshot.Addon.Tfs.csproj b/src/Greenshot.Addon.Tfs/Greenshot.Addon.Tfs.csproj
new file mode 100644
index 000000000..9d30ab543
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Greenshot.Addon.Tfs.csproj
@@ -0,0 +1,198 @@
+
+
+
+
+ {8B3643A5-AFED-49FF-8D66-6348FB102EB2}
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Library
+ Greenshot.Addon.Tfs
+ Greenshot.Addon.Tfs
+ v4.5.2
+ Properties
+ False
+ False
+ 4
+ false
+ Always
+
+
+
+ 3.5
+
+
+
+
+
+
+
+
+ {f041c685-eb96-4ed1-9ace-0f5bd836610f}
+ Greenshot.Gfx
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ Greenshot.Addons
+
+
+ ..\packages\Caliburn.Micro.Core.3.2.0\lib\net45\Caliburn.Micro.dll
+
+
+ ..\packages\Caliburn.Micro.3.2.0\lib\net45\Caliburn.Micro.Platform.dll
+
+
+ ..\packages\Caliburn.Micro.3.2.0\lib\net45\Caliburn.Micro.Platform.Core.dll
+
+
+ ..\packages\CommonServiceLocator.2.0.3\lib\net45\CommonServiceLocator.dll
+
+
+ ..\packages\ControlzEx.3.0.2.4\lib\net45\ControlzEx.dll
+
+
+ ..\packages\Dapplo.Addons.0.5.56\lib\net45\Dapplo.Addons.dll
+
+
+ ..\packages\Dapplo.Addons.Bootstrapper.0.5.56\lib\net45\Dapplo.Addons.Bootstrapper.dll
+
+
+ ..\packages\Dapplo.CaliburnMicro.0.5.28\lib\net45\Dapplo.CaliburnMicro.dll
+
+
+ ..\packages\Dapplo.CaliburnMicro.Configuration.0.5.28\lib\net45\Dapplo.CaliburnMicro.Configuration.dll
+
+
+ ..\packages\Dapplo.CaliburnMicro.Dapp.0.5.28\lib\net45\Dapplo.CaliburnMicro.Dapp.dll
+
+
+ ..\packages\Dapplo.CaliburnMicro.Menu.0.5.28\lib\net45\Dapplo.CaliburnMicro.Menu.dll
+
+
+ ..\packages\Dapplo.CaliburnMicro.Security.0.5.28\lib\net45\Dapplo.CaliburnMicro.Security.dll
+
+
+ ..\packages\Dapplo.CaliburnMicro.Translations.0.5.28\lib\net45\Dapplo.CaliburnMicro.Translations.dll
+
+
+ ..\packages\Dapplo.HttpExtensions.0.8.35\lib\net45\Dapplo.HttpExtensions.dll
+
+
+ ..\packages\Dapplo.HttpExtensions.JsonNet.0.8.35\lib\net45\Dapplo.HttpExtensions.JsonNet.dll
+
+
+ ..\packages\Dapplo.Ini.0.5.24\lib\net45\Dapplo.Ini.dll
+
+
+ ..\packages\Dapplo.InterfaceImpl.0.2.12\lib\net45\Dapplo.InterfaceImpl.dll
+
+
+ ..\packages\Dapplo.Language.0.5.24\lib\net45\Dapplo.Language.dll
+
+
+ ..\packages\Dapplo.Log.1.2.1\lib\net45\Dapplo.Log.dll
+
+
+ ..\packages\Dapplo.Utils.1.0.158\lib\net45\Dapplo.Utils.dll
+
+
+ ..\packages\Dapplo.Windows.0.5.54\lib\net45\Dapplo.Windows.dll
+
+
+ ..\packages\Dapplo.Windows.Common.0.5.54\lib\net45\Dapplo.Windows.Common.dll
+
+
+ ..\packages\Dapplo.Windows.DesktopWindowsManager.0.5.54\lib\net45\Dapplo.Windows.DesktopWindowsManager.dll
+
+
+ ..\packages\Dapplo.Windows.Dpi.0.5.54\lib\net45\Dapplo.Windows.Dpi.dll
+
+
+ ..\packages\Dapplo.Windows.Gdi32.0.5.54\lib\net45\Dapplo.Windows.Gdi32.dll
+
+
+ ..\packages\Dapplo.Windows.Input.0.5.54\lib\net45\Dapplo.Windows.Input.dll
+
+
+ ..\packages\Dapplo.Windows.Kernel32.0.5.54\lib\net45\Dapplo.Windows.Kernel32.dll
+
+
+ ..\packages\Dapplo.Windows.Messages.0.5.54\lib\net45\Dapplo.Windows.Messages.dll
+
+
+ ..\packages\Dapplo.Windows.User32.0.5.54\lib\net45\Dapplo.Windows.User32.dll
+
+
+ ..\packages\MahApps.Metro.1.6.1\lib\net45\MahApps.Metro.dll
+
+
+ ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll
+
+
+ ..\packages\System.Reactive.Core.3.1.1\lib\net45\System.Reactive.Core.dll
+ True
+
+
+ ..\packages\System.Reactive.Interfaces.3.1.1\lib\net45\System.Reactive.Interfaces.dll
+ True
+
+
+ ..\packages\System.Reactive.Linq.3.1.1\lib\net45\System.Reactive.Linq.dll
+ True
+
+
+ ..\packages\ControlzEx.3.0.2.4\lib\net45\System.Windows.Interactivity.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+
+
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Addon.Tfs/ITfsConfiguration.cs b/src/Greenshot.Addon.Tfs/ITfsConfiguration.cs
new file mode 100644
index 000000000..c8b9fac76
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/ITfsConfiguration.cs
@@ -0,0 +1,51 @@
+#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.ComponentModel;
+using Dapplo.Ini;
+using Dapplo.Ini.Converters;
+using Dapplo.InterfaceImpl.Extensions;
+using Greenshot.Addons.Core;
+
+#endregion
+
+namespace Greenshot.Addon.Tfs
+{
+ [IniSection("Tfs")]
+ [Description("Greenshot Tfs Addon configuration")]
+ public interface ITfsConfiguration : IIniSection, IDestinationFileConfiguration, ITransactionalProperties, INotifyPropertyChanged
+ {
+ [Description("After upload copy OneDrive link to clipboard.")]
+ [DefaultValue("true")]
+ bool AfterUploadLinkToClipBoard { get; set; }
+
+ [Description("The URI to your TFS system.")]
+ Uri TfsUri { get; set; }
+
+ [TypeConverter(typeof(StringEncryptionTypeConverter))]
+ string ApiKey { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Addon.Tfs/ITfsLanguage.cs b/src/Greenshot.Addon.Tfs/ITfsLanguage.cs
new file mode 100644
index 000000000..a40c99144
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/ITfsLanguage.cs
@@ -0,0 +1,50 @@
+#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.ComponentModel;
+using Dapplo.Language;
+
+#endregion
+
+namespace Greenshot.Addon.Tfs
+{
+ [Language("Tfs")]
+ public interface ITfsLanguage : ILanguage, INotifyPropertyChanged
+ {
+ string CommunicationWait { get; }
+
+ string LabelUrl { get; }
+
+ string LabelApiKey { get; }
+
+ string SettingsTitle { get; }
+
+ string UploadFailure { get; }
+
+ string UploadMenuItem { get; }
+
+ string UsePageLink { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Addon.Tfs/Languages/language_tfsplugin-en-US.xml b/src/Greenshot.Addon.Tfs/Languages/language_tfsplugin-en-US.xml
new file mode 100644
index 000000000..ea4042b8d
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Languages/language_tfsplugin-en-US.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ Communicating with TFS. Please wait...
+ Link Type
+ TFS settings
+ An error occured while uploading to TFS:
+ Upload to TFS
+ Url
+ Api Key
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Addon.Tfs/Properties/AssemblyInfo.cs b/src/Greenshot.Addon.Tfs/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..2b0625fa5
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+#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.Reflection;
+using System.Runtime.InteropServices;
+
+#endregion
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Greenshot.Addon.Tfs")]
+[assembly: AssemblyDescription("A plugin to upload screenshots to Tfs")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot")]
+[assembly: AssemblyProduct("Tfs plugin")]
+[assembly: AssemblyCopyright("Copyright (C) Greenshot 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// This sets the default COM visibility of types in the assembly to invisible.
+// If you need to expose a type to COM, use [ComVisible(true)] on that type.
+
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyInformationalVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
diff --git a/src/Greenshot.Addon.Tfs/TfsClient.cs b/src/Greenshot.Addon.Tfs/TfsClient.cs
new file mode 100644
index 000000000..ed3b7eb40
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/TfsClient.cs
@@ -0,0 +1,186 @@
+#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
+
+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.Factory;
+using Dapplo.HttpExtensions.JsonNet;
+using Greenshot.Addon.Tfs.Entities;
+using Greenshot.Addons.Core;
+using Greenshot.Addons.Extensions;
+using Greenshot.Addons.Interfaces;
+using Newtonsoft.Json.Linq;
+
+namespace Greenshot.Addon.Tfs
+{
+ ///
+ /// This capsulates the TFS api calls
+ ///
+ [Export]
+ public class TfsClient
+ {
+ private readonly ICoreConfiguration _coreConfiguration;
+ private readonly ITfsConfiguration _tfsConfiguration;
+ private readonly HttpBehaviour _tfsHttpBehaviour;
+
+ [ImportingConstructor]
+ public TfsClient(
+ ICoreConfiguration coreConfiguration,
+ ITfsConfiguration tfsConfiguration,
+ INetworkConfiguration networkConfiguration)
+ {
+ _coreConfiguration = coreConfiguration;
+ _tfsConfiguration = tfsConfiguration;
+
+ _tfsHttpBehaviour = new HttpBehaviour
+ {
+ HttpSettings = networkConfiguration,
+ JsonSerializer = new JsonNetJsonSerializer()
+ };
+ }
+
+ public bool CanUpdate => _tfsConfiguration.TfsUri != null && !string.IsNullOrEmpty(_tfsConfiguration.ApiKey);
+ public IDictionary WorkItems { get; } = new Dictionary();
+
+ public async Task UpdateWorkItems()
+ {
+ if (!CanUpdate)
+ {
+ return;
+ }
+ var workItems = await GetOwnWorkitems();
+ foreach (var workItem in workItems.Items)
+ {
+ WorkItems[workItem.Id] = workItem;
+ }
+ }
+ ///
+ /// Retrieve the own workitems
+ ///
+ /// WorkItemList
+ public async Task GetOwnWorkitems()
+ {
+ _tfsHttpBehaviour.MakeCurrent();
+ Uri apiUri = _tfsConfiguration.TfsUri.AppendSegments("_apis").ExtendQuery("api-version", "3.0");
+ var client = HttpClientFactory.Create(_tfsConfiguration.TfsUri).SetBasicAuthorization("", _tfsConfiguration.ApiKey);
+
+ var workitemsQueryUri = apiUri.AppendSegments("wit", "wiql");
+
+ var wiql = new JObject { { "query", "Select [System.Id] FROM WorkItems WHERE [System.AssignedTo] = @me" } };
+
+ var queryResult = await client.PostAsync>(workitemsQueryUri, wiql);
+ 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>(workItemsUri);
+ if (result.HasError)
+ {
+ throw new Exception(result.ErrorResponse);
+ }
+
+ return result.Response;
+ }
+
+ ///
+ /// See here
+ ///
+ /// ISurface to attach
+ ///
+ public async Task CreateAttachment(ISurface surface)
+ {
+ _tfsHttpBehaviour.MakeCurrent();
+
+ var client = HttpClientFactory.Create(_tfsConfiguration.TfsUri).SetBasicAuthorization("", _tfsConfiguration.ApiKey);
+ Uri apiUri = _tfsConfiguration.TfsUri.AppendSegments("_apis").ExtendQuery("api-version", "3.0");
+
+ var filename = surface.GenerateFilename(_coreConfiguration, _tfsConfiguration);
+ var attachmentUri = apiUri.AppendSegments("wit", "attachments").ExtendQuery("fileName", filename);
+ using (var imageStream = new MemoryStream())
+ {
+ surface.WriteToStream(imageStream, _coreConfiguration, _tfsConfiguration);
+ imageStream.Position = 0;
+ using (var content = new StreamContent(imageStream))
+ {
+ content.SetContentType("application/octet-stream");
+ var createAttachmentresult = await client.PostAsync>(attachmentUri, content);
+ if (createAttachmentresult.HasError)
+ {
+ throw new Exception(createAttachmentresult.ErrorResponse);
+ }
+ return createAttachmentresult.Response;
+ }
+ }
+ }
+
+ ///
+ /// Link the WorkItem and the attachment that was created
+ ///
+ /// WorkItem
+ /// CreateAttachmentResult
+ /// string with optional comment
+ public async Task LinkAttachment(WorkItem workItem, CreateAttachmentResult attachmentResult, string comment = "Attached screenshot from Greenshot")
+ {
+ _tfsHttpBehaviour.MakeCurrent();
+ var client = HttpClientFactory.Create(_tfsConfiguration.TfsUri).SetBasicAuthorization("", _tfsConfiguration.ApiKey);
+
+ Uri apiUri = _tfsConfiguration.TfsUri.AppendSegments("_apis").ExtendQuery("api-version", "3.0");
+ // https://docs.microsoft.com/en-us/rest/api/vsts/wit/work%20items/update#add_an_attachment
+ var linkAttachmentUri = apiUri.AppendSegments("wit", "workItems", workItem.Id);
+ var linkAttachmentRequest = new List
+ {
+ new Operation
+ {
+ OperationType = "add",
+ Path = "/relations/-",
+ Value = new Value
+ {
+ Relation = "AttachedFile",
+ Url = attachmentResult.Url,
+ Attributes = new Attributes
+ {
+ Comment = comment
+ }
+ }
+ }
+ };
+
+ var content = HttpContentFactory.Create(linkAttachmentRequest);
+ content.SetContentType("application/json-patch+json");
+ var result = await client.PatchAsync>(linkAttachmentUri, content);
+ if (result.HasError)
+ {
+ throw new Exception(result.ErrorResponse);
+ }
+ }
+ }
+}
diff --git a/src/Greenshot.Addon.Tfs/TfsDestination.cs b/src/Greenshot.Addon.Tfs/TfsDestination.cs
new file mode 100644
index 000000000..115ffac57
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/TfsDestination.cs
@@ -0,0 +1,193 @@
+#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.ComponentModel.Composition;
+using System.Drawing;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Dapplo.Addons.Bootstrapper.Resolving;
+using Dapplo.Log;
+using Greenshot.Addon.Tfs.Entities;
+using Greenshot.Addons.Addons;
+using Greenshot.Addons.Controls;
+using Greenshot.Addons.Core;
+using Greenshot.Addons.Interfaces;
+using Greenshot.Gfx;
+
+#endregion
+
+namespace Greenshot.Addon.Tfs
+{
+ ///
+ /// Description of OneDriveDestination.
+ ///
+ [Destination("Tfs")]
+ public class TfsDestination : AbstractDestination
+ {
+ private static readonly LogSource Log = new LogSource();
+ private readonly ITfsConfiguration _tfsConfiguration;
+ private readonly ITfsLanguage _tfsLanguage;
+ private readonly TfsClient _tfsClient;
+ private readonly WorkItem _workItem;
+
+ [ImportingConstructor]
+ public TfsDestination(
+ ITfsConfiguration tfsConfiguration,
+ ITfsLanguage tfsLanguage,
+ TfsClient tfsClient)
+ {
+ _tfsConfiguration = tfsConfiguration;
+ _tfsLanguage = tfsLanguage;
+ _tfsClient = tfsClient;
+ var ignoreTask = _tfsClient.UpdateWorkItems();
+ }
+
+ public TfsDestination(
+ ITfsConfiguration tfsConfiguration,
+ ITfsLanguage tfsLanguage,
+ TfsClient tfsClient, WorkItem workItem) : this(tfsConfiguration, tfsLanguage, tfsClient)
+ {
+ _workItem = workItem;
+ }
+
+ public override bool IsActive => base.IsActive && _tfsClient.CanUpdate;
+ public override bool IsDynamic => true;
+
+ public override IEnumerable DynamicDestinations()
+ {
+ var workitems = _tfsClient.WorkItems.Values;
+ if (workitems.Count == 0)
+ {
+ yield break;
+ }
+ foreach (var workitem in workitems)
+ {
+ yield return new TfsDestination(_tfsConfiguration, _tfsLanguage, _tfsClient, workitem)
+ {
+ CoreConfiguration = CoreConfiguration,
+ GreenshotLanguage = GreenshotLanguage
+ };
+ }
+ }
+
+
+ public override string Description
+ {
+ get
+ {
+ if (_workItem?.Fields?.Title == null)
+ {
+ return _tfsLanguage.UploadMenuItem;
+ }
+ // Format the title of this destination
+ return _workItem.Id + ": " + _workItem.Fields.Title.Substring(0, Math.Min(20, _workItem.Fields.Title.Length));
+ }
+ }
+
+ public override Bitmap DisplayIcon
+ {
+ get
+ {
+ // TODO: Optimize this
+ var embeddedResource = GetType().Assembly.FindEmbeddedResources(@".*vsts\.png").FirstOrDefault();
+ using (var bitmapStream = GetType().Assembly.GetEmbeddedResourceAsStream(embeddedResource))
+ {
+ return BitmapHelper.FromStream(bitmapStream);
+ }
+ }
+ }
+
+ public override async Task ExportCaptureAsync(bool manuallyInitiated, ISurface surface,
+ ICaptureDetails captureDetails)
+ {
+ if (_workItem == null)
+ {
+ return new ExportInformation(Designation, Description)
+ {
+ ExportMade = false
+ };
+ }
+ var uploadUrl = await Upload(_workItem, surface);
+
+ var exportInformation = new ExportInformation(Designation, Description)
+ {
+ ExportMade = uploadUrl != null,
+ Uri = uploadUrl?.AbsoluteUri
+ };
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+
+ ///
+ /// Upload the capture to Tfs
+ ///
+ /// WorkItem
+ /// ISurface
+ /// Uri
+ private async Task Upload(WorkItem workItem, ISurface surfaceToUpload)
+ {
+ try
+ {
+ Uri response;
+
+ var cancellationTokenSource = new CancellationTokenSource();
+ using (var pleaseWaitForm = new PleaseWaitForm("OneDrive plug-in", _tfsLanguage.CommunicationWait,
+ cancellationTokenSource))
+ {
+ pleaseWaitForm.Show();
+ try
+ {
+ var result = await _tfsClient.CreateAttachment(surfaceToUpload);
+ await _tfsClient.LinkAttachment(workItem, result);
+ response = result.Url;
+ }
+ finally
+ {
+ pleaseWaitForm.Close();
+ }
+ }
+
+ if (_tfsConfiguration.AfterUploadLinkToClipBoard)
+ {
+ ClipboardHelper.SetClipboardData(response.ToString());
+ }
+
+ return response;
+ }
+ catch (Exception e)
+ {
+ Log.Error().WriteLine(e, "Error uploading.");
+ MessageBox.Show(_tfsLanguage.UploadFailure + " " + e.Message);
+ }
+
+ return null;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Addon.Tfs/ViewModels/TfsConfigViewModel.cs b/src/Greenshot.Addon.Tfs/ViewModels/TfsConfigViewModel.cs
new file mode 100644
index 000000000..01dc30ba7
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/ViewModels/TfsConfigViewModel.cs
@@ -0,0 +1,84 @@
+#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
+
+using System.ComponentModel.Composition;
+using System.Reactive.Disposables;
+using Dapplo.CaliburnMicro.Configuration;
+using Dapplo.CaliburnMicro.Extensions;
+using Greenshot.Addons;
+using Greenshot.Addons.Core;
+using Greenshot.Addons.ViewModels;
+
+namespace Greenshot.Addon.Tfs.ViewModels
+{
+ [Export(typeof(IConfigScreen))]
+ public sealed class TfsConfigViewModel : SimpleConfigScreen
+ {
+ ///
+ /// Here all disposables are registered, so we can clean the up
+ ///
+ private CompositeDisposable _disposables;
+
+ [Import]
+ public ITfsConfiguration TfsConfiguration { get; set; }
+
+ [Import]
+ public ITfsLanguage TfsLanguage { get; set; }
+
+ [Import]
+ public IGreenshotLanguage GreenshotLanguage { get; set; }
+
+ [Import]
+ public TfsClient TfsClient { get; private set; }
+
+ [Import]
+ public FileConfigPartViewModel FileConfigPartViewModel { get; private set; }
+
+ public override void Initialize(IConfig config)
+ {
+ FileConfigPartViewModel.DestinationFileConfiguration = TfsConfiguration;
+ // Prepare disposables
+ _disposables?.Dispose();
+
+ // Place this config viewmodel under the Destinations parent
+ ParentId = nameof(ConfigIds.Destinations);
+
+ // Make sure Commit/Rollback is called on the IUiConfiguration
+ config.Register(TfsConfiguration);
+
+ // automatically update the DisplayName
+ _disposables = new CompositeDisposable
+ {
+ TfsLanguage.CreateDisplayNameBinding(this, nameof(ITfsLanguage.SettingsTitle))
+ };
+ base.Initialize(config);
+ }
+
+ protected override void OnDeactivate(bool close)
+ {
+ var ignoreTask = TfsClient.UpdateWorkItems();
+ _disposables.Dispose();
+ base.OnDeactivate(close);
+ }
+ }
+}
diff --git a/src/Greenshot.Addon.Tfs/Views/TfsConfigView.xaml b/src/Greenshot.Addon.Tfs/Views/TfsConfigView.xaml
new file mode 100644
index 000000000..b59065d63
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/Views/TfsConfigView.xaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Greenshot.Addon.Tfs/packages.config b/src/Greenshot.Addon.Tfs/packages.config
new file mode 100644
index 000000000..4062a4b64
--- /dev/null
+++ b/src/Greenshot.Addon.Tfs/packages.config
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Addon.Tfs/vsts.png b/src/Greenshot.Addon.Tfs/vsts.png
new file mode 100644
index 000000000..8b3d8c1ef
Binary files /dev/null and b/src/Greenshot.Addon.Tfs/vsts.png differ
diff --git a/src/Greenshot.sln b/src/Greenshot.sln
index c055c88e0..344ab6436 100644
--- a/src/Greenshot.sln
+++ b/src/Greenshot.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.27130.2036
+VisualStudioVersion = 15.0.27130.2027
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greenshot", "Greenshot\Greenshot.csproj", "{CD642BF4-D815-4D67-A0B5-C69F0B8231AF}"
EndProject
@@ -50,6 +50,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greenshot.Gfx.Experimental"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greenshot.Addon.OneDrive", "Greenshot.Addon.OneDrive\Greenshot.Addon.OneDrive.csproj", "{B35272D3-4631-4FA5-9A3E-85D70ECA9A8D}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greenshot.Addon.Tfs", "Greenshot.Addon.Tfs\Greenshot.Addon.Tfs.csproj", "{8B3643A5-AFED-49FF-8D66-6348FB102EB2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -222,6 +224,14 @@ Global
{B35272D3-4631-4FA5-9A3E-85D70ECA9A8D}.Release|Any CPU.Build.0 = Release|Any CPU
{B35272D3-4631-4FA5-9A3E-85D70ECA9A8D}.Release|x86.ActiveCfg = Release|x86
{B35272D3-4631-4FA5-9A3E-85D70ECA9A8D}.Release|x86.Build.0 = Release|x86
+ {8B3643A5-AFED-49FF-8D66-6348FB102EB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8B3643A5-AFED-49FF-8D66-6348FB102EB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8B3643A5-AFED-49FF-8D66-6348FB102EB2}.Debug|x86.ActiveCfg = Debug|x86
+ {8B3643A5-AFED-49FF-8D66-6348FB102EB2}.Debug|x86.Build.0 = Debug|x86
+ {8B3643A5-AFED-49FF-8D66-6348FB102EB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8B3643A5-AFED-49FF-8D66-6348FB102EB2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8B3643A5-AFED-49FF-8D66-6348FB102EB2}.Release|x86.ActiveCfg = Release|x86
+ {8B3643A5-AFED-49FF-8D66-6348FB102EB2}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE