)Bly7
zfH4I@K)ZnFya8`M&^{o(1l{F75E5Si-M<6p7N!rA|5ua$v$X%sAC&;D-SYoSra$$6
z=mA*&HHG^Bd-eJ3^Lr6f5Ck}HAmrSEz7k&mJ*A`d#NPDbgZn`LRmqPoozG7GXHEa1
zS=BG^nYb8d9V`9cqW_Ud|NkKUKI*!o|7$t`bpgl67XB>fRFPZZKa2&A*fxZM0@daWpU<`qm{%aKfcZL2BX!8F7>Hv8EKfrfC;DOHd
z|7#E6{oi~14}B;NnyC1H7jNo(dKGD%?tW>nebBK7h~JQ4&-nvFb1xP-5FA$^XBKwa
zj~v^8@+Xnl0?R%?KLXeSI)wjwl>T#||B?Q4dzSwDApg1l4?S>U+lAiI|M5Iipu6G=
zB&I-}UFfkHw4H5opE)T00XmLhAE3PeF;X3EXPdG9JD6It2J1hpo#Vc1S#G_O|K$IX
zu>Vs358(e^q(607=m86{N1qx0A5*{Q9(x#s>HkVEl=B9>^+d!M@R?zL<(6-GYhX-)
z?pF|IAK-JiM-3g2=i8_G?FxRsBzygz>wla6FN6NCdFYRP^UJXRd@1yAcj(`{`u|7D
zhT}eO!0S)oA74P50qKH$*uZ(fvj^(y{rv~@c!Mze0DTC&^v8FvdXWA@dPV;4hy14u
zQ~cl78W{f{cb`ABT#)WB*X^?g{OSmeFA$#su>*Lq^9_R-=MzT67eM##!1oQ(HQ;}K
z(jJ?0t9^^X!>%RxN_A{AphFn-XhxC82$KU^mV^jYBd-vk~fA-7O
z|D)^)-De-@dVB%S6zFI@xi4LFXg}x=`Jb)+-{i;NJ01>!G29|ENt9L4(oM5RXm
zEcL$yBl{Ttd+6Us^#3To0J!b{Dj@z+5klU&xQO)xt`Yl_wRSp|4Y~ZqwEXdZ->Sj&&xF(%N!8fpg)d|
zFA$r69aGZF^dFLyewmFf%CZOc?^pW&zI}V4|F`tY{=ew{#G(3s)O{bn0d;nv=eq6_
z;ForM1ay0VH*J5v0Ot#Iw4H0l`tML`E!Tfp>;I7dS@D0*)1Nvl=})~DY4`bmUVXfa
z`7Z1KF`h@=FU+@``?mDo4+Gr};FsoEh}4NOM*Id|n%}ovhwqy5o448U-1_;X|3mir
zAHE;2JwzP<^8X>qe!xRm|KA7y56b_CApd)Z{`>dsbJ4%=>Hl7PfR(4sfNc$w^A}VT%5JSpWC42{_kiKM)&$AGZAp0{sWFun$1@
z@4z<@)1?1;MgJ`Qe;oeD`R*_G0scR*U+Mp(e_z-C!|elmyU~9j*gk-`fsVFQ`_r|D
z4}kuV|CcXxQT~JeuYmr4^~itZn_q$apEKB!|8sj-{vSA?^nXSFYe4@OJAi|s+bh3v
z(Hk`VfVu$p5P9~1?n9va4~RX$i@o-N&hHoO?r1w%rO`iI{||Zp_fh&^Bl^GC2k0|E
z-vNm&Q2W--9I)&HCvf(FuJ^}H>-GWd`vn&LYYwK?ufzNQa#!g8FxG#hKlXn9`Y_jk
zSpPlDwV%m6<$}fk55xZ3v;2S1=Klkf|9xTqU-&o+?CVS5%mGUVxO@pb{saDYflfan
zfzbc*
z<*TFr>l**Rj`u%oKP|80{ZAVZ^3MAo<<`#~oRxl&jV+304;?(9_Wuta0RLah`oH)P
z_+haLbTz&}>;v#CfbI|eZ&mc)p!h#q{U7|_r|5rB>HnnvwXXk%#TL+Z&>j8*_--Ne
z{{!hdtp7Lg{eL<0`@dm4xSsF-*B|M8|G)kSbpY`HBV7A~{~rPWKVYr@QLg9tAN0rf
z-=GIv6Z`*;-j98MmGW
zJ@m)eeYyVsS?K-3-$L&oEaemqvkTy!vJ(W@2k1|LcoLic52fC_4(N|KMz#Nsb>MZQ
z|BHV?q;El#ZGhi8)a(N)eYUCN()pw5`nsCbdmA=D|IhOLXXpJN!T+-dE#x|3{hXd%
z|C9dI|4ILAasNM#{!iP3*da1-s9iv82G;irxW^0|KnDQyuLu3#>ze-m`lDF?f&Tvu
z-{03C#rp3Ntp6Ux`VVVBHlbtum3vff6zt$>remp_aBJ+eM33Fko1SYNzc
z@jvL_)BJxJ{Ez+rLkCI!zU%+*?Da#J&q({}{Q5P&|9Gy2#utd)0RMsR-+{7e_>-jG
zfA78IC!b{N|HJiv4F2y$`ZNBY^k-Zf(t+Rq3*Udw{9a&Y`JmW;UXSzturgO)cP#tB
ziK>qFmV@bry2BRzuVnfCAAHX{7X9b+lKek>Sn2;3{Tutd|G((*4$e~lcm5~#0}l?e
z4>;d1I9}e-4jv)>Hj`2lc4^7jaA${ST4p}nbyGZ{x9<$ef@cnt?F|Gm4mNy>b+RtRZ`IQG@{{#P{-1@n_Lx03GEBase
z`hS#tA;dnQ{E3AB>uW&&_q)dbeT@Fx|A!v1u>D%|{}0&zkFEdv{NH6W@Yn~`Ifdt%
zJ1$>1mOj!@m-=8M=>Kt+=RfoP-^b`r{h##5Ir`U}|Nm9%|55%8wtYapUtsBfS3v&;
z(0?P=|DR;_e&+YwE&30K{{Q96|Js_v%Kqb}|5s1{54R6c|K~Y{(EXwRUuX1({*QPj
z@c&m=|Ie@~_}B+vC&Bj%T01_v+^+b4)5Z_Fp#R6^|AD=-{;RF2QTzX-fBRQl|Btpo
zAjaTib;qUC2h&He{@X(I5N&7X5Sje~^8^IltgUdB>%ey&CL1yMgIoy{|Ds%>xBL_7X82S`hSRhfc^!rk16^$g8rMkME~Jf|HqL3y~h8w
zYX2X4z`{!xud(=lAN^f)e`1#|-%WYM4|H6)cr4v`q&~HI6V`t|`v2l-Lyi0=h8n~w
zJ#7f^V89?__3WXE{V(DBpZLC4==*>6fQ9@2-^9e~nf()se{#FA_$Rj+`GCbgzQtJl
zFW*4=R)xcS4ddLatF2Y~AJzd2q4VYR{{VY{#4kYi>wvuk^gjanZwl1^SI@c2ST=LG
zv0~PU#G(IqAaU~b$qB6O5(ocq-wmhUm~z89uK!+rB;E4H6s`fW{+q(JA90%VVjcLO
zM_}RCUOaArtB>2BS`2P;@|JS>X|Leg2(En>|!T&t}^GaKqd*Re|qjch|@9TT=
zerb=+9lL(Ny7X&Zt=IcM)T#9UEA8Nap?~K7Kk2{x$>B!+w4tMx&KS1h!{^5}?0#`V
zQ`w6XQsp*O{C+~~@z);h0KEx1{X2NQ;>B^T<-ffZLjQ4-P
zC0P6A|HN7c#-VXonGE{p_Wv_t1!xoS>i>%W1L)83E}S{cSTkp&0oo@vJ~O6Y(afP!
zFb66i2R;K$DFYljBMtih6V`uR19V~wCC?14DEj$#rfi%)upj0?V$JmL8Ngv=
zjeXBce_j8lzMBL07>NE){@=10>wh2qm%)eZ#~c`eIWPosU^M2y;3*})8iP6TuxAeZ
z6XpWxPi)b@llH?Zil%-Sv>(*3@bPaY*39TW+OwSvkpJBOudl7m>Hjfo1fu^p9cf5y
zDZ%>RNB8~1O0XVKO~+$EY|vZzbE=%Q)46OU*fC(d5KauV=(5xFwB8LiH%Q>#2gqnrR0~K
z1AG@y|0mB2?WaKIKm1wAv%_t^9}K?#4ru=aqww+Wr9Io3qkr(Z5q@)7r~ijB>CbU4
zd}5%nW)|ka69X^@?!p`xfH^SAnFA*=2RIij+K;Fxn)dxE8y5`eSNL<%{*E4@y-j}u
z{WQS;&x8NJK>7>2kF;~;z%vFI8`?;}z;`E_KismVKm3075(Ac^f}U>qkn1O9Qcd@
zY0ojjxuZ>_|EHgRn$@s_{~-rB2l}fyuxxt&DVu*evi#70-2d_BXGfGT6WUMxUSiEJ
z`Wu)7S=FCyVeI=Gr(0T#nnQ;wEma_gMjbk`R@G+r{3|{${GFNE}Z&<
z$JWomI)Cc-ZQ6H_jX$h``2L51vp)=c2j&)>0hV;ZzI{pDcL3iCOX52b4&a+HNeilg
ztCIMJB%soQ%E~0ZDQ&}^WaS=#3ZwxQ70Epc%7M$173BhD$%?YFWVr*olV!Vg*p=M9
zONY|ru2MIYBHsx+lchU5Vdst=Nr4?m@7TWG1>3i6OA2g5dfV2m4s88!YjW#{9|E=}
zLHj#OHgCQW>9FAqya(DFYo5d$c%r|7GyZNYns&!6IP2p^(B4pd58NBSBMtQiWf<%L
z2HtH6q!aXMCC)+S7|7T(H#H?7|BcT+`>e}k0>2vtKmUQT6!_iQ0~1S;E_nRA2Cw(l
zkNmG-?_LAE?S|@V1AOfO_}c(~I{^MREZ76Q#{iE5DlDj|Fu>n7lpEl08_IwIWn~6<
z9I#sfc-*jHmr=HBmjNEPq0|6>Yp~M*KWnhV06%N6-2hKJuzmYB1N`g&_}LKHiZuAy
z1*ECK7No)F4wP&zF~IWx;7yyH^wrX8@lU^t{e1v%?w1>Z+z8}GAU6WJ5y*`|ZUk~8
zkQ;&A2;@c}Hv+j4$c;d51iCT;=Jod5BBOAlX_laKizJ^g&4KRx7hiMdKfz!0@~!ww
zhy2|z%x1%#-(oCu-Ctx(cI6FYpq@unx9a&X4C8B8llRt_(LQf`b9p!Ya^sO3k1+nu
z&5vH4A6|Kut$g(U-
+
@@ -53,6 +54,7 @@
+
diff --git a/Plugins/Discord/source/Plugin.Discord/Properties/AssemblyInfo.cs b/Plugins/Discord/source/Plugin.Discord/Properties/AssemblyInfo.cs
index 6cfb03ee..d7975adb 100644
--- a/Plugins/Discord/source/Plugin.Discord/Properties/AssemblyInfo.cs
+++ b/Plugins/Discord/source/Plugin.Discord/Properties/AssemblyInfo.cs
@@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("1.0.17.1")]
-[assembly: AssemblyFileVersion("1.0.17.1")]
+[assembly: AssemblyVersion("1.0.17.2")]
+[assembly: AssemblyFileVersion("1.0.17.2")]
diff --git a/Plugins/Discord/source/Plugin.Discord/Utils/WindowUtils.cs b/Plugins/Discord/source/Plugin.Discord/Utils/WindowUtils.cs
new file mode 100644
index 00000000..6c765945
--- /dev/null
+++ b/Plugins/Discord/source/Plugin.Discord/Utils/WindowUtils.cs
@@ -0,0 +1,122 @@
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace ServerManagerTool.Plugin.Discord
+{
+ public static class WindowUtils
+ {
+ public static void RemoveDefaultResourceDictionary(Window window, string defaultDictionary)
+ {
+ if (window == null)
+ return;
+
+ var dictToRemove = window.Resources.MergedDictionaries.FirstOrDefault(d => d.Source.OriginalString.Contains(defaultDictionary));
+ if (dictToRemove != null)
+ {
+ window.Resources.MergedDictionaries.Remove(dictToRemove);
+ }
+ }
+
+ public static void RemoveDefaultResourceDictionary(UserControl control, string defaultDictionary)
+ {
+ if (control == null)
+ return;
+
+ var dictToRemove = control.Resources.MergedDictionaries.FirstOrDefault(d => d.Source.OriginalString.Contains(defaultDictionary));
+ if (dictToRemove != null)
+ {
+ control.Resources.MergedDictionaries.Remove(dictToRemove);
+ }
+ }
+
+ ///
+ /// Finds a parent of a given item on the visual tree.
+ ///
+ /// The type of the queried item.
+ /// A direct or indirect child of the queried item.
+ /// The first parent item that matches the submitted type parameter. If not matching item can be found, a null reference is being returned.
+ public static T TryFindParent(DependencyObject child)
+ where T : DependencyObject
+ {
+ //get parent item
+ DependencyObject parentObject = GetParentObject(child);
+
+ //we've reached the end of the tree
+ if (parentObject == null) return null;
+
+ //check if the parent matches the type we're looking for
+ T parent = parentObject as T;
+ if (parent != null)
+ return parent;
+
+ //use recursion to proceed with next level
+ return TryFindParent(parentObject);
+ }
+
+ ///
+ /// This method is an alternative to WPF's method, which also supports content elements.
+ /// Do note, that for content element, this method falls back to the logical tree of the element.
+ ///
+ /// The item to be processed.
+ /// The submitted item's parent, if available. Otherwise null.
+ public static DependencyObject GetParentObject(DependencyObject child)
+ {
+ if (child == null) return null;
+ var contentElement = child as ContentElement;
+
+ if (contentElement != null)
+ {
+ var parent = ContentOperations.GetParent(contentElement);
+ if (parent != null) return parent;
+
+ var fce = contentElement as FrameworkContentElement;
+ return fce?.Parent;
+ }
+
+ //if it's not a ContentElement, rely on VisualTreeHelper
+ return VisualTreeHelper.GetParent(child);
+ }
+
+ ///
+ /// Recursively processes a given dependency object and all its children, and updates sources of all objects that use a binding expression on a given property.
+ ///
+ /// The dependency object that marks a starting point. This could be a dialog window or a panel control that hosts bound controls.
+ /// The properties to be updated if
+ /// or one of its childs provide it along with a binding expression.
+ public static void UpdateBindingSources(DependencyObject obj, params DependencyProperty[] properties)
+ {
+ foreach (var depProperty in properties)
+ {
+ //check whether the submitted object provides a bound property that matches the property parameters
+ var be = BindingOperations.GetBindingExpression(obj, depProperty);
+ be?.UpdateSource();
+ }
+
+ int count = VisualTreeHelper.GetChildrenCount(obj);
+ for (int i = 0; i < count; i++)
+ {
+ //process child items recursively
+ var childObject = VisualTreeHelper.GetChild(obj, i);
+ UpdateBindingSources(childObject, properties);
+ }
+ }
+
+ ///
+ /// Tries to locate a given item within the visual tree, starting with the dependency object at a given position.
+ ///
+ /// The type of the element to be found on the visual tree of the element at the given location.
+ /// The main element which is used to perform hit testing.
+ /// The position to be evaluated on the origin.
+ public static T TryFindFromPoint(UIElement reference, Point point)
+ where T : DependencyObject
+ {
+ var element = reference.InputHitTest(point) as DependencyObject;
+ if (element == null) return null;
+ if (element is T) return (T)element;
+ return TryFindParent(element);
+ }
+ }
+}
diff --git a/Plugins/Discord/source/Plugin.Discord/VersionFeed.xml b/Plugins/Discord/source/Plugin.Discord/VersionFeed.xml
index 9b8651ab..82e77d98 100644
--- a/Plugins/Discord/source/Plugin.Discord/VersionFeed.xml
+++ b/Plugins/Discord/source/Plugin.Discord/VersionFeed.xml
@@ -9,8 +9,8 @@
urn:uuid:D8974ABF-8444-4D40-A594-D4443921B3B8
- 1.0.17 (1.0.17.1)
- 1.0.17.1
+ 1.0.17 (1.0.17.2)
+ 1.0.17.22020-07-13T00:00:00Z
@@ -20,6 +20,7 @@
Profile name has been converted to a droplist and is now populated with the Server Manager Profile Names for selection.
+
Added drag/drop feature to the config window.
diff --git a/Plugins/Discord/source/Plugin.Discord/VersionFeedBeta.xml b/Plugins/Discord/source/Plugin.Discord/VersionFeedBeta.xml
index eae3c759..de95f6f5 100644
--- a/Plugins/Discord/source/Plugin.Discord/VersionFeedBeta.xml
+++ b/Plugins/Discord/source/Plugin.Discord/VersionFeedBeta.xml
@@ -5,14 +5,37 @@
Discord Plugin Version FeedThis is the Discord Plugin beta version feed.
- 2020-07-13T00:00:00Z
+ 2020-07-12T02:00:00Z
+
+
+ urn:uuid:4750D17C-2C8F-4D8C-AA17-B3512F002170
+ 1.0.17 (1.0.17.2)
+ 1.0.17.2
+
+ 2020-07-12T02:00:00Z
+
+