1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-09-14 19:32:10 +02:00

Compare commits

...

55 Commits
1.3.2 ... 1.3.3

Author SHA1 Message Date
7388eb07ca Increase process close timeouts to 20 seconds from 10 2016-09-18 21:49:41 +02:00
c38d507e50 Hopefully fix an occasional crash when importing session and restarting 2016-09-18 21:48:40 +02:00
5aee087a57 Add a Program Files warning if not running as administrator 2016-09-18 21:17:30 +02:00
0cda3702ea Change notification scroll trigger cursor position for windows without side borders 2016-09-18 21:08:09 +02:00
ce55226d0c Add error handling to logging 2016-09-18 20:50:43 +02:00
0bab0a9963 Update reply-account plugin metadata and default config warning 2016-09-18 20:29:49 +02:00
34955b7083 Rewrite Plugin default config handling and config error reporting 2016-09-18 20:29:31 +02:00
ba6ce072ac Add support for a -datafolder command line argument 2016-09-18 19:42:00 +02:00
f39fd00697 Add a TweetDick warning and migration prompt 2016-09-18 19:41:37 +02:00
58fc1be1d5 Add CefSharp version to NuGet instructions 2016-09-12 14:29:48 +02:00
1fdf9bffb6 Disable global context menu items when in textarea or text selection 2016-09-07 21:47:31 +02:00
2ad179ef8e Rename configuration file in reply-account plugin 2016-09-07 15:03:06 +02:00
d42cc5b762 Remove .js file block in Plugin folders 2016-09-07 15:01:08 +02:00
403658f622 Add config file to reply-account plugin metadata 2016-09-07 14:43:17 +02:00
6ca35685db Add button for easy Plugin config file access 2016-09-07 14:42:21 +02:00
bfc6822f69 Fix Plugins window title 2016-09-07 14:20:35 +02:00
b0386937d7 Remove lnk updater from the TweetDeck migration system 2016-09-05 21:25:25 +02:00
9436540b2f Add CultureInfo.CurrentCulture to time in logger 2016-09-05 20:45:39 +02:00
45b0ece342 Update Plugin sorting and design (separator, colors) 2016-09-05 20:44:58 +02:00
5c147d3648 Fix missing and unfocused scrollbar in Plugins window 2016-09-05 20:44:07 +02:00
8fa68c428f Add 'Open (quoted) tweet in browser' context menu items and move them down 2016-09-05 16:17:23 +02:00
e2be90191e Standardize context menu items using Chrome's style 2016-09-05 14:30:07 +02:00
339da2f1a9 Add unsupported system notification
Closes #58
2016-09-04 20:30:35 +02:00
b2cc5d50bd Address code analysis issues and fix unused parameter in CombinedFileStream.WriteToFile 2016-09-04 19:32:33 +02:00
f38b188046 Add a safety net to plugin file export in case the path is too long 2016-09-04 18:10:50 +02:00
9e45628e87 Rename 'Export/Import Settings' to Profile and add Plugin exporting 2016-09-04 16:58:03 +02:00
bf76398627 Optimize icon loading and size in Forms, fix Plugins Form title inconsistency 2016-09-04 15:32:00 +02:00
81d5728964 Add scrollbars to Edit CSS window 2016-09-04 13:57:38 +02:00
d76027558b Add a custom alert function with customizable icon and no text length limit 2016-09-04 13:19:52 +02:00
1450cc24a3 Reorganize global context menu items into a sub-menu 2016-09-04 13:10:32 +02:00
f41523c1b2 Remove redundant 'using' directives 2016-09-04 04:53:37 +02:00
4019463e68 Fix occasional incorrect location of child windows 2016-09-04 04:52:59 +02:00
5e2e239f5e Force Reload All button in Plugins window to trigger the event even without changes 2016-09-04 04:44:08 +02:00
bc7856b6c0 Tweak wording in reply-account configuration file 2016-09-04 04:39:19 +02:00
e2bba8d9e1 Update reply-account plugin to use default config and swap event order when enabled late 2016-09-04 04:36:01 +02:00
520db2c32e Rewrite loadConfigurationFile in plugins.js to accept default config file 2016-09-04 04:33:55 +02:00
da71f2de2b Add CheckFileExists function to PluginBridge 2016-09-04 04:33:13 +02:00
6dd2c6678b Add custom exception messages to file reading in PluginBridge 2016-09-04 04:01:40 +02:00
fb3d9e6d6b Add a reply-account plugin with config 2016-09-04 04:01:00 +02:00
36473c2df9 Add a global plugins.js file with loadConfigurationFile utility function 2016-09-04 03:59:37 +02:00
81aa30b2ec Allow custom .js files in plugin folders when prefixed by 'user.' 2016-09-04 03:50:35 +02:00
85d5160782 Add plugin identifier to the object itself 2016-09-04 03:38:42 +02:00
44bf7b870e Rewrote notification mouse hook to only be active if the window is visible
Closes #57
2016-09-04 00:59:13 +02:00
44da2e6082 Add debug example notification padding for scrollbar testing 2016-09-04 00:58:47 +02:00
d576bc3972 Work around Scheduled column update delay bug in TweetDeck
Closes #53
2016-09-03 16:15:28 +02:00
dbeb4c7205 Reorganize path constants and allow the program to be portable 2016-09-02 20:59:03 +02:00
e5223a852e Fix profile picture in example tweet 2016-09-02 20:58:18 +02:00
f3884315c0 Fix visual issues with clear-columns plugin (icon in temp columns, misaligned Messages icons) 2016-09-02 20:46:54 +02:00
53cd9dc9a6 Move script files to /scripts/ folder and exclude them from Visual Studio 2016-09-02 19:05:48 +02:00
a3666a7ab2 Fix formatting in JavaScript files 2016-09-02 17:35:21 +02:00
ca4eb17308 Add a clear-columns plugins 2016-09-02 17:28:32 +02:00
b729dca2e5 Seal PluginConfig and add a method to disable official plugins from config 2016-09-02 17:25:25 +02:00
21354e675a Fix TweetDeck keyboard shortcut list alignment 2016-09-02 17:17:08 +02:00
2085ddd347 Update website in design-revert plugin to https 2016-09-02 16:41:52 +02:00
31a475861b Reformat (missing space after comma), minor code tweaks 2016-09-02 13:34:41 +02:00
69 changed files with 1227 additions and 1398 deletions

View File

@@ -4,7 +4,7 @@ using System.IO;
using System.Threading; using System.Threading;
namespace TweetDck.Configuration{ namespace TweetDck.Configuration{
class LockManager{ sealed class LockManager{
public Process LockingProcess { get; private set; } public Process LockingProcess { get; private set; }
private readonly string file; private readonly string file;

View File

@@ -16,7 +16,7 @@ namespace TweetDck.Configuration{
Binder = new SerializationCompatibilityHandler() Binder = new SerializationCompatibilityHandler()
}; };
private const int CurrentFileVersion = 4; private const int CurrentFileVersion = 5;
// START OF CONFIGURATION // START OF CONFIGURATION
@@ -116,6 +116,9 @@ namespace TweetDck.Configuration{
EnableTrayHighlight = true; EnableTrayHighlight = true;
Plugins = new PluginConfig(); Plugins = new PluginConfig();
PluginsWindow = new WindowState(); PluginsWindow = new WindowState();
Plugins.DisableOfficialFromConfig("clear-columns");
Plugins.DisableOfficialFromConfig("reply-account");
} }
private void UpgradeFile(){ private void UpgradeFile(){
@@ -155,6 +158,12 @@ namespace TweetDck.Configuration{
++fileVersion; ++fileVersion;
} }
if (fileVersion == 4){
Plugins.DisableOfficialFromConfig("clear-columns");
Plugins.DisableOfficialFromConfig("reply-account");
++fileVersion;
}
// update the version // update the version
fileVersion = CurrentFileVersion; fileVersion = CurrentFileVersion;
Save(); Save();

View File

@@ -2,7 +2,7 @@
using System.Windows.Forms; using System.Windows.Forms;
namespace TweetDck.Core.Controls{ namespace TweetDck.Core.Controls{
public partial class FlatProgressBar : ProgressBar{ sealed partial class FlatProgressBar : ProgressBar{
private readonly SolidBrush brush; private readonly SolidBrush brush;
public FlatProgressBar(){ public FlatProgressBar(){

View File

@@ -24,7 +24,6 @@
/// </summary> /// </summary>
private void InitializeComponent() { private void InitializeComponent() {
this.components = new System.ComponentModel.Container(); this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormBrowser));
this.trayIcon = new TweetDck.Core.TrayIcon(); this.trayIcon = new TweetDck.Core.TrayIcon();
this.toolTip = new System.Windows.Forms.ToolTip(this.components); this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.SuspendLayout(); this.SuspendLayout();
@@ -38,7 +37,7 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(324, 386); this.ClientSize = new System.Drawing.Size(324, 386);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Icon = Properties.Resources.icon;
this.Location = new System.Drawing.Point(-32000, -32000); this.Location = new System.Drawing.Point(-32000, -32000);
this.MinimumSize = new System.Drawing.Size(340, 424); this.MinimumSize = new System.Drawing.Size(340, 424);
this.Name = "FormBrowser"; this.Name = "FormBrowser";

View File

@@ -73,7 +73,7 @@ namespace TweetDck.Core{
private void ShowChildForm(Form form){ private void ShowChildForm(Form form){
form.Show(this); form.Show(this);
form.MoveToCenter(this); form.Shown += (sender, args) => form.MoveToCenter(this);
} }
private void ForceClose(){ private void ForceClose(){
@@ -112,6 +112,7 @@ namespace TweetDck.Core{
if (plugins.HasAnyPlugin(PluginEnvironment.Browser)){ if (plugins.HasAnyPlugin(PluginEnvironment.Browser)){
ScriptLoader.ExecuteFile(e.Frame, PluginManager.PluginBrowserScriptFile); ScriptLoader.ExecuteFile(e.Frame, PluginManager.PluginBrowserScriptFile);
ScriptLoader.ExecuteFile(e.Frame, PluginManager.PluginGlobalScriptFile);
plugins.ExecutePlugins(e.Frame, PluginEnvironment.Browser, true); plugins.ExecutePlugins(e.Frame, PluginEnvironment.Browser, true);
} }
} }
@@ -230,7 +231,7 @@ namespace TweetDck.Core{
else{ else{
bool prevEnableUpdateCheck = Config.EnableUpdateCheck; bool prevEnableUpdateCheck = Config.EnableUpdateCheck;
currentFormSettings = new FormSettings(this,updates); currentFormSettings = new FormSettings(this, plugins, updates);
currentFormSettings.FormClosed += (sender, args) => { currentFormSettings.FormClosed += (sender, args) => {
currentFormSettings = null; currentFormSettings = null;

View File

@@ -117,267 +117,11 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<metadata name="trayIcon.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>112, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="trayIcon.TrayLocation" type="System.Drawing.Point, System.Drawing">
<value> <value>17, 17</value>
AAABAAMAMDAAAAEAIACoJQAANgAAACAgAAABACAAqBAAAN4lAAAQEAAAAQAgAGgEAACGNgAAKAAAADAA </data>
AABgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA <data name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing">
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqHg5IrF+OlS+hjyMw4g7tcmM <value>112, 17</value>
PM/MjTzezY485s2OPObMjjzfyIw80MOJPLe8hDyNs387WKx8OyQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApHU4FrB8OGXGijzAzo889dKR
PP/SkTz/0pE8/9GRPP/RkDz/0JA8/9CQPP/RkDz/0ZE8/9KRPP/TkTz/0pE8/86PPPbGijzCt4E8bKp6
OxoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKN1OB+9hTuLzI486NOR
PP/SkTz/0ZA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GQ
PP/SkTz/0pE8/82OPOu9hTuOq3w8IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACidTkFuoM8csyN
POrTkjz/0ZE8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GRPP/Tkjz/zY887bqEPHimeDsHAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKp6
OynDiDvA05I8/9GRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0ZA8/9ORPP/GijzFr308LgAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAArXw7UM2OPOvTkTz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/SkTz/zo887rOAPFYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACxfjxm0ZA8/NGRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0ZE8/9GQPP64gjxtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAALaBPGXRkTz/0ZE8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GQPP/SkTz/uIM8bAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqnk6TtCQPPzRkTz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkDz/0ZA8/rSA
PFUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACtfDwmzo887dKRPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0ZE8/86PPPGtfDwrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKZ4PAXFijzC0pE8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CURf/TpGT/2baJ/9/GpP/l0bf/59W//+fVvf/kz7P/3sOg/9mz
hP/ToWH/0JND/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9KRPP/EiTvJo3Y7CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALiC
PG/Tkjz/0JA8/9CQPP/QkDz/0JA8/9CSQf/Vq3P/5tO7//j07v//////////////////////////////
////////////////////////9vHq/+TQtf/UqG7/0JA+/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/Tkjz/uYM8dgAAAAAAAAAAAAAAAAAA
AAAAAAAArXw8Gc2OPOzRkTz/0JA8/9CQPP/QlEX/27qP//fz7P//////////////////////////////
////////////////////////////////////////////////////////8ObZ/9auev/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkTz/zI488J1x
OB8AAAAAAAAAAAAAAAAAAAAAuoM7h9OSPP/QkDz/0JA8/9GXTf/TpGb/27uS/9u6kP/ewZz/59W9//Xv
5///////////////////////////////////////////////////////////////////////////////
///r3cr/0ZxV/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/1JI8/7mDO5AAAAAAAAAAAAAAAADFj0cR0pNB6s+PO//Ojjv/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CRQP/TpGf/5NC2//38+v//////////////////////////////////////////////
////////////////////////+vf0/9auev/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0ZE8/8uOPO6SajYVAAAAAAAAAADzr1df7qxV/+WkT//ZmUT/0JA9/86O
O//Pjzv/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GaUv/l07r/////////////////////////
///////////////////////////////////////////////////buo//0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9OSPP+ldjdoAAAAAAAAAADurFW67qxV//Ct
Vv/vrVb/6adR/92dSP/Skz//zo47/8+PO//QkDz/0JA8/9CQPP/QkDz/0JJB/9Smaf/dv5j/+fXw////
////////////////////////////////////////////////////////////////////////2riM/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9KRPP/FiTzGoHQ6Ae6s
VRrurFXz7qxV/+6sVf/urFX/761W//CuVv/sqlT/4qFM/9aVQv/Pjzv/zo47/9CQPP/VqnH/8+vh////
////////////////////////////////////////////////////////////////////////////////
/////////////9aueP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GQ
PP/Ojzz4oHM5Iu6sVU3urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/vrVX/8K5W/+6sVf/mpU//2plF/9q6
j///////////////////////////////////////////////////////////////////////////////
//////////////////////////////n18P/Rm1P/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/SkTz/rXs6Vu6sVYPurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/wrVb/6r2B////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////o18L/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/v4Y8j+6sVa3urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFb/9Onb///////+/v3/////////////////////////////////////////
////////////////////////////////////////////////////////////////////////1qx2/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/wYc7uO6sVcrurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/trlr/67Zy/+m+h//y5NP/////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////7+TW/9CQPf/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkTz/yYw80e6s
VdvurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/6sme//v49P//////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////9arc//QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/RkDz/zI083+6sVeLurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/u2b3/////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////+fVvv/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/zo885u6sVeLurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+vL
of//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////r28v/Rl0r/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/zo885u6sVdrurFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7LBj//r28f//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///Vq3P/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkDz/zI083+6sVcrurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/6cKO////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///////////////////ewp7/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkTz/yYw80O6s
VazurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7NOy//z59v/u2b7/+fPr////////////////////
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////n1sD/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/SkTz/xIo8uO6sVYHurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/67Zx/+2uWf/qy6H/////////
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////v5dj/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/SkTz/vYU8je6sVUvurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+nC
kP///////////////////////////////////////////////////////fz6//fu5P/w4Mv/793F//7+
/v/////////////////////////////////////////////////////////////////17eT/0JA//86O
Ov/Pjzv/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/tYA8Vu6sVRnurFXy7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7a5b//fw5///////////////////////////////////////+/jz/+7av//pwIr/67Jn/+6t
Vv/urFX/6rd1////////////////////////////////////////////////////////////////////
///48ej/6KhU/92cR//Tkj7/zo47/8+PO//QkDz/0JA8/9GQPP/Pjzz3rXw8IAAAAADurFW37qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/6b2D//////////////////////////////////nz6//qyZ3/7K9h/+6s
Vf/urFX/7qxV/+6sVf/urFX/6rl6////////////////////////////////////////////////////
///////////////////9/Pr/6r6C//CuV//sqlT/4aBL/9aWQv/Pjzv/zo47/9GRPP/GijzCp3g8AQAA
AADurFVb7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/68yk///////////////////////+/fz/68+q/+2v
XP/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/6rNr//7+/f//////////////////////////////
/////////////////////////////////////////////+nEk//vrVX/8K5W/+6sVf/lpE//2ZlF/9KR
Pf+zfzpoAAAAAAAAAADurFUP7qxV5u6sVf/urFX/7qxV/+6sVf/urFX/7NGu//////////////////fu
5P/quHb/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxW//Xr3///////////////
///////////////////////////////////////////////////7+PP/+vXu///////pxJL/7qxV/+6s
Vf/wrVb/8K1W/+mnUevUmUsUAAAAAAAAAAAAAAAA7qxVgO6sVf/urFX/7qxV/+6sVf/urFX/6sqg////
////////8eLO/+yvX//urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+nF
lf/////////////////////////////////////////////////////////////////8+vf/6cWV/+q5
ev/s07H/6rd1/+6sVf/urFX/7qxV/++tVogAAAAAAAAAAAAAAAAAAAAA7qxVFe6sVejurFX/7qxV/+6s
Vf/urFX/6bp8///////w4Mn/7a1Z/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/x4cz////////////////////////////////////////////////////+//7+
/v/////////+/+m8gP/urFX/7a1Y/+6sVf/urFX/7qxV7O6sVRoAAAAAAAAAAAAAAAAAAAAAAAAAAO6s
VWburFX/7qxV/+6sVf/urFX/7a5b/+zTs//sr1//7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/sr1//8uPQ////////////////////////////////////
////////6suj/+qzav/pxpj/9Onb//n07f/rr2D/7qxV/+6sVf/urFX/7qxVbwAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAO6sVQPurFW67qxV/+6sVf/urFX/7qxV/+6sVv/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7axY/+nGl//27uP/////////
/////////fz6//Lj0P/qunv/7qxV/+6sVf/urFX/7qxV/+m9gv/qt3X/7qxV/+6sVf/urFXB7qxVBQAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADurFUg7qxV6O6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/qtnP/6sqg/+3WuP/s07P/6cSS/+uyZf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVv/trVr/7qxV/+6s
VezurFUlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVRu6sVfjurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV++6sVUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6s
VVzurFX97qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxVYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADurFVd7qxV+O6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVfvurFVjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVR+6sVeXurFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV6O6sVU0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVSPurFW37qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFW77qxVJgAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADurFUB7qxVae6sVeTurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV5+6sVW3urFUDAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVRjurFWA7qxV4u6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVeTurFWE7qxVGwAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVEu6sVV7urFW17qxV7+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVfDurFW47qxVX+6s
VRMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA7qxVG+6sVUzurFWA7qxVrO6sVcnurFXa7qxV4u6sVeLurFXa7qxVye6sVa3urFWC7qxVTe6s
VR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP//gAH//6gr//wAAD//qCv/8AAAD/+oK//AAAAD/6gr/4AAAAH/qCv/AAAAAP+oK/4A
AAAAf6gr/AAAAAA/qCv4AAAAAB+oK/AAAAAAD6gr4AAAAAAHqCvgAAAAAAeoK8AAAAAAA6grwAAAAAAD
qCuAAAAAAAGoK4AAAAAAAagrgAAAAAAAqCsAAAAAAACoKwAAAAAAAKgrAAAAAAAAqCsAAAAAAACoKwAA
AAAAAKgrAAAAAAAAqCsAAAAAAACoKwAAAAAAAKgrAAAAAAAAqCsAAAAAAACoKwAAAAAAAKgrAAAAAAAA
qCsAAAAAAACoKwAAAAAAAKgrgAAAAAAAqCuAAAAAAAGoK4AAAAAAAagrwAAAAAADqCvAAAAAAAOoK+AA
AAAAB6gr4AAAAAAHqCvwAAAAAA+oK/gAAAAAH6gr/AAAAAA/qCv+AAAAAH+oK/8AAAAA/6gr/4AAAAH/
qCv/wAAAA/+oK//wAAAP/6gr//wAAD//qCv//4AB//+oKygAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApHY4FrR/
Ole+hjuVxos7w8uNPNvOjzznzo8858uNPNzGijzEvoU7l7WBO1mpejsYAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqHg5Kr6F
O5XLjTvo0pE8/9ORPP/SkTz/0ZE8/9CQPP/QkDz/0ZE8/9KRPP/TkTz/0pE8/82OPOq/hjyZrXw7LAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo3U6CbuE
O4bPjzz005I8/9GRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0ZE8/9OS
PP/PkDz1vYU8iah6PAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKR3
OibGizvG05E8/9GQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9GQPP/TkTz/yIs8yqx8PCkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACsezsxy40849KRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/zI485rKAPTUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAApXc6JMuNPOTSkTz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/zI485659PCcAAAAAAAAAAAAA
AAAAAAAAAAAAAKd4OwnHizzJ0pE8/9CQPP/QkDz/0JA9/9OgYP/YtIX/38Sh/+LMr//iy67/3sOf/9iy
gv/Tn13/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/x4s8zaV4
OwsAAAAAAAAAAAAAAAAAAAAAu4Q8hNOSPP/QkDz/0JA8/9GXS//YtIX/6NfC//Xv5//8+vj/////////
///8+vf/9O3k/+fVvv/YsYH/0JRF/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/Tkjz/u4Q7iQAAAAAAAAAAAAAAAKx7OyTPjzz10ZA8/9GXS//Ztoj/8une////////////////////
///////////////////////////////////38uz/3L2V/9CRP//QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9GRPP/Ojzz3onU5KQAAAAAAAAAAxo1BlNGQO//Ojjv/0JNC/9GWSP/QlET/0ZpR/9au
eP/n1b3//v79////////////////////////////////////////////7+TV/9GdWP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9SSPP+4gjqaAAAAAPGuVhHvrVXq5qRO/9qZRP/QkT3/zo46/8+P
O//QkDz/0JA8/9CQPP/To2P/8+vh////////////////////////////////////////////+fXw/9Oh
Yf/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0pE8/8qMO+2WbTYV7qxVUe6sVf/wrVb/761W/+mo
Uv/enUj/05M//86PO//PkD7/3cCZ//Lp3v/7+PT/////////////////////////////////////////
////////+PTv/9GcVf/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/05I8/699OljurFWR7qxV/+6s
Vf/urFX/761W//CuV//sqlT/4qJQ/+zdyf//////////////////////////////////////////////
////////////////////////7+TV/9CRP//QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/Tkjz/vIQ7mO6s
Vb/urFX/7qxV/+6sVf/urFX/7qxV/++tVf/ry5///v79//7+/f//////////////////////////////
////////////////////////////////////////2rqO/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9KR
PP/GijvF7qxV2u6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+u1bv/t1bb//fv4////////////////////
///////////////////////////////////////////////////48+3/0ZRG/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0ZA8/8uNPNzurFXl7qxV/+6sVf/urFX/7qxV/+6sVf/rsWP/9OjZ////////////////////
///////////////////////////////////////////////////////////////////YtIX/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/zo886O6sVeXurFX/7qxV/+6sVf/urFX/7qxW//Hiz///////////////
/////////////////////////////////////////////////////////////////////////////+rb
yP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/Ojzzo7qxV2e6sVf/urFX/7qxV/+6sVf/quHb/////////
////////////////////////////////////////////////////////////////////////////////
////////+fXw/9CURf/QkDz/0JA8/9CQPP/QkDz/0ZA8/8yOPNzurFW/7qxV/+6sVf/urFX/7qxV/+nA
if/s1LT/9Onb////////////////////////////////////////////////////////////////////
////////////////////////0Z5b/9CQPP/QkDz/0JA8/9CQPP/SkTz/x4s8xe6sVY/urFX/7qxV/+6s
Vf/urFX/7qxV/+nEk//+/fz////////////////////////////+/v3/+PHo//To2f/+/v7/////////
///////////////////////////////////VqGz/zo46/8+PO//QkDz/0JA8/9KRPP+/hjyX7qxVUO6s
Vf/urFX/7qxV/+6sVf/ssGH//Pr2///////////////////////y49D/6cOR/+qyaf/urVb/6rJp////
/////////////////////////////////////////////+e7f//goEr/1ZVB/8+PO//Ojzv/0pE8/7WB
PFfurFUQ7qxV6O6sVf/urFX/7qxV/+m+hv/////////////////z5tX/6rl6/+6sVf/urFX/7qxV/+6s
Vf/qs2r////+////////////////////////////////////////////+PLp/+y4c//urFX/5aRO/9qZ
RP/Mjjztp3g6FQAAAADurFWQ7qxV/+6sVf/urFX/6cKP////////////682m/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+2sV//17N////////////////////////////////////////7+/v/06Nn/8uTT/+qz
a//wrVb/761W/+alUZYAAAAAAAAAAO6sVSHurFX07qxV/+6sVf/quXj//////+nDkf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+m+hP////////////////////////////////////////////jy
6v/qtnH/67Fj/+6sVf/urFX2761WJQAAAAAAAAAAAAAAAO6sVX7urFX/7qxV/+2vW//pvID/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+nEkv/7+PT//////////////////fz6/+rJ
n//rtW7/682n/+zTs//urFb/7qxV/+6sVYQAAAAAAAAAAAAAAAAAAAAA7qxVB+6sVcTurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+u0bP/qy6H/7da4/+vN
pv/qtnP/7qxV/+6sVf/urFX/7K9f/+2sWP/urFXI7qxVCQAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVIO6s
VeDurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV4+6sVSMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA7qxVLO6sVd/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVeLurFUwAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA7qxVIu6sVcHurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFXE7qxVJAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVBu6sVX/urFXw7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFXy7qxVgu6sVQgAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVSXurFWP7qxV5e6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFXl7qxVke6sVScAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADurFUS7qxVUO6sVY7urFW97qxV2O6sVeXurFXl7qxV2O6sVb7urFWP7qxVUu6sVRMAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8AD//8AAP/8AAA/+AAAH/AAAA/gAAAHwAAAA8AA
AAOAAAABgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA
AAGAAAABwAAAA8AAAAPgAAAH8AAAD/gAAB/8AAA//wAA///AA/8oAAAAEAAAACAAAAABACAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKx7Oja9hTqTyYw8zs6PPOfOjzznyYw8zr6G
PJSvfjw3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo3Y7CbyEO5PRkDz805I8/9GRPP/QkDz/0JA8/9GR
PP/TkTz/0ZA8/b+GPJWrfDwKAAAAAAAAAAAAAAAAp3g8CcSJPLfTkjz/0ZA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/Tkjz/xoo8uqx8PQoAAAAAAAAAAL2FPJPUk0D/06Rm/92/mf/izK//4sut/9u6
j//Snlr/0JA8/9CQPP/QkDz/0JA8/9OSPP+9hTyWAAAAALiEQDLQkDz90JpS/93Amf/u4tP/////////
/////////fv5/+DIqP/QkkH/0JA8/9CQPP/RkDz/0JA8/qN1OTTtq1WS56VP/9qaRf/RkT3/0JdO/+rc
yP//////////////////////693L/9CSQf/QkDz/0JA8/9SSPP+3gTqW761Vz++tVv/wrVb/6K5h//fy
6v/////////////////////////////////gx6b/0JA8/9CQPP/RkTz/yYw80e6sVefurFX/7qxV/+q+
hP/69vD//////////////////////////////////fz7/9GbU//QkDz/0JA8/8+PPOnurFXn7qxV/+yw
Y//79/P////////////////////////////////////////////ZuIz/0JA8/9CQPP/Pjzzp7qxVz+6s
Vf/sr2H/8eLO/////////////v7+//n07f/+/v7/////////////////48yu/8+PO//Qjzv/yYs80e6s
VZLurFX/67Jm//7+/f/8+fb/68yl/+qza//rsmf//v37//////////////////Pn2P/ip1n/2phC/8CH
PJXurFUw7qxV/eq2c//169//6rNr/+6sVf/urFX/7q1W//Pm1f/////////////////8+fX/67+G/++t
Vf3lpVEyAAAAAO6sVZHtrVr/7a9c/+6sVf/urFX/7qxV/+6sVf/rsWP/7de5//Lj0P/pxJL/67Zy/+qz
av/urFWTAAAAAAAAAADurFUI7qxVtO6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFW37qxVCQAAAAAAAAAAAAAAAO6sVQjurFWQ7qxV++6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
VfvurFWS7qxVCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVTPurFWQ7qxVzO6sVeburFXm7qxVzO6s
VZDurFU0AAAAAAAAAAAAAAAAAAAAAPAPrEHAA6xBgAGsQYABrEEAAKxBAACsQQAArEEAAKxBAACsQQAA
rEEAAKxBAACsQYABrEGAAaxBwAOsQfAPrEE=
</value>
</data> </data>
</root> </root>

View File

@@ -112,7 +112,6 @@ namespace TweetDck.Core{
} }
mouseHookDelegate = MouseHookProc; mouseHookDelegate = MouseHookProc;
mouseHook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL,mouseHookDelegate,IntPtr.Zero,0);
Disposed += FormNotification_Disposed; Disposed += FormNotification_Disposed;
} }
@@ -125,11 +124,26 @@ namespace TweetDck.Core{
base.WndProc(ref m); base.WndProc(ref m);
} }
// mouse wheel hook
private void StartMouseHook(){
if (mouseHook == IntPtr.Zero){
mouseHook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL, mouseHookDelegate, IntPtr.Zero, 0);
}
}
private void StopMouseHook(){
if (mouseHook != IntPtr.Zero){
NativeMethods.UnhookWindowsHookEx(mouseHook);
mouseHook = IntPtr.Zero;
}
}
private IntPtr MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam){ private IntPtr MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam){
if (!ContainsFocus && wParam.ToInt32() == NativeMethods.WH_MOUSEWHEEL && browser.Bounds.Contains(PointToClient(Cursor.Position))){ if (!ContainsFocus && wParam.ToInt32() == NativeMethods.WH_MOUSEWHEEL && browser.Bounds.Contains(PointToClient(Cursor.Position))){
// fuck it, Activate() doesn't work with this // fuck it, Activate() doesn't work with this
Point prevPos = Cursor.Position; Point prevPos = Cursor.Position;
Cursor.Position = PointToScreen(new Point(-1,-1)); Cursor.Position = PointToScreen(new Point(0, -1));
NativeMethods.SimulateMouseClick(NativeMethods.MouseButton.Left); NativeMethods.SimulateMouseClick(NativeMethods.MouseButton.Left);
Cursor.Position = prevPos; Cursor.Position = prevPos;
} }
@@ -182,6 +196,7 @@ namespace TweetDck.Core{
if (plugins.HasAnyPlugin(PluginEnvironment.Notification)){ if (plugins.HasAnyPlugin(PluginEnvironment.Notification)){
ScriptLoader.ExecuteScript(e.Frame, pluginJS, PluginScriptIdentifier); ScriptLoader.ExecuteScript(e.Frame, pluginJS, PluginScriptIdentifier);
ScriptLoader.ExecuteFile(e.Frame, PluginManager.PluginGlobalScriptFile);
plugins.ExecutePlugins(e.Frame, PluginEnvironment.Notification, false); plugins.ExecutePlugins(e.Frame, PluginEnvironment.Notification, false);
} }
} }
@@ -197,11 +212,7 @@ namespace TweetDck.Core{
private void FormNotification_Disposed(object sender, EventArgs e){ private void FormNotification_Disposed(object sender, EventArgs e){
browser.Dispose(); browser.Dispose();
StopMouseHook();
if (mouseHook != IntPtr.Zero){
NativeMethods.UnhookWindowsHookEx(mouseHook);
mouseHook = IntPtr.Zero;
}
} }
// notification methods // notification methods
@@ -237,6 +248,8 @@ namespace TweetDck.Core{
Location = new Point(-32000, -32000); Location = new Point(-32000, -32000);
progressBarTimer.Value = Program.UserConfig.NotificationTimerCountDown ? 1000 : 0; progressBarTimer.Value = Program.UserConfig.NotificationTimerCountDown ? 1000 : 0;
timerProgress.Stop(); timerProgress.Stop();
StopMouseHook();
} }
public void OnNotificationReady(){ public void OnNotificationReady(){
@@ -332,6 +345,8 @@ namespace TweetDck.Core{
if (needsReactivating){ if (needsReactivating){
NativeMethods.SetFormPos(this, NativeMethods.HWND_TOPMOST, NativeMethods.SWP_NOACTIVATE); NativeMethods.SetFormPos(this, NativeMethods.HWND_TOPMOST, NativeMethods.SWP_NOACTIVATE);
} }
StartMouseHook();
} }
private void UpdateTitle(){ private void UpdateTitle(){

View File

@@ -6,38 +6,38 @@ using TweetDck.Core.Utils;
namespace TweetDck.Core.Handling{ namespace TweetDck.Core.Handling{
abstract class ContextMenuBase : IContextMenuHandler{ abstract class ContextMenuBase : IContextMenuHandler{
private const int MenuOpenUrlInBrowser = 26500; private const int MenuOpenLinkUrl = 26500;
private const int MenuCopyUrl = 26501; private const int MenuCopyLinkUrl = 26501;
private const int MenuOpenImageInBrowser = 26502; private const int MenuOpenImage = 26502;
private const int MenuSaveImage = 26503; private const int MenuSaveImage = 26503;
private const int MenuCopyImageUrl = 26504; private const int MenuCopyImageUrl = 26504;
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){ public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
if (parameters.TypeFlags.HasFlag(ContextMenuType.Link) && !parameters.UnfilteredLinkUrl.EndsWith("tweetdeck.twitter.com/#", StringComparison.Ordinal)){ if (parameters.TypeFlags.HasFlag(ContextMenuType.Link) && !parameters.UnfilteredLinkUrl.EndsWith("tweetdeck.twitter.com/#", StringComparison.Ordinal)){
model.AddItem((CefMenuCommand)MenuOpenUrlInBrowser,"Open in browser"); model.AddItem((CefMenuCommand)MenuOpenLinkUrl, "Open link in browser");
model.AddItem((CefMenuCommand)MenuCopyUrl,"Copy link address"); model.AddItem((CefMenuCommand)MenuCopyLinkUrl, "Copy link address");
model.AddSeparator(); model.AddSeparator();
} }
if (parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents){ if (parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents){
model.AddItem((CefMenuCommand)MenuOpenImageInBrowser,"Open image in browser"); model.AddItem((CefMenuCommand)MenuOpenImage, "Open image in browser");
model.AddItem((CefMenuCommand)MenuSaveImage, "Save image as..."); model.AddItem((CefMenuCommand)MenuSaveImage, "Save image as...");
model.AddItem((CefMenuCommand)MenuCopyImageUrl,"Copy image URL"); model.AddItem((CefMenuCommand)MenuCopyImageUrl, "Copy image address");
model.AddSeparator(); model.AddSeparator();
} }
} }
public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){ public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
switch((int)commandId){ switch((int)commandId){
case MenuOpenUrlInBrowser: case MenuOpenLinkUrl:
BrowserUtils.OpenExternalBrowser(parameters.LinkUrl); BrowserUtils.OpenExternalBrowser(parameters.LinkUrl);
break; break;
case MenuCopyUrl: case MenuCopyLinkUrl:
Clipboard.SetText(string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedLink) ? parameters.UnfilteredLinkUrl : TweetDeckBridge.LastRightClickedLink, TextDataFormat.UnicodeText); Clipboard.SetText(string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedLink) ? parameters.UnfilteredLinkUrl : TweetDeckBridge.LastRightClickedLink, TextDataFormat.UnicodeText);
break; break;
case MenuOpenImageInBrowser: case MenuOpenImage:
BrowserUtils.OpenExternalBrowser(parameters.SourceUrl); BrowserUtils.OpenExternalBrowser(parameters.SourceUrl);
break; break;
@@ -84,6 +84,12 @@ namespace TweetDck.Core.Handling{
} }
} }
protected static void AddSeparator(IMenuModel model){
if (model.Count > 0 && model.GetTypeAt(model.Count-1) != MenuItemType.Separator){ // do not add separators if there is nothing to separate
model.AddSeparator();
}
}
private static string GetImageFileName(string url){ private static string GetImageFileName(string url){
// twimg adds a colon after file extension // twimg adds a colon after file extension
int dot = url.LastIndexOf('.'); int dot = url.LastIndexOf('.');

View File

@@ -1,15 +1,20 @@
using CefSharp; using CefSharp;
using System.Windows.Forms; using System.Windows.Forms;
using TweetDck.Core.Controls; using TweetDck.Core.Controls;
using TweetDck.Core.Utils;
namespace TweetDck.Core.Handling{ namespace TweetDck.Core.Handling{
class ContextMenuBrowser : ContextMenuBase{ class ContextMenuBrowser : ContextMenuBase{
private const int MenuSettings = 26600; private const int MenuGlobal = 26600;
private const int MenuPlugins = 26005; private const int MenuMute = 26601;
private const int MenuAbout = 26601; private const int MenuSettings = 26602;
private const int MenuMute = 26602; private const int MenuPlugins = 26003;
private const int MenuCopyTweetUrl = 26603; private const int MenuAbout = 26604;
private const int MenuCopyTweetEmbeddedUrl = 26604;
private const int MenuOpenTweetUrl = 26610;
private const int MenuCopyTweetUrl = 26611;
private const int MenuOpenQuotedTweetUrl = 26612;
private const int MenuCopyQuotedTweetUrl = 26613;
private readonly FormBrowser form; private readonly FormBrowser form;
@@ -24,31 +29,35 @@ namespace TweetDck.Core.Handling{
model.Remove(CefMenuCommand.ViewSource); model.Remove(CefMenuCommand.ViewSource);
RemoveSeparatorIfLast(model); RemoveSeparatorIfLast(model);
if (!string.IsNullOrEmpty(TweetDeckBridge.LastHighlightedTweet)){
model.AddItem((CefMenuCommand)MenuCopyTweetUrl,"Copy tweet address");
if (!string.IsNullOrEmpty(TweetDeckBridge.LastHighlightedTweetEmbedded)){
model.AddItem((CefMenuCommand)MenuCopyTweetEmbeddedUrl,"Copy quoted tweet address");
}
model.AddSeparator();
}
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model); base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
if (model.Count > 0){ if (!string.IsNullOrEmpty(TweetDeckBridge.LastHighlightedTweet) && (parameters.TypeFlags & (ContextMenuType.Editable | ContextMenuType.Selection)) == 0){
RemoveSeparatorIfLast(model); model.AddItem((CefMenuCommand)MenuOpenTweetUrl, "Open tweet in browser");
model.AddItem((CefMenuCommand)MenuCopyTweetUrl, "Copy tweet address");
if (!string.IsNullOrEmpty(TweetDeckBridge.LastHighlightedQuotedTweet)){
model.AddSeparator();
model.AddItem((CefMenuCommand)MenuOpenQuotedTweetUrl, "Open quoted tweet in browser");
model.AddItem((CefMenuCommand)MenuCopyQuotedTweetUrl, "Copy quoted tweet address");
}
model.AddSeparator(); model.AddSeparator();
} }
model.AddItem(CefMenuCommand.Reload,"Reload"); if ((parameters.TypeFlags & (ContextMenuType.Editable | ContextMenuType.Selection)) == 0){
model.AddCheckItem((CefMenuCommand)MenuMute,"Mute notifications"); AddSeparator(model);
model.SetChecked((CefMenuCommand)MenuMute,Program.UserConfig.MuteNotifications);
model.AddSeparator();
model.AddItem((CefMenuCommand)MenuSettings,"Settings"); IMenuModel globalMenu = model.Count == 0 ? model : model.AddSubMenu((CefMenuCommand)MenuGlobal, Program.BrandName);
model.AddItem((CefMenuCommand)MenuPlugins,"Plugins");
model.AddItem((CefMenuCommand)MenuAbout,"About "+Program.BrandName); globalMenu.AddItem(CefMenuCommand.Reload, "Reload browser");
globalMenu.AddCheckItem((CefMenuCommand)MenuMute, "Mute notifications");
globalMenu.SetChecked((CefMenuCommand)MenuMute, Program.UserConfig.MuteNotifications);
globalMenu.AddSeparator();
globalMenu.AddItem((CefMenuCommand)MenuSettings, "Settings");
globalMenu.AddItem((CefMenuCommand)MenuPlugins, "Plugins");
globalMenu.AddItem((CefMenuCommand)MenuAbout, "About "+Program.BrandName);
}
} }
public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){ public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
@@ -81,12 +90,20 @@ namespace TweetDck.Core.Handling{
return true; return true;
case MenuOpenTweetUrl:
BrowserUtils.OpenExternalBrowser(TweetDeckBridge.LastHighlightedTweet);
return true;
case MenuCopyTweetUrl: case MenuCopyTweetUrl:
Clipboard.SetText(TweetDeckBridge.LastHighlightedTweet, TextDataFormat.UnicodeText); Clipboard.SetText(TweetDeckBridge.LastHighlightedTweet, TextDataFormat.UnicodeText);
return true; return true;
case MenuCopyTweetEmbeddedUrl: case MenuOpenQuotedTweetUrl:
Clipboard.SetText(TweetDeckBridge.LastHighlightedTweetEmbedded,TextDataFormat.UnicodeText); BrowserUtils.OpenExternalBrowser(TweetDeckBridge.LastHighlightedQuotedTweet);
return true;
case MenuCopyQuotedTweetUrl:
Clipboard.SetText(TweetDeckBridge.LastHighlightedQuotedTweet, TextDataFormat.UnicodeText);
return true; return true;
} }

View File

@@ -10,7 +10,7 @@ namespace TweetDck.Core.Handling{
class TweetDeckBridge{ class TweetDeckBridge{
public static string LastRightClickedLink = string.Empty; public static string LastRightClickedLink = string.Empty;
public static string LastHighlightedTweet = string.Empty; public static string LastHighlightedTweet = string.Empty;
public static string LastHighlightedTweetEmbedded = string.Empty; public static string LastHighlightedQuotedTweet = string.Empty;
public static string NotificationTweetEmbedded = string.Empty; public static string NotificationTweetEmbedded = string.Empty;
public static string ClipboardImagePath = string.Empty; public static string ClipboardImagePath = string.Empty;
@@ -74,10 +74,10 @@ namespace TweetDck.Core.Handling{
form.InvokeSafe(() => LastRightClickedLink = link); form.InvokeSafe(() => LastRightClickedLink = link);
} }
public void SetLastHighlightedTweet(string link, string embeddedLink){ public void SetLastHighlightedTweet(string link, string quotedLink){
form.InvokeSafe(() => { form.InvokeSafe(() => {
LastHighlightedTweet = link; LastHighlightedTweet = link;
LastHighlightedTweetEmbedded = embeddedLink; LastHighlightedQuotedTweet = quotedLink;
}); });
} }
@@ -155,6 +155,19 @@ namespace TweetDck.Core.Handling{
BrowserUtils.OpenExternalBrowser(url); BrowserUtils.OpenExternalBrowser(url);
} }
public void Alert(string type, string contents){
MessageBoxIcon icon;
switch(type){
case "error": icon = MessageBoxIcon.Error; break;
case "warning": icon = MessageBoxIcon.Warning; break;
case "info": icon = MessageBoxIcon.Information; break;
default: icon = MessageBoxIcon.None; break;
}
MessageBox.Show(contents, Program.BrandName+" Browser Message", MessageBoxButtons.OK, icon);
}
public void Log(string data){ public void Log(string data){
System.Diagnostics.Debug.WriteLine(data); System.Diagnostics.Debug.WriteLine(data);
} }

View File

@@ -43,11 +43,16 @@ namespace TweetDck.Core.Handling{
build.Append(@"<header class='tweet-header'>"); build.Append(@"<header class='tweet-header'>");
build.Append(@"<time class='tweet-timestamp js-timestamp pull-right txt-mute'><a target='_blank' rel='url' href='https://twitter.com/chylexmc' class='txt-small'>0s</a></time>"); build.Append(@"<time class='tweet-timestamp js-timestamp pull-right txt-mute'><a target='_blank' rel='url' href='https://twitter.com/chylexmc' class='txt-small'>0s</a></time>");
build.Append(@"<a target='_blank' rel='user' href='https://twitter.com/chylexmc' class='account-link link-complex block'>"); build.Append(@"<a target='_blank' rel='user' href='https://twitter.com/chylexmc' class='account-link link-complex block'>");
build.Append(@"<div class='obj-left item-img tweet-img'><img width='48' height='48' alt='chylexmc's avatar' src='https://pbs.twimg.com/profile_images/645532929930608642/J56NBJVY_normal.png' class='tweet-avatar avatar pull-right'></div>"); build.Append(@"<div class='obj-left item-img tweet-img'><img width='48' height='48' alt='chylexmc's avatar' src='https://pbs.twimg.com/profile_images/765161905312980992/AhDP9iY-_normal.jpg' class='tweet-avatar avatar pull-right'></div>");
build.Append(@"<div class='nbfc'><span class='account-inline txt-ellipsis'><b class='fullname link-complex-target'>chylex</b> <span class='username txt-mute'>@chylexmc</span></span></div>"); build.Append(@"<div class='nbfc'><span class='account-inline txt-ellipsis'><b class='fullname link-complex-target'>chylex</b> <span class='username txt-mute'>@chylexmc</span></span></div>");
build.Append(@"</a>"); build.Append(@"</a>");
build.Append(@"</header>"); build.Append(@"</header>");
build.Append(@"<div class='tweet-body'><p class='js-tweet-text tweet-text with-linebreaks'>This is an example tweet, which lets you test the location and duration of popup notifications.</p></div>"); build.Append(@"<div class='tweet-body'><p class='js-tweet-text tweet-text with-linebreaks'>This is an example tweet, which lets you test the location and duration of popup notifications.</p></div>");
#if DEBUG
build.Append(@"<div style='margin-top:64px'>Scrollbar test padding...</div>");
#endif
build.Append(@"</div></div></article>"); build.Append(@"</div></div></article>");
return new TweetNotification(build.ToString(), "", 95); return new TweetNotification(build.ToString(), "", 95);

View File

@@ -23,7 +23,6 @@
/// the contents of this method with the code editor. /// the contents of this method with the code editor.
/// </summary> /// </summary>
private void InitializeComponent() { private void InitializeComponent() {
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormPlugins));
this.btnClose = new System.Windows.Forms.Button(); this.btnClose = new System.Windows.Forms.Button();
this.btnReload = new System.Windows.Forms.Button(); this.btnReload = new System.Windows.Forms.Button();
this.btnOpenFolder = new System.Windows.Forms.Button(); this.btnOpenFolder = new System.Windows.Forms.Button();
@@ -69,7 +68,7 @@
this.btnOpenFolder.UseVisualStyleBackColor = true; this.btnOpenFolder.UseVisualStyleBackColor = true;
this.btnOpenFolder.Click += new System.EventHandler(this.btnOpenFolder_Click); this.btnOpenFolder.Click += new System.EventHandler(this.btnOpenFolder_Click);
// //
// pluginList // tabPanelPlugins
// //
this.tabPanelPlugins.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) this.tabPanelPlugins.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Left)
@@ -88,11 +87,10 @@
this.Controls.Add(this.btnOpenFolder); this.Controls.Add(this.btnOpenFolder);
this.Controls.Add(this.btnReload); this.Controls.Add(this.btnReload);
this.Controls.Add(this.btnClose); this.Controls.Add(this.btnClose);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Icon = global::TweetDck.Properties.Resources.icon;
this.MinimumSize = new System.Drawing.Size(480, 320); this.MinimumSize = new System.Drawing.Size(480, 320);
this.Name = "FormPlugins"; this.Name = "FormPlugins";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Plugins";
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using TweetDck.Core.Controls; using TweetDck.Core.Controls;
using TweetDck.Plugins; using TweetDck.Plugins;
@@ -7,7 +9,7 @@ using TweetDck.Plugins.Controls;
using TweetDck.Plugins.Events; using TweetDck.Plugins.Events;
namespace TweetDck.Core.Other{ namespace TweetDck.Core.Other{
partial class FormPlugins : Form{ sealed partial class FormPlugins : Form{
private readonly PluginManager pluginManager; private readonly PluginManager pluginManager;
private readonly TabButton tabBtnOfficial, tabBtnCustom; private readonly TabButton tabBtnOfficial, tabBtnCustom;
private readonly PluginListFlowLayout flowLayoutPlugins; private readonly PluginListFlowLayout flowLayoutPlugins;
@@ -16,6 +18,8 @@ namespace TweetDck.Core.Other{
public FormPlugins(){ public FormPlugins(){
InitializeComponent(); InitializeComponent();
Text = Program.BrandName+" Plugins";
} }
public FormPlugins(PluginManager pluginManager) : this(){ public FormPlugins(PluginManager pluginManager) : this(){
@@ -58,8 +62,17 @@ namespace TweetDck.Core.Other{
flowLayoutPlugins.SuspendLayout(); flowLayoutPlugins.SuspendLayout();
flowLayoutPlugins.Controls.Clear(); flowLayoutPlugins.Controls.Clear();
foreach(Plugin plugin in pluginManager.GetPluginsByGroup(selectedGroup.Value)){ Plugin[] plugins = pluginManager.GetPluginsByGroup(selectedGroup.Value).OrderBy(plugin => !plugin.CanRun ? 0 : pluginManager.Config.IsEnabled(plugin) ? 1 : 2).ThenBy(plugin => plugin.Name).ToArray();
flowLayoutPlugins.Controls.Add(new PluginControl(pluginManager,plugin));
for(int index = 0; index < plugins.Length; index++){
flowLayoutPlugins.Controls.Add(new PluginControl(pluginManager, plugins[index]));
if (index < plugins.Length-1){
flowLayoutPlugins.Controls.Add(new Panel{
BackColor = Color.DimGray,
Size = new Size(1, 1)
});
}
} }
flowLayoutPlugins_Resize(flowLayoutPlugins, new EventArgs()); flowLayoutPlugins_Resize(flowLayoutPlugins, new EventArgs());
@@ -72,11 +85,22 @@ namespace TweetDck.Core.Other{
} }
private void flowLayoutPlugins_Resize(object sender, EventArgs e){ private void flowLayoutPlugins_Resize(object sender, EventArgs e){
int horizontalOffset = 8+(flowLayoutPlugins.VerticalScroll.Visible ? SystemInformation.VerticalScrollBarWidth : 0); if (flowLayoutPlugins.Controls.Count == 0){
return;
}
Control lastControl = flowLayoutPlugins.Controls[flowLayoutPlugins.Controls.Count-1];
bool showScrollBar = lastControl.Location.Y+lastControl.Height >= flowLayoutPlugins.Height;
int horizontalOffset = showScrollBar ? SystemInformation.VerticalScrollBarWidth : 0;
flowLayoutPlugins.AutoScroll = showScrollBar;
flowLayoutPlugins.VerticalScroll.Visible = showScrollBar;
foreach(Control control in flowLayoutPlugins.Controls){ foreach(Control control in flowLayoutPlugins.Controls){
control.Width = flowLayoutPlugins.Width-control.Margin.Horizontal-horizontalOffset; control.Width = flowLayoutPlugins.Width-control.Margin.Horizontal-horizontalOffset;
} }
flowLayoutPlugins.Focus();
} }
private void btnOpenFolder_Click(object sender, EventArgs e){ private void btnOpenFolder_Click(object sender, EventArgs e){
@@ -84,9 +108,11 @@ namespace TweetDck.Core.Other{
} }
private void btnReload_Click(object sender, EventArgs e){ private void btnReload_Click(object sender, EventArgs e){
if (MessageBox.Show("This will also reload the browser window. Do you want to proceed?", "Reloading Plugins", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
pluginManager.Reload(); pluginManager.Reload();
ReloadPluginTab(); ReloadPluginTab();
} }
}
private void btnClose_Click(object sender, EventArgs e){ private void btnClose_Click(object sender, EventArgs e){
Close(); Close();

View File

@@ -117,261 +117,4 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAMAMDAAAAEAIACoJQAANgAAACAgAAABACAAqBAAAN4lAAAQEAAAAQAgAGgEAACGNgAAKAAAADAA
AABgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqHg5IrF+OlS+hjyMw4g7tcmM
PM/MjTzezY485s2OPObMjjzfyIw80MOJPLe8hDyNs387WKx8OyQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApHU4FrB8OGXGijzAzo889dKR
PP/SkTz/0pE8/9GRPP/RkDz/0JA8/9CQPP/RkDz/0ZE8/9KRPP/TkTz/0pE8/86PPPbGijzCt4E8bKp6
OxoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKN1OB+9hTuLzI486NOR
PP/SkTz/0ZA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GQ
PP/SkTz/0pE8/82OPOu9hTuOq3w8IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACidTkFuoM8csyN
POrTkjz/0ZE8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GRPP/Tkjz/zY887bqEPHimeDsHAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKp6
OynDiDvA05I8/9GRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0ZA8/9ORPP/GijzFr308LgAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAArXw7UM2OPOvTkTz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/SkTz/zo887rOAPFYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACxfjxm0ZA8/NGRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0ZE8/9GQPP64gjxtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAALaBPGXRkTz/0ZE8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GQPP/SkTz/uIM8bAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqnk6TtCQPPzRkTz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkDz/0ZA8/rSA
PFUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACtfDwmzo887dKRPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0ZE8/86PPPGtfDwrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKZ4PAXFijzC0pE8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CURf/TpGT/2baJ/9/GpP/l0bf/59W//+fVvf/kz7P/3sOg/9mz
hP/ToWH/0JND/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9KRPP/EiTvJo3Y7CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALiC
PG/Tkjz/0JA8/9CQPP/QkDz/0JA8/9CSQf/Vq3P/5tO7//j07v//////////////////////////////
////////////////////////9vHq/+TQtf/UqG7/0JA+/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/Tkjz/uYM8dgAAAAAAAAAAAAAAAAAA
AAAAAAAArXw8Gc2OPOzRkTz/0JA8/9CQPP/QlEX/27qP//fz7P//////////////////////////////
////////////////////////////////////////////////////////8ObZ/9auev/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkTz/zI488J1x
OB8AAAAAAAAAAAAAAAAAAAAAuoM7h9OSPP/QkDz/0JA8/9GXTf/TpGb/27uS/9u6kP/ewZz/59W9//Xv
5///////////////////////////////////////////////////////////////////////////////
///r3cr/0ZxV/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/1JI8/7mDO5AAAAAAAAAAAAAAAADFj0cR0pNB6s+PO//Ojjv/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CRQP/TpGf/5NC2//38+v//////////////////////////////////////////////
////////////////////////+vf0/9auev/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0ZE8/8uOPO6SajYVAAAAAAAAAADzr1df7qxV/+WkT//ZmUT/0JA9/86O
O//Pjzv/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GaUv/l07r/////////////////////////
///////////////////////////////////////////////////buo//0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9OSPP+ldjdoAAAAAAAAAADurFW67qxV//Ct
Vv/vrVb/6adR/92dSP/Skz//zo47/8+PO//QkDz/0JA8/9CQPP/QkDz/0JJB/9Smaf/dv5j/+fXw////
////////////////////////////////////////////////////////////////////////2riM/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9KRPP/FiTzGoHQ6Ae6s
VRrurFXz7qxV/+6sVf/urFX/761W//CuVv/sqlT/4qFM/9aVQv/Pjzv/zo47/9CQPP/VqnH/8+vh////
////////////////////////////////////////////////////////////////////////////////
/////////////9aueP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GQ
PP/Ojzz4oHM5Iu6sVU3urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/vrVX/8K5W/+6sVf/mpU//2plF/9q6
j///////////////////////////////////////////////////////////////////////////////
//////////////////////////////n18P/Rm1P/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/SkTz/rXs6Vu6sVYPurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/wrVb/6r2B////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////o18L/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/v4Y8j+6sVa3urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFb/9Onb///////+/v3/////////////////////////////////////////
////////////////////////////////////////////////////////////////////////1qx2/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/wYc7uO6sVcrurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/trlr/67Zy/+m+h//y5NP/////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////7+TW/9CQPf/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkTz/yYw80e6s
VdvurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/6sme//v49P//////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////9arc//QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/RkDz/zI083+6sVeLurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/u2b3/////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////+fVvv/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/zo885u6sVeLurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+vL
of//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////r28v/Rl0r/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/zo885u6sVdrurFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7LBj//r28f//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///Vq3P/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkDz/zI083+6sVcrurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/6cKO////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///////////////////ewp7/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkTz/yYw80O6s
VazurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7NOy//z59v/u2b7/+fPr////////////////////
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////n1sD/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/SkTz/xIo8uO6sVYHurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/67Zx/+2uWf/qy6H/////////
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////v5dj/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/SkTz/vYU8je6sVUvurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+nC
kP///////////////////////////////////////////////////////fz6//fu5P/w4Mv/793F//7+
/v/////////////////////////////////////////////////////////////////17eT/0JA//86O
Ov/Pjzv/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/tYA8Vu6sVRnurFXy7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7a5b//fw5///////////////////////////////////////+/jz/+7av//pwIr/67Jn/+6t
Vv/urFX/6rd1////////////////////////////////////////////////////////////////////
///48ej/6KhU/92cR//Tkj7/zo47/8+PO//QkDz/0JA8/9GQPP/Pjzz3rXw8IAAAAADurFW37qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/6b2D//////////////////////////////////nz6//qyZ3/7K9h/+6s
Vf/urFX/7qxV/+6sVf/urFX/6rl6////////////////////////////////////////////////////
///////////////////9/Pr/6r6C//CuV//sqlT/4aBL/9aWQv/Pjzv/zo47/9GRPP/GijzCp3g8AQAA
AADurFVb7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/68yk///////////////////////+/fz/68+q/+2v
XP/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/6rNr//7+/f//////////////////////////////
/////////////////////////////////////////////+nEk//vrVX/8K5W/+6sVf/lpE//2ZlF/9KR
Pf+zfzpoAAAAAAAAAADurFUP7qxV5u6sVf/urFX/7qxV/+6sVf/urFX/7NGu//////////////////fu
5P/quHb/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxW//Xr3///////////////
///////////////////////////////////////////////////7+PP/+vXu///////pxJL/7qxV/+6s
Vf/wrVb/8K1W/+mnUevUmUsUAAAAAAAAAAAAAAAA7qxVgO6sVf/urFX/7qxV/+6sVf/urFX/6sqg////
////////8eLO/+yvX//urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+nF
lf/////////////////////////////////////////////////////////////////8+vf/6cWV/+q5
ev/s07H/6rd1/+6sVf/urFX/7qxV/++tVogAAAAAAAAAAAAAAAAAAAAA7qxVFe6sVejurFX/7qxV/+6s
Vf/urFX/6bp8///////w4Mn/7a1Z/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/x4cz////////////////////////////////////////////////////+//7+
/v/////////+/+m8gP/urFX/7a1Y/+6sVf/urFX/7qxV7O6sVRoAAAAAAAAAAAAAAAAAAAAAAAAAAO6s
VWburFX/7qxV/+6sVf/urFX/7a5b/+zTs//sr1//7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/sr1//8uPQ////////////////////////////////////
////////6suj/+qzav/pxpj/9Onb//n07f/rr2D/7qxV/+6sVf/urFX/7qxVbwAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAO6sVQPurFW67qxV/+6sVf/urFX/7qxV/+6sVv/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7axY/+nGl//27uP/////////
/////////fz6//Lj0P/qunv/7qxV/+6sVf/urFX/7qxV/+m9gv/qt3X/7qxV/+6sVf/urFXB7qxVBQAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADurFUg7qxV6O6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/qtnP/6sqg/+3WuP/s07P/6cSS/+uyZf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVv/trVr/7qxV/+6s
VezurFUlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVRu6sVfjurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV++6sVUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6s
VVzurFX97qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxVYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADurFVd7qxV+O6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVfvurFVjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVR+6sVeXurFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV6O6sVU0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVSPurFW37qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFW77qxVJgAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADurFUB7qxVae6sVeTurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV5+6sVW3urFUDAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVRjurFWA7qxV4u6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVeTurFWE7qxVGwAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVEu6sVV7urFW17qxV7+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVfDurFW47qxVX+6s
VRMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA7qxVG+6sVUzurFWA7qxVrO6sVcnurFXa7qxV4u6sVeLurFXa7qxVye6sVa3urFWC7qxVTe6s
VR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP//gAH//6gr//wAAD//qCv/8AAAD/+oK//AAAAD/6gr/4AAAAH/qCv/AAAAAP+oK/4A
AAAAf6gr/AAAAAA/qCv4AAAAAB+oK/AAAAAAD6gr4AAAAAAHqCvgAAAAAAeoK8AAAAAAA6grwAAAAAAD
qCuAAAAAAAGoK4AAAAAAAagrgAAAAAAAqCsAAAAAAACoKwAAAAAAAKgrAAAAAAAAqCsAAAAAAACoKwAA
AAAAAKgrAAAAAAAAqCsAAAAAAACoKwAAAAAAAKgrAAAAAAAAqCsAAAAAAACoKwAAAAAAAKgrAAAAAAAA
qCsAAAAAAACoKwAAAAAAAKgrgAAAAAAAqCuAAAAAAAGoK4AAAAAAAagrwAAAAAADqCvAAAAAAAOoK+AA
AAAAB6gr4AAAAAAHqCvwAAAAAA+oK/gAAAAAH6gr/AAAAAA/qCv+AAAAAH+oK/8AAAAA/6gr/4AAAAH/
qCv/wAAAA/+oK//wAAAP/6gr//wAAD//qCv//4AB//+oKygAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApHY4FrR/
Ole+hjuVxos7w8uNPNvOjzznzo8858uNPNzGijzEvoU7l7WBO1mpejsYAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqHg5Kr6F
O5XLjTvo0pE8/9ORPP/SkTz/0ZE8/9CQPP/QkDz/0ZE8/9KRPP/TkTz/0pE8/82OPOq/hjyZrXw7LAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo3U6CbuE
O4bPjzz005I8/9GRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0ZE8/9OS
PP/PkDz1vYU8iah6PAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKR3
OibGizvG05E8/9GQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9GQPP/TkTz/yIs8yqx8PCkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACsezsxy40849KRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/zI485rKAPTUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAApXc6JMuNPOTSkTz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/zI485659PCcAAAAAAAAAAAAA
AAAAAAAAAAAAAKd4OwnHizzJ0pE8/9CQPP/QkDz/0JA9/9OgYP/YtIX/38Sh/+LMr//iy67/3sOf/9iy
gv/Tn13/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/x4s8zaV4
OwsAAAAAAAAAAAAAAAAAAAAAu4Q8hNOSPP/QkDz/0JA8/9GXS//YtIX/6NfC//Xv5//8+vj/////////
///8+vf/9O3k/+fVvv/YsYH/0JRF/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/Tkjz/u4Q7iQAAAAAAAAAAAAAAAKx7OyTPjzz10ZA8/9GXS//Ztoj/8une////////////////////
///////////////////////////////////38uz/3L2V/9CRP//QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9GRPP/Ojzz3onU5KQAAAAAAAAAAxo1BlNGQO//Ojjv/0JNC/9GWSP/QlET/0ZpR/9au
eP/n1b3//v79////////////////////////////////////////////7+TV/9GdWP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9SSPP+4gjqaAAAAAPGuVhHvrVXq5qRO/9qZRP/QkT3/zo46/8+P
O//QkDz/0JA8/9CQPP/To2P/8+vh////////////////////////////////////////////+fXw/9Oh
Yf/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0pE8/8qMO+2WbTYV7qxVUe6sVf/wrVb/761W/+mo
Uv/enUj/05M//86PO//PkD7/3cCZ//Lp3v/7+PT/////////////////////////////////////////
////////+PTv/9GcVf/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/05I8/699OljurFWR7qxV/+6s
Vf/urFX/761W//CuV//sqlT/4qJQ/+zdyf//////////////////////////////////////////////
////////////////////////7+TV/9CRP//QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/Tkjz/vIQ7mO6s
Vb/urFX/7qxV/+6sVf/urFX/7qxV/++tVf/ry5///v79//7+/f//////////////////////////////
////////////////////////////////////////2rqO/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9KR
PP/GijvF7qxV2u6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+u1bv/t1bb//fv4////////////////////
///////////////////////////////////////////////////48+3/0ZRG/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0ZA8/8uNPNzurFXl7qxV/+6sVf/urFX/7qxV/+6sVf/rsWP/9OjZ////////////////////
///////////////////////////////////////////////////////////////////YtIX/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/zo886O6sVeXurFX/7qxV/+6sVf/urFX/7qxW//Hiz///////////////
/////////////////////////////////////////////////////////////////////////////+rb
yP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/Ojzzo7qxV2e6sVf/urFX/7qxV/+6sVf/quHb/////////
////////////////////////////////////////////////////////////////////////////////
////////+fXw/9CURf/QkDz/0JA8/9CQPP/QkDz/0ZA8/8yOPNzurFW/7qxV/+6sVf/urFX/7qxV/+nA
if/s1LT/9Onb////////////////////////////////////////////////////////////////////
////////////////////////0Z5b/9CQPP/QkDz/0JA8/9CQPP/SkTz/x4s8xe6sVY/urFX/7qxV/+6s
Vf/urFX/7qxV/+nEk//+/fz////////////////////////////+/v3/+PHo//To2f/+/v7/////////
///////////////////////////////////VqGz/zo46/8+PO//QkDz/0JA8/9KRPP+/hjyX7qxVUO6s
Vf/urFX/7qxV/+6sVf/ssGH//Pr2///////////////////////y49D/6cOR/+qyaf/urVb/6rJp////
/////////////////////////////////////////////+e7f//goEr/1ZVB/8+PO//Ojzv/0pE8/7WB
PFfurFUQ7qxV6O6sVf/urFX/7qxV/+m+hv/////////////////z5tX/6rl6/+6sVf/urFX/7qxV/+6s
Vf/qs2r////+////////////////////////////////////////////+PLp/+y4c//urFX/5aRO/9qZ
RP/Mjjztp3g6FQAAAADurFWQ7qxV/+6sVf/urFX/6cKP////////////682m/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+2sV//17N////////////////////////////////////////7+/v/06Nn/8uTT/+qz
a//wrVb/761W/+alUZYAAAAAAAAAAO6sVSHurFX07qxV/+6sVf/quXj//////+nDkf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+m+hP////////////////////////////////////////////jy
6v/qtnH/67Fj/+6sVf/urFX2761WJQAAAAAAAAAAAAAAAO6sVX7urFX/7qxV/+2vW//pvID/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+nEkv/7+PT//////////////////fz6/+rJ
n//rtW7/682n/+zTs//urFb/7qxV/+6sVYQAAAAAAAAAAAAAAAAAAAAA7qxVB+6sVcTurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+u0bP/qy6H/7da4/+vN
pv/qtnP/7qxV/+6sVf/urFX/7K9f/+2sWP/urFXI7qxVCQAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVIO6s
VeDurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV4+6sVSMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA7qxVLO6sVd/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVeLurFUwAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA7qxVIu6sVcHurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFXE7qxVJAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVBu6sVX/urFXw7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFXy7qxVgu6sVQgAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVSXurFWP7qxV5e6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFXl7qxVke6sVScAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADurFUS7qxVUO6sVY7urFW97qxV2O6sVeXurFXl7qxV2O6sVb7urFWP7qxVUu6sVRMAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8AD//8AAP/8AAA/+AAAH/AAAA/gAAAHwAAAA8AA
AAOAAAABgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA
AAGAAAABwAAAA8AAAAPgAAAH8AAAD/gAAB/8AAA//wAA///AA/8oAAAAEAAAACAAAAABACAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKx7Oja9hTqTyYw8zs6PPOfOjzznyYw8zr6G
PJSvfjw3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo3Y7CbyEO5PRkDz805I8/9GRPP/QkDz/0JA8/9GR
PP/TkTz/0ZA8/b+GPJWrfDwKAAAAAAAAAAAAAAAAp3g8CcSJPLfTkjz/0ZA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/Tkjz/xoo8uqx8PQoAAAAAAAAAAL2FPJPUk0D/06Rm/92/mf/izK//4sut/9u6
j//Snlr/0JA8/9CQPP/QkDz/0JA8/9OSPP+9hTyWAAAAALiEQDLQkDz90JpS/93Amf/u4tP/////////
/////////fv5/+DIqP/QkkH/0JA8/9CQPP/RkDz/0JA8/qN1OTTtq1WS56VP/9qaRf/RkT3/0JdO/+rc
yP//////////////////////693L/9CSQf/QkDz/0JA8/9SSPP+3gTqW761Vz++tVv/wrVb/6K5h//fy
6v/////////////////////////////////gx6b/0JA8/9CQPP/RkTz/yYw80e6sVefurFX/7qxV/+q+
hP/69vD//////////////////////////////////fz7/9GbU//QkDz/0JA8/8+PPOnurFXn7qxV/+yw
Y//79/P////////////////////////////////////////////ZuIz/0JA8/9CQPP/Pjzzp7qxVz+6s
Vf/sr2H/8eLO/////////////v7+//n07f/+/v7/////////////////48yu/8+PO//Qjzv/yYs80e6s
VZLurFX/67Jm//7+/f/8+fb/68yl/+qza//rsmf//v37//////////////////Pn2P/ip1n/2phC/8CH
PJXurFUw7qxV/eq2c//169//6rNr/+6sVf/urFX/7q1W//Pm1f/////////////////8+fX/67+G/++t
Vf3lpVEyAAAAAO6sVZHtrVr/7a9c/+6sVf/urFX/7qxV/+6sVf/rsWP/7de5//Lj0P/pxJL/67Zy/+qz
av/urFWTAAAAAAAAAADurFUI7qxVtO6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFW37qxVCQAAAAAAAAAAAAAAAO6sVQjurFWQ7qxV++6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
VfvurFWS7qxVCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVTPurFWQ7qxVzO6sVeburFXm7qxVzO6s
VZDurFU0AAAAAAAAAAAAAAAAAAAAAPAPrEHAA6xBgAGsQYABrEEAAKxBAACsQQAArEEAAKxBAACsQQAA
rEEAAKxBAACsQYABrEGAAaxBwAOsQfAPrEE=
</value>
</data>
</root> </root>

View File

@@ -23,7 +23,6 @@
/// the contents of this method with the code editor. /// the contents of this method with the code editor.
/// </summary> /// </summary>
private void InitializeComponent() { private void InitializeComponent() {
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormSettings));
this.btnClose = new System.Windows.Forms.Button(); this.btnClose = new System.Windows.Forms.Button();
this.labelTip = new System.Windows.Forms.Label(); this.labelTip = new System.Windows.Forms.Label();
this.tabPanel = new TweetDck.Core.Controls.TabPanel(); this.tabPanel = new TweetDck.Core.Controls.TabPanel();
@@ -70,7 +69,7 @@
this.Controls.Add(this.btnClose); this.Controls.Add(this.btnClose);
this.Controls.Add(this.tabPanel); this.Controls.Add(this.tabPanel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Icon = Properties.Resources.icon;
this.MaximizeBox = false; this.MaximizeBox = false;
this.MinimizeBox = false; this.MinimizeBox = false;
this.Name = "FormSettings"; this.Name = "FormSettings";

View File

@@ -3,14 +3,14 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using TweetDck.Core.Other.Settings; using TweetDck.Core.Other.Settings;
using TweetDck.Core.Other.Settings.Export; using TweetDck.Plugins;
using TweetDck.Updates; using TweetDck.Updates;
namespace TweetDck.Core.Other{ namespace TweetDck.Core.Other{
sealed partial class FormSettings : Form{ sealed partial class FormSettings : Form{
private readonly Dictionary<Type, BaseTabSettings> tabs = new Dictionary<Type, BaseTabSettings>(4); private readonly Dictionary<Type, BaseTabSettings> tabs = new Dictionary<Type, BaseTabSettings>(4);
public FormSettings(FormBrowser browserForm, UpdateHandler updates){ public FormSettings(FormBrowser browserForm, PluginManager plugins, UpdateHandler updates){
InitializeComponent(); InitializeComponent();
Text = Program.BrandName+" Settings"; Text = Program.BrandName+" Settings";
@@ -19,7 +19,7 @@ namespace TweetDck.Core.Other{
this.tabPanel.AddButton("General", SelectTab<TabSettingsGeneral>); this.tabPanel.AddButton("General", SelectTab<TabSettingsGeneral>);
this.tabPanel.AddButton("Notifications", () => SelectTab(() => new TabSettingsNotifications(browserForm.CreateNotificationForm(false)))); this.tabPanel.AddButton("Notifications", () => SelectTab(() => new TabSettingsNotifications(browserForm.CreateNotificationForm(false))));
this.tabPanel.AddButton("Updates", () => SelectTab(() => new TabSettingsUpdates(updates))); this.tabPanel.AddButton("Updates", () => SelectTab(() => new TabSettingsUpdates(updates)));
this.tabPanel.AddButton("Advanced",() => SelectTab(() => new TabSettingsAdvanced(browserForm.ReloadBrowser))); this.tabPanel.AddButton("Advanced", () => SelectTab(() => new TabSettingsAdvanced(browserForm.ReloadBrowser, plugins)));
this.tabPanel.SelectTab(tabPanel.Buttons.First()); this.tabPanel.SelectTab(tabPanel.Buttons.First());
} }

View File

@@ -117,261 +117,4 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAMAMDAAAAEAIACoJQAANgAAACAgAAABACAAqBAAAN4lAAAQEAAAAQAgAGgEAACGNgAAKAAAADAA
AABgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqHg5IrF+OlS+hjyMw4g7tcmM
PM/MjTzezY485s2OPObMjjzfyIw80MOJPLe8hDyNs387WKx8OyQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApHU4FrB8OGXGijzAzo889dKR
PP/SkTz/0pE8/9GRPP/RkDz/0JA8/9CQPP/RkDz/0ZE8/9KRPP/TkTz/0pE8/86PPPbGijzCt4E8bKp6
OxoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKN1OB+9hTuLzI486NOR
PP/SkTz/0ZA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GQ
PP/SkTz/0pE8/82OPOu9hTuOq3w8IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACidTkFuoM8csyN
POrTkjz/0ZE8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GRPP/Tkjz/zY887bqEPHimeDsHAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKp6
OynDiDvA05I8/9GRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0ZA8/9ORPP/GijzFr308LgAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAArXw7UM2OPOvTkTz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/SkTz/zo887rOAPFYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACxfjxm0ZA8/NGRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0ZE8/9GQPP64gjxtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAALaBPGXRkTz/0ZE8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GQPP/SkTz/uIM8bAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqnk6TtCQPPzRkTz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkDz/0ZA8/rSA
PFUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACtfDwmzo887dKRPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0ZE8/86PPPGtfDwrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKZ4PAXFijzC0pE8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CURf/TpGT/2baJ/9/GpP/l0bf/59W//+fVvf/kz7P/3sOg/9mz
hP/ToWH/0JND/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9KRPP/EiTvJo3Y7CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALiC
PG/Tkjz/0JA8/9CQPP/QkDz/0JA8/9CSQf/Vq3P/5tO7//j07v//////////////////////////////
////////////////////////9vHq/+TQtf/UqG7/0JA+/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/Tkjz/uYM8dgAAAAAAAAAAAAAAAAAA
AAAAAAAArXw8Gc2OPOzRkTz/0JA8/9CQPP/QlEX/27qP//fz7P//////////////////////////////
////////////////////////////////////////////////////////8ObZ/9auev/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkTz/zI488J1x
OB8AAAAAAAAAAAAAAAAAAAAAuoM7h9OSPP/QkDz/0JA8/9GXTf/TpGb/27uS/9u6kP/ewZz/59W9//Xv
5///////////////////////////////////////////////////////////////////////////////
///r3cr/0ZxV/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/1JI8/7mDO5AAAAAAAAAAAAAAAADFj0cR0pNB6s+PO//Ojjv/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CRQP/TpGf/5NC2//38+v//////////////////////////////////////////////
////////////////////////+vf0/9auev/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0ZE8/8uOPO6SajYVAAAAAAAAAADzr1df7qxV/+WkT//ZmUT/0JA9/86O
O//Pjzv/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GaUv/l07r/////////////////////////
///////////////////////////////////////////////////buo//0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9OSPP+ldjdoAAAAAAAAAADurFW67qxV//Ct
Vv/vrVb/6adR/92dSP/Skz//zo47/8+PO//QkDz/0JA8/9CQPP/QkDz/0JJB/9Smaf/dv5j/+fXw////
////////////////////////////////////////////////////////////////////////2riM/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9KRPP/FiTzGoHQ6Ae6s
VRrurFXz7qxV/+6sVf/urFX/761W//CuVv/sqlT/4qFM/9aVQv/Pjzv/zo47/9CQPP/VqnH/8+vh////
////////////////////////////////////////////////////////////////////////////////
/////////////9aueP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9GQ
PP/Ojzz4oHM5Iu6sVU3urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/vrVX/8K5W/+6sVf/mpU//2plF/9q6
j///////////////////////////////////////////////////////////////////////////////
//////////////////////////////n18P/Rm1P/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/SkTz/rXs6Vu6sVYPurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/wrVb/6r2B////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////o18L/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/v4Y8j+6sVa3urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFb/9Onb///////+/v3/////////////////////////////////////////
////////////////////////////////////////////////////////////////////////1qx2/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/wYc7uO6sVcrurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/trlr/67Zy/+m+h//y5NP/////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////7+TW/9CQPf/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkTz/yYw80e6s
VdvurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/6sme//v49P//////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////9arc//QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/RkDz/zI083+6sVeLurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/u2b3/////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////+fVvv/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/zo885u6sVeLurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+vL
of//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////r28v/Rl0r/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/zo885u6sVdrurFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7LBj//r28f//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///Vq3P/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkDz/zI083+6sVcrurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/6cKO////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///////////////////ewp7/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/RkTz/yYw80O6s
VazurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7NOy//z59v/u2b7/+fPr////////////////////
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////n1sD/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/SkTz/xIo8uO6sVYHurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/67Zx/+2uWf/qy6H/////////
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////v5dj/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/SkTz/vYU8je6sVUvurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+nC
kP///////////////////////////////////////////////////////fz6//fu5P/w4Mv/793F//7+
/v/////////////////////////////////////////////////////////////////17eT/0JA//86O
Ov/Pjzv/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/tYA8Vu6sVRnurFXy7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7a5b//fw5///////////////////////////////////////+/jz/+7av//pwIr/67Jn/+6t
Vv/urFX/6rd1////////////////////////////////////////////////////////////////////
///48ej/6KhU/92cR//Tkj7/zo47/8+PO//QkDz/0JA8/9GQPP/Pjzz3rXw8IAAAAADurFW37qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/6b2D//////////////////////////////////nz6//qyZ3/7K9h/+6s
Vf/urFX/7qxV/+6sVf/urFX/6rl6////////////////////////////////////////////////////
///////////////////9/Pr/6r6C//CuV//sqlT/4aBL/9aWQv/Pjzv/zo47/9GRPP/GijzCp3g8AQAA
AADurFVb7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/68yk///////////////////////+/fz/68+q/+2v
XP/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/6rNr//7+/f//////////////////////////////
/////////////////////////////////////////////+nEk//vrVX/8K5W/+6sVf/lpE//2ZlF/9KR
Pf+zfzpoAAAAAAAAAADurFUP7qxV5u6sVf/urFX/7qxV/+6sVf/urFX/7NGu//////////////////fu
5P/quHb/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxW//Xr3///////////////
///////////////////////////////////////////////////7+PP/+vXu///////pxJL/7qxV/+6s
Vf/wrVb/8K1W/+mnUevUmUsUAAAAAAAAAAAAAAAA7qxVgO6sVf/urFX/7qxV/+6sVf/urFX/6sqg////
////////8eLO/+yvX//urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+nF
lf/////////////////////////////////////////////////////////////////8+vf/6cWV/+q5
ev/s07H/6rd1/+6sVf/urFX/7qxV/++tVogAAAAAAAAAAAAAAAAAAAAA7qxVFe6sVejurFX/7qxV/+6s
Vf/urFX/6bp8///////w4Mn/7a1Z/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/x4cz////////////////////////////////////////////////////+//7+
/v/////////+/+m8gP/urFX/7a1Y/+6sVf/urFX/7qxV7O6sVRoAAAAAAAAAAAAAAAAAAAAAAAAAAO6s
VWburFX/7qxV/+6sVf/urFX/7a5b/+zTs//sr1//7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/sr1//8uPQ////////////////////////////////////
////////6suj/+qzav/pxpj/9Onb//n07f/rr2D/7qxV/+6sVf/urFX/7qxVbwAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAO6sVQPurFW67qxV/+6sVf/urFX/7qxV/+6sVv/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7axY/+nGl//27uP/////////
/////////fz6//Lj0P/qunv/7qxV/+6sVf/urFX/7qxV/+m9gv/qt3X/7qxV/+6sVf/urFXB7qxVBQAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADurFUg7qxV6O6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/qtnP/6sqg/+3WuP/s07P/6cSS/+uyZf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVv/trVr/7qxV/+6s
VezurFUlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVRu6sVfjurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV++6sVUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6s
VVzurFX97qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxVYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADurFVd7qxV+O6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVfvurFVjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVR+6sVeXurFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV6O6sVU0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVSPurFW37qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFW77qxVJgAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADurFUB7qxVae6sVeTurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV5+6sVW3urFUDAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVRjurFWA7qxV4u6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVeTurFWE7qxVGwAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVEu6sVV7urFW17qxV7+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVfDurFW47qxVX+6s
VRMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA7qxVG+6sVUzurFWA7qxVrO6sVcnurFXa7qxV4u6sVeLurFXa7qxVye6sVa3urFWC7qxVTe6s
VR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP//gAH//6gr//wAAD//qCv/8AAAD/+oK//AAAAD/6gr/4AAAAH/qCv/AAAAAP+oK/4A
AAAAf6gr/AAAAAA/qCv4AAAAAB+oK/AAAAAAD6gr4AAAAAAHqCvgAAAAAAeoK8AAAAAAA6grwAAAAAAD
qCuAAAAAAAGoK4AAAAAAAagrgAAAAAAAqCsAAAAAAACoKwAAAAAAAKgrAAAAAAAAqCsAAAAAAACoKwAA
AAAAAKgrAAAAAAAAqCsAAAAAAACoKwAAAAAAAKgrAAAAAAAAqCsAAAAAAACoKwAAAAAAAKgrAAAAAAAA
qCsAAAAAAACoKwAAAAAAAKgrgAAAAAAAqCuAAAAAAAGoK4AAAAAAAagrwAAAAAADqCvAAAAAAAOoK+AA
AAAAB6gr4AAAAAAHqCvwAAAAAA+oK/gAAAAAH6gr/AAAAAA/qCv+AAAAAH+oK/8AAAAA/6gr/4AAAAH/
qCv/wAAAA/+oK//wAAAP/6gr//wAAD//qCv//4AB//+oKygAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApHY4FrR/
Ole+hjuVxos7w8uNPNvOjzznzo8858uNPNzGijzEvoU7l7WBO1mpejsYAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqHg5Kr6F
O5XLjTvo0pE8/9ORPP/SkTz/0ZE8/9CQPP/QkDz/0ZE8/9KRPP/TkTz/0pE8/82OPOq/hjyZrXw7LAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo3U6CbuE
O4bPjzz005I8/9GRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0ZE8/9OS
PP/PkDz1vYU8iah6PAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKR3
OibGizvG05E8/9GQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9GQPP/TkTz/yIs8yqx8PCkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACsezsxy40849KRPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/zI485rKAPTUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAApXc6JMuNPOTSkTz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/zI485659PCcAAAAAAAAAAAAA
AAAAAAAAAAAAAKd4OwnHizzJ0pE8/9CQPP/QkDz/0JA9/9OgYP/YtIX/38Sh/+LMr//iy67/3sOf/9iy
gv/Tn13/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/SkTz/x4s8zaV4
OwsAAAAAAAAAAAAAAAAAAAAAu4Q8hNOSPP/QkDz/0JA8/9GXS//YtIX/6NfC//Xv5//8+vj/////////
///8+vf/9O3k/+fVvv/YsYH/0JRF/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/Tkjz/u4Q7iQAAAAAAAAAAAAAAAKx7OyTPjzz10ZA8/9GXS//Ztoj/8une////////////////////
///////////////////////////////////38uz/3L2V/9CRP//QkDz/0JA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9GRPP/Ojzz3onU5KQAAAAAAAAAAxo1BlNGQO//Ojjv/0JNC/9GWSP/QlET/0ZpR/9au
eP/n1b3//v79////////////////////////////////////////////7+TV/9GdWP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/0JA8/9SSPP+4gjqaAAAAAPGuVhHvrVXq5qRO/9qZRP/QkT3/zo46/8+P
O//QkDz/0JA8/9CQPP/To2P/8+vh////////////////////////////////////////////+fXw/9Oh
Yf/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/0pE8/8qMO+2WbTYV7qxVUe6sVf/wrVb/761W/+mo
Uv/enUj/05M//86PO//PkD7/3cCZ//Lp3v/7+PT/////////////////////////////////////////
////////+PTv/9GcVf/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/QkDz/05I8/699OljurFWR7qxV/+6s
Vf/urFX/761W//CuV//sqlT/4qJQ/+zdyf//////////////////////////////////////////////
////////////////////////7+TV/9CRP//QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/Tkjz/vIQ7mO6s
Vb/urFX/7qxV/+6sVf/urFX/7qxV/++tVf/ry5///v79//7+/f//////////////////////////////
////////////////////////////////////////2rqO/9CQPP/QkDz/0JA8/9CQPP/QkDz/0JA8/9KR
PP/GijvF7qxV2u6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+u1bv/t1bb//fv4////////////////////
///////////////////////////////////////////////////48+3/0ZRG/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0ZA8/8uNPNzurFXl7qxV/+6sVf/urFX/7qxV/+6sVf/rsWP/9OjZ////////////////////
///////////////////////////////////////////////////////////////////YtIX/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/QkDz/zo886O6sVeXurFX/7qxV/+6sVf/urFX/7qxW//Hiz///////////////
/////////////////////////////////////////////////////////////////////////////+rb
yP/QkDz/0JA8/9CQPP/QkDz/0JA8/9CQPP/Ojzzo7qxV2e6sVf/urFX/7qxV/+6sVf/quHb/////////
////////////////////////////////////////////////////////////////////////////////
////////+fXw/9CURf/QkDz/0JA8/9CQPP/QkDz/0ZA8/8yOPNzurFW/7qxV/+6sVf/urFX/7qxV/+nA
if/s1LT/9Onb////////////////////////////////////////////////////////////////////
////////////////////////0Z5b/9CQPP/QkDz/0JA8/9CQPP/SkTz/x4s8xe6sVY/urFX/7qxV/+6s
Vf/urFX/7qxV/+nEk//+/fz////////////////////////////+/v3/+PHo//To2f/+/v7/////////
///////////////////////////////////VqGz/zo46/8+PO//QkDz/0JA8/9KRPP+/hjyX7qxVUO6s
Vf/urFX/7qxV/+6sVf/ssGH//Pr2///////////////////////y49D/6cOR/+qyaf/urVb/6rJp////
/////////////////////////////////////////////+e7f//goEr/1ZVB/8+PO//Ojzv/0pE8/7WB
PFfurFUQ7qxV6O6sVf/urFX/7qxV/+m+hv/////////////////z5tX/6rl6/+6sVf/urFX/7qxV/+6s
Vf/qs2r////+////////////////////////////////////////////+PLp/+y4c//urFX/5aRO/9qZ
RP/Mjjztp3g6FQAAAADurFWQ7qxV/+6sVf/urFX/6cKP////////////682m/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+2sV//17N////////////////////////////////////////7+/v/06Nn/8uTT/+qz
a//wrVb/761W/+alUZYAAAAAAAAAAO6sVSHurFX07qxV/+6sVf/quXj//////+nDkf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+m+hP////////////////////////////////////////////jy
6v/qtnH/67Fj/+6sVf/urFX2761WJQAAAAAAAAAAAAAAAO6sVX7urFX/7qxV/+2vW//pvID/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+nEkv/7+PT//////////////////fz6/+rJ
n//rtW7/682n/+zTs//urFb/7qxV/+6sVYQAAAAAAAAAAAAAAAAAAAAA7qxVB+6sVcTurFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+u0bP/qy6H/7da4/+vN
pv/qtnP/7qxV/+6sVf/urFX/7K9f/+2sWP/urFXI7qxVCQAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVIO6s
VeDurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV4+6sVSMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA7qxVLO6sVd/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVeLurFUwAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA7qxVIu6sVcHurFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFXE7qxVJAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7qxVBu6sVX/urFXw7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFXy7qxVgu6sVQgAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVSXurFWP7qxV5e6s
Vf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFXl7qxVke6sVScAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADurFUS7qxVUO6sVY7urFW97qxV2O6sVeXurFXl7qxV2O6sVb7urFWP7qxVUu6sVRMAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8AD//8AAP/8AAA/+AAAH/AAAA/gAAAHwAAAA8AA
AAOAAAABgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA
AAGAAAABwAAAA8AAAAPgAAAH8AAAD/gAAB/8AAA//wAA///AA/8oAAAAEAAAACAAAAABACAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKx7Oja9hTqTyYw8zs6PPOfOjzznyYw8zr6G
PJSvfjw3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo3Y7CbyEO5PRkDz805I8/9GRPP/QkDz/0JA8/9GR
PP/TkTz/0ZA8/b+GPJWrfDwKAAAAAAAAAAAAAAAAp3g8CcSJPLfTkjz/0ZA8/9CQPP/QkDz/0JA8/9CQ
PP/QkDz/0JA8/9CQPP/Tkjz/xoo8uqx8PQoAAAAAAAAAAL2FPJPUk0D/06Rm/92/mf/izK//4sut/9u6
j//Snlr/0JA8/9CQPP/QkDz/0JA8/9OSPP+9hTyWAAAAALiEQDLQkDz90JpS/93Amf/u4tP/////////
/////////fv5/+DIqP/QkkH/0JA8/9CQPP/RkDz/0JA8/qN1OTTtq1WS56VP/9qaRf/RkT3/0JdO/+rc
yP//////////////////////693L/9CSQf/QkDz/0JA8/9SSPP+3gTqW761Vz++tVv/wrVb/6K5h//fy
6v/////////////////////////////////gx6b/0JA8/9CQPP/RkTz/yYw80e6sVefurFX/7qxV/+q+
hP/69vD//////////////////////////////////fz7/9GbU//QkDz/0JA8/8+PPOnurFXn7qxV/+yw
Y//79/P////////////////////////////////////////////ZuIz/0JA8/9CQPP/Pjzzp7qxVz+6s
Vf/sr2H/8eLO/////////////v7+//n07f/+/v7/////////////////48yu/8+PO//Qjzv/yYs80e6s
VZLurFX/67Jm//7+/f/8+fb/68yl/+qza//rsmf//v37//////////////////Pn2P/ip1n/2phC/8CH
PJXurFUw7qxV/eq2c//169//6rNr/+6sVf/urFX/7q1W//Pm1f/////////////////8+fX/67+G/++t
Vf3lpVEyAAAAAO6sVZHtrVr/7a9c/+6sVf/urFX/7qxV/+6sVf/rsWP/7de5//Lj0P/pxJL/67Zy/+qz
av/urFWTAAAAAAAAAADurFUI7qxVtO6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
Vf/urFW37qxVCQAAAAAAAAAAAAAAAO6sVQjurFWQ7qxV++6sVf/urFX/7qxV/+6sVf/urFX/7qxV/+6s
VfvurFWS7qxVCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO6sVTPurFWQ7qxVzO6sVeburFXm7qxVzO6s
VZDurFU0AAAAAAAAAAAAAAAAAAAAAPAPrEHAA6xBgAGsQYABrEEAAKxBAACsQQAArEEAAKxBAACsQQAA
rEEAAKxBAACsQYABrEGAAaxBwAOsQfAPrEE=
</value>
</data>
</root> </root>

View File

@@ -12,7 +12,7 @@ namespace TweetDck.Core.Other.Settings{
public bool Ready { get; set; } public bool Ready { get; set; }
public BaseTabSettings(){ public BaseTabSettings(){
Padding = new Padding(6,6,6,6); Padding = new Padding(6);
} }
} }
} }

View File

@@ -47,6 +47,7 @@
this.textBoxBrowserCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0); this.textBoxBrowserCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
this.textBoxBrowserCSS.Multiline = true; this.textBoxBrowserCSS.Multiline = true;
this.textBoxBrowserCSS.Name = "textBoxBrowserCSS"; this.textBoxBrowserCSS.Name = "textBoxBrowserCSS";
this.textBoxBrowserCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.textBoxBrowserCSS.Size = new System.Drawing.Size(226, 193); this.textBoxBrowserCSS.Size = new System.Drawing.Size(226, 193);
this.textBoxBrowserCSS.TabIndex = 0; this.textBoxBrowserCSS.TabIndex = 0;
this.textBoxBrowserCSS.WordWrap = false; this.textBoxBrowserCSS.WordWrap = false;
@@ -129,7 +130,8 @@
this.textBoxNotificationCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0); this.textBoxNotificationCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
this.textBoxNotificationCSS.Multiline = true; this.textBoxNotificationCSS.Multiline = true;
this.textBoxNotificationCSS.Name = "textBoxNotificationCSS"; this.textBoxNotificationCSS.Name = "textBoxNotificationCSS";
this.textBoxNotificationCSS.Size = new System.Drawing.Size(227, 193); this.textBoxNotificationCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.textBoxNotificationCSS.Size = new System.Drawing.Size(226, 193);
this.textBoxNotificationCSS.TabIndex = 1; this.textBoxNotificationCSS.TabIndex = 1;
this.textBoxNotificationCSS.WordWrap = false; this.textBoxNotificationCSS.WordWrap = false;
// //

View File

@@ -4,6 +4,8 @@ using System.Text;
namespace TweetDck.Core.Other.Settings.Export{ namespace TweetDck.Core.Other.Settings.Export{
class CombinedFileStream : IDisposable{ class CombinedFileStream : IDisposable{
public const char KeySeparator = '/';
private readonly Stream stream; private readonly Stream stream;
public CombinedFileStream(Stream stream){ public CombinedFileStream(Stream stream){
@@ -11,6 +13,12 @@ namespace TweetDck.Core.Other.Settings.Export{
} }
public void WriteFile(string identifier, string path){ public void WriteFile(string identifier, string path){
byte[] name = Encoding.UTF8.GetBytes(identifier);
if (name.Length > 255){
throw new ArgumentOutOfRangeException("Identifier cannot be 256 or more characters long: "+identifier);
}
byte[] contents; byte[] contents;
using(FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){ using(FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
@@ -26,12 +34,9 @@ namespace TweetDck.Core.Other.Settings.Export{
} }
} }
byte[] name = Encoding.UTF8.GetBytes(identifier);
byte[] contentsLength = BitConverter.GetBytes(contents.Length);
stream.WriteByte((byte)name.Length); stream.WriteByte((byte)name.Length);
stream.Write(name, 0, name.Length); stream.Write(name, 0, name.Length);
stream.Write(contentsLength,0,4); stream.Write(BitConverter.GetBytes(contents.Length), 0, 4);
stream.Write(contents, 0, contents.Length); stream.Write(contents, 0, contents.Length);
} }
@@ -65,6 +70,13 @@ namespace TweetDck.Core.Other.Settings.Export{
public class Entry{ public class Entry{
public string Identifier { get; private set; } public string Identifier { get; private set; }
public string KeyName{
get{
int index = Identifier.IndexOf(KeySeparator);
return index == -1 ? Identifier : Identifier.Substring(0, index);
}
}
private readonly byte[] contents; private readonly byte[] contents;
public Entry(string identifier, byte[] contents){ public Entry(string identifier, byte[] contents){
@@ -75,6 +87,15 @@ namespace TweetDck.Core.Other.Settings.Export{
public void WriteToFile(string path){ public void WriteToFile(string path){
File.WriteAllBytes(path, contents); File.WriteAllBytes(path, contents);
} }
public void WriteToFile(string path, bool createDirectory){
if (createDirectory){
// ReSharper disable once AssignNullToNotNullAttribute
Directory.CreateDirectory(Path.GetDirectoryName(path));
}
File.WriteAllBytes(path, contents);
}
} }
} }
} }

View File

@@ -1,19 +1,25 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using TweetDck.Plugins;
namespace TweetDck.Core.Other.Settings.Export{ namespace TweetDck.Core.Other.Settings.Export{
sealed class ExportManager{ sealed class ExportManager{
public static readonly string CookiesPath = Path.Combine(Program.StoragePath, "Cookies"); public static readonly string CookiesPath = Path.Combine(Program.StoragePath, "Cookies");
public static readonly string TempCookiesPath = Path.Combine(Program.StoragePath, "CookiesTmp"); public static readonly string TempCookiesPath = Path.Combine(Program.StoragePath, "CookiesTmp");
public bool IsRestarting { get; private set; }
public Exception LastException { get; private set; } public Exception LastException { get; private set; }
private readonly string file; private readonly string file;
private readonly PluginManager plugins;
public ExportManager(string file){ public ExportManager(string file, PluginManager plugins){
this.file = file; this.file = file;
this.plugins = plugins;
} }
public bool Export(bool includeSession){ public bool Export(bool includeSession){
@@ -21,6 +27,35 @@ namespace TweetDck.Core.Other.Settings.Export{
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None))){ using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None))){
stream.WriteFile("config", Program.ConfigFilePath); stream.WriteFile("config", Program.ConfigFilePath);
foreach(PathInfo path in EnumerateFilesRelative(plugins.PathOfficialPlugins)){
string[] split = path.Relative.Split(CombinedFileStream.KeySeparator);
if (split.Length < 3){
continue;
}
else if (split.Length == 3){
if (split[2].Equals(".meta", StringComparison.OrdinalIgnoreCase) ||
split[2].Equals("browser.js", StringComparison.OrdinalIgnoreCase) ||
split[2].Equals("notification.js", StringComparison.OrdinalIgnoreCase)){
continue;
}
}
try{
stream.WriteFile("plugin.off"+path.Relative, path.Full);
}catch(ArgumentOutOfRangeException e){
MessageBox.Show("Could not include a file in the export. "+e.Message, "Export Profile", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
foreach(PathInfo path in EnumerateFilesRelative(plugins.PathCustomPlugins)){
try{
stream.WriteFile("plugin.usr"+path.Relative, path.Full);
}catch(ArgumentOutOfRangeException e){
MessageBox.Show("Could not include a file in the export. "+e.Message, "Export Profile", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
if (includeSession){ if (includeSession){
stream.WriteFile("cookies", CookiesPath); stream.WriteFile("cookies", CookiesPath);
} }
@@ -37,21 +72,39 @@ namespace TweetDck.Core.Other.Settings.Export{
public bool Import(){ public bool Import(){
try{ try{
bool updatedPlugins = false;
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None))){ using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None))){
CombinedFileStream.Entry entry; CombinedFileStream.Entry entry;
while((entry = stream.ReadFile()) != null){ while((entry = stream.ReadFile()) != null){
switch(entry.Identifier){ switch(entry.KeyName){
case "config": case "config":
entry.WriteToFile(Program.ConfigFilePath); entry.WriteToFile(Program.ConfigFilePath);
Program.ReloadConfig(); Program.ReloadConfig();
break; break;
case "plugin.off":
string root = Path.Combine(plugins.PathOfficialPlugins, entry.Identifier.Split(CombinedFileStream.KeySeparator)[1]);
if (Directory.Exists(root)){
entry.WriteToFile(Path.Combine(plugins.PathOfficialPlugins, entry.Identifier.Substring(entry.KeyName.Length+1)), true);
updatedPlugins = true;
}
break;
case "plugin.usr":
entry.WriteToFile(Path.Combine(plugins.PathCustomPlugins, entry.Identifier.Substring(entry.KeyName.Length+1)), true);
updatedPlugins = true;
break;
case "cookies": case "cookies":
if (MessageBox.Show("Do you want to import the login session? This will restart "+Program.BrandName+".", "Importing "+Program.BrandName+" Settings", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes){ if (MessageBox.Show("Do you want to import the login session? This will restart "+Program.BrandName+".", "Importing "+Program.BrandName+" Settings", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
entry.WriteToFile(Path.Combine(Program.StoragePath, TempCookiesPath)); entry.WriteToFile(Path.Combine(Program.StoragePath, TempCookiesPath));
// okay to and restart, 'cookies' is always the last entry // okay to and restart, 'cookies' is always the last entry
IsRestarting = true;
Process.Start(Application.ExecutablePath, "-restart -importcookies"); Process.Start(Application.ExecutablePath, "-restart -importcookies");
Application.Exit(); Application.Exit();
} }
@@ -61,11 +114,27 @@ namespace TweetDck.Core.Other.Settings.Export{
} }
} }
if (updatedPlugins){
plugins.Reload();
}
return true; return true;
}catch(Exception e){ }catch(Exception e){
LastException = e; LastException = e;
return false; return false;
} }
} }
private static IEnumerable<PathInfo> EnumerateFilesRelative(string root){
return Directory.EnumerateFiles(root, "*.*", SearchOption.AllDirectories).Select(fullPath => new PathInfo{
Full = fullPath,
Relative = fullPath.Substring(root.Length).Replace(Path.DirectorySeparatorChar, CombinedFileStream.KeySeparator) // includes leading separator character
});
}
private class PathInfo{
public string Full { get; set; }
public string Relative { get; set; }
}
} }
} }

View File

@@ -28,12 +28,12 @@
this.checkHardwareAcceleration = new System.Windows.Forms.CheckBox(); this.checkHardwareAcceleration = new System.Windows.Forms.CheckBox();
this.toolTip = new System.Windows.Forms.ToolTip(this.components); this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.btnEditCefArgs = new System.Windows.Forms.Button(); this.btnEditCefArgs = new System.Windows.Forms.Button();
this.btnEditCSS = new System.Windows.Forms.Button();
this.btnReset = new System.Windows.Forms.Button(); this.btnReset = new System.Windows.Forms.Button();
this.btnImport = new System.Windows.Forms.Button(); this.btnImport = new System.Windows.Forms.Button();
this.btnExport = new System.Windows.Forms.Button(); this.btnExport = new System.Windows.Forms.Button();
this.groupPerformance = new System.Windows.Forms.GroupBox(); this.groupPerformance = new System.Windows.Forms.GroupBox();
this.groupConfiguration = new System.Windows.Forms.GroupBox(); this.groupConfiguration = new System.Windows.Forms.GroupBox();
this.btnEditCSS = new System.Windows.Forms.Button();
this.groupPerformance.SuspendLayout(); this.groupPerformance.SuspendLayout();
this.groupConfiguration.SuspendLayout(); this.groupConfiguration.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
@@ -75,11 +75,22 @@
this.btnEditCefArgs.UseVisualStyleBackColor = true; this.btnEditCefArgs.UseVisualStyleBackColor = true;
this.btnEditCefArgs.Click += new System.EventHandler(this.btnEditCefArgs_Click); this.btnEditCefArgs.Click += new System.EventHandler(this.btnEditCefArgs_Click);
// //
// btnEditCSS
//
this.btnEditCSS.Location = new System.Drawing.Point(6, 48);
this.btnEditCSS.Name = "btnEditCSS";
this.btnEditCSS.Size = new System.Drawing.Size(171, 23);
this.btnEditCSS.TabIndex = 16;
this.btnEditCSS.Text = "Edit CSS";
this.toolTip.SetToolTip(this.btnEditCSS, "Set custom CSS for browser and notification windows.");
this.btnEditCSS.UseVisualStyleBackColor = true;
this.btnEditCSS.Click += new System.EventHandler(this.btnEditCSS_Click);
//
// btnReset // btnReset
// //
this.btnReset.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnReset.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnReset.AutoSize = true; this.btnReset.AutoSize = true;
this.btnReset.Location = new System.Drawing.Point(209, 250); this.btnReset.Location = new System.Drawing.Point(190, 250);
this.btnReset.Name = "btnReset"; this.btnReset.Name = "btnReset";
this.btnReset.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0); this.btnReset.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnReset.Size = new System.Drawing.Size(102, 23); this.btnReset.Size = new System.Drawing.Size(102, 23);
@@ -92,12 +103,12 @@
// //
this.btnImport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnImport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnImport.AutoSize = true; this.btnImport.AutoSize = true;
this.btnImport.Location = new System.Drawing.Point(109, 250); this.btnImport.Location = new System.Drawing.Point(100, 250);
this.btnImport.Name = "btnImport"; this.btnImport.Name = "btnImport";
this.btnImport.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0); this.btnImport.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnImport.Size = new System.Drawing.Size(94, 23); this.btnImport.Size = new System.Drawing.Size(84, 23);
this.btnImport.TabIndex = 16; this.btnImport.TabIndex = 16;
this.btnImport.Text = "Import Settings"; this.btnImport.Text = "Import Profile";
this.btnImport.UseVisualStyleBackColor = true; this.btnImport.UseVisualStyleBackColor = true;
this.btnImport.Click += new System.EventHandler(this.btnImport_Click); this.btnImport.Click += new System.EventHandler(this.btnImport_Click);
// //
@@ -105,12 +116,13 @@
// //
this.btnExport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnExport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnExport.AutoSize = true; this.btnExport.AutoSize = true;
this.btnExport.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.btnExport.Location = new System.Drawing.Point(9, 250); this.btnExport.Location = new System.Drawing.Point(9, 250);
this.btnExport.Name = "btnExport"; this.btnExport.Name = "btnExport";
this.btnExport.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0); this.btnExport.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnExport.Size = new System.Drawing.Size(94, 23); this.btnExport.Size = new System.Drawing.Size(85, 23);
this.btnExport.TabIndex = 15; this.btnExport.TabIndex = 15;
this.btnExport.Text = "Export Settings"; this.btnExport.Text = "Export Profile";
this.btnExport.UseVisualStyleBackColor = true; this.btnExport.UseVisualStyleBackColor = true;
this.btnExport.Click += new System.EventHandler(this.btnExport_Click); this.btnExport.Click += new System.EventHandler(this.btnExport_Click);
// //
@@ -136,17 +148,6 @@
this.groupConfiguration.TabStop = false; this.groupConfiguration.TabStop = false;
this.groupConfiguration.Text = "Configuration"; this.groupConfiguration.Text = "Configuration";
// //
// btnEditCSS
//
this.btnEditCSS.Location = new System.Drawing.Point(6, 48);
this.btnEditCSS.Name = "btnEditCSS";
this.btnEditCSS.Size = new System.Drawing.Size(171, 23);
this.btnEditCSS.TabIndex = 16;
this.btnEditCSS.Text = "Edit CSS";
this.toolTip.SetToolTip(this.btnEditCSS, "Set custom CSS for browser and notification windows.");
this.btnEditCSS.UseVisualStyleBackColor = true;
this.btnEditCSS.Click += new System.EventHandler(this.btnEditCSS_Click);
//
// TabSettingsAdvanced // TabSettingsAdvanced
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);

View File

@@ -5,15 +5,18 @@ using TweetDck.Core.Controls;
using TweetDck.Core.Other.Settings.Dialogs; using TweetDck.Core.Other.Settings.Dialogs;
using TweetDck.Core.Other.Settings.Export; using TweetDck.Core.Other.Settings.Export;
using TweetDck.Core.Utils; using TweetDck.Core.Utils;
using TweetDck.Plugins;
namespace TweetDck.Core.Other.Settings{ namespace TweetDck.Core.Other.Settings{
partial class TabSettingsAdvanced : BaseTabSettings{ partial class TabSettingsAdvanced : BaseTabSettings{
private readonly Action browserReloadAction; private readonly Action browserReloadAction;
private readonly PluginManager plugins;
public TabSettingsAdvanced(Action browserReloadAction){ public TabSettingsAdvanced(Action browserReloadAction, PluginManager plugins){
InitializeComponent(); InitializeComponent();
this.browserReloadAction = browserReloadAction; this.browserReloadAction = browserReloadAction;
this.plugins = plugins;
checkHardwareAcceleration.Checked = HardwareAcceleration.IsEnabled; checkHardwareAcceleration.Checked = HardwareAcceleration.IsEnabled;
@@ -109,7 +112,7 @@ namespace TweetDck.Core.Other.Settings{
if (file != null){ if (file != null){
Program.UserConfig.Save(); Program.UserConfig.Save();
ExportManager manager = new ExportManager(file); ExportManager manager = new ExportManager(file, plugins);
if (!manager.Export(saveCredentials)){ if (!manager.Export(saveCredentials)){
Program.HandleException("An exception happened while exporting "+Program.BrandName+" settings.", manager.LastException); Program.HandleException("An exception happened while exporting "+Program.BrandName+" settings.", manager.LastException);
@@ -130,11 +133,13 @@ namespace TweetDck.Core.Other.Settings{
} }
if (file != null){ if (file != null){
ExportManager manager = new ExportManager(file); ExportManager manager = new ExportManager(file, plugins);
if (manager.Import()){ if (manager.Import()){
if (!manager.IsRestarting){
((FormSettings)ParentForm).ReloadUI(); ((FormSettings)ParentForm).ReloadUI();
} }
}
else{ else{
Program.HandleException("An exception happened while importing "+Program.BrandName+" settings.", manager.LastException); Program.HandleException("An exception happened while importing "+Program.BrandName+" settings.", manager.LastException);
} }

View File

@@ -33,7 +33,7 @@ namespace TweetDck.Core.Utils{
value = matchValue.Substring(indexEquals+1).Trim('"'); value = matchValue.Substring(indexEquals+1).Trim('"');
} }
if (key != string.Empty){ if (key.Length != 0){
dictionary[key] = value; dictionary[key] = value;
++count; ++count;
} }

View File

@@ -25,9 +25,6 @@ namespace TweetDck.Core.Utils{
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam); public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("Shell32.dll")]
public static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")] [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern bool SetWindowPos(int hWnd, int hWndOrder, int x, int y, int width, int height, uint flags); public static extern bool SetWindowPos(int hWnd, int hWndOrder, int x, int y, int width, int height, uint flags);

View File

@@ -1,42 +0,0 @@
using System;
using System.IO;
using Shell32;
namespace TweetDck.Migration.Helpers{
sealed class LnkEditor{
private readonly ShellLinkObject obj;
public LnkEditor(string file){
try{
Shell shell = new Shell();
Folder folder = shell.NameSpace(Path.GetDirectoryName(file));
FolderItem item = folder.Items().Item(Path.GetFileName(file));
obj = item.GetLink as ShellLinkObject;
}catch(Exception){
obj = null;
}
}
public void SetComment(string newComment){
if (obj == null)return;
obj.Description = newComment;
}
public void SetPath(string newPath){
if (obj == null)return;
obj.Path = newPath;
obj.SetIconLocation(newPath,0);
}
public void SetWorkingDirectory(string newWorkingDirectory){
if (obj == null)return;
obj.WorkingDirectory = newWorkingDirectory;
}
public void Save(){
if (obj == null)return;
obj.Save();
}
}
}

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -8,14 +7,30 @@ using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using Microsoft.Win32; using Microsoft.Win32;
using TweetDck.Migration.Helpers; using TweetDck.Migration.Helpers;
using TweetDck.Core.Utils;
namespace TweetDck.Migration{ namespace TweetDck.Migration{
static class MigrationManager{ static class MigrationManager{
private static readonly string TweetDeckPathParent = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "twitter"); private static readonly string TweetDeckPathParent = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "twitter");
private static readonly string TweetDeckPath = Path.Combine(TweetDeckPathParent, "TweetDeck"); private static readonly string TweetDeckPath = Path.Combine(TweetDeckPathParent, "TweetDeck");
private static readonly string TweetDickStorage = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "TweetDick");
public static void Run(){ public static void Run(){
#if DUCK
if (!Program.IsPortable && Directory.Exists(TweetDickStorage) && !Directory.Exists(Program.StoragePath)){
if (MessageBox.Show("Welcome to TweetDuck! Would you like to move your old TweetDick configuration and login data?", "TweetDick Migration", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes){
try{
Directory.Move(TweetDickStorage, Program.StoragePath);
MessageBox.Show("All done! You can now uninstall TweetDick.", "TweetDick Migration", MessageBoxButtons.OK, MessageBoxIcon.Information);
}catch(Exception ex){
Program.HandleException("An unexpected exception has occurred during the migration process.", ex);
}
}
return;
}
#endif
if (!Program.UserConfig.IgnoreMigration && Directory.Exists(TweetDeckPath)){ if (!Program.UserConfig.IgnoreMigration && Directory.Exists(TweetDeckPath)){
MigrationDecision decision; MigrationDecision decision;
@@ -121,36 +136,6 @@ namespace TweetDck.Migration{
} }
if (decision == MigrationDecision.MigratePurge){ if (decision == MigrationDecision.MigratePurge){
// update the lnk files wherever possible (desktop icons, pinned taskbar, start menu)
foreach(string location in GetLnkDirectories()){
if (string.IsNullOrEmpty(location))continue;
string linkFile = Path.Combine(location,"TweetDeck.lnk");
if (File.Exists(linkFile)){
LnkEditor lnk = new LnkEditor(linkFile);
lnk.SetPath(Application.ExecutablePath);
lnk.SetWorkingDirectory(Environment.CurrentDirectory);
lnk.SetComment(Program.BrandName+" client for Windows");
lnk.Save();
string renamed = Path.Combine(location,Program.BrandName+".lnk");
try{
if (!File.Exists(renamed)){
File.Move(linkFile,renamed);
}
else{
File.Delete(linkFile);
}
}catch{
// eh, too bad
}
}
}
NativeMethods.SHChangeNotify(0x8000000,0x1000,IntPtr.Zero,IntPtr.Zero); // refreshes desktop
// uninstall in the background // uninstall in the background
string guid = ProgramRegistrySearch.FindByDisplayName("TweetDeck"); string guid = ProgramRegistrySearch.FindByDisplayName("TweetDeck");
@@ -179,12 +164,6 @@ namespace TweetDck.Migration{
} }
} }
private static IEnumerable<string> GetLnkDirectories(){
yield return Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
yield return Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory);
yield return Environment.ExpandEnvironmentVariables(@"%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar");
}
private static void RunUninstaller(string guid, int timeout){ private static void RunUninstaller(string guid, int timeout){
Process uninstaller = Process.Start("msiexec.exe", "/x "+guid+" /quiet /qn"); Process uninstaller = Process.Start("msiexec.exe", "/x "+guid+" /quiet /qn");

View File

@@ -31,6 +31,7 @@
this.flowLayoutInfo = new System.Windows.Forms.FlowLayoutPanel(); this.flowLayoutInfo = new System.Windows.Forms.FlowLayoutPanel();
this.labelWebsite = new System.Windows.Forms.Label(); this.labelWebsite = new System.Windows.Forms.Label();
this.labelVersion = new System.Windows.Forms.Label(); this.labelVersion = new System.Windows.Forms.Label();
this.btnOpenConfig = new System.Windows.Forms.Button();
this.panelDescription.SuspendLayout(); this.panelDescription.SuspendLayout();
this.flowLayoutInfo.SuspendLayout(); this.flowLayoutInfo.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
@@ -38,9 +39,9 @@
// btnToggleState // btnToggleState
// //
this.btnToggleState.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnToggleState.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnToggleState.Location = new System.Drawing.Point(449, 80); this.btnToggleState.Location = new System.Drawing.Point(459, 80);
this.btnToggleState.Name = "btnToggleState"; this.btnToggleState.Name = "btnToggleState";
this.btnToggleState.Size = new System.Drawing.Size(75, 23); this.btnToggleState.Size = new System.Drawing.Size(65, 23);
this.btnToggleState.TabIndex = 0; this.btnToggleState.TabIndex = 0;
this.btnToggleState.Text = "Disable"; this.btnToggleState.Text = "Disable";
this.btnToggleState.UseVisualStyleBackColor = true; this.btnToggleState.UseVisualStyleBackColor = true;
@@ -99,7 +100,7 @@
this.flowLayoutInfo.Controls.Add(this.labelWebsite); this.flowLayoutInfo.Controls.Add(this.labelWebsite);
this.flowLayoutInfo.Location = new System.Drawing.Point(11, 85); this.flowLayoutInfo.Location = new System.Drawing.Point(11, 85);
this.flowLayoutInfo.Name = "flowLayoutInfo"; this.flowLayoutInfo.Name = "flowLayoutInfo";
this.flowLayoutInfo.Size = new System.Drawing.Size(432, 18); this.flowLayoutInfo.Size = new System.Drawing.Size(368, 18);
this.flowLayoutInfo.TabIndex = 4; this.flowLayoutInfo.TabIndex = 4;
this.flowLayoutInfo.WrapContents = false; this.flowLayoutInfo.WrapContents = false;
// //
@@ -128,10 +129,22 @@
this.labelVersion.Text = "Version"; this.labelVersion.Text = "Version";
this.labelVersion.TextAlign = System.Drawing.ContentAlignment.TopRight; this.labelVersion.TextAlign = System.Drawing.ContentAlignment.TopRight;
// //
// btnOpenConfig
//
this.btnOpenConfig.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnOpenConfig.Location = new System.Drawing.Point(385, 80);
this.btnOpenConfig.Name = "btnOpenConfig";
this.btnOpenConfig.Size = new System.Drawing.Size(68, 23);
this.btnOpenConfig.TabIndex = 6;
this.btnOpenConfig.Text = "Configure";
this.btnOpenConfig.UseVisualStyleBackColor = true;
this.btnOpenConfig.Click += new System.EventHandler(this.btnOpenConfig_Click);
//
// PluginControl // PluginControl
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.btnOpenConfig);
this.Controls.Add(this.flowLayoutInfo); this.Controls.Add(this.flowLayoutInfo);
this.Controls.Add(this.panelDescription); this.Controls.Add(this.panelDescription);
this.Controls.Add(this.labelName); this.Controls.Add(this.labelName);
@@ -161,5 +174,6 @@
private System.Windows.Forms.FlowLayoutPanel flowLayoutInfo; private System.Windows.Forms.FlowLayoutPanel flowLayoutInfo;
private System.Windows.Forms.Label labelWebsite; private System.Windows.Forms.Label labelWebsite;
private System.Windows.Forms.Label labelVersion; private System.Windows.Forms.Label labelVersion;
private System.Windows.Forms.Button btnOpenConfig;
} }
} }

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
using TweetDck.Core.Utils; using TweetDck.Core.Utils;
@@ -21,13 +23,10 @@ namespace TweetDck.Plugins.Controls{
this.labelVersion.Text = plugin.Version; this.labelVersion.Text = plugin.Version;
this.labelAuthor.Text = plugin.Author; this.labelAuthor.Text = plugin.Author;
this.labelWebsite.Text = plugin.Website; this.labelWebsite.Text = plugin.Website;
this.btnToggleState.Text = pluginManager.Config.IsEnabled(plugin) ? "Disable" : "Enable";
if (!plugin.CanRun){ UpdatePluginState();
this.labelName.ForeColor = Color.DarkRed;
this.btnToggleState.Enabled = false; if (labelDescription.Text.Length == 0){
}
else if (labelDescription.Text == string.Empty){
labelDescription.Visible = false; labelDescription.Visible = false;
} }
@@ -35,7 +34,7 @@ namespace TweetDck.Plugins.Controls{
} }
private void panelDescription_Resize(object sender, EventArgs e){ private void panelDescription_Resize(object sender, EventArgs e){
if (labelDescription.Text == string.Empty){ if (labelDescription.Text.Length == 0){
Height = MinimumSize.Height; Height = MinimumSize.Height;
} }
else{ else{
@@ -50,11 +49,38 @@ namespace TweetDck.Plugins.Controls{
} }
} }
private void btnOpenConfig_Click(object sender, EventArgs e){
using(Process.Start("explorer.exe", "/select,\""+plugin.ConfigPath+"\"")){}
}
private void btnToggleState_Click(object sender, EventArgs e){ private void btnToggleState_Click(object sender, EventArgs e){
bool newState = !pluginManager.Config.IsEnabled(plugin); bool newState = !pluginManager.Config.IsEnabled(plugin);
pluginManager.Config.SetEnabled(plugin, newState); pluginManager.Config.SetEnabled(plugin, newState);
btnToggleState.Text = newState ? "Disable" : "Enable"; UpdatePluginState();
}
private void UpdatePluginState(){
bool isEnabled = plugin.CanRun && pluginManager.Config.IsEnabled(plugin);
Color textColor = isEnabled ? Color.Black : Color.FromArgb(90, 90, 90);
labelVersion.ForeColor = textColor;
labelAuthor.ForeColor = textColor;
labelWebsite.ForeColor = isEnabled ? Color.Blue : Color.FromArgb(90, 90, 249);
if (plugin.CanRun){
labelName.ForeColor = textColor;
labelDescription.ForeColor = textColor;
btnToggleState.Text = isEnabled ? "Disable" : "Enable";
btnOpenConfig.Visible = plugin.HasConfig;
btnOpenConfig.Enabled = btnOpenConfig.Visible && File.Exists(plugin.ConfigPath);
}
else{
labelName.ForeColor = Color.DarkRed;
labelDescription.ForeColor = Color.DarkRed;
btnToggleState.Visible = false;
btnOpenConfig.Visible = false;
}
} }
} }
} }

View File

@@ -3,6 +3,11 @@ using TweetDck.Core.Utils;
namespace TweetDck.Plugins.Controls{ namespace TweetDck.Plugins.Controls{
sealed partial class PluginListFlowLayout : FlowLayoutPanel{ sealed partial class PluginListFlowLayout : FlowLayoutPanel{
public PluginListFlowLayout(){
FlowDirection = FlowDirection.TopDown;
WrapContents = false;
}
protected override void WndProc(ref Message m){ protected override void WndProc(ref Message m){
NativeMethods.ShowScrollBar(Handle, NativeMethods.SB_HORZ, false); // basically fuck the horizontal scrollbar very much NativeMethods.ShowScrollBar(Handle, NativeMethods.SB_HORZ, false); // basically fuck the horizontal scrollbar very much
base.WndProc(ref m); base.WndProc(ref m);

View File

@@ -12,6 +12,8 @@ namespace TweetDck.Plugins{
public string Author { get { return metadata["AUTHOR"]; } } public string Author { get { return metadata["AUTHOR"]; } }
public string Version { get { return metadata["VERSION"]; } } public string Version { get { return metadata["VERSION"]; } }
public string Website { get { return metadata["WEBSITE"]; } } public string Website { get { return metadata["WEBSITE"]; } }
public string ConfigFile { get { return metadata["CONFIGFILE"]; } }
public string ConfigDefault { get { return metadata["CONFIGDEFAULT"]; } }
public string RequiredVersion { get { return metadata["REQUIRES"]; } } public string RequiredVersion { get { return metadata["REQUIRES"]; } }
public PluginGroup Group { get; private set; } public PluginGroup Group { get; private set; }
public PluginEnvironment Environments { get; private set; } public PluginEnvironment Environments { get; private set; }
@@ -28,6 +30,30 @@ namespace TweetDck.Plugins{
} }
} }
public bool HasConfig{
get{
return ConfigFile.Length > 0 && GetFullPathIfSafe(ConfigFile).Length > 0;
}
}
public string ConfigPath{
get{
return HasConfig ? Path.Combine(path, ConfigFile) : string.Empty;
}
}
public bool HasDefaultConfig{
get{
return ConfigDefault.Length > 0 && GetFullPathIfSafe(ConfigDefault).Length > 0;
}
}
public string DefaultConfigPath{
get{
return HasDefaultConfig ? Path.Combine(path, ConfigDefault) : string.Empty;
}
}
private readonly string path; private readonly string path;
private readonly string identifier; private readonly string identifier;
private readonly Dictionary<string, string> metadata = new Dictionary<string, string>(4){ private readonly Dictionary<string, string> metadata = new Dictionary<string, string>(4){
@@ -36,6 +62,8 @@ namespace TweetDck.Plugins{
{ "AUTHOR", "(anonymous)" }, { "AUTHOR", "(anonymous)" },
{ "VERSION", "(unknown)" }, { "VERSION", "(unknown)" },
{ "WEBSITE", "" }, { "WEBSITE", "" },
{ "CONFIGFILE", "" },
{ "CONFIGDEFAULT", "" },
{ "REQUIRES", "*" } { "REQUIRES", "*" }
}; };
@@ -48,6 +76,18 @@ namespace TweetDck.Plugins{
this.Environments = PluginEnvironment.None; this.Environments = PluginEnvironment.None;
} }
private void OnMetadataLoaded(){
string configPath = ConfigPath, defaultConfigPath = DefaultConfigPath;
if (configPath.Length > 0 && defaultConfigPath.Length > 0 && !File.Exists(configPath) && File.Exists(defaultConfigPath)){
try{
File.Copy(defaultConfigPath, configPath, false);
}catch(Exception e){
Program.HandleException("Could not generate a configuration file for '"+identifier+"' plugin.", e);
}
}
}
public string GetScriptPath(PluginEnvironment environment){ public string GetScriptPath(PluginEnvironment environment){
if (Environments.HasFlag(environment)){ if (Environments.HasFlag(environment)){
string file = environment.GetScriptFile(); string file = environment.GetScriptFile();
@@ -58,6 +98,28 @@ namespace TweetDck.Plugins{
} }
} }
public string GetFullPathIfSafe(string relativePath){
string fullPath = Path.Combine(path, relativePath);
try{
string folderPathName = new DirectoryInfo(path).FullName;
DirectoryInfo currentInfo = new DirectoryInfo(fullPath);
while(currentInfo.Parent != null){
if (currentInfo.Parent.FullName == folderPathName){
return fullPath;
}
currentInfo = currentInfo.Parent;
}
}
catch{
// ignore
}
return string.Empty;
}
public override string ToString(){ public override string ToString(){
return Identifier; return Identifier;
} }
@@ -88,15 +150,7 @@ namespace TweetDck.Plugins{
private static bool LoadEnvironments(string path, Plugin plugin, out string error){ private static bool LoadEnvironments(string path, Plugin plugin, out string error){
foreach(string file in Directory.EnumerateFiles(path, "*.js", SearchOption.TopDirectoryOnly).Select(Path.GetFileName)){ foreach(string file in Directory.EnumerateFiles(path, "*.js", SearchOption.TopDirectoryOnly).Select(Path.GetFileName)){
PluginEnvironment environment = PluginEnvironmentExtensions.Values.FirstOrDefault(env => file.Equals(env.GetScriptFile(),StringComparison.Ordinal)); plugin.Environments |= PluginEnvironmentExtensions.Values.FirstOrDefault(env => file.Equals(env.GetScriptFile(), StringComparison.Ordinal));
if (environment != PluginEnvironment.None){
plugin.Environments |= environment;
}
else{
error = "Unknown script file: "+file;
return false;
}
} }
if (plugin.Environments == PluginEnvironment.None){ if (plugin.Environments == PluginEnvironment.None){
@@ -160,6 +214,8 @@ namespace TweetDck.Plugins{
return false; return false;
} }
plugin.OnMetadataLoaded();
error = string.Empty; error = string.Empty;
return true; return true;
} }

View File

@@ -20,30 +20,7 @@ namespace TweetDck.Plugins{
private string GetFullPathIfSafe(int token, string path){ private string GetFullPathIfSafe(int token, string path){
Plugin plugin = manager.GetPluginFromToken(token); Plugin plugin = manager.GetPluginFromToken(token);
return plugin == null ? string.Empty : plugin.GetFullPathIfSafe(path);
if (plugin == null){
return string.Empty;
}
string fullPath = Path.Combine(plugin.FolderPath,path);
try{
string folderPathName = new DirectoryInfo(plugin.FolderPath).FullName;
DirectoryInfo currentInfo = new DirectoryInfo(fullPath);
while(currentInfo.Parent != null){
if (currentInfo.Parent.FullName == folderPathName){
return fullPath;
}
currentInfo = currentInfo.Parent;
}
}
catch{
// ignore
}
return string.Empty;
} }
public void WriteFile(int token, string path, string contents){ public void WriteFile(int token, string path, string contents){
@@ -73,18 +50,34 @@ namespace TweetDck.Plugins{
return cachedContents; return cachedContents;
} }
try{
return fileCache[fullPath] = File.ReadAllText(fullPath, Encoding.UTF8); return fileCache[fullPath] = File.ReadAllText(fullPath, Encoding.UTF8);
}catch(FileNotFoundException){
throw new Exception("File not found.");
}catch(DirectoryNotFoundException){
throw new Exception("Directory not found.");
}
} }
public void DeleteFile(int token, string path){ public void DeleteFile(int token, string path){
string fullPath = GetFullPathIfSafe(token, path); string fullPath = GetFullPathIfSafe(token, path);
if (fullPath == string.Empty){ if (fullPath.Length == 0){
throw new Exception("File path has to be relative to the plugin folder."); throw new Exception("File path has to be relative to the plugin folder.");
} }
fileCache.Remove(fullPath); fileCache.Remove(fullPath);
File.Delete(fullPath); File.Delete(fullPath);
} }
public bool CheckFileExists(int token, string path){
string fullPath = GetFullPathIfSafe(token, path);
if (fullPath.Length == 0){
throw new Exception("File path has to be relative to the plugin folder.");
}
return File.Exists(fullPath);
}
} }
} }

View File

@@ -4,7 +4,7 @@ using TweetDck.Plugins.Events;
namespace TweetDck.Plugins{ namespace TweetDck.Plugins{
[Serializable] [Serializable]
class PluginConfig{ sealed class PluginConfig{
[field:NonSerialized] [field:NonSerialized]
public event EventHandler<PluginChangedStateEventArgs> PluginChangedState; public event EventHandler<PluginChangedStateEventArgs> PluginChangedState;
@@ -33,5 +33,9 @@ namespace TweetDck.Plugins{
public bool IsEnabled(Plugin plugin){ public bool IsEnabled(Plugin plugin){
return !Disabled.Contains(plugin.Identifier) && plugin.CanRun; return !Disabled.Contains(plugin.Identifier) && plugin.CanRun;
} }
public void DisableOfficialFromConfig(string pluginName){
Disabled.Add("official/"+pluginName);
}
} }
} }

View File

@@ -10,6 +10,7 @@ namespace TweetDck.Plugins{
class PluginManager{ class PluginManager{
public const string PluginBrowserScriptFile = "plugins.browser.js"; public const string PluginBrowserScriptFile = "plugins.browser.js";
public const string PluginNotificationScriptFile = "plugins.notification.js"; public const string PluginNotificationScriptFile = "plugins.notification.js";
public const string PluginGlobalScriptFile = "plugins.js";
public string PathOfficialPlugins { get { return Path.Combine(rootPath, "official"); } } public string PathOfficialPlugins { get { return Path.Combine(rootPath, "official"); } }
public string PathCustomPlugins { get { return Path.Combine(rootPath, "user"); } } public string PathCustomPlugins { get { return Path.Combine(rootPath, "user"); } }
@@ -51,7 +52,6 @@ namespace TweetDck.Plugins{
} }
public void Reload(){ public void Reload(){
HashSet<Plugin> prevPlugins = new HashSet<Plugin>(plugins);
plugins.Clear(); plugins.Clear();
tokens.Clear(); tokens.Clear();
@@ -65,7 +65,7 @@ namespace TweetDck.Plugins{
plugins.Add(plugin); plugins.Add(plugin);
} }
if (Reloaded != null && (loadErrors.Count > 0 || !prevPlugins.SetEquals(plugins))){ if (Reloaded != null){
Reloaded(this, new PluginLoadEventArgs(loadErrors)); Reloaded(this, new PluginLoadEventArgs(loadErrors));
} }
} }

View File

@@ -7,7 +7,7 @@ namespace TweetDck.Plugins{
} }
public static string GeneratePlugin(string pluginIdentifier, string pluginContents, int pluginToken, PluginEnvironment environment){ public static string GeneratePlugin(string pluginIdentifier, string pluginContents, int pluginToken, PluginEnvironment environment){
StringBuilder build = new StringBuilder(pluginIdentifier.Length+pluginContents.Length+150); StringBuilder build = new StringBuilder(2*pluginIdentifier.Length+pluginContents.Length+165);
build.Append("(function(").Append(environment.GetScriptVariables()).Append("){"); build.Append("(function(").Append(environment.GetScriptVariables()).Append("){");
@@ -16,6 +16,7 @@ namespace TweetDck.Plugins{
build.Append("obj:new class extends PluginBase{").Append(pluginContents).Append("}"); build.Append("obj:new class extends PluginBase{").Append(pluginContents).Append("}");
build.Append("};"); build.Append("};");
build.Append("tmp.obj.$id=\"").Append(pluginIdentifier).Append("\";");
build.Append("tmp.obj.$token=").Append(pluginToken).Append(";"); build.Append("tmp.obj.$token=").Append(pluginToken).Append(";");
build.Append("window.TD_PLUGINS.install(tmp);"); build.Append("window.TD_PLUGINS.install(tmp);");

View File

@@ -33,11 +33,16 @@ namespace TweetDck{
public static readonly Version Version = new Version(VersionTag); public static readonly Version Version = new Version(VersionTag);
public static readonly string StoragePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),BrandName); public static readonly bool IsPortable = File.Exists("makeportable");
public static readonly string PluginPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"plugins");
public static readonly string TemporaryPath = Path.Combine(Path.GetTempPath(),BrandName); public static readonly string ProgramPath = AppDomain.CurrentDomain.BaseDirectory;
public static readonly string StoragePath = IsPortable ? Path.Combine(ProgramPath, "portable", "storage") : GetDataStoragePath();
public static readonly string TemporaryPath = IsPortable ? Path.Combine(ProgramPath, "portable", "tmp") : Path.Combine(Path.GetTempPath(), BrandName+'_'+Path.GetRandomFileName().Substring(0, 6));
public static readonly string ConfigFilePath = Path.Combine(StoragePath, "TD_UserConfig.cfg"); public static readonly string ConfigFilePath = Path.Combine(StoragePath, "TD_UserConfig.cfg");
public static readonly string ScriptPath = Path.Combine(ProgramPath, "scripts");
public static readonly string PluginPath = Path.Combine(ProgramPath, "plugins");
public static uint WindowRestoreMessage; public static uint WindowRestoreMessage;
private static readonly LockManager LockManager = new LockManager(Path.Combine(StoragePath, ".lock")); private static readonly LockManager LockManager = new LockManager(Path.Combine(StoragePath, ".lock"));
@@ -47,7 +52,7 @@ namespace TweetDck{
public static string LogFile{ public static string LogFile{
get{ get{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"td-log.txt"); return Path.Combine(ProgramPath, "td-log.txt");
} }
} }
@@ -58,14 +63,19 @@ namespace TweetDck{
WindowRestoreMessage = NativeMethods.RegisterWindowMessage("TweetDuckRestore"); WindowRestoreMessage = NativeMethods.RegisterWindowMessage("TweetDuckRestore");
if (!File.Exists(LogFile) && !Log(string.Empty)){
MessageBox.Show("Could not write to the log file. If you installed "+BrandName+" to Program Files, please run it as Administrator.", "Administrator Required", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
string[] programArguments = Environment.GetCommandLineArgs(); string[] programArguments = Environment.GetCommandLineArgs();
if (programArguments.Contains("-restart")){ if (programArguments.Contains("-restart")){
for(int attempt = 0; attempt < 21; attempt++){ for(int attempt = 0; attempt < 41; attempt++){
if (LockManager.Lock()){ if (LockManager.Lock()){
break; break;
} }
else if (attempt == 20){ else if (attempt == 40){
MessageBox.Show(BrandName+" is taking too long to close, please wait and then start the application again manually.", BrandName+" Cannot Restart", MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show(BrandName+" is taking too long to close, please wait and then start the application again manually.", BrandName+" Cannot Restart", MessageBoxButtons.OK, MessageBoxIcon.Error);
return; return;
} }
@@ -81,7 +91,7 @@ namespace TweetDck{
return; return;
} }
else if (MessageBox.Show("Another instance of "+BrandName+" is already running.\r\nDo you want to close it?", BrandName+" is Already Running", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button2) == DialogResult.Yes){ else if (MessageBox.Show("Another instance of "+BrandName+" is already running.\r\nDo you want to close it?", BrandName+" is Already Running", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
if (!LockManager.CloseLockingProcess(10000)){ if (!LockManager.CloseLockingProcess(20000)){
MessageBox.Show("Could not close the other process.", BrandName+" Has Failed :(", MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show("Could not close the other process.", BrandName+" Has Failed :(", MessageBoxButtons.OK, MessageBoxIcon.Error);
return; return;
} }
@@ -162,28 +172,52 @@ namespace TweetDck{
} }
} }
public static void HandleException(string message, Exception e){ private static string GetCmdArgumentValue(string search){
Log(e.ToString()); string[] args = Environment.GetCommandLineArgs();
int index = Array.FindIndex(args, arg => arg.Equals(search, StringComparison.OrdinalIgnoreCase));
return index >= 0 && index < args.Length-1 ? args[index+1] : null;
}
private static string GetDataStoragePath(){
string custom = GetCmdArgumentValue("-datafolder");
if (custom != null && (custom.Contains(Path.DirectorySeparatorChar) || custom.Contains(Path.AltDirectorySeparatorChar))){
return custom;
}
else{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), custom ?? BrandName);
}
}
public static void HandleException(string message, Exception e){
if (Log(e.ToString())){
if (MessageBox.Show(message+"\r\nDo you want to open the log file to report the issue?", BrandName+" Has Failed :(", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button2) == DialogResult.Yes){ if (MessageBox.Show(message+"\r\nDo you want to open the log file to report the issue?", BrandName+" Has Failed :(", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
Process.Start(LogFile); Process.Start(LogFile);
} }
} }
else{
MessageBox.Show(message+"\r\nFailed writing the error into the log file.\r\nOriginal exception: "+e, BrandName+" Has Failed :(", MessageBoxButtons.OK);
}
}
public static void Log(string data){ public static bool Log(string data){
StringBuilder build = new StringBuilder(); StringBuilder build = new StringBuilder();
if (!File.Exists(LogFile)){ if (!File.Exists(LogFile)){
build.Append("Please, report all issues to: https://github.com/chylex/TweetDuck/issues\r\n\r\n"); build.Append("Please, report all issues to: https://github.com/chylex/TweetDuck/issues\r\n\r\n");
} }
build.Append("[").Append(DateTime.Now.ToString("G")).Append("]\r\n"); if (data.Length > 0){
build.Append("[").Append(DateTime.Now.ToString("G", CultureInfo.CurrentCulture)).Append("]\r\n");
build.Append(data).Append("\r\n\r\n"); build.Append(data).Append("\r\n\r\n");
}
try{ try{
File.AppendAllText(LogFile, build.ToString(), Encoding.UTF8); File.AppendAllText(LogFile, build.ToString(), Encoding.UTF8);
return true;
}catch{ }catch{
// oops return false;
} }
} }

View File

@@ -2,7 +2,7 @@
The program was build using Visual Studio 2013. After opening the solution, make sure you have **CefSharp.WinForms** and **Microsoft.VC120.CRT.JetBrains** included - if not, download them using NuGet. For **CefSharp**, you will need version 49 or newer currently available as a pre-release. The program was build using Visual Studio 2013. After opening the solution, make sure you have **CefSharp.WinForms** and **Microsoft.VC120.CRT.JetBrains** included - if not, download them using NuGet. For **CefSharp**, you will need version 49 or newer currently available as a pre-release.
``` ```
PM> Install-Package CefSharp.WinForms -Pre PM> Install-Package CefSharp.WinForms -Pre -Version 49.0.0-pre02
PM> Install-Package Microsoft.VC120.CRT.JetBrains PM> Install-Package Microsoft.VC120.CRT.JetBrains
``` ```

View File

@@ -0,0 +1,14 @@
[name]
Clear columns
[description]
- Adds buttons and keyboard shortcuts to quickly clear columns
[author]
chylex
[version]
1.0
[website]
https://tweetduck.chylex.com

View File

@@ -0,0 +1,92 @@
constructor(){
super({
requiresPageReload: true
});
}
enabled(){
// prepare variables and functions
var clearColumn = (columnName) => {
TD.controller.columnManager.get(columnName).clear();
TD.controller.stats.columnActionClick("clear");
};
var clearAllColumns = () => {
Object.keys(TD.controller.columnManager.getAll()).forEach(key => clearColumn(key));
};
var replaceMustache = (key, search, replace) => {
TD.mustaches[key] = TD.mustaches[key].replace(search, replace);
};
// prepare event handlers
this.eventClearSingle = function(){
clearColumn($(this).closest(".js-column").attr("data-column"));
};
this.eventClearAll = function(){
clearAllColumns();
};
this.eventKeys = function(e){
if (e.keyCode === 46 && (document.activeElement === null || document.activeElement === document.body)){ // 46 = delete
if (e.altKey){
clearAllColumns();
}
else{
var focusedColumn = $(".js-column.is-focused");
if (focusedColumn.length){
clearColumn(focusedColumn.attr("data-column"));
}
}
}
};
// add column buttons and keyboard shortcut info to UI
replaceMustache("column/column_header.mustache", "</header>", [
'{{^isTemporary}}',
'<a class="column-header-link" href="#" data-action="td-clearcolumns-dosingle" style="right:34px">',
'<i class="icon icon-clear-timeline"></i>',
'</a>',
'{{/isTemporary}}',
'</header>'
].join(""));
replaceMustache("keyboard_shortcut_list.mustache", "</dl> <dl", [
'<dd class="keyboard-shortcut-definition" style="white-space:nowrap">',
'<span class="text-like-keyboard-key">1</span> … <span class="text-like-keyboard-key">9</span> + <span class="text-like-keyboard-key">Del</span> Clear column 19',
'</dd><dd class="keyboard-shortcut-definition">',
'<span class="text-like-keyboard-key">Alt</span> + <span class="text-like-keyboard-key">Del</span> Clear all',
'</dd></dl><dl'
].join(""));
// load custom style
var style = document.createElement("style");
document.head.appendChild(style);
var sheet = style.sheet;
sheet.insertRule(".column-title { margin-right: 60px !important; }", 0);
sheet.insertRule(".column-type-message .column-title { margin-right: 115px !important; }", 0);
sheet.insertRule(".mark-all-read-link { right: 59px !important; }", 0);
sheet.insertRule(".open-compose-dm-link { right: 90px !important; }", 0);
}
ready(){
// setup events
$(document).on("click", "[data-action='td-clearcolumns-dosingle']", this.eventClearSingle);
$(document).on("click", "[data-action='td-clearcolumns-doall']", this.eventClearAll);
$(document).on("keydown", this.eventKeys);
// add clear all button
$("nav.app-navigator").first().append([
'<a class="link-clean cf app-nav-link padding-hl" data-title="Clear all" data-action="td-clearcolumns-doall">',
'<div class="obj-left"><i class="icon icon-large icon-clear-timeline"></i></div>',
'<div class="nbfc padding-ts hide-condensed">Clear all</div>',
'</a></nav>'
].join(""));
}
disabled(){
// not needed, plugin reloads the page when enabled or disabled
}

View File

@@ -12,4 +12,4 @@ chylex
1.0 1.0
[website] [website]
http://tweetduck.chylex.com https://tweetduck.chylex.com

View File

@@ -0,0 +1,23 @@
[name]
Custom reply account
[description]
- Allows customizing the automatically selected reply account per column
[author]
chylex
[version]
1.0
[website]
https://tweetduck.chylex.com
[configfile]
configuration.js
[configdefault]
configuration.default.js
[requires]
1.3.3

View File

@@ -0,0 +1,67 @@
enabled(){
var configuration = { defaultAccount: "" };
window.TDPF_loadConfigurationFile(this, "configuration.js", "configuration.default.js", obj => configuration = obj);
this.uiInlineComposeTweetEvent = function(e, data){
var account = null;
if (configuration.useAdvancedSelector && configuration.customSelector){
var column = TD.controller.columnManager.get(data.element.closest("section.column").attr("data-column"));
var result = configuration.customSelector(column);
if (typeof result === "string" && result[0] === '@'){
account = result.substring(1);
}
}
if (account === null){
if (configuration.defaultAccount === false){
return;
}
else if (configuration.defaultAccount !== "" && configuration.defaultAccount[0] === '@'){
account = configuration.defaultAccount.substring(1);
}
}
var identifier;
if (account === null){
identifier = TD.storage.clientController.client.getDefaultAccount();
}
else{
var obj = TD.storage.accountController.getAccountFromUsername(account);
if (obj.length === 0){
return;
}
else{
identifier = obj[0].privateState.key;
}
}
data.singleFrom = data.from = [ identifier ];
};
}
ready(){
var events = $._data(document, "events");
if ("uiInlineComposeTweet" in events){
$(document).on("uiInlineComposeTweet", this.uiInlineComposeTweetEvent);
var handlers = events["uiInlineComposeTweet"];
var oldHandler = handlers[0];
var newHandler = handlers[1];
handlers[0] = newHandler;
handlers[1] = oldHandler;
}
else{
$(document).on("uiInlineComposeTweet", this.uiInlineComposeTweetEvent);
}
}
disabled(){
$(document).off("uiInlineComposeTweet", this.uiInlineComposeTweetEvent);
}

View File

@@ -0,0 +1,79 @@
{
/*
* WARNING
* -------
*
* Make sure you are editing 'configuration.js' and not the default configuration file, as the default one will be replaced with each update.
*
*/
/*
* Simple way of configuring the plugin
* ------------------------------------
*
* Set value of 'defaultAccount' to one of the following values:
*
* "" to use your preferred TweetDeck account for all replies (default)
* "@myAccount" to specify an account name to use; has to be one of your registered account names
* false to fall back to default TweetDeck behavior; useful for advanced configuration below, otherwise disable the plugin instead
*
*/
defaultAccount: "",
/*
* Advanced way of configuring the plugin
* --------------------------------------
*
* This assumes a basic knowledge of JavaScript and jQuery.
*
* 1. Set value of 'useAdvancedSelector' to true
* 2. Uncomment the 'customSelector' function, and replace the example code with your desired behavior
*
* If 'customSelector' returns a string containing a full name of one of the registered accounts (including @), that account is used.
* If it returns anything else (for example false, undefined, or an account name that is not registered), it falls back to 'defaultAccount' behavior.
*
* The 'column' parameter is a TweetDeck column object. If you want to see all properties of the object, open your browser, nagivate to TweetDeck,
* log in, and run the following code in your browser console, which will return an object containing all of the column objects mapped to their IDs:
* TD.controller.columnManager.getAll()
*
* The example below shows how to extract the column type, title, and account from the object.
* Column type is prefixed with col_, and may be one of the following:
*
* col_timeline, col_interactions, col_mentions, col_followers, col_search, col_list,
* col_customtimeline, col_messages, col_usertweets, col_favorites, col_activity,
* col_dataminr, col_home, col_me, col_inbox, col_scheduled, col_unknown
*
* Some of these appear to be unused (for example, Home columns are 'col_timeline' instead of 'col_home').
*
* If you want to see your column types, run this in your browser console:
* Object.values(TD.controller.columnManager.getAll()).forEach(obj => console.log(obj.getColumnType()));
*
* You can also get the jQuery column object using: $("section.column[data-column='"+column.ui.state.columnKey+"']")
*
*/
useAdvancedSelector: false,
/*customSelector: function(column){
var titleObj = $(column.getTitleHTML());
var columnType = column.getColumnType(); // col_timeline
var columnTitle = titleObj.siblings(".column-head-title").text(); // Home
var columnAccount = titleObj.siblings(".attribution").text(); // @chylexmc
if (columnType === "col_search" && columnTitle === "TweetDuck"){
// This is a search column that looks for 'TweetDuck' in the tweets,
// search columns are normally linked to the preferred account
// so this forces the @TryTweetDuck account to be used instead.
return "@TryTweetDuck";
}
else if (columnType === "col_timeline" && columnAccount === "@chylexcz"){
// This is a Home column of my test account @chylexcz,
// but I want to reply to tweets from my official account.
return "@chylexmc";
}
// otherwise returns 'undefined' which falls back to 'defaultAccount' behavior
}*/
}

View File

@@ -11,7 +11,7 @@ namespace TweetDck.Resources{
public static string LoadResource(string name){ public static string LoadResource(string name){
try{ try{
return File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,name),Encoding.UTF8); return File.ReadAllText(Path.Combine(Program.ScriptPath, name), Encoding.UTF8);
}catch(Exception ex){ }catch(Exception ex){
MessageBox.Show("Unfortunately, "+Program.BrandName+" could not load the "+name+" file. The program will continue running with limited functionality.\r\n\r\n"+ex.Message, Program.BrandName+" Has Failed :(", MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show("Unfortunately, "+Program.BrandName+" could not load the "+name+" file. The program will continue running with limited functionality.\r\n\r\n"+ex.Message, Program.BrandName+" Has Failed :(", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null; return null;

View File

@@ -397,6 +397,21 @@
} }
}; };
//
// Block: Fix scheduled tweets not showing up sometimes.
//
$(document).on("dataTweetSent", function(e, data){
if (data.response.state && data.response.state === "scheduled"){
var column = Object.values(TD.controller.columnManager.getAll()).find(column => column.model.state.type === "scheduled");
if (column){
setTimeout(function(){
column.reloadTweets();
}, 1000);
}
}
});
// //
// Block: Inject custom CSS and layout into the page. // Block: Inject custom CSS and layout into the page.
// //
@@ -407,6 +422,7 @@
styleOfficial.sheet.insertRule("a[data-full-url] { word-break: break-all; }", 0); // break long urls styleOfficial.sheet.insertRule("a[data-full-url] { word-break: break-all; }", 0); // break long urls
styleOfficial.sheet.insertRule(".column-nav-link .attribution { position: absolute; }", 0); // fix cut off account names styleOfficial.sheet.insertRule(".column-nav-link .attribution { position: absolute; }", 0); // fix cut off account names
styleOfficial.sheet.insertRule(".txt-base-smallest .badge-verified:before { height: 13px !important; }", 0); // fix cut off badge icon styleOfficial.sheet.insertRule(".txt-base-smallest .badge-verified:before { height: 13px !important; }", 0); // fix cut off badge icon
styleOfficial.sheet.insertRule(".keyboard-shortcut-list { vertical-align: top; }", 0); // fix keyboard navigation alignment
if ($TD.hasCustomBrowserCSS){ if ($TD.hasCustomBrowserCSS){
var styleCustom = document.createElement("style"); var styleCustom = document.createElement("style");

View File

@@ -0,0 +1,37 @@
(function($TDP){
//
// Block: Setup a simple JavaScript object configuration loader.
//
window.TDPF_loadConfigurationFile = function(pluginObject, fileNameUser, fileNameDefault, onSuccess, onFailure){
var identifier = pluginObject.$id;
var token = pluginObject.$token;
$TDP.checkFileExists(token, fileNameUser).then(exists => {
var fileName = exists ? fileNameUser : fileNameDefault;
$TDP.readFile(token, fileName, true).then(contents => {
var obj;
try{
obj = eval("("+contents+")");
}catch(err){
if (!(onFailure && onFailure(err.message))){
$TD.alert("warning", "Problem loading '"+fileName+"' file for '"+identifier+"' plugin, the JavaScript syntax is invalid: "+err.message);
}
return;
}
onSuccess && onSuccess(obj);
}).catch(err => {
if (!(onFailure && onFailure(err))){
$TD.alert("warning", "Problem loading '"+fileName+"' file for '"+identifier+"' plugin: "+err.message);
}
});
}).catch(err => {
if (!(onFailure && onFailure(err))){
$TD.alert("warning", "Problem checking '"+fileNameUser+"' file for '"+identifier+"' plugin: "+err.message);
}
});
};
})($TDP);

View File

@@ -18,6 +18,9 @@
// Function: Creates the update notification element. Removes the old one if already exists. // Function: Creates the update notification element. Removes the old one if already exists.
// //
var createUpdateNotificationElement = function(version, download){ var createUpdateNotificationElement = function(version, download){
var outdated = version === "unsupported";
var tweetdick = version === "tweetdick";
var ele = $("#tweetdck-update"); var ele = $("#tweetdck-update");
var existed = ele.length > 0; var existed = ele.length > 0;
@@ -25,13 +28,31 @@
ele.remove(); ele.remove();
} }
var html = [ var html = outdated ? [
"<div id='tweetdck-update'>",
"<p class='tdu-title'>Unsupported System</p>",
"<p class='tdu-info'>You will not receive updates.</p>",
"<div class='tdu-buttons'>",
"<button class='btn btn-positive tdu-btn-unsupported'><span class='label'>Read More</span></button>",
"<button class='btn btn-negative tdu-btn-dismiss'><span class='label'>Dismiss</span></button>",
"</div>",
"</div>"
] : tweetdick ? [
"<div id='tweetdck-update'>",
"<p class='tdu-title'>TweetDick Ending</p>",
"<p class='tdu-info'>Please, move to TweetDuck.</p>",
"<div class='tdu-buttons'>",
"<button class='btn btn-positive tdu-btn-unsupported'><span class='label'>Read More</span></button>",
"<button class='btn btn-negative tdu-btn-dismiss'><span class='label'>Dismiss</span></button>",
"</div>",
"</div>"
] : [
"<div id='tweetdck-update'>", "<div id='tweetdck-update'>",
"<p class='tdu-title'>"+$TDU.brandName+" Update</p>", "<p class='tdu-title'>"+$TDU.brandName+" Update</p>",
"<p class='tdu-info'>Version "+version+" is now available.</p>", "<p class='tdu-info'>Version "+version+" is now available.</p>",
"<div class='tdu-buttons'>", "<div class='tdu-buttons'>",
"<button class='btn btn-positive tdu-btn-download'><span class='label'>Download</button>", "<button class='btn btn-positive tdu-btn-download'><span class='label'>Download</span></button>",
"<button class='btn btn-negative tdu-btn-dismiss'><span class='label'>Dismiss</button>", "<button class='btn btn-negative tdu-btn-dismiss'><span class='label'>Dismiss</span></button>",
"</div>", "</div>",
"</div>" "</div>"
]; ];
@@ -60,7 +81,7 @@
fontWeight: "bold", fontWeight: "bold",
textAlign: "center", textAlign: "center",
letterSpacing: "0.2px", letterSpacing: "0.2px",
margin: "4px auto 2px" margin: "5px auto 2px"
}); });
ele.children("p.tdu-info").first().css({ ele.children("p.tdu-info").first().css({
@@ -93,7 +114,15 @@
$TDU.onUpdateAccepted(version, download); $TDU.onUpdateAccepted(version, download);
}); });
buttonDiv.children(".tdu-btn-dismiss").click(function(){ buttonDiv.children(".tdu-btn-unsupported").click(function(){
$TDU.openBrowser("https://github.com/chylex/TweetDuck/wiki/Supported-Systems");
});
buttonDiv.children(".tdu-btn-tweetdick").click(function(){
$TDU.openBrowser("https://github.com/chylex/TweetDick/wiki/Future-of-TweetDick");
});
buttonDiv.children(".tdu-btn-dismiss,.tdu-btn-unsupported").click(function(){
$TDU.onUpdateDismissed(version); $TDU.onUpdateDismissed(version);
ele.slideUp(function(){ ele.remove(); }); ele.slideUp(function(){ ele.remove(); });
}); });
@@ -109,6 +138,21 @@
// Function: Runs an update check and updates all DOM elements appropriately. // Function: Runs an update check and updates all DOM elements appropriately.
// //
var runUpdateCheck = function(force, eventID){ var runUpdateCheck = function(force, eventID){
if (!$TDU.isSystemSupported){
if ($TDU.dismissedVersionTag !== "unsupported"){
createUpdateNotificationElement("unsupported");
}
return;
}
else if ($TDU.brandName === "TweetDick"){
if ($TDU.dismissedVersionTag !== "tweetdick"){
createUpdateNotificationElement("tweetdick");
}
return;
}
clearTimeout(updateCheckTimeoutID); clearTimeout(updateCheckTimeoutID);
updateCheckTimeoutID = setTimeout(runUpdateCheck, 1000*60*60); // 1 hour updateCheckTimeoutID = setTimeout(runUpdateCheck, 1000*60*60); // 1 hour

View File

@@ -235,7 +235,6 @@
<Compile Include="Migration\FormMigrationQuestion.Designer.cs"> <Compile Include="Migration\FormMigrationQuestion.Designer.cs">
<DependentUpon>FormMigrationQuestion.cs</DependentUpon> <DependentUpon>FormMigrationQuestion.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Migration\Helpers\LnkEditor.cs" />
<Compile Include="Migration\MigrationDecision.cs" /> <Compile Include="Migration\MigrationDecision.cs" />
<Compile Include="Migration\MigrationManager.cs" /> <Compile Include="Migration\MigrationManager.cs" />
<Compile Include="Migration\Helpers\ProgramRegistrySearch.cs" /> <Compile Include="Migration\Helpers\ProgramRegistrySearch.cs" />
@@ -272,17 +271,6 @@
<Install>true</Install> <Install>true</Install>
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>
<ItemGroup>
<COMReference Include="Shell32">
<Guid>{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Core\FormBrowser.resx"> <EmbeddedResource Include="Core\FormBrowser.resx">
<DependentUpon>FormBrowser.cs</DependentUpon> <DependentUpon>FormBrowser.cs</DependentUpon>
@@ -310,36 +298,6 @@
<TargetPath>icon.ico</TargetPath> <TargetPath>icon.ico</TargetPath>
</ContentWithTargetPath> </ContentWithTargetPath>
</ItemGroup> </ItemGroup>
<ItemGroup>
<ContentWithTargetPath Include="Resources\Scripts\code.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>code.js</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup>
<ContentWithTargetPath Include="Resources\Scripts\notification.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>notification.js</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup>
<ContentWithTargetPath Include="Resources\Scripts\plugins.browser.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>plugins.browser.js</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup>
<ContentWithTargetPath Include="Resources\Scripts\plugins.notification.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>plugins.notification.js</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup>
<ContentWithTargetPath Include="Resources\Scripts\update.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>update.js</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Resources\icon-small.ico" /> <None Include="Resources\icon-small.ico" />
<None Include="Resources\icon-tray-new.ico" /> <None Include="Resources\icon-tray-new.ico" />
@@ -347,6 +305,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Resources\Plugins\" /> <Folder Include="Resources\Plugins\" />
<Folder Include="Resources\Scripts\" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
@@ -370,6 +329,10 @@ ren "$(TargetDir)LICENSE.md" "LICENSE.txt"
xcopy "$(ProjectDir)Libraries\CEFSHARP-LICENSE.txt" "$(TargetDir)" /Y xcopy "$(ProjectDir)Libraries\CEFSHARP-LICENSE.txt" "$(TargetDir)" /Y
xcopy "$(ProjectDir)packages\Microsoft.VC120.CRT.JetBrains.12.0.21005.2\DotFiles\msvcp120.dll" "$(TargetDir)" /Y xcopy "$(ProjectDir)packages\Microsoft.VC120.CRT.JetBrains.12.0.21005.2\DotFiles\msvcp120.dll" "$(TargetDir)" /Y
xcopy "$(ProjectDir)packages\Microsoft.VC120.CRT.JetBrains.12.0.21005.2\DotFiles\msvcr120.dll" "$(TargetDir)" /Y xcopy "$(ProjectDir)packages\Microsoft.VC120.CRT.JetBrains.12.0.21005.2\DotFiles\msvcr120.dll" "$(TargetDir)" /Y
rmdir "$(TargetDir)scripts"
mkdir "$(TargetDir)scripts"
xcopy "$(ProjectDir)Resources\Scripts\*" "$(TargetDir)scripts\" /E /Y
rmdir "$(TargetDir)plugins"
mkdir "$(TargetDir)plugins" mkdir "$(TargetDir)plugins"
mkdir "$(TargetDir)plugins\official" mkdir "$(TargetDir)plugins\official"
mkdir "$(TargetDir)plugins\user" mkdir "$(TargetDir)plugins\user"

View File

@@ -3,6 +3,7 @@ using CefSharp;
using CefSharp.WinForms; using CefSharp.WinForms;
using TweetDck.Core; using TweetDck.Core;
using TweetDck.Core.Controls; using TweetDck.Core.Controls;
using TweetDck.Core.Utils;
using TweetDck.Resources; using TweetDck.Resources;
namespace TweetDck.Updates{ namespace TweetDck.Updates{
@@ -70,6 +71,12 @@ namespace TweetDck.Updates{
} }
} }
public bool IsSystemSupported{
get{
return Environment.OSVersion.Version >= new Version("6.1"); // 6.1 NT version = Windows 7
}
}
private readonly UpdateHandler owner; private readonly UpdateHandler owner;
public Bridge(UpdateHandler owner){ public Bridge(UpdateHandler owner){
@@ -90,6 +97,10 @@ namespace TweetDck.Updates{
Program.UserConfig.Save(); Program.UserConfig.Save();
}); });
} }
public void OpenBrowser(string url){
BrowserUtils.OpenExternalBrowser(url);
}
} }
} }
} }