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

Compare commits

..

36 Commits
1.4 ... 1.4.1

Author SHA1 Message Date
28cc60d007 Tweak CommandLineArgsParser to slightly improve reliability with quoted strings 2016-09-27 18:11:50 +02:00
1fa69bdb3b Add invalid data folder error reporting and env variable expansion for absolute paths 2016-09-27 18:00:05 +02:00
11f5f9b72e Add Reporter.HandleEarlyFailure for non-recoverable errors before Reporter is setup 2016-09-27 17:58:13 +02:00
61f6543041 Change Source Code link to Tips & Tricks 2016-09-27 17:37:19 +02:00
0c9ab32f37 Add additional functionality to the back mouse button (inline and drawer composer, fix order) 2016-09-27 04:16:50 +02:00
fde984d02b Add a hover class to Notification body element and only display skip button when over 2016-09-27 03:48:14 +02:00
f23db31306 Increase default size of Edit CSS dialog 2016-09-26 17:20:25 +02:00
8dce99b8b3 Add support for ctrl+a shortcut in multiline textboxes 2016-09-26 17:20:10 +02:00
342ac51cda Tweak the skip button position in Notification window 2016-09-26 17:14:17 +02:00
ba31f7ae01 Update TweetDuck website to https 2016-09-26 16:31:06 +02:00
8d0fa030f8 Remove d3dcompiler_43.dll that used to be required for Win XP 2016-09-26 16:16:20 +02:00
d030a79c81 Fix Release build compliation error 2016-09-26 16:10:21 +02:00
6690efc4d9 Address code analysis issues 2016-09-26 15:53:08 +02:00
afa8098463 Add two restart buttons to Settings - Advanced 2016-09-26 14:28:14 +02:00
c064e579d2 Add Program.Restart and fix restarting causing loss of initial program arguments 2016-09-26 14:05:44 +02:00
01dc4e4714 Update CommandLineArgsParser to use CommandLineArgs 2016-09-26 13:58:59 +02:00
6fbc246b12 Use CommandLineArgs in Program and fix broken -locale parameter 2016-09-26 13:56:13 +02:00
1efe2a02f7 Add a CommandLineArgs class for easy arg management 2016-09-26 13:52:55 +02:00
ab2ab06f60 Reorganize utility classes and methods in TweetDeck Migration code 2016-09-26 04:19:50 +02:00
a71d889682 Replace FormMigrationQuestion with a custom FormMessage 2016-09-25 23:10:18 +02:00
2252d85b27 Add MessageBoxIcon.Question support to FormMessage 2016-09-25 23:09:36 +02:00
3f09100177 Update version of the design-revert plugin 2016-09-25 19:01:39 +02:00
6b79c89f42 Add a button to skip current notification 2016-09-25 16:53:00 +02:00
5f249d4603 Add a <body> td-example-notification attribute for example notifications 2016-09-25 16:52:22 +02:00
fa64309909 Hide the old TweetDeck column Clear button when clear-columns plugin is enabled 2016-09-25 15:35:15 +02:00
c46aafdab6 Add column resetting to clear-columns plugin 2016-09-25 15:31:18 +02:00
3e9c397494 Fix inconsistency with loadConfigurationFile's onFailure parameter 2016-09-25 03:21:44 +02:00
47935165db Update current plugins to use the new CSS functionality 2016-09-25 02:37:16 +02:00
be77f753e7 Add a global function to easily add custom styles in plugins 2016-09-25 02:34:19 +02:00
2c30613279 Fix reply-account plugin for docked replies 2016-09-23 22:09:06 +02:00
d83eaec987 Update reply-account plugin version 2016-09-23 21:14:53 +02:00
e6f199a224 Implement #last in reply-account and fix bugs in its code 2016-09-23 21:13:54 +02:00
6636a2aa9e Add an experimental timeline-polls plugin 2016-09-23 19:49:56 +02:00
221bdc58fe Tweak support for old configs in reply-account plugin 2016-09-23 16:05:53 +02:00
e48a068e9d Redesign reply-account plugin configuration and add WIP last account setting 2016-09-23 15:55:13 +02:00
3371c31e63 Release 1.4 2016-09-22 00:58:27 +02:00
37 changed files with 620 additions and 393 deletions

View File

@@ -34,5 +34,15 @@ namespace TweetDck.Core.Controls{
trackBar.Value = value; trackBar.Value = value;
} }
} }
public static void EnableMultilineShortcuts(this TextBox textBox){
textBox.KeyDown += (sender, args) => {
if (args.Control && args.KeyCode == Keys.A){
((TextBox)sender).SelectAll();
args.SuppressKeyPress = true;
args.Handled = true;
}
};
}
} }
} }

View File

@@ -119,6 +119,10 @@ namespace TweetDck.Core.Handling{
} }
} }
public void LoadNextNotification(){
notification.InvokeSafe(notification.FinishCurrentTweet);
}
public void TryPasteImage(){ public void TryPasteImage(){
form.InvokeSafe(() => { form.InvokeSafe(() => {
if (Clipboard.ContainsImage()){ if (Clipboard.ContainsImage()){

View File

@@ -20,7 +20,7 @@ namespace TweetDck.Core.Handling{
private static string CustomCSS{ private static string CustomCSS{
get{ get{
return @".scroll-styled-v::-webkit-scrollbar{width:8px}.scroll-styled-v::-webkit-scrollbar-thumb{border-radius:0}a[data-full-url]{word-break:break-all}"; return @".scroll-styled-v::-webkit-scrollbar{width:8px}.scroll-styled-v::-webkit-scrollbar-thumb{border-radius:0}a[data-full-url]{word-break:break-all}#td-skip{opacity:0;cursor:pointer;transition:opacity 0.15s ease}.td-hover #td-skip{opacity:0.75}#td-skip:hover{opacity:1}";
} }
} }
@@ -55,7 +55,7 @@ namespace TweetDck.Core.Handling{
build.Append(@"</div></div></article>"); build.Append(@"</div></div></article>");
return new TweetNotification(build.ToString(), "", 95); return new TweetNotification(build.ToString(), "", 95, true);
} }
} }
@@ -84,11 +84,15 @@ namespace TweetDck.Core.Handling{
private readonly string html; private readonly string html;
private readonly string url; private readonly string url;
private readonly int characters; private readonly int characters;
private readonly bool isExample;
public TweetNotification(string html, string url, int characters){ public TweetNotification(string html, string url, int characters) : this(html, url, characters, false){}
private TweetNotification(string html, string url, int characters, bool isExample){
this.html = html; this.html = html;
this.url = url; this.url = url;
this.characters = characters; this.characters = characters;
this.isExample = isExample;
} }
public int GetDisplayDuration(int value){ public int GetDisplayDuration(int value){
@@ -106,7 +110,7 @@ namespace TweetDck.Core.Handling{
} }
build.Append("</head>"); build.Append("</head>");
build.Append("<body class='hearty'><div class='app-columns-container'><div class='column scroll-styled-v' style='width:100%;overflow-y:auto'>"); build.Append("<body class='hearty'").Append(isExample ? " td-example-notification" : "").Append("><div class='app-columns-container'><div class='column scroll-styled-v' style='width:100%;overflow-y:auto'>");
build.Append(html); build.Append(html);
build.Append("</div></div></body>"); build.Append("</div></div></body>");
build.Append("</html>"); build.Append("</html>");

View File

@@ -28,7 +28,7 @@ namespace TweetDck.Core.Other {
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormAbout)); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormAbout));
this.pictureLogo = new System.Windows.Forms.PictureBox(); this.pictureLogo = new System.Windows.Forms.PictureBox();
this.labelDescription = new System.Windows.Forms.Label(); this.labelDescription = new System.Windows.Forms.Label();
this.labelSourceCode = new System.Windows.Forms.LinkLabel(); this.labelTips = new System.Windows.Forms.LinkLabel();
this.labelWebsite = new System.Windows.Forms.LinkLabel(); this.labelWebsite = new System.Windows.Forms.LinkLabel();
this.tablePanelLinks = new System.Windows.Forms.TableLayoutPanel(); this.tablePanelLinks = new System.Windows.Forms.TableLayoutPanel();
this.labelIssues = new System.Windows.Forms.LinkLabel(); this.labelIssues = new System.Windows.Forms.LinkLabel();
@@ -59,19 +59,19 @@ namespace TweetDck.Core.Other {
this.labelDescription.Size = new System.Drawing.Size(232, 109); this.labelDescription.Size = new System.Drawing.Size(232, 109);
this.labelDescription.TabIndex = 1; this.labelDescription.TabIndex = 1;
// //
// labelSourceCode // labelTips
// //
this.labelSourceCode.Dock = System.Windows.Forms.DockStyle.Fill; this.labelTips.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelSourceCode.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); this.labelTips.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelSourceCode.LinkArea = new System.Windows.Forms.LinkArea(0, 0); this.labelTips.LinkArea = new System.Windows.Forms.LinkArea(0, 0);
this.labelSourceCode.Location = new System.Drawing.Point(117, 0); this.labelTips.Location = new System.Drawing.Point(117, 0);
this.labelSourceCode.Margin = new System.Windows.Forms.Padding(0); this.labelTips.Margin = new System.Windows.Forms.Padding(0);
this.labelSourceCode.Name = "labelSourceCode"; this.labelTips.Name = "labelTips";
this.labelSourceCode.Size = new System.Drawing.Size(99, 16); this.labelTips.Size = new System.Drawing.Size(99, 16);
this.labelSourceCode.TabIndex = 3; this.labelTips.TabIndex = 3;
this.labelSourceCode.Text = "Source Code"; this.labelTips.Text = "Tips && Tricks";
this.labelSourceCode.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; this.labelTips.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.labelSourceCode.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked); this.labelTips.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
// //
// labelWebsite // labelWebsite
// //
@@ -98,7 +98,7 @@ namespace TweetDck.Core.Other {
this.tablePanelLinks.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 35.14F)); this.tablePanelLinks.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 35.14F));
this.tablePanelLinks.Controls.Add(this.labelIssues, 2, 0); this.tablePanelLinks.Controls.Add(this.labelIssues, 2, 0);
this.tablePanelLinks.Controls.Add(this.labelWebsite, 0, 0); this.tablePanelLinks.Controls.Add(this.labelWebsite, 0, 0);
this.tablePanelLinks.Controls.Add(this.labelSourceCode, 1, 0); this.tablePanelLinks.Controls.Add(this.labelTips, 1, 0);
this.tablePanelLinks.Location = new System.Drawing.Point(12, 124); this.tablePanelLinks.Location = new System.Drawing.Point(12, 124);
this.tablePanelLinks.Name = "tablePanelLinks"; this.tablePanelLinks.Name = "tablePanelLinks";
this.tablePanelLinks.RowCount = 1; this.tablePanelLinks.RowCount = 1;
@@ -146,7 +146,7 @@ namespace TweetDck.Core.Other {
private System.Windows.Forms.PictureBox pictureLogo; private System.Windows.Forms.PictureBox pictureLogo;
private System.Windows.Forms.Label labelDescription; private System.Windows.Forms.Label labelDescription;
private System.Windows.Forms.LinkLabel labelSourceCode; private System.Windows.Forms.LinkLabel labelTips;
private System.Windows.Forms.LinkLabel labelWebsite; private System.Windows.Forms.LinkLabel labelWebsite;
private System.Windows.Forms.TableLayoutPanel tablePanelLinks; private System.Windows.Forms.TableLayoutPanel tablePanelLinks;
private System.Windows.Forms.LinkLabel labelIssues; private System.Windows.Forms.LinkLabel labelIssues;

View File

@@ -3,7 +3,7 @@ using TweetDck.Core.Utils;
namespace TweetDck.Core.Other{ namespace TweetDck.Core.Other{
sealed partial class FormAbout : Form{ sealed partial class FormAbout : Form{
private const string GitHubLink = "https://github.com/chylex/TweetDuck"; private const string TipsLink = "https://github.com/chylex/TweetDuck/wiki";
private const string IssuesLink = "https://github.com/chylex/TweetDuck/issues"; private const string IssuesLink = "https://github.com/chylex/TweetDuck/issues";
public FormAbout(){ public FormAbout(){
@@ -14,7 +14,7 @@ namespace TweetDck.Core.Other{
labelDescription.Text = Program.BrandName+" was created by chylex as a replacement to the discontinued official TweetDeck client for Windows.\n\nThe program is available for free under the open source MIT license."; labelDescription.Text = Program.BrandName+" was created by chylex as a replacement to the discontinued official TweetDeck client for Windows.\n\nThe program is available for free under the open source MIT license.";
labelWebsite.Links.Add(new LinkLabel.Link(0, labelWebsite.Text.Length, Program.Website)); labelWebsite.Links.Add(new LinkLabel.Link(0, labelWebsite.Text.Length, Program.Website));
labelSourceCode.Links.Add(new LinkLabel.Link(0, labelSourceCode.Text.Length, GitHubLink)); labelTips.Links.Add(new LinkLabel.Link(0, labelTips.Text.Length, TipsLink));
labelIssues.Links.Add(new LinkLabel.Link(0, labelIssues.Text.Length, IssuesLink)); labelIssues.Links.Add(new LinkLabel.Link(0, labelIssues.Text.Length, IssuesLink));
} }

View File

@@ -34,6 +34,10 @@ namespace TweetDck.Core.Other{
icon = SystemIcons.Error; icon = SystemIcons.Error;
break; break;
case MessageBoxIcon.Question:
icon = SystemIcons.Question;
break;
default: default:
icon = null; icon = null;
labelMessage.Location = new Point(labelMessage.Location.X-32, labelMessage.Location.Y); labelMessage.Location = new Point(labelMessage.Location.X-32, labelMessage.Location.Y);

View File

@@ -1,5 +1,4 @@
using System.Diagnostics; using System.Windows.Forms;
using System.Windows.Forms;
using TweetDck.Configuration; using TweetDck.Configuration;
namespace TweetDck.Core.Other.Settings{ namespace TweetDck.Core.Other.Settings{
@@ -18,8 +17,7 @@ namespace TweetDck.Core.Other.Settings{
protected static void PromptRestart(){ protected static void PromptRestart(){
if (MessageBox.Show("The application must restart for the setting to take place. Do you want to restart now?", Program.BrandName+" Settings", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes){ if (MessageBox.Show("The application must restart for the setting to take place. Do you want to restart now?", Program.BrandName+" Settings", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes){
Process.Start(Application.ExecutablePath, "-restart"); Program.Restart();
Application.Exit();
} }
} }
} }

View File

@@ -48,14 +48,14 @@
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.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.textBoxBrowserCSS.Size = new System.Drawing.Size(226, 193); this.textBoxBrowserCSS.Size = new System.Drawing.Size(373, 253);
this.textBoxBrowserCSS.TabIndex = 0; this.textBoxBrowserCSS.TabIndex = 0;
this.textBoxBrowserCSS.WordWrap = false; this.textBoxBrowserCSS.WordWrap = false;
// //
// btnCancel // btnCancel
// //
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.Location = new System.Drawing.Point(354, 227); this.btnCancel.Location = new System.Drawing.Point(654, 287);
this.btnCancel.Name = "btnCancel"; this.btnCancel.Name = "btnCancel";
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0); this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnCancel.Size = new System.Drawing.Size(56, 23); this.btnCancel.Size = new System.Drawing.Size(56, 23);
@@ -67,7 +67,7 @@
// btnApply // btnApply
// //
this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnApply.Location = new System.Drawing.Point(416, 227); this.btnApply.Location = new System.Drawing.Point(716, 287);
this.btnApply.Name = "btnApply"; this.btnApply.Name = "btnApply";
this.btnApply.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0); this.btnApply.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnApply.Size = new System.Drawing.Size(56, 23); this.btnApply.Size = new System.Drawing.Size(56, 23);
@@ -95,8 +95,8 @@
this.splitContainer.Panel2.Controls.Add(this.labelNotification); this.splitContainer.Panel2.Controls.Add(this.labelNotification);
this.splitContainer.Panel2.Controls.Add(this.textBoxNotificationCSS); this.splitContainer.Panel2.Controls.Add(this.textBoxNotificationCSS);
this.splitContainer.Panel2MinSize = 64; this.splitContainer.Panel2MinSize = 64;
this.splitContainer.Size = new System.Drawing.Size(460, 209); this.splitContainer.Size = new System.Drawing.Size(760, 269);
this.splitContainer.SplitterDistance = 226; this.splitContainer.SplitterDistance = 373;
this.splitContainer.SplitterWidth = 5; this.splitContainer.SplitterWidth = 5;
this.splitContainer.TabIndex = 5; this.splitContainer.TabIndex = 5;
// //
@@ -131,7 +131,7 @@
this.textBoxNotificationCSS.Multiline = true; this.textBoxNotificationCSS.Multiline = true;
this.textBoxNotificationCSS.Name = "textBoxNotificationCSS"; this.textBoxNotificationCSS.Name = "textBoxNotificationCSS";
this.textBoxNotificationCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.textBoxNotificationCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.textBoxNotificationCSS.Size = new System.Drawing.Size(226, 193); this.textBoxNotificationCSS.Size = new System.Drawing.Size(378, 253);
this.textBoxNotificationCSS.TabIndex = 1; this.textBoxNotificationCSS.TabIndex = 1;
this.textBoxNotificationCSS.WordWrap = false; this.textBoxNotificationCSS.WordWrap = false;
// //
@@ -139,7 +139,7 @@
// //
this.labelWarning.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.labelWarning.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.labelWarning.AutoSize = true; this.labelWarning.AutoSize = true;
this.labelWarning.Location = new System.Drawing.Point(9, 232); this.labelWarning.Location = new System.Drawing.Point(9, 292);
this.labelWarning.Name = "labelWarning"; this.labelWarning.Name = "labelWarning";
this.labelWarning.Size = new System.Drawing.Size(341, 13); this.labelWarning.Size = new System.Drawing.Size(341, 13);
this.labelWarning.TabIndex = 6; this.labelWarning.TabIndex = 6;
@@ -149,7 +149,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(484, 262); this.ClientSize = new System.Drawing.Size(784, 322);
this.Controls.Add(this.labelWarning); this.Controls.Add(this.labelWarning);
this.Controls.Add(this.splitContainer); this.Controls.Add(this.splitContainer);
this.Controls.Add(this.btnApply); this.Controls.Add(this.btnApply);

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Windows.Forms; using System.Windows.Forms;
using TweetDck.Core.Controls;
namespace TweetDck.Core.Other.Settings.Dialogs{ namespace TweetDck.Core.Other.Settings.Dialogs{
sealed partial class DialogSettingsCSS : Form{ sealed partial class DialogSettingsCSS : Form{
@@ -19,8 +20,11 @@ namespace TweetDck.Core.Other.Settings.Dialogs{
InitializeComponent(); InitializeComponent();
Text = Program.BrandName+" Settings - CSS"; Text = Program.BrandName+" Settings - CSS";
textBoxBrowserCSS.EnableMultilineShortcuts();
textBoxBrowserCSS.Text = Program.UserConfig.CustomBrowserCSS ?? ""; textBoxBrowserCSS.Text = Program.UserConfig.CustomBrowserCSS ?? "";
textBoxNotificationCSS.EnableMultilineShortcuts();
textBoxNotificationCSS.Text = Program.UserConfig.CustomNotificationCSS ?? ""; textBoxNotificationCSS.Text = Program.UserConfig.CustomNotificationCSS ?? "";
} }

View File

@@ -1,6 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Windows.Forms; using System.Windows.Forms;
using TweetDck.Core.Controls;
using TweetDck.Core.Utils; using TweetDck.Core.Utils;
namespace TweetDck.Core.Other.Settings.Dialogs{ namespace TweetDck.Core.Other.Settings.Dialogs{
@@ -15,7 +15,8 @@ namespace TweetDck.Core.Other.Settings.Dialogs{
InitializeComponent(); InitializeComponent();
Text = Program.BrandName+" Settings - CEF Arguments"; Text = Program.BrandName+" Settings - CEF Arguments";
textBoxArgs.EnableMultilineShortcuts();
textBoxArgs.Text = Program.UserConfig.CustomCefArgs ?? ""; textBoxArgs.Text = Program.UserConfig.CustomCefArgs ?? "";
textBoxArgs.Select(textBoxArgs.Text.Length, 0); textBoxArgs.Select(textBoxArgs.Text.Length, 0);
} }
@@ -33,7 +34,7 @@ namespace TweetDck.Core.Other.Settings.Dialogs{
return; return;
} }
int count = CommandLineArgsParser.AddToDictionary(CefArgs, new Dictionary<string, string>()); int count = CommandLineArgsParser.ReadCefArguments(CefArgs).Count;
string prompt = count == 0 && !string.IsNullOrWhiteSpace(prevArgs) ? "All arguments will be removed from the settings. Continue?" : count+(count == 1 ? " argument" : " arguments")+" will be added to the settings. Continue?"; string prompt = count == 0 && !string.IsNullOrWhiteSpace(prevArgs) ? "All arguments will be removed from the settings. Continue?" : count+(count == 1 ? " argument" : " arguments")+" will be added to the settings. Continue?";
if (MessageBox.Show(prompt, "Confirm CEF Arguments", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.OK){ if (MessageBox.Show(prompt, "Confirm CEF Arguments", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.OK){

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
@@ -105,8 +104,7 @@ namespace TweetDck.Core.Other.Settings.Export{
// okay to and restart, 'cookies' is always the last entry // okay to and restart, 'cookies' is always the last entry
IsRestarting = true; IsRestarting = true;
Process.Start(Application.ExecutablePath, "-restart -importcookies"); Program.Restart(new string[]{ "-importcookies" });
Application.Exit();
} }
break; break;

View File

@@ -34,8 +34,12 @@
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.groupApp = new System.Windows.Forms.GroupBox();
this.btnRestartLog = new System.Windows.Forms.Button();
this.btnRestart = new System.Windows.Forms.Button();
this.groupPerformance.SuspendLayout(); this.groupPerformance.SuspendLayout();
this.groupConfiguration.SuspendLayout(); this.groupConfiguration.SuspendLayout();
this.groupApp.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
// //
// btnClearCache // btnClearCache
@@ -148,10 +152,46 @@
this.groupConfiguration.TabStop = false; this.groupConfiguration.TabStop = false;
this.groupConfiguration.Text = "Configuration"; this.groupConfiguration.Text = "Configuration";
// //
// groupApp
//
this.groupApp.Controls.Add(this.btnRestartLog);
this.groupApp.Controls.Add(this.btnRestart);
this.groupApp.Location = new System.Drawing.Point(198, 9);
this.groupApp.Name = "groupApp";
this.groupApp.Size = new System.Drawing.Size(183, 77);
this.groupApp.TabIndex = 20;
this.groupApp.TabStop = false;
this.groupApp.Text = "App";
//
// btnRestartLog
//
this.btnRestartLog.Location = new System.Drawing.Point(6, 48);
this.btnRestartLog.Name = "btnRestartLog";
this.btnRestartLog.Size = new System.Drawing.Size(171, 23);
this.btnRestartLog.TabIndex = 17;
this.btnRestartLog.Text = "Restart with Logging";
this.toolTip.SetToolTip(this.btnRestartLog, "Restarts the program and enables logging\r\ninto a debug.txt file in the installati" +
"on folder.");
this.btnRestartLog.UseVisualStyleBackColor = true;
this.btnRestartLog.Click += new System.EventHandler(this.btnRestartLog_Click);
//
// btnRestart
//
this.btnRestart.Location = new System.Drawing.Point(6, 19);
this.btnRestart.Name = "btnRestart";
this.btnRestart.Size = new System.Drawing.Size(171, 23);
this.btnRestart.TabIndex = 16;
this.btnRestart.Text = "Restart the Program";
this.toolTip.SetToolTip(this.btnRestart, "Restarts the program using the same command\r\nline arguments that were used at lau" +
"nch.");
this.btnRestart.UseVisualStyleBackColor = true;
this.btnRestart.Click += new System.EventHandler(this.btnRestart_Click);
//
// TabSettingsAdvanced // TabSettingsAdvanced
// //
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.groupApp);
this.Controls.Add(this.groupConfiguration); this.Controls.Add(this.groupConfiguration);
this.Controls.Add(this.groupPerformance); this.Controls.Add(this.groupPerformance);
this.Controls.Add(this.btnReset); this.Controls.Add(this.btnReset);
@@ -162,6 +202,7 @@
this.groupPerformance.ResumeLayout(false); this.groupPerformance.ResumeLayout(false);
this.groupPerformance.PerformLayout(); this.groupPerformance.PerformLayout();
this.groupConfiguration.ResumeLayout(false); this.groupConfiguration.ResumeLayout(false);
this.groupApp.ResumeLayout(false);
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
@@ -179,5 +220,8 @@
private System.Windows.Forms.GroupBox groupConfiguration; private System.Windows.Forms.GroupBox groupConfiguration;
private System.Windows.Forms.Button btnEditCefArgs; private System.Windows.Forms.Button btnEditCefArgs;
private System.Windows.Forms.Button btnEditCSS; private System.Windows.Forms.Button btnEditCSS;
private System.Windows.Forms.GroupBox groupApp;
private System.Windows.Forms.Button btnRestartLog;
private System.Windows.Forms.Button btnRestart;
} }
} }

View File

@@ -70,21 +70,25 @@ namespace TweetDck.Core.Other.Settings{
if (form.ShowDialog(ParentForm) == DialogResult.OK){ if (form.ShowDialog(ParentForm) == DialogResult.OK){
Config.CustomCefArgs = form.CefArgs; Config.CustomCefArgs = form.CefArgs;
form.Dispose();
PromptRestart(); PromptRestart();
} }
else{
form.Dispose();
}
} }
private void btnEditCSS_Click(object sender, EventArgs e){ private void btnEditCSS_Click(object sender, EventArgs e){
DialogSettingsCSS form = new DialogSettingsCSS(); using(DialogSettingsCSS form = new DialogSettingsCSS()){
if (form.ShowDialog(ParentForm) == DialogResult.OK){
bool hasChangedBrowser = form.BrowserCSS != Config.CustomBrowserCSS;
if (form.ShowDialog(ParentForm) == DialogResult.OK){ Config.CustomBrowserCSS = form.BrowserCSS;
bool hasChangedBrowser = form.BrowserCSS != Config.CustomBrowserCSS; Config.CustomNotificationCSS = form.NotificationCSS;
Config.CustomBrowserCSS = form.BrowserCSS; if (hasChangedBrowser && MessageBox.Show("The browser CSS has changed, do you want to reload it?", "Browser CSS Changed", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
Config.CustomNotificationCSS = form.NotificationCSS; browserReloadAction();
}
if (hasChangedBrowser && MessageBox.Show("The browser CSS has changed, do you want to reload it?", "Browser CSS Changed", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
browserReloadAction();
} }
} }
} }
@@ -151,5 +155,13 @@ namespace TweetDck.Core.Other.Settings{
((FormSettings)ParentForm).ReloadUI(); ((FormSettings)ParentForm).ReloadUI();
} }
} }
private void btnRestart_Click(object sender, EventArgs e){
Program.Restart();
}
private void btnRestartLog_Click(object sender, EventArgs e){
Program.Restart(new string[]{ "-log" });
}
} }
} }

View File

@@ -0,0 +1,107 @@
using System.Collections.Generic;
using System.Text;
namespace TweetDck.Core.Utils{
class CommandLineArgs{
public static CommandLineArgs FromStringArray(char entryChar, string[] array){
CommandLineArgs args = new CommandLineArgs();
ReadStringArray(entryChar, array, args);
return args;
}
public static void ReadStringArray(char entryChar, string[] array, CommandLineArgs targetArgs){
for(int index = 0; index < array.Length; index++){
string entry = array[index];
if (entry.Length > 0 && entry[0] == entryChar){
if (index < array.Length-1){
string potentialValue = array[index+1];
if (potentialValue.Length > 0 && potentialValue[0] == entryChar){
targetArgs.AddFlag(entry);
}
else{
targetArgs.SetValue(entry, potentialValue);
++index;
}
}
else{
targetArgs.AddFlag(entry);
}
}
}
}
private readonly HashSet<string> flags = new HashSet<string>();
private readonly Dictionary<string, string> values = new Dictionary<string, string>();
public int Count{
get{
return flags.Count+values.Count;
}
}
public void AddFlag(string flag){
flags.Add(flag.ToLowerInvariant());
}
public bool HasFlag(string flag){
return flags.Contains(flag.ToLowerInvariant());
}
public void RemoveFlag(string flag){
flags.Remove(flag.ToLowerInvariant());
}
public void SetValue(string key, string value){
values[key.ToLowerInvariant()] = value;
}
public string GetValue(string key, string defaultValue){
string val;
return values.TryGetValue(key.ToLowerInvariant(), out val) ? val : defaultValue;
}
public void RemoveValue(string key){
values.Remove(key.ToLowerInvariant());
}
public CommandLineArgs Clone(){
CommandLineArgs copy = new CommandLineArgs();
foreach(string flag in flags){
copy.AddFlag(flag);
}
foreach(KeyValuePair<string, string> kvp in values){
copy.SetValue(kvp.Key, kvp.Value);
}
return copy;
}
public void ToDictionary(IDictionary<string, string> target){
foreach(string flag in flags){
target[flag] = "1";
}
foreach(KeyValuePair<string, string> kvp in values){
target[kvp.Key] = kvp.Value;
}
}
public override string ToString(){
StringBuilder build = new StringBuilder();
foreach(string flag in flags){
build.Append(flag).Append(' ');
}
foreach(KeyValuePair<string, string> kvp in values){
build.Append(kvp.Key).Append(" \"").Append(kvp.Value).Append("\" ");
}
return build.Remove(build.Length-1, 1).ToString();
}
}
}

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Text.RegularExpressions;
using System.Text.RegularExpressions;
namespace TweetDck.Core.Utils{ namespace TweetDck.Core.Utils{
static class CommandLineArgsParser{ static class CommandLineArgsParser{
@@ -7,18 +6,18 @@ namespace TweetDck.Core.Utils{
private static Regex SplitRegex{ private static Regex SplitRegex{
get{ get{
return splitRegex ?? (splitRegex = new Regex(@"([^=\s]+(?:=(?:""[^""]*?""|[^ ]*))?)", RegexOptions.Compiled)); return splitRegex ?? (splitRegex = new Regex(@"([^=\s]+(?:=(?:[^ ]*""[^""]*?""[^ ]*|[^ ]*))?)", RegexOptions.Compiled));
} }
} }
public static int AddToDictionary(string args, IDictionary<string, string> dictionary){ public static CommandLineArgs ReadCefArguments(string argumentString){
if (string.IsNullOrWhiteSpace(args)){ CommandLineArgs args = new CommandLineArgs();
return 0;
if (string.IsNullOrWhiteSpace(argumentString)){
return args;
} }
int count = 0; foreach(Match match in SplitRegex.Matches(argumentString)){
foreach(Match match in SplitRegex.Matches(args)){
string matchValue = match.Value; string matchValue = match.Value;
int indexEquals = matchValue.IndexOf('='); int indexEquals = matchValue.IndexOf('=');
@@ -34,12 +33,11 @@ namespace TweetDck.Core.Utils{
} }
if (key.Length != 0){ if (key.Length != 0){
dictionary[key] = value; args.SetValue(key, value);
++count;
} }
} }
return count; return args;
} }
} }
} }

View File

@@ -1,148 +0,0 @@
using TweetDck.Core.Controls;
namespace TweetDck.Migration {
partial class FormMigrationQuestion {
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
this.btnIgnore = new System.Windows.Forms.Button();
this.panelButtons = new System.Windows.Forms.FlowLayoutPanel();
this.btnAskLater = new System.Windows.Forms.Button();
this.btnMigrate = new System.Windows.Forms.Button();
this.btnMigrateUninstall = new System.Windows.Forms.Button();
this.labelQuestion = new System.Windows.Forms.Label();
this.panelButtons.SuspendLayout();
this.SuspendLayout();
//
// btnIgnore
//
this.btnIgnore.AutoSize = true;
this.btnIgnore.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.btnIgnore.Location = new System.Drawing.Point(391, 0);
this.btnIgnore.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnIgnore.Name = "btnIgnore";
this.btnIgnore.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnIgnore.Size = new System.Drawing.Size(53, 23);
this.btnIgnore.TabIndex = 1;
this.btnIgnore.Text = "Ignore";
this.btnIgnore.UseVisualStyleBackColor = true;
this.btnIgnore.Click += new System.EventHandler(this.btnIgnore_Click);
//
// panelButtons
//
this.panelButtons.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelButtons.Controls.Add(this.btnAskLater);
this.panelButtons.Controls.Add(this.btnIgnore);
this.panelButtons.Controls.Add(this.btnMigrate);
this.panelButtons.Controls.Add(this.btnMigrateUninstall);
this.panelButtons.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;
this.panelButtons.Location = new System.Drawing.Point(12, 67);
this.panelButtons.Name = "panelButtons";
this.panelButtons.Size = new System.Drawing.Size(518, 23);
this.panelButtons.TabIndex = 0;
//
// btnAskLater
//
this.btnAskLater.AutoSize = true;
this.btnAskLater.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.btnAskLater.Location = new System.Drawing.Point(450, 0);
this.btnAskLater.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.btnAskLater.Name = "btnAskLater";
this.btnAskLater.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnAskLater.Size = new System.Drawing.Size(68, 23);
this.btnAskLater.TabIndex = 0;
this.btnAskLater.Text = "Ask Later";
this.btnAskLater.UseVisualStyleBackColor = true;
this.btnAskLater.Click += new System.EventHandler(this.btnAskLater_Click);
//
// btnMigrate
//
this.btnMigrate.AutoSize = true;
this.btnMigrate.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.btnMigrate.Location = new System.Drawing.Point(327, 0);
this.btnMigrate.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnMigrate.Name = "btnMigrate";
this.btnMigrate.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnMigrate.Size = new System.Drawing.Size(58, 23);
this.btnMigrate.TabIndex = 3;
this.btnMigrate.Text = "Migrate";
this.btnMigrate.UseVisualStyleBackColor = true;
this.btnMigrate.Click += new System.EventHandler(this.btnMigrate_Click);
//
// btnMigrateUninstall
//
this.btnMigrateUninstall.AutoSize = true;
this.btnMigrateUninstall.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.btnMigrateUninstall.Location = new System.Drawing.Point(223, 0);
this.btnMigrateUninstall.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
this.btnMigrateUninstall.Name = "btnMigrateUninstall";
this.btnMigrateUninstall.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnMigrateUninstall.Size = new System.Drawing.Size(98, 23);
this.btnMigrateUninstall.TabIndex = 4;
this.btnMigrateUninstall.Text = "Migrate && Purge";
this.btnMigrateUninstall.UseVisualStyleBackColor = true;
this.btnMigrateUninstall.Click += new System.EventHandler(this.btnMigrateUninstall_Click);
//
// labelQuestion
//
this.labelQuestion.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.labelQuestion.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelQuestion.Location = new System.Drawing.Point(49, 9);
this.labelQuestion.Margin = new System.Windows.Forms.Padding(40, 3, 3, 3);
this.labelQuestion.Name = "labelQuestion";
this.labelQuestion.Size = new System.Drawing.Size(481, 52);
this.labelQuestion.TabIndex = 2;
//
// FormMigrationQuestion
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(542, 102);
this.Controls.Add(this.labelQuestion);
this.Controls.Add(this.panelButtons);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "FormMigrationQuestion";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "TweetDeck Migration";
this.panelButtons.ResumeLayout(false);
this.panelButtons.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button btnIgnore;
private System.Windows.Forms.FlowLayoutPanel panelButtons;
private System.Windows.Forms.Button btnMigrate;
private System.Windows.Forms.Label labelQuestion;
private System.Windows.Forms.Button btnAskLater;
private System.Windows.Forms.Button btnMigrateUninstall;
}
}

View File

@@ -1,42 +0,0 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace TweetDck.Migration{
partial class FormMigrationQuestion : Form{
public MigrationDecision Decision { get; private set; }
public FormMigrationQuestion(){
InitializeComponent();
labelQuestion.Text = "Hey there, I found some TweetDeck data! Do you want to »Migrate« it and delete the old data folder, »Ignore« the request forever, or try "+Program.BrandName+" out first?\r\nYou may also »Migrate && Purge« which uninstalls TweetDeck too!";
}
protected override void OnPaint(PaintEventArgs e){
e.Graphics.DrawIcon(SystemIcons.Question, 10, 10);
base.OnPaint(e);
}
private void btnMigrateUninstall_Click(object sender, EventArgs e){
Close(MigrationDecision.MigratePurge);
}
private void btnMigrate_Click(object sender, EventArgs e){
Close(MigrationDecision.Migrate);
}
private void btnIgnore_Click(object sender, EventArgs e){
Close(MigrationDecision.Ignore);
}
private void btnAskLater_Click(object sender, EventArgs e){
Close(MigrationDecision.AskLater);
}
private void Close(MigrationDecision decision){
Decision = decision;
DialogResult = DialogResult.OK;
Close();
}
}
}

View File

@@ -6,7 +6,8 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using Microsoft.Win32; using Microsoft.Win32;
using TweetDck.Migration.Helpers; using TweetDck.Core.Other;
using System.Drawing;
namespace TweetDck.Migration{ namespace TweetDck.Migration{
static class MigrationManager{ static class MigrationManager{
@@ -32,8 +33,25 @@ namespace TweetDck.Migration{
if (!Program.UserConfig.IgnoreMigration && Directory.Exists(TweetDeckPath)){ if (!Program.UserConfig.IgnoreMigration && Directory.Exists(TweetDeckPath)){
MigrationDecision decision; MigrationDecision decision;
using(FormMigrationQuestion formQuestion = new FormMigrationQuestion()){ const string prompt = "Hey there, I found some TweetDeck data! Do you want to »Migrate« it and delete the old data folder, »Ignore« the prompt, or try "+Program.BrandName+" out first? You may also »Migrate && Purge« which uninstalls TweetDeck too!";
decision = formQuestion.ShowDialog() == DialogResult.OK ? formQuestion.Decision : MigrationDecision.AskLater;
using(FormMessage formQuestion = new FormMessage("TweetDeck Migration", prompt, MessageBoxIcon.Question)){
formQuestion.AddButton("Ask Later");
Button btnIgnore = formQuestion.AddButton("Ignore");
Button btnMigrate = formQuestion.AddButton("Migrate");
Button btnMigrateAndPurge = formQuestion.AddButton("Migrate && Purge");
btnMigrateAndPurge.Location = new Point(btnMigrateAndPurge.Location.X-18, btnMigrateAndPurge.Location.Y);
btnMigrateAndPurge.Width += 18;
if (formQuestion.ShowDialog() == DialogResult.OK){
decision = formQuestion.ClickedButton == btnMigrateAndPurge ? MigrationDecision.MigratePurge :
formQuestion.ClickedButton == btnMigrate ? MigrationDecision.Migrate :
formQuestion.ClickedButton == btnIgnore ? MigrationDecision.Ignore : MigrationDecision.AskLater;
}
else{
decision = MigrationDecision.AskLater;
}
} }
switch(decision){ switch(decision){
@@ -66,10 +84,10 @@ namespace TweetDck.Migration{
} }
} }
else if (!Program.UserConfig.IgnoreUninstallCheck){ else if (!Program.UserConfig.IgnoreUninstallCheck){
string guid = ProgramRegistrySearch.FindByDisplayName("TweetDeck"); string guid = MigrationUtils.FindProgramGuidByDisplayName("TweetDeck");
if (guid != null && MessageBox.Show("TweetDeck is still installed on your computer, do you want to uninstall it?", "Uninstall TweetDeck", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes){ if (guid != null && MessageBox.Show("TweetDeck is still installed on your computer, do you want to uninstall it?", "Uninstall TweetDeck", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
RunUninstaller(guid, 0); MigrationUtils.RunUninstaller(guid, 0);
CleanupTweetDeck(); CleanupTweetDeck();
} }
@@ -135,10 +153,10 @@ namespace TweetDck.Migration{
if (decision == MigrationDecision.MigratePurge){ if (decision == MigrationDecision.MigratePurge){
// uninstall in the background // uninstall in the background
string guid = ProgramRegistrySearch.FindByDisplayName("TweetDeck"); string guid = MigrationUtils.FindProgramGuidByDisplayName("TweetDeck");
if (guid != null){ if (guid != null){
RunUninstaller(guid, 5000); MigrationUtils.RunUninstaller(guid, 5000);
} }
// registry cleanup // registry cleanup
@@ -162,18 +180,6 @@ namespace TweetDck.Migration{
} }
} }
private static void RunUninstaller(string guid, int timeout){
Process uninstaller = Process.Start("msiexec.exe", "/x "+guid+" /quiet /qn");
if (uninstaller != null){
if (timeout > 0){
uninstaller.WaitForExit(timeout); // it appears that the process is restarted or something that triggers this, but it shouldn't be a problem
}
uninstaller.Close();
}
}
private static void CleanupTweetDeck(){ private static void CleanupTweetDeck(){
try{ try{
Registry.CurrentUser.DeleteSubKeyTree(@"Software\Twitter\TweetDeck", true); Registry.CurrentUser.DeleteSubKeyTree(@"Software\Twitter\TweetDeck", true);

View File

@@ -1,10 +1,23 @@
using System; using System;
using System.Diagnostics;
using System.Linq; using System.Linq;
using Microsoft.Win32; using Microsoft.Win32;
namespace TweetDck.Migration.Helpers{ namespace TweetDck.Migration{
static class ProgramRegistrySearch{ static class MigrationUtils{
public static string FindByDisplayName(string displayName){ public static void RunUninstaller(string guid, int timeout){
Process uninstaller = Process.Start("msiexec.exe", "/x "+guid+" /quiet /qn");
if (uninstaller != null){
if (timeout > 0){
uninstaller.WaitForExit(timeout); // it appears that the process is restarted or something that triggers this, but it shouldn't be a problem
}
uninstaller.Close();
}
}
public static string FindProgramGuidByDisplayName(string displayName){
Predicate<RegistryKey> predicate = key => displayName.Equals(key.GetValue("DisplayName") as string, StringComparison.OrdinalIgnoreCase); Predicate<RegistryKey> predicate = key => displayName.Equals(key.GetValue("DisplayName") as string, StringComparison.OrdinalIgnoreCase);
string guid; string guid;

View File

@@ -24,12 +24,6 @@ namespace TweetDck.Plugins{
} }
} }
public string FolderPath{
get{
return path;
}
}
public bool HasConfig{ public bool HasConfig{
get{ get{
return ConfigFile.Length > 0 && GetFullPathIfSafe(ConfigFile).Length > 0; return ConfigFile.Length > 0 && GetFullPathIfSafe(ConfigFile).Length > 0;

View File

@@ -40,7 +40,7 @@ namespace TweetDck.Plugins{
public string ReadFile(int token, string path, bool cache){ public string ReadFile(int token, string path, bool cache){
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.");
} }

View File

@@ -19,16 +19,17 @@ using System.Security.AccessControl;
namespace TweetDck{ namespace TweetDck{
static class Program{ static class Program{
public const string BrandName = "TweetDuck"; public const string BrandName = "TweetDuck";
public const string Website = "http://tweetduck.chylex.com"; public const string Website = "https://tweetduck.chylex.com";
public const string BrowserSubprocess = BrandName+".Browser.exe"; public const string BrowserSubprocess = BrandName+".Browser.exe";
public const string VersionTag = "1.3.3"; public const string VersionTag = "1.4";
public const string VersionFull = "1.3.3.0"; public const string VersionFull = "1.4.0.0";
public static readonly Version Version = new Version(VersionTag); public static readonly Version Version = new Version(VersionTag);
public static readonly bool IsPortable = File.Exists("makeportable"); public static readonly bool IsPortable = File.Exists("makeportable");
private static readonly CommandLineArgs Args = CommandLineArgs.FromStringArray('-', Environment.GetCommandLineArgs());
public static readonly string ProgramPath = AppDomain.CurrentDomain.BaseDirectory; public static readonly string ProgramPath = AppDomain.CurrentDomain.BaseDirectory;
public static readonly string StoragePath = IsPortable ? Path.Combine(ProgramPath, "portable", "storage") : GetDataStoragePath(); public static readonly string StoragePath = IsPortable ? Path.Combine(ProgramPath, "portable", "storage") : GetDataStoragePath();
@@ -70,9 +71,7 @@ namespace TweetDck{
} }
}; };
string[] programArguments = Environment.GetCommandLineArgs(); if (Args.HasFlag("-restart")){
if (programArguments.Contains("-restart")){
for(int attempt = 0; attempt < 41; attempt++){ for(int attempt = 0; attempt < 41; attempt++){
if (LockManager.Lock()){ if (LockManager.Lock()){
break; break;
@@ -109,7 +108,7 @@ namespace TweetDck{
} }
} }
if (programArguments.Contains("-importcookies")){ if (Args.HasFlag("-importcookies")){
ExportManager.ImportCookies(); ExportManager.ImportCookies();
} }
@@ -118,15 +117,15 @@ namespace TweetDck{
CefSettings settings = new CefSettings{ CefSettings settings = new CefSettings{
AcceptLanguageList = BrowserUtils.HeaderAcceptLanguage, AcceptLanguageList = BrowserUtils.HeaderAcceptLanguage,
UserAgent = BrowserUtils.HeaderUserAgent, UserAgent = BrowserUtils.HeaderUserAgent,
Locale = GetCmdArgumentValue("locale") ?? "en", Locale = Args.GetValue("-locale", "en"),
CachePath = StoragePath, CachePath = StoragePath,
BrowserSubprocessPath = File.Exists(BrowserSubprocess) ? BrowserSubprocess : "CefSharp.BrowserSubprocess.exe", BrowserSubprocessPath = File.Exists(BrowserSubprocess) ? BrowserSubprocess : "CefSharp.BrowserSubprocess.exe",
#if !DEBUG #if !DEBUG
LogSeverity = programArguments.Contains("-log") ? LogSeverity.Info : LogSeverity.Disable LogSeverity = Args.HasFlag("-log") ? LogSeverity.Info : LogSeverity.Disable
#endif #endif
}; };
CommandLineArgsParser.AddToDictionary(UserConfig.CustomCefArgs, settings.CefCommandLineArgs); CommandLineArgsParser.ReadCefArguments(UserConfig.CustomCefArgs).ToDictionary(settings.CefCommandLineArgs);
Cef.Initialize(settings, false, new BrowserProcessHandler()); Cef.Initialize(settings, false, new BrowserProcessHandler());
@@ -154,18 +153,18 @@ namespace TweetDck{
} }
} }
private static string GetCmdArgumentValue(string search){
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(){ private static string GetDataStoragePath(){
string custom = GetCmdArgumentValue("-datafolder"); string custom = Args.GetValue("-datafolder", null);
if (custom != null && (custom.Contains(Path.DirectorySeparatorChar) || custom.Contains(Path.AltDirectorySeparatorChar))){ if (custom != null && (custom.Contains(Path.DirectorySeparatorChar) || custom.Contains(Path.AltDirectorySeparatorChar))){
return custom; if (Path.GetInvalidPathChars().Any(custom.Contains)){
Reporter.HandleEarlyFailure("Data Folder Invalid", "The data folder contains invalid characters:\n"+custom);
}
else if (!Path.IsPathRooted(custom)){
Reporter.HandleEarlyFailure("Data Folder Invalid", "The data folder has to be either a simple folder name, or a full path:\n"+custom);
}
return Environment.ExpandEnvironmentVariables(custom);
} }
else{ else{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), custom ?? BrandName); return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), custom ?? BrandName);
@@ -188,6 +187,21 @@ namespace TweetDck{
ReloadConfig(); ReloadConfig();
} }
public static void Restart(){
Restart(new string[0]);
}
public static void Restart(string[] extraArgs){
CommandLineArgs args = Args.Clone();
args.AddFlag("-restart");
args.RemoveFlag("-importcookies");
CommandLineArgs.ReadStringArray('-', extraArgs, args);
Process.Start(Application.ExecutablePath, args.ToString());
Application.Exit();
}
private static void ExitCleanup(){ private static void ExitCleanup(){
if (HasCleanedUp)return; if (HasCleanedUp)return;

View File

@@ -70,5 +70,20 @@ namespace TweetDck{
Environment.FailFast(message, e); Environment.FailFast(message, e);
} }
} }
public static void HandleEarlyFailure(string caption, string message){
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
FormMessage form = new FormMessage(caption, message, MessageBoxIcon.Error);
form.AddButton("Exit");
form.ShowDialog();
try{
Process.GetCurrentProcess().Kill();
}catch{
Environment.FailFast(message, new Exception(message));
}
}
} }
} }

View File

@@ -3,12 +3,16 @@ Clear columns
[description] [description]
- Adds buttons and keyboard shortcuts to quickly clear columns - Adds buttons and keyboard shortcuts to quickly clear columns
- Hold Shift when clicking or using a keyboard shortcut to reset the column instead
[author] [author]
chylex chylex
[version] [version]
1.0 1.1
[website] [website]
https://tweetduck.chylex.com https://tweetduck.chylex.com
[requires]
1.4.1

View File

@@ -11,38 +11,75 @@ enabled(){
TD.controller.stats.columnActionClick("clear"); TD.controller.stats.columnActionClick("clear");
}; };
var clearAllColumns = () => { var resetColumn = (columnName) => {
Object.keys(TD.controller.columnManager.getAll()).forEach(key => clearColumn(key)); var col = TD.controller.columnManager.get(columnName);
col.model.setClearedTimestamp(0);
col.reloadTweets();
};
var forEachColumn = (func) => {
Object.keys(TD.controller.columnManager.getAll()).forEach(func);
}; };
var replaceMustache = (key, search, replace) => { var replaceMustache = (key, search, replace) => {
TD.mustaches[key] = TD.mustaches[key].replace(search, replace); TD.mustaches[key] = TD.mustaches[key].replace(search, replace);
}; };
var wasShiftPressed = false;
var updateShiftState = (pressed) => {
if (pressed != wasShiftPressed){
wasShiftPressed = pressed;
if (pressed){
$(document).on("mousemove", this.eventKeyUp);
}
else{
$(document).off("mousemove", this.eventKeyUp);
}
$("#clear-columns-btn-all").text(pressed ? "Reset all" : "Clear all");
}
};
// prepare event handlers // prepare event handlers
this.eventClearSingle = function(){ this.eventClickSingle = function(e){
clearColumn($(this).closest(".js-column").attr("data-column")); var name = $(this).closest(".js-column").attr("data-column");
e.shiftKey ? resetColumn(name) : clearColumn(name);
}; };
this.eventClearAll = function(){ this.eventClickAll = function(e){
clearAllColumns(); forEachColumn(e.shiftKey ? resetColumn : clearColumn);
}; };
this.eventKeys = function(e){ this.eventKeyDown = function(e){
if (e.keyCode === 46 && (document.activeElement === null || document.activeElement === document.body)){ // 46 = delete if (!(document.activeElement === null || document.activeElement === document.body)){
return;
}
updateShiftState(e.shiftKey);
if (e.keyCode === 46){ // 46 = delete
if (e.altKey){ if (e.altKey){
clearAllColumns(); forEachColumn(e.shiftKey ? resetColumn : clearColumn);
} }
else{ else{
var focusedColumn = $(".js-column.is-focused"); var focusedColumn = $(".js-column.is-focused");
if (focusedColumn.length){ if (focusedColumn.length){
clearColumn(focusedColumn.attr("data-column")); var name = focusedColumn.attr("data-column");
e.shiftKey ? resetColumn(name) : clearColumn(name);
} }
} }
} }
}; };
this.eventKeyUp = function(e){
if (!e.shiftKey){
updateShiftState(false);
}
};
// add column buttons and keyboard shortcut info to UI // add column buttons and keyboard shortcut info to UI
replaceMustache("column/column_header.mustache", "</header>", [ replaceMustache("column/column_header.mustache", "</header>", [
'{{^isTemporary}}', '{{^isTemporary}}',
@@ -62,27 +99,26 @@ enabled(){
].join("")); ].join(""));
// load custom style // load custom style
var style = document.createElement("style"); var css = window.TDPF_createCustomStyle(this);
document.head.appendChild(style); css.insert(".column-title { margin-right: 60px !important; }");
css.insert(".column-type-message .column-title { margin-right: 115px !important; }");
var sheet = style.sheet; css.insert(".mark-all-read-link { right: 59px !important; }");
sheet.insertRule(".column-title { margin-right: 60px !important; }", 0); css.insert(".open-compose-dm-link { right: 90px !important; }");
sheet.insertRule(".column-type-message .column-title { margin-right: 115px !important; }", 0); css.insert("button[data-action='clear'].btn-options-tray { display: none !important; }");
sheet.insertRule(".mark-all-read-link { right: 59px !important; }", 0);
sheet.insertRule(".open-compose-dm-link { right: 90px !important; }", 0);
} }
ready(){ ready(){
// setup events // setup events
$(document).on("click", "[data-action='td-clearcolumns-dosingle']", this.eventClearSingle); $(document).on("click", "[data-action='td-clearcolumns-dosingle']", this.eventClickSingle);
$(document).on("click", "[data-action='td-clearcolumns-doall']", this.eventClearAll); $(document).on("click", "[data-action='td-clearcolumns-doall']", this.eventClickAll);
$(document).on("keydown", this.eventKeys); $(document).on("keydown", this.eventKeyDown);
$(document).on("keyup", this.eventKeyUp);
// add clear all button // add clear all button
$("nav.app-navigator").first().append([ $("nav.app-navigator").first().append([
'<a class="link-clean cf app-nav-link padding-hl" data-title="Clear all" data-action="td-clearcolumns-doall">', '<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="obj-left"><i class="icon icon-large icon-clear-timeline"></i></div>',
'<div class="nbfc padding-ts hide-condensed">Clear all</div>', '<div id="clear-columns-btn-all" class="nbfc padding-ts hide-condensed">Clear all</div>',
'</a></nav>' '</a></nav>'
].join("")); ].join(""));
} }

View File

@@ -9,7 +9,10 @@ Revert TweetDeck design changes
chylex chylex
[version] [version]
1.0 1.1
[website] [website]
https://tweetduck.chylex.com https://tweetduck.chylex.com
[requires]
1.4.1

View File

@@ -1,15 +1,11 @@
enabled(){ enabled(){
// add a stylesheet to change tweet actions // add a stylesheet to change tweet actions
var style = document.createElement("style"); this.css = window.TDPF_createCustomStyle(this);
style.id = "design-revert"; this.css.insert(".tweet-actions { float: right !important; width: auto !important; }");
document.head.appendChild(style); this.css.insert(".tweet-action { opacity: 0; }");
this.css.insert(".is-favorite .tweet-action, .is-retweet .tweet-action { opacity: 0.5; visibility: visible !important; }");
var sheet = style.sheet; this.css.insert(".tweet:hover .tweet-action, .is-favorite .tweet-action[rel='favorite'], .is-retweet .tweet-action[rel='retweet'] { opacity: 1; visibility: visible !important; }");
sheet.insertRule(".tweet-actions { float: right !important; width: auto !important; }", 0); this.css.insert(".tweet-actions > li:nth-child(4) { margin-right: 2px !important; }");
sheet.insertRule(".tweet-action { opacity: 0; }", 0);
sheet.insertRule(".is-favorite .tweet-action, .is-retweet .tweet-action { opacity: 0.5; visibility: visible !important; }", 0);
sheet.insertRule(".tweet:hover .tweet-action, .is-favorite .tweet-action[rel='favorite'], .is-retweet .tweet-action[rel='retweet'] { opacity: 1; visibility: visible !important; }", 0);
sheet.insertRule(".tweet-actions > li:nth-child(4) { margin-right: 2px !important; }", 0);
// revert small links around the tweet // revert small links around the tweet
this.prevFooterMustache = TD.mustaches["status/tweet_single_footer.mustache"]; this.prevFooterMustache = TD.mustaches["status/tweet_single_footer.mustache"];
@@ -31,7 +27,8 @@ ready(){
} }
disabled(){ disabled(){
$("#design-revert").remove(); this.css.remove();
$(document).off("uiShowActionsMenu", this.uiShowActionsMenuEvent); $(document).off("uiShowActionsMenu", this.uiShowActionsMenuEvent);
TD.mustaches["status/tweet_single_footer.mustache"] = this.prevFooterMustache; TD.mustaches["status/tweet_single_footer.mustache"] = this.prevFooterMustache;
} }

View File

@@ -8,7 +8,7 @@ Custom reply account
chylex chylex
[version] [version]
1.0 1.1
[website] [website]
https://tweetduck.chylex.com https://tweetduck.chylex.com

View File

@@ -1,67 +1,120 @@
enabled(){ enabled(){
var configuration = { defaultAccount: "" }; var configuration = { defaultAccount: "#preferred" };
window.TDPF_loadConfigurationFile(this, "configuration.js", "configuration.default.js", obj => configuration = obj); window.TDPF_loadConfigurationFile(this, "configuration.js", "configuration.default.js", obj => configuration = obj);
this.uiInlineComposeTweetEvent = function(e, data){ this.lastSelectedAccount = null;
var account = null;
this.uiComposeTweetEvent = (e, data) => {
if (configuration.useAdvancedSelector && configuration.customSelector){ if (data.type !== "reply"){
var column = TD.controller.columnManager.get(data.element.closest("section.column").attr("data-column")); return;
var result = configuration.customSelector(column);
if (typeof result === "string" && result[0] === '@'){
account = result.substring(1);
}
} }
if (account === null){ var query;
if (configuration.defaultAccount === false){
return;
}
else if (configuration.defaultAccount !== "" && configuration.defaultAccount[0] === '@'){
account = configuration.defaultAccount.substring(1);
}
}
var identifier; if (configuration.useAdvancedSelector){
if (configuration.customSelector){
if (account === null){ var column = TD.controller.columnManager.get(data.element.closest("section.column").attr("data-column"));
identifier = TD.storage.clientController.client.getDefaultAccount(); query = configuration.customSelector(column);
}
else{
var obj = TD.storage.accountController.getAccountFromUsername(account);
if (obj.length === 0){
return;
} }
else{ else{
identifier = obj[0].privateState.key; $TD.alert("warning", "Plugin reply-account has invalid configuration: useAdvancedSelector is true, but customSelector function is missing");
return;
} }
} }
else{
query = configuration.defaultAccount;
if (query === ""){
query = "#preferred";
}
else if (typeof query !== "string"){
query = "#default";
}
}
if (typeof query === "undefined"){
query = "#preferred";
}
if (typeof query !== "string"){
return;
}
else if (query.length === 0){
$TD.alert("warning", "Plugin reply-account has invalid configuration: the requested account is empty");
return;
}
else if (query[0] !== '@' && query[0] !== '#'){
$TD.alert("warning", "Plugin reply-account has invalid configuration: the requested account does not begin with @ or #: "+query);
return;
}
var identifier = null;
switch(query){
case "#preferred":
identifier = TD.storage.clientController.client.getDefaultAccount();
break;
case "#last":
if (this.lastSelectedAccount === null){
return;
}
identifier = this.lastSelectedAccount;
break;
case "#default":
return;
default:
if (query[0] === '@'){
var obj = TD.storage.accountController.getAccountFromUsername(query.substring(1));
if (obj.length === 0){
$TD.alert("warning", "Plugin reply-account has invalid configuration: requested account not found: "+query);
return;
}
else{
identifier = obj[0].privateState.key;
}
}
else{
$TD.alert("warning", "Plugin reply-account has invalid configuration: unknown requested account query: "+query);
return;
}
}
data.singleFrom = data.from = [ identifier ]; data.singleFrom = data.from = [ identifier ];
}; };
this.onSelectedAccountChanged = () => {
var selected = $(".js-account-item.is-selected", ".js-account-list");
this.lastSelectedAccount = selected.length === 1 ? selected.attr("data-account-key") : null;
};
} }
ready(){ ready(){
var events = $._data(document, "events"); var events = $._data(document, "events");
if ("uiInlineComposeTweet" in events){ for(var event of [ "uiInlineComposeTweet", "uiDockedComposeTweet" ]){
$(document).on("uiInlineComposeTweet", this.uiInlineComposeTweetEvent); $(document).on(event, this.uiComposeTweetEvent);
var handlers = events["uiInlineComposeTweet"]; var handlers = events[event];
var oldHandler = handlers[0]; var newHandler = handlers[handlers.length-1];
var newHandler = handlers[1];
for(var index = handlers.length-1; index > 0; index--){
handlers[index] = handlers[index-1];
}
handlers[0] = newHandler; handlers[0] = newHandler;
handlers[1] = oldHandler;
}
else{
$(document).on("uiInlineComposeTweet", this.uiInlineComposeTweetEvent);
} }
$(document).on("click", ".js-account-list .js-account-item", this.onSelectedAccountChanged);
} }
disabled(){ disabled(){
$(document).off("uiInlineComposeTweet", this.uiInlineComposeTweetEvent); $(document).off("uiInlineComposeTweet", this.uiComposeTweetEvent);
$(document).off("uiDockedComposeTweet", this.uiComposeTweetEvent);
$(document).off("click", ".js-account-list .js-account-item", this.onSelectedAccountChanged);
} }

View File

@@ -13,13 +13,14 @@
* *
* Set value of 'defaultAccount' to one of the following values: * Set value of 'defaultAccount' to one of the following values:
* *
* "" to use your preferred TweetDeck account for all replies (default) * "#preferred" to use your preferred TweetDeck account (the one used to log into TweetDeck)
* "#last" to specify the account that was selected last time (only updates if a single account is selected)
* "#default" to fall back to default TweetDeck behavior; useful for advanced configuration below, otherwise disable the plugin instead
* "@myAccount" to specify an account name to use; has to be one of your registered account names * "@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: "", defaultAccount: "#preferred",
/* /*
* Advanced way of configuring the plugin * Advanced way of configuring the plugin
@@ -30,8 +31,8 @@
* 1. Set value of 'useAdvancedSelector' to true * 1. Set value of 'useAdvancedSelector' to true
* 2. Uncomment the 'customSelector' function, and replace the example code with your desired behavior * 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. * The 'customSelector' function should return a string in one of the formats supported by 'defaultAccount'.
* If it returns anything else (for example false, undefined, or an account name that is not registered), it falls back to 'defaultAccount' behavior. * If it returns anything else (for example, false or undefined), 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, * 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: * 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:

View File

@@ -0,0 +1,18 @@
[name]
Polls in timelines
[description]
- Adds poll result display directly into timelines
- Experimental, may be buggy or break when TweetDeck updates
[author]
chylex
[version]
1.0
[website]
https://tweetduck.chylex.com
[requires]
1.4.1

View File

@@ -0,0 +1,30 @@
constructor(){
super({
requiresPageReload: true
});
}
enabled(){
// add a stylesheet
this.css = window.TDPF_createCustomStyle(this);
this.css.insert(".column-detail .timeline-poll-container { display: none }");
// setup layout injecting
this.prevMustaches = {};
var injectLayout = (mustache, onlyIfNotFound, search, replace) => {
if (TD.mustaches[mustache].indexOf(onlyIfNotFound) === -1){
this.prevMustaches[mustache] = TD.mustaches[mustache];
TD.mustaches[mustache] = TD.mustaches[mustache].replace(search, replace);
}
};
// add poll rendering to tweets
injectLayout("status/tweet_single.mustache", "status/poll", "{{/quotedTweetMissing}} {{#translation}}", "{{/quotedTweetMissing}} <div class='timeline-poll-container'>{{>duck/tweet_single/poll}}</div> {{#translation}}");
TD.mustaches["duck/tweet_single/poll.mustache"] = '<div class="js-poll margin-tl"> {{#poll}} <ul class="margin-b--12"> {{#choices}} <li class="position-rel margin-b--8 height-3"> <div class="poll-bar pin-top height-p--100 br-1 {{#isWinner}}poll-bar--winner{{/isWinner}} {{#hasTimeLeft}}br-left{{/hasTimeLeft}} width-p--{{percentage}}"/> <div class="poll-label position-rel padding-a--4"> <span class="txt-bold txt-right inline-block width-5 padding-r--4">{{percentage}}%</span> {{{label}}} {{#isSelectedChoice}} <i class="icon icon-check txt-size-variable--11"></i> {{/isSelectedChoice}} </div> </li> {{/choices}} </ul> <span class="inline-block txt-small padding-ls txt-seamful-deep-gray"> {{{prettyCount}}} &middot; {{#hasTimeLeft}} {{{prettyTimeLeft}}} {{/hasTimeLeft}} {{^hasTimeLeft}} {{_i}}Final results{{/i}} {{/hasTimeLeft}} </span> {{/poll}} </div>';
}
disabled(){
this.css.remove();
Object.keys(this.prevMustaches).forEach(mustache => TD.mustaches[mustache] = this.prevMustaches[mustache]);
}

View File

@@ -378,13 +378,19 @@
// //
window.TDGF_onMouseClickExtra = function(button){ window.TDGF_onMouseClickExtra = function(button){
if (button === 1){ // back button if (button === 1){ // back button
var modal = $("#open-modal"); var inlineComposer, drawerComposer, modal;
if (highlightedColumnEle && highlightedColumnEle.closest(".js-column").is(".is-shifted-1")){ if ((modal = $("#open-modal")).is(":visible")){
modal.find("a[rel=dismiss]").click();
}
else if ((inlineComposer = $(".js-inline-compose-close")).length === 1){
inlineComposer.click();
}
else if (highlightedColumnEle && highlightedColumnEle.closest(".js-column").is(".is-shifted-1")){
highlightedColumnEle.find(".js-column-back").first().click(); highlightedColumnEle.find(".js-column-back").first().click();
} }
else if (modal.is(":visible")){ else if ((drawerComposer = $(".js-app-content.is-open .js-drawer-close:visible")).length === 1){
modal.find("a[rel=dismiss]").click(); drawerComposer.click();
} }
else{ else{
$(".js-column-back").click(); $(".js-column-back").click();

View File

@@ -117,6 +117,36 @@
$TD.setNotificationTweetEmbedded(account[0].getAttribute("href")+"/status/"+tweetId); $TD.setNotificationTweetEmbedded(account[0].getAttribute("href")+"/status/"+tweetId);
})(); })();
//
// Block: Setup a skip button.
//
(function(){
if (document.body.hasAttribute("td-example-notification")){
return;
}
document.body.insertAdjacentHTML("afterbegin", [
'<svg id="td-skip" xmlns="http://www.w3.org/2000/svg" width="10" height="17" viewBox="0 0 350 600" style="position:fixed;left:30px;bottom:10px;z-index:1000">',
'<path fill="#888" d="M0,151.656l102.208-102.22l247.777,247.775L102.208,544.986L0,442.758l145.546-145.547">',
'</svg>'
].join(""));
document.getElementById("td-skip").addEventListener("click", function(){
$TD.loadNextNotification();
});
})();
//
// Block: Setup a hover class on body.
//
document.body.addEventListener("mouseenter", function(){
document.body.classList.add("td-hover");
});
document.body.addEventListener("mouseleave", function(){
document.body.classList.remove("td-hover");
});
// //
// Block: Page fully loaded. // Block: Page fully loaded.
// //

View File

@@ -15,7 +15,7 @@
try{ try{
obj = eval("("+contents+")"); obj = eval("("+contents+")");
}catch(err){ }catch(err){
if (!(onFailure && onFailure(err.message))){ if (!(onFailure && onFailure(err))){
$TD.alert("warning", "Problem loading '"+fileName+"' file for '"+identifier+"' plugin, the JavaScript syntax is invalid: "+err.message); $TD.alert("warning", "Problem loading '"+fileName+"' file for '"+identifier+"' plugin, the JavaScript syntax is invalid: "+err.message);
} }
@@ -34,4 +34,21 @@
} }
}); });
}; };
//
// Block: Setup a function to add/remove custom CSS.
//
window.TDPF_createCustomStyle = function(pluginObject){
var element = document.createElement("style");
element.id = "plugin-"+pluginObject.$id+"-"+Math.random().toString(36).substring(2, 7);
document.head.appendChild(element);
var obj = {
insert: (rule) => element.sheet.insertRule(rule, 0),
remove: () => $(element).remove()
};
obj.element = element;
return obj;
};
})($TDP); })($TDP);

View File

@@ -176,6 +176,7 @@
<Compile Include="Core\Other\Settings\TabSettingsUpdates.Designer.cs"> <Compile Include="Core\Other\Settings\TabSettingsUpdates.Designer.cs">
<DependentUpon>TabSettingsUpdates.cs</DependentUpon> <DependentUpon>TabSettingsUpdates.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Core\Utils\CommandLineArgs.cs" />
<Compile Include="Core\Utils\CommandLineArgsParser.cs" /> <Compile Include="Core\Utils\CommandLineArgsParser.cs" />
<Compile Include="Core\Utils\WindowState.cs" /> <Compile Include="Core\Utils\WindowState.cs" />
<Compile Include="Core\Utils\WindowsUtils.cs" /> <Compile Include="Core\Utils\WindowsUtils.cs" />
@@ -192,6 +193,7 @@
<Compile Include="Core\Other\FormSettings.Designer.cs"> <Compile Include="Core\Other\FormSettings.Designer.cs">
<DependentUpon>FormSettings.cs</DependentUpon> <DependentUpon>FormSettings.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Migration\MigrationUtils.cs" />
<Compile Include="Plugins\Controls\PluginControl.cs"> <Compile Include="Plugins\Controls\PluginControl.cs">
<SubType>UserControl</SubType> <SubType>UserControl</SubType>
</Compile> </Compile>
@@ -234,15 +236,8 @@
<Compile Include="Updates\UpdateCheckEventArgs.cs" /> <Compile Include="Updates\UpdateCheckEventArgs.cs" />
<Compile Include="Updates\UpdateHandler.cs" /> <Compile Include="Updates\UpdateHandler.cs" />
<Compile Include="Updates\UpdateInfo.cs" /> <Compile Include="Updates\UpdateInfo.cs" />
<Compile Include="Migration\FormMigrationQuestion.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Migration\FormMigrationQuestion.Designer.cs">
<DependentUpon>FormMigrationQuestion.cs</DependentUpon>
</Compile>
<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="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs"> <Compile Include="Properties\Resources.Designer.cs">

View File

@@ -1,5 +1,6 @@
del "bin\x86\Release\*.xml" del "bin\x86\Release\*.xml"
del "bin\x86\Release\devtools_resources.pak" del "bin\x86\Release\devtools_resources.pak"
del "bin\x86\Release\d3dcompiler_43.dll"
del "bin\x86\Release\TweetDuck.Browser.exe" del "bin\x86\Release\TweetDuck.Browser.exe"
ren "bin\x86\Release\CefSharp.BrowserSubprocess.exe" "TweetDuck.Browser.exe" ren "bin\x86\Release\CefSharp.BrowserSubprocess.exe" "TweetDuck.Browser.exe"