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

Compare commits

...

56 Commits
1.3.3 ... 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
aa2c60f7e9 Move cookie import code to ExportManager 2016-09-20 17:15:34 +02:00
f7dc200684 Kill process instead of Environment.FailFast if possible 2016-09-20 17:11:36 +02:00
ad306c56c7 Move log file to storage path 2016-09-20 16:58:00 +02:00
86aba1eb52 Update all exception handlers 2016-09-20 16:55:51 +02:00
826f1aba7a Tweak exception handling in Reporter (use Environment.FailFast and change log button title) 2016-09-20 16:51:29 +02:00
8abf4364c6 Replace calls to Program.Log 2016-09-20 16:39:31 +02:00
4c45d91d4e Move logging to Reporter and make a static instance of it in Program 2016-09-20 16:38:15 +02:00
3176b6cb8f Create a Reporter class with improved HandleException code 2016-09-20 16:34:56 +02:00
27971e09cd Add new Control related functionality to FormMessage 2016-09-20 16:31:53 +02:00
bf95ae00de Tweak the message for missing write permission 2016-09-20 16:10:46 +02:00
0dbfa7e101 Improve reliability of directory write perm checking 2016-09-20 16:00:41 +02:00
85d09c4b5e Add a FormMessage class for custom message boxes 2016-09-20 07:47:16 +02:00
4f9bc40476 Update cache clearing for CEF 53 and clear old cache files on first startup 2016-09-19 14:03:37 +02:00
757ccbf9d3 Switch locale to English and add spell check setting
Closes #62
2016-09-19 13:33:44 +02:00
4cf9730130 Make sure the config is not loaded before old process exits when restarting 2016-09-19 13:24:23 +02:00
1dd0d70ab9 Reorganize Program.LogFile from property to readonly field 2016-09-19 13:08:27 +02:00
340eaece0f Update CefSharp to 53 and update the readme 2016-09-19 00:12:48 +02:00
c151e7cd37 Remove everything TweetDick related 2016-09-18 23:24:11 +02:00
ca0baae832 Release 1.3.3 2016-09-18 22:23:48 +02:00
478e6ed8df Move config loading and migration execution to an earlier point 2016-09-18 22:19:02 +02:00
51 changed files with 1104 additions and 550 deletions

View File

@@ -90,7 +90,7 @@ namespace TweetDck.Configuration{
try{
File.Delete(file);
}catch(Exception e){
Program.Log(e.ToString());
Program.Reporter.Log(e.ToString());
result = false;
}

View File

@@ -35,6 +35,7 @@ namespace TweetDck.Configuration{
public int NotificationDurationValue { get; set; }
public bool NotificationLegacyLoad { get; set; }
public bool EnableSpellCheck { get; set; }
public bool ExpandLinksOnHover { get; set; }
public bool EnableTrayHighlight { get; set; }
@@ -188,13 +189,14 @@ namespace TweetDck.Configuration{
return true;
}catch(Exception e){
Program.HandleException("Could not save the configuration file.", e);
Program.Reporter.HandleException("Configuration Error", "Could not save the configuration file.", true, e);
return false;
}
}
public static UserConfig Load(string file){
UserConfig config = null;
Exception firstException = null;
for(int attempt = 0; attempt < 2; attempt++){
try{
@@ -210,11 +212,23 @@ namespace TweetDck.Configuration{
break;
}catch(FileNotFoundException){
}catch(DirectoryNotFoundException){
break;
}catch(Exception e){
Program.HandleException("Could not open the configuration file.", e);
if (attempt == 0){
firstException = e;
Program.Reporter.Log(e.ToString());
}
else if (firstException != null){
Program.Reporter.HandleException("Configuration Error", "Could not open the backup configuration file. If you continue, you may lose your settings and list of enabled plugins.", true, e);
}
}
}
if (firstException != null && config == null){
Program.Reporter.HandleException("Configuration Error", "Could not open the configuration file.", true, firstException);
}
return config ?? new UserConfig(file);
}
@@ -224,12 +238,7 @@ namespace TweetDck.Configuration{
private class SerializationCompatibilityHandler : SerializationBinder{
public override Type BindToType(string assemblyName, string typeName){
#if DUCK
assemblyName = assemblyName.Replace("TweetDick", "TweetDuck");
#else
assemblyName = assemblyName.Replace("TweetDuck", "TweetDick");
#endif
typeName = typeName.Replace("TweetDick", "TweetDck");
return Type.GetType(string.Format(CultureInfo.CurrentCulture, "{0}, {1}", typeName, assemblyName));
}

View File

@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/></startup></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<package id="cef.redist.x64" version="3.2623.1396" targetFramework="net40-Client" />
<package id="cef.redist.x86" version="3.2623.1396" targetFramework="net40-Client" />
<package id="CefSharp.Common" version="49.0.0-pre02" targetFramework="net40-Client" />
<package id="CefSharp.WinForms" version="49.0.0-pre02" targetFramework="net40-Client" />
<package id="Microsoft.VC120.CRT.JetBrains" version="12.0.21005.2" targetFramework="net40-Client" />
<package id="cef.redist.x64" version="3.2785.1478" targetFramework="net452" />
<package id="cef.redist.x86" version="3.2785.1478" targetFramework="net452" />
<package id="CefSharp.Common" version="53.0.0-pre01" targetFramework="net452" />
<package id="CefSharp.WinForms" version="53.0.0-pre01" targetFramework="net452" />
<package id="Microsoft.VC120.CRT.JetBrains" version="12.0.21005.2" targetFramework="net452" />
</packages>

View File

@@ -34,5 +34,15 @@ namespace TweetDck.Core.Controls{
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

@@ -101,6 +101,12 @@ namespace TweetDck.Core{
private void Browser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e){
if (!e.IsLoading){
browser.AddWordToDictionary("tweetdeck");
browser.AddWordToDictionary("TweetDeck");
browser.AddWordToDictionary("tweetduck");
browser.AddWordToDictionary("TweetDuck");
browser.AddWordToDictionary("TD");
Invoke(new Action(SetupWindow));
browser.LoadingStateChanged -= Browser_LoadingStateChanged;
}

View File

@@ -0,0 +1,16 @@
using CefSharp;
using System;
namespace TweetDck.Core.Handling{
class BrowserProcessHandler : IBrowserProcessHandler{
void IBrowserProcessHandler.OnContextInitialized(){
using(IRequestContext ctx = Cef.GetGlobalRequestContext()){
string err;
ctx.SetPreference("browser.enable_spellchecking", Program.UserConfig.EnableSpellCheck, out err);
}
}
void IBrowserProcessHandler.OnScheduleMessagePumpWork(long delay){}
void IDisposable.Dispose(){}
}
}

View File

@@ -119,6 +119,10 @@ namespace TweetDck.Core.Handling{
}
}
public void LoadNextNotification(){
notification.InvokeSafe(notification.FinishCurrentTweet);
}
public void TryPasteImage(){
form.InvokeSafe(() => {
if (Clipboard.ContainsImage()){
@@ -133,7 +137,7 @@ namespace TweetDck.Core.Handling{
form.OnImagePasted();
}catch(Exception e){
Program.HandleException("Could not paste image from clipboard.", e);
Program.Reporter.HandleException("Clipboard Image Error", "Could not paste image from clipboard.", true, e);
}
}
});

View File

@@ -20,7 +20,7 @@ namespace TweetDck.Core.Handling{
private static string CustomCSS{
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>");
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 url;
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.url = url;
this.characters = characters;
this.isExample = isExample;
}
public int GetDisplayDuration(int value){
@@ -106,7 +110,7 @@ namespace TweetDck.Core.Handling{
}
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("</div></div></body>");
build.Append("</html>");

View File

@@ -28,7 +28,7 @@ namespace TweetDck.Core.Other {
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormAbout));
this.pictureLogo = new System.Windows.Forms.PictureBox();
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.tablePanelLinks = new System.Windows.Forms.TableLayoutPanel();
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.TabIndex = 1;
//
// labelSourceCode
// labelTips
//
this.labelSourceCode.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.labelSourceCode.LinkArea = new System.Windows.Forms.LinkArea(0, 0);
this.labelSourceCode.Location = new System.Drawing.Point(117, 0);
this.labelSourceCode.Margin = new System.Windows.Forms.Padding(0);
this.labelSourceCode.Name = "labelSourceCode";
this.labelSourceCode.Size = new System.Drawing.Size(99, 16);
this.labelSourceCode.TabIndex = 3;
this.labelSourceCode.Text = "Source Code";
this.labelSourceCode.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.labelSourceCode.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
this.labelTips.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelTips.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelTips.LinkArea = new System.Windows.Forms.LinkArea(0, 0);
this.labelTips.Location = new System.Drawing.Point(117, 0);
this.labelTips.Margin = new System.Windows.Forms.Padding(0);
this.labelTips.Name = "labelTips";
this.labelTips.Size = new System.Drawing.Size(99, 16);
this.labelTips.TabIndex = 3;
this.labelTips.Text = "Tips && Tricks";
this.labelTips.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.labelTips.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
//
// 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.Controls.Add(this.labelIssues, 2, 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.Name = "tablePanelLinks";
this.tablePanelLinks.RowCount = 1;
@@ -146,7 +146,7 @@ namespace TweetDck.Core.Other {
private System.Windows.Forms.PictureBox pictureLogo;
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.TableLayoutPanel tablePanelLinks;
private System.Windows.Forms.LinkLabel labelIssues;

View File

@@ -3,7 +3,7 @@ using TweetDck.Core.Utils;
namespace TweetDck.Core.Other{
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";
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.";
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));
}

79
Core/Other/FormMessage.Designer.cs generated Normal file
View File

@@ -0,0 +1,79 @@
namespace TweetDck.Core.Other {
partial class FormMessage {
/// <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.panelActions = new System.Windows.Forms.Panel();
this.labelMessage = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// panelActions
//
this.panelActions.BackColor = System.Drawing.SystemColors.Control;
this.panelActions.Dock = System.Windows.Forms.DockStyle.Bottom;
this.panelActions.Location = new System.Drawing.Point(0, 84);
this.panelActions.Name = "panelActions";
this.panelActions.Size = new System.Drawing.Size(233, 49);
this.panelActions.TabIndex = 0;
//
// labelMessage
//
this.labelMessage.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.labelMessage.AutoSize = true;
this.labelMessage.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelMessage.Location = new System.Drawing.Point(62, 33);
this.labelMessage.Margin = new System.Windows.Forms.Padding(53, 24, 27, 24);
this.labelMessage.MaximumSize = new System.Drawing.Size(600, 0);
this.labelMessage.MinimumSize = new System.Drawing.Size(0, 24);
this.labelMessage.Name = "labelMessage";
this.labelMessage.Size = new System.Drawing.Size(0, 24);
this.labelMessage.TabIndex = 1;
this.labelMessage.SizeChanged += new System.EventHandler(this.labelMessage_SizeChanged);
//
// FormMessage
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.White;
this.ClientSize = new System.Drawing.Size(98, 133);
this.Controls.Add(this.labelMessage);
this.Controls.Add(this.panelActions);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "FormMessage";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panelActions;
private System.Windows.Forms.Label labelMessage;
}
}

118
Core/Other/FormMessage.cs Normal file
View File

@@ -0,0 +1,118 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace TweetDck.Core.Other{
sealed partial class FormMessage : Form{
public Button ClickedButton { get; private set; }
private readonly Icon icon;
private readonly bool isReady;
private int realFormWidth, minFormWidth;
private int buttonCount;
private int prevLabelWidth, prevLabelHeight;
private bool wasLabelMultiline;
public FormMessage(string caption, string text, MessageBoxIcon messageIcon){
InitializeComponent();
this.prevLabelWidth = labelMessage.Width;
this.prevLabelHeight = labelMessage.Height;
this.minFormWidth = 18;
switch(messageIcon){
case MessageBoxIcon.Information:
icon = SystemIcons.Information;
break;
case MessageBoxIcon.Warning:
icon = SystemIcons.Warning;
break;
case MessageBoxIcon.Error:
icon = SystemIcons.Error;
break;
case MessageBoxIcon.Question:
icon = SystemIcons.Question;
break;
default:
icon = null;
labelMessage.Location = new Point(labelMessage.Location.X-32, labelMessage.Location.Y);
break;
}
this.isReady = true;
this.Text = caption;
this.labelMessage.Text = text;
}
public Button AddButton(string title){
Button button = new Button{
Anchor = AnchorStyles.Bottom | AnchorStyles.Right,
Location = new Point(Width-112-buttonCount*96, 12),
Size = new Size(88, 26),
TabIndex = buttonCount,
Text = title,
UseVisualStyleBackColor = true
};
button.Click += (sender, args) => {
ClickedButton = (Button)sender;
DialogResult = DialogResult.OK;
Close();
};
panelActions.Controls.Add(button);
minFormWidth += 96;
Width = Math.Max(realFormWidth, minFormWidth);
++buttonCount;
return button;
}
public void AddActionControl(Control control){
panelActions.Controls.Add(control);
minFormWidth += control.Width+control.Margin.Horizontal;
Width = Math.Max(realFormWidth, minFormWidth);
}
private void labelMessage_SizeChanged(object sender, EventArgs e){
if (!isReady){
return;
}
bool isMultiline = labelMessage.Height > labelMessage.MinimumSize.Height;
if (isMultiline && !wasLabelMultiline){
labelMessage.Location = new Point(labelMessage.Location.X, labelMessage.Location.Y-8);
prevLabelHeight += 8;
}
else if (!isMultiline && wasLabelMultiline){
labelMessage.Location = new Point(labelMessage.Location.X, labelMessage.Location.Y+8);
prevLabelHeight -= 8;
}
realFormWidth = Width-(icon == null ? 32+35+(labelMessage.Margin.Left-labelMessage.Margin.Right) : 0)+labelMessage.Margin.Right+labelMessage.Width-prevLabelWidth;
Width = Math.Max(realFormWidth, minFormWidth);
Height += labelMessage.Height-prevLabelHeight;
prevLabelWidth = labelMessage.Width;
prevLabelHeight = labelMessage.Height;
wasLabelMultiline = isMultiline;
}
protected override void OnPaint(PaintEventArgs e){
if (icon != null){
e.Graphics.DrawIcon(icon, 25, 26);
}
base.OnPaint(e);
}
}
}

View File

@@ -14,5 +14,11 @@ namespace TweetDck.Core.Other.Settings{
public BaseTabSettings(){
Padding = new Padding(6);
}
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){
Program.Restart();
}
}
}
}

View File

@@ -48,14 +48,14 @@
this.textBoxBrowserCSS.Multiline = true;
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(373, 253);
this.textBoxBrowserCSS.TabIndex = 0;
this.textBoxBrowserCSS.WordWrap = false;
//
// btnCancel
//
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.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnCancel.Size = new System.Drawing.Size(56, 23);
@@ -67,7 +67,7 @@
// btnApply
//
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.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
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.textBoxNotificationCSS);
this.splitContainer.Panel2MinSize = 64;
this.splitContainer.Size = new System.Drawing.Size(460, 209);
this.splitContainer.SplitterDistance = 226;
this.splitContainer.Size = new System.Drawing.Size(760, 269);
this.splitContainer.SplitterDistance = 373;
this.splitContainer.SplitterWidth = 5;
this.splitContainer.TabIndex = 5;
//
@@ -131,7 +131,7 @@
this.textBoxNotificationCSS.Multiline = true;
this.textBoxNotificationCSS.Name = "textBoxNotificationCSS";
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.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.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.Size = new System.Drawing.Size(341, 13);
this.labelWarning.TabIndex = 6;
@@ -149,7 +149,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
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.splitContainer);
this.Controls.Add(this.btnApply);

View File

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

View File

@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using TweetDck.Core.Controls;
using TweetDck.Core.Utils;
namespace TweetDck.Core.Other.Settings.Dialogs{
@@ -15,7 +15,8 @@ namespace TweetDck.Core.Other.Settings.Dialogs{
InitializeComponent();
Text = Program.BrandName+" Settings - CEF Arguments";
textBoxArgs.EnableMultilineShortcuts();
textBoxArgs.Text = Program.UserConfig.CustomCefArgs ?? "";
textBoxArgs.Select(textBoxArgs.Text.Length, 0);
}
@@ -33,7 +34,7 @@ namespace TweetDck.Core.Other.Settings.Dialogs{
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?";
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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Forms;
@@ -8,8 +7,8 @@ using TweetDck.Plugins;
namespace TweetDck.Core.Other.Settings.Export{
sealed class ExportManager{
public static readonly string CookiesPath = Path.Combine(Program.StoragePath, "Cookies");
public static readonly string TempCookiesPath = Path.Combine(Program.StoragePath, "CookiesTmp");
private static readonly string CookiesPath = Path.Combine(Program.StoragePath, "Cookies");
private static readonly string TempCookiesPath = Path.Combine(Program.StoragePath, "CookiesTmp");
public bool IsRestarting { get; private set; }
public Exception LastException { get; private set; }
@@ -105,8 +104,7 @@ namespace TweetDck.Core.Other.Settings.Export{
// okay to and restart, 'cookies' is always the last entry
IsRestarting = true;
Process.Start(Application.ExecutablePath, "-restart -importcookies");
Application.Exit();
Program.Restart(new string[]{ "-importcookies" });
}
break;
@@ -125,6 +123,20 @@ namespace TweetDck.Core.Other.Settings.Export{
}
}
public static void ImportCookies(){
if (File.Exists(TempCookiesPath)){
try{
if (File.Exists(CookiesPath)){
File.Delete(CookiesPath);
}
File.Move(TempCookiesPath, CookiesPath);
}catch(Exception e){
Program.Reporter.HandleException("Profile Import Error", "Could not import the cookie file to restore login session.", true, e);
}
}
}
private static IEnumerable<PathInfo> EnumerateFilesRelative(string root){
return Directory.EnumerateFiles(root, "*.*", SearchOption.AllDirectories).Select(fullPath => new PathInfo{
Full = fullPath,

View File

@@ -34,8 +34,12 @@
this.btnExport = new System.Windows.Forms.Button();
this.groupPerformance = 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.groupConfiguration.SuspendLayout();
this.groupApp.SuspendLayout();
this.SuspendLayout();
//
// btnClearCache
@@ -148,10 +152,46 @@
this.groupConfiguration.TabStop = false;
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
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.groupApp);
this.Controls.Add(this.groupConfiguration);
this.Controls.Add(this.groupPerformance);
this.Controls.Add(this.btnReset);
@@ -162,6 +202,7 @@
this.groupPerformance.ResumeLayout(false);
this.groupPerformance.PerformLayout();
this.groupConfiguration.ResumeLayout(false);
this.groupApp.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
@@ -179,5 +220,8 @@
private System.Windows.Forms.GroupBox groupConfiguration;
private System.Windows.Forms.Button btnEditCefArgs;
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

@@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.Windows.Forms;
using TweetDck.Core.Controls;
using TweetDck.Core.Other.Settings.Dialogs;
@@ -71,21 +70,25 @@ namespace TweetDck.Core.Other.Settings{
if (form.ShowDialog(ParentForm) == DialogResult.OK){
Config.CustomCefArgs = form.CefArgs;
form.Dispose();
PromptRestart();
}
else{
form.Dispose();
}
}
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){
bool hasChangedBrowser = form.BrowserCSS != Config.CustomBrowserCSS;
Config.CustomBrowserCSS = form.BrowserCSS;
Config.CustomNotificationCSS = form.NotificationCSS;
Config.CustomBrowserCSS = form.BrowserCSS;
Config.CustomNotificationCSS = form.NotificationCSS;
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();
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();
}
}
}
}
@@ -115,7 +118,7 @@ namespace TweetDck.Core.Other.Settings{
ExportManager manager = new ExportManager(file, plugins);
if (!manager.Export(saveCredentials)){
Program.HandleException("An exception happened while exporting "+Program.BrandName+" settings.", manager.LastException);
Program.Reporter.HandleException("Profile Export Error", "An exception happened while exporting "+Program.BrandName+" settings.", true, manager.LastException);
}
}
}
@@ -141,7 +144,7 @@ namespace TweetDck.Core.Other.Settings{
}
}
else{
Program.HandleException("An exception happened while importing "+Program.BrandName+" settings.", manager.LastException);
Program.Reporter.HandleException("Profile Import Error", "An exception happened while importing "+Program.BrandName+" settings.", true, manager.LastException);
}
}
}
@@ -153,11 +156,12 @@ namespace TweetDck.Core.Other.Settings{
}
}
private 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){
Process.Start(Application.ExecutablePath, "-restart");
Application.Exit();
}
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

@@ -28,6 +28,7 @@
this.comboBoxTrayType = new System.Windows.Forms.ComboBox();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.checkTrayHighlight = new System.Windows.Forms.CheckBox();
this.checkSpellCheck = new System.Windows.Forms.CheckBox();
this.groupTray = new System.Windows.Forms.GroupBox();
this.labelTrayIcon = new System.Windows.Forms.Label();
this.groupInterface = new System.Windows.Forms.GroupBox();
@@ -74,12 +75,24 @@
this.checkTrayHighlight.UseVisualStyleBackColor = true;
this.checkTrayHighlight.CheckedChanged += new System.EventHandler(this.checkTrayHighlight_CheckedChanged);
//
// checkSpellCheck
//
this.checkSpellCheck.AutoSize = true;
this.checkSpellCheck.Location = new System.Drawing.Point(9, 44);
this.checkSpellCheck.Name = "checkSpellCheck";
this.checkSpellCheck.Size = new System.Drawing.Size(119, 17);
this.checkSpellCheck.TabIndex = 15;
this.checkSpellCheck.Text = "Enable Spell Check";
this.toolTip.SetToolTip(this.checkSpellCheck, "Underlines words that are spelled incorrectly.");
this.checkSpellCheck.UseVisualStyleBackColor = true;
this.checkSpellCheck.CheckedChanged += new System.EventHandler(this.checkSpellCheck_CheckedChanged);
//
// groupTray
//
this.groupTray.Controls.Add(this.checkTrayHighlight);
this.groupTray.Controls.Add(this.labelTrayIcon);
this.groupTray.Controls.Add(this.comboBoxTrayType);
this.groupTray.Location = new System.Drawing.Point(9, 63);
this.groupTray.Location = new System.Drawing.Point(9, 86);
this.groupTray.Name = "groupTray";
this.groupTray.Size = new System.Drawing.Size(183, 93);
this.groupTray.TabIndex = 15;
@@ -98,10 +111,11 @@
//
// groupInterface
//
this.groupInterface.Controls.Add(this.checkSpellCheck);
this.groupInterface.Controls.Add(this.checkExpandLinks);
this.groupInterface.Location = new System.Drawing.Point(9, 9);
this.groupInterface.Name = "groupInterface";
this.groupInterface.Size = new System.Drawing.Size(183, 48);
this.groupInterface.Size = new System.Drawing.Size(183, 71);
this.groupInterface.TabIndex = 16;
this.groupInterface.TabStop = false;
this.groupInterface.Text = "User Interface";
@@ -131,5 +145,6 @@
private System.Windows.Forms.GroupBox groupInterface;
private System.Windows.Forms.Label labelTrayIcon;
private System.Windows.Forms.CheckBox checkTrayHighlight;
private System.Windows.Forms.CheckBox checkSpellCheck;
}
}

View File

@@ -12,8 +12,9 @@ namespace TweetDck.Core.Other.Settings{
comboBoxTrayType.Items.Add("Combined");
comboBoxTrayType.SelectedIndex = Math.Min(Math.Max((int)Config.TrayBehavior, 0), comboBoxTrayType.Items.Count-1);
checkExpandLinks.Checked = Program.UserConfig.ExpandLinksOnHover;
checkTrayHighlight.Checked = Program.UserConfig.EnableTrayHighlight;
checkExpandLinks.Checked = Config.ExpandLinksOnHover;
checkSpellCheck.Checked = Config.EnableSpellCheck;
checkTrayHighlight.Checked = Config.EnableTrayHighlight;
}
private void checkExpandLinks_CheckedChanged(object sender, EventArgs e){
@@ -22,6 +23,13 @@ namespace TweetDck.Core.Other.Settings{
Config.ExpandLinksOnHover = checkExpandLinks.Checked;
}
private void checkSpellCheck_CheckedChanged(object sender, EventArgs e){
if (!Ready)return;
Config.EnableSpellCheck = checkSpellCheck.Checked;
PromptRestart();
}
private void comboBoxTrayType_SelectedIndexChanged(object sender, EventArgs e){
if (!Ready)return;

View File

@@ -8,14 +8,11 @@ namespace TweetDck.Core.Utils{
static class BrowserCache{
private static bool ClearOnExit { get; set; }
private static readonly string IndexFile = Path.Combine(Program.StoragePath, "index");
private static readonly string CacheFolder = Path.Combine(Program.StoragePath, "Cache");
private static IEnumerable<string> CacheFiles{
get{
return Directory.EnumerateFiles(Program.StoragePath).Where(path => {
string file = Path.GetFileName(path);
return file != null && (file.StartsWith("data_", StringComparison.Ordinal) || file.StartsWith("f_", StringComparison.Ordinal));
}).Concat(new[]{ IndexFile });
return Directory.EnumerateFiles(CacheFolder);
}
}
@@ -34,6 +31,21 @@ namespace TweetDck.Core.Utils{
task.Start();
}
public static void ClearOldCacheFiles(){
if (!Directory.Exists(CacheFolder)){
foreach(string file in Directory.EnumerateFiles(Program.StoragePath).Where(path => {
string file = Path.GetFileName(path);
return file != null && (file.StartsWith("data_", StringComparison.Ordinal) || file.StartsWith("f_", StringComparison.Ordinal));
}).Concat(new[]{ Path.Combine(Program.StoragePath, "index") })){
try{
File.Delete(file);
}catch{
// welp, too bad
}
}
}
}
public static void SetClearOnExit(){
ClearOnExit = true;
}

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{
static class CommandLineArgsParser{
@@ -7,18 +6,18 @@ namespace TweetDck.Core.Utils{
private static Regex SplitRegex{
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){
if (string.IsNullOrWhiteSpace(args)){
return 0;
public static CommandLineArgs ReadCefArguments(string argumentString){
CommandLineArgs args = new CommandLineArgs();
if (string.IsNullOrWhiteSpace(argumentString)){
return args;
}
int count = 0;
foreach(Match match in SplitRegex.Matches(args)){
foreach(Match match in SplitRegex.Matches(argumentString)){
string matchValue = match.Value;
int indexEquals = matchValue.IndexOf('=');
@@ -34,12 +33,11 @@ namespace TweetDck.Core.Utils{
}
if (key.Length != 0){
dictionary[key] = value;
++count;
args.SetValue(key, value);
}
}
return count;
return args;
}
}
}

View File

@@ -0,0 +1,33 @@
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.Security.Principal;
namespace TweetDck.Core.Utils{
static class WindowsUtils{
public static bool CheckFolderPermission(string path, FileSystemRights right){
try{
AuthorizationRuleCollection rules = Directory.GetAccessControl(path).GetAccessRules(true, true, typeof(SecurityIdentifier));
WindowsIdentity identity = WindowsIdentity.GetCurrent();
if (identity == null || identity.Groups == null){
return false;
}
bool accessAllow = false, accessDeny = false;
foreach(FileSystemAccessRule rule in rules.Cast<FileSystemAccessRule>().Where(rule => identity.Groups.Contains(rule.IdentityReference) && (right & rule.FileSystemRights) == right)){
switch(rule.AccessControlType){
case AccessControlType.Allow: accessAllow = true; break;
case AccessControlType.Deny: accessDeny = true; break;
}
}
return accessAllow && !accessDeny;
}
catch{
return false;
}
}
}
}

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.Windows.Forms;
using Microsoft.Win32;
using TweetDck.Migration.Helpers;
using TweetDck.Core.Other;
using System.Drawing;
namespace TweetDck.Migration{
static class MigrationManager{
@@ -16,26 +17,41 @@ namespace TweetDck.Migration{
private static readonly string TweetDickStorage = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "TweetDick");
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);
Program.Reporter.HandleException("Migration Error", "An unexpected error occurred during the migration process.", true, ex);
}
}
return;
}
#endif
if (!Program.UserConfig.IgnoreMigration && Directory.Exists(TweetDeckPath)){
MigrationDecision decision;
using(FormMigrationQuestion formQuestion = new FormMigrationQuestion()){
decision = formQuestion.ShowDialog() == DialogResult.OK ? formQuestion.Decision : MigrationDecision.AskLater;
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!";
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){
@@ -48,7 +64,7 @@ namespace TweetDck.Migration{
formWait.Close();
if (ex != null){
Program.HandleException("An unexpected exception has occurred during the migration process.", ex);
Program.Reporter.HandleException("Migration Error", "An unexpected error occurred during the migration process.", true, ex);
return;
}
@@ -68,10 +84,10 @@ namespace TweetDck.Migration{
}
}
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){
RunUninstaller(guid, 0);
MigrationUtils.RunUninstaller(guid, 0);
CleanupTweetDeck();
}
@@ -137,10 +153,10 @@ namespace TweetDck.Migration{
if (decision == MigrationDecision.MigratePurge){
// uninstall in the background
string guid = ProgramRegistrySearch.FindByDisplayName("TweetDeck");
string guid = MigrationUtils.FindProgramGuidByDisplayName("TweetDeck");
if (guid != null){
RunUninstaller(guid, 5000);
MigrationUtils.RunUninstaller(guid, 5000);
}
// registry cleanup
@@ -164,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(){
try{
Registry.CurrentUser.DeleteSubKeyTree(@"Software\Twitter\TweetDeck", true);

View File

@@ -1,10 +1,23 @@
using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.Win32;
namespace TweetDck.Migration.Helpers{
static class ProgramRegistrySearch{
public static string FindByDisplayName(string displayName){
namespace TweetDck.Migration{
static class MigrationUtils{
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);
string guid;

View File

@@ -24,12 +24,6 @@ namespace TweetDck.Plugins{
}
}
public string FolderPath{
get{
return path;
}
}
public bool HasConfig{
get{
return ConfigFile.Length > 0 && GetFullPathIfSafe(ConfigFile).Length > 0;
@@ -83,7 +77,7 @@ namespace TweetDck.Plugins{
try{
File.Copy(defaultConfigPath, configPath, false);
}catch(Exception e){
Program.HandleException("Could not generate a configuration file for '"+identifier+"' plugin.", e);
Program.Reporter.HandleException("Plugin Loading Error", "Could not generate a configuration file for '"+identifier+"' plugin.", true, e);
}
}
}

View File

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

View File

@@ -1,8 +1,6 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using System.Windows.Forms;
using CefSharp;
using TweetDck.Configuration;
@@ -14,31 +12,31 @@ using System.Threading;
using TweetDck.Plugins;
using TweetDck.Plugins.Events;
using TweetDck.Core.Other.Settings.Export;
using TweetDck.Core.Handling;
using System.Security.AccessControl;
[assembly: CLSCompliant(true)]
namespace TweetDck{
static class Program{
#if DUCK
public const string BrandName = "TweetDuck";
public const string Website = "http://tweetduck.chylex.com";
#else
public const string BrandName = "TweetDick";
public const string Website = "http://tweetdick.chylex.com";
#endif
public const string Website = "https://tweetduck.chylex.com";
public const string BrowserSubprocess = BrandName+".Browser.exe";
public const string VersionTag = "1.3.2";
public const string VersionFull = "1.3.2.0";
public const string VersionTag = "1.4";
public const string VersionFull = "1.4.0.0";
public static readonly Version Version = new Version(VersionTag);
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 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");
private static readonly string LogFilePath = Path.Combine(StoragePath, "TD_Log.txt");
public static readonly string ScriptPath = Path.Combine(ProgramPath, "scripts");
public static readonly string PluginPath = Path.Combine(ProgramPath, "plugins");
@@ -49,12 +47,7 @@ namespace TweetDck{
private static bool HasCleanedUp;
public static UserConfig UserConfig { get; private set; }
public static string LogFile{
get{
return Path.Combine(ProgramPath, "td-log.txt");
}
}
public static Reporter Reporter { get; private set; }
[STAThread]
private static void Main(){
@@ -63,14 +56,22 @@ namespace TweetDck{
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);
if (!WindowsUtils.CheckFolderPermission(ProgramPath, FileSystemRights.WriteData)){
MessageBox.Show(BrandName+" does not have write permissions to the program folder. If it is installed in Program Files, please run it as Administrator.", "Administrator Required", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
string[] programArguments = Environment.GetCommandLineArgs();
Reporter = new Reporter(LogFilePath);
if (programArguments.Contains("-restart")){
AppDomain.CurrentDomain.UnhandledException += (sender, args) => {
Exception ex = args.ExceptionObject as Exception;
if (ex != null){
Reporter.HandleException(BrandName+" Has Failed :(", "An unhandled exception has occurred.", false, ex);
}
};
if (Args.HasFlag("-restart")){
for(int attempt = 0; attempt < 41; attempt++){
if (LockManager.Lock()){
break;
@@ -83,8 +84,13 @@ namespace TweetDck{
Thread.Sleep(500);
}
}
ReloadConfig();
}
else{
ReloadConfig();
MigrationManager.Run();
if (!LockManager.Lock()){
if (LockManager.LockingProcess.MainWindowHandle == IntPtr.Zero && LockManager.LockingProcess.Responding){ // restore if the original process is in tray
NativeMethods.SendMessage(NativeMethods.HWND_BROADCAST, WindowRestoreMessage, 0, IntPtr.Zero);
@@ -102,51 +108,26 @@ namespace TweetDck{
}
}
if (programArguments.Contains("-importcookies") && File.Exists(ExportManager.TempCookiesPath)){
try{
if (File.Exists(ExportManager.CookiesPath)){
File.Delete(ExportManager.CookiesPath);
}
File.Move(ExportManager.TempCookiesPath, ExportManager.CookiesPath);
}catch(Exception e){
HandleException("Could not import the cookie file to restore login session.", e);
}
if (Args.HasFlag("-importcookies")){
ExportManager.ImportCookies();
}
ReloadConfig();
MigrationManager.Run();
Cef.OnContextInitialized = () => {
using(IRequestContext ctx = Cef.GetGlobalRequestContext()){
string err;
ctx.SetPreference("browser.enable_spellchecking", false, out err);
}
};
BrowserCache.ClearOldCacheFiles();
CefSettings settings = new CefSettings{
AcceptLanguageList = BrowserUtils.HeaderAcceptLanguage,
UserAgent = BrowserUtils.HeaderUserAgent,
Locale = CultureInfo.CurrentCulture.TwoLetterISOLanguageName,
Locale = Args.GetValue("-locale", "en"),
CachePath = StoragePath,
BrowserSubprocessPath = File.Exists(BrowserSubprocess) ? BrowserSubprocess : "CefSharp.BrowserSubprocess.exe",
#if !DEBUG
LogSeverity = programArguments.Contains("-log") ? LogSeverity.Info : LogSeverity.Disable
LogSeverity = Args.HasFlag("-log") ? LogSeverity.Info : LogSeverity.Disable
#endif
};
CommandLineArgsParser.AddToDictionary(UserConfig.CustomCefArgs, settings.CefCommandLineArgs);
CommandLineArgsParser.ReadCefArguments(UserConfig.CustomCefArgs).ToDictionary(settings.CefCommandLineArgs);
Cef.Initialize(settings);
AppDomain.CurrentDomain.UnhandledException += (sender, args) => {
Exception ex = args.ExceptionObject as Exception;
if (ex != null){
HandleException("An unhandled exception has occurred.", ex);
}
};
Cef.Initialize(settings, false, new BrowserProcessHandler());
Application.ApplicationExit += (sender, args) => ExitCleanup();
@@ -172,55 +153,24 @@ 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(){
string custom = GetCmdArgumentValue("-datafolder");
string custom = Args.GetValue("-datafolder", null);
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{
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){
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 bool Log(string data){
StringBuilder build = new StringBuilder();
if (!File.Exists(LogFile)){
build.Append("Please, report all issues to: https://github.com/chylex/TweetDuck/issues\r\n\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");
}
try{
File.AppendAllText(LogFile, build.ToString(), Encoding.UTF8);
return true;
}catch{
return false;
}
}
public static void ReloadConfig(){
UserConfig = UserConfig.Load(ConfigFilePath);
}
@@ -230,13 +180,28 @@ namespace TweetDck{
File.Delete(ConfigFilePath);
File.Delete(UserConfig.GetBackupFile(ConfigFilePath));
}catch(Exception e){
HandleException("Could not delete configuration files to reset the settings.", e);
Reporter.HandleException("Configuration Reset Error", "Could not delete configuration files to reset the settings.", true, e);
return;
}
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(){
if (HasCleanedUp)return;

View File

@@ -1,13 +1,11 @@
# Build Instructions
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 53 or newer currently available as a pre-release.
```
PM> Install-Package CefSharp.WinForms -Pre -Version 49.0.0-pre02
PM> Install-Package CefSharp.WinForms -Pre -Version 53.0.0-pre01
PM> Install-Package Microsoft.VC120.CRT.JetBrains
```
TweetD\*ck comes in two variants - TweetDick and TweetDuck. The solution includes both configurations under the names **Release Dick** and **Release Duck**, so make sure to select the correct one, or build both using Batch Build.
After building, run **_postbuild.bat** which deletes unnecessary files that CefSharp adds after post-build events >_>
Built files are then available in **bin/x86** and/or **bin/x64**.

89
Reporter.cs Normal file
View File

@@ -0,0 +1,89 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Text;
using System.Windows.Forms;
using TweetDck.Core.Other;
namespace TweetDck{
class Reporter{
private readonly string logFile;
public Reporter(string logFile){
this.logFile = logFile;
}
public bool Log(string data){
StringBuilder build = new StringBuilder();
if (!File.Exists(logFile)){
build.Append("Please, report all issues to: https://github.com/chylex/TweetDuck/issues\r\n\r\n");
}
build.Append("[").Append(DateTime.Now.ToString("G", CultureInfo.CurrentCulture)).Append("]\r\n");
build.Append(data).Append("\r\n\r\n");
try{
File.AppendAllText(logFile, build.ToString(), Encoding.UTF8);
return true;
}catch{
return false;
}
}
public void HandleException(string caption, string message, bool canIgnore, Exception e){
Log(e.ToString());
FormMessage form = new FormMessage(caption, message+"\r\nError: "+e.Message, canIgnore ? MessageBoxIcon.Warning : MessageBoxIcon.Error);
form.AddButton("Exit");
Button btnIgnore = form.AddButton("Ignore");
Button btnOpenLog = new Button{
Anchor = AnchorStyles.Bottom | AnchorStyles.Left,
Location = new Point(12, 12),
Margin = new Padding(0, 0, 48, 0),
Size = new Size(88, 26),
Text = "Show Error Log",
UseVisualStyleBackColor = true
};
btnOpenLog.Click += (sender, args) => Process.Start(logFile);
form.AddActionControl(btnOpenLog);
if (!canIgnore){
btnIgnore.Enabled = false;
}
if (form.ShowDialog() == DialogResult.OK){
if (form.ClickedButton == btnIgnore){
return;
}
}
try{
Process.GetCurrentProcess().Kill();
}catch{
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]
- Adds buttons and keyboard shortcuts to quickly clear columns
- Hold Shift when clicking or using a keyboard shortcut to reset the column instead
[author]
chylex
[version]
1.0
1.1
[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");
};
var clearAllColumns = () => {
Object.keys(TD.controller.columnManager.getAll()).forEach(key => clearColumn(key));
var resetColumn = (columnName) => {
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) => {
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
this.eventClearSingle = function(){
clearColumn($(this).closest(".js-column").attr("data-column"));
this.eventClickSingle = function(e){
var name = $(this).closest(".js-column").attr("data-column");
e.shiftKey ? resetColumn(name) : clearColumn(name);
};
this.eventClearAll = function(){
clearAllColumns();
this.eventClickAll = function(e){
forEachColumn(e.shiftKey ? resetColumn : clearColumn);
};
this.eventKeys = function(e){
if (e.keyCode === 46 && (document.activeElement === null || document.activeElement === document.body)){ // 46 = delete
this.eventKeyDown = function(e){
if (!(document.activeElement === null || document.activeElement === document.body)){
return;
}
updateShiftState(e.shiftKey);
if (e.keyCode === 46){ // 46 = delete
if (e.altKey){
clearAllColumns();
forEachColumn(e.shiftKey ? resetColumn : clearColumn);
}
else{
var focusedColumn = $(".js-column.is-focused");
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
replaceMustache("column/column_header.mustache", "</header>", [
'{{^isTemporary}}',
@@ -62,27 +99,26 @@ enabled(){
].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);
var css = window.TDPF_createCustomStyle(this);
css.insert(".column-title { margin-right: 60px !important; }");
css.insert(".column-type-message .column-title { margin-right: 115px !important; }");
css.insert(".mark-all-read-link { right: 59px !important; }");
css.insert(".open-compose-dm-link { right: 90px !important; }");
css.insert("button[data-action='clear'].btn-options-tray { display: none !important; }");
}
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);
$(document).on("click", "[data-action='td-clearcolumns-dosingle']", this.eventClickSingle);
$(document).on("click", "[data-action='td-clearcolumns-doall']", this.eventClickAll);
$(document).on("keydown", this.eventKeyDown);
$(document).on("keyup", this.eventKeyUp);
// 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>',
'<div id="clear-columns-btn-all" class="nbfc padding-ts hide-condensed">Clear all</div>',
'</a></nav>'
].join(""));
}

View File

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

View File

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

View File

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

View File

@@ -1,67 +1,120 @@
enabled(){
var configuration = { defaultAccount: "" };
var configuration = { defaultAccount: "#preferred" };
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);
}
this.lastSelectedAccount = null;
this.uiComposeTweetEvent = (e, data) => {
if (data.type !== "reply"){
return;
}
if (account === null){
if (configuration.defaultAccount === false){
return;
}
else if (configuration.defaultAccount !== "" && configuration.defaultAccount[0] === '@'){
account = configuration.defaultAccount.substring(1);
}
}
var query;
var identifier;
if (account === null){
identifier = TD.storage.clientController.client.getDefaultAccount();
}
else{
var obj = TD.storage.accountController.getAccountFromUsername(account);
if (obj.length === 0){
return;
if (configuration.useAdvancedSelector){
if (configuration.customSelector){
var column = TD.controller.columnManager.get(data.element.closest("section.column").attr("data-column"));
query = configuration.customSelector(column);
}
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 ];
};
this.onSelectedAccountChanged = () => {
var selected = $(".js-account-item.is-selected", ".js-account-list");
this.lastSelectedAccount = selected.length === 1 ? selected.attr("data-account-key") : null;
};
}
ready(){
var events = $._data(document, "events");
if ("uiInlineComposeTweet" in events){
$(document).on("uiInlineComposeTweet", this.uiInlineComposeTweetEvent);
for(var event of [ "uiInlineComposeTweet", "uiDockedComposeTweet" ]){
$(document).on(event, this.uiComposeTweetEvent);
var handlers = events["uiInlineComposeTweet"];
var oldHandler = handlers[0];
var newHandler = handlers[1];
var handlers = events[event];
var newHandler = handlers[handlers.length-1];
for(var index = handlers.length-1; index > 0; index--){
handlers[index] = handlers[index-1];
}
handlers[0] = newHandler;
handlers[1] = oldHandler;
}
else{
$(document).on("uiInlineComposeTweet", this.uiInlineComposeTweetEvent);
}
$(document).on("click", ".js-account-list .js-account-item", this.onSelectedAccountChanged);
}
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:
*
* "" 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
* 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
@@ -30,8 +31,8 @@
* 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 'customSelector' function should return a string in one of the formats supported by 'defaultAccount'.
* 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,
* 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){
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();
}
else if (modal.is(":visible")){
modal.find("a[rel=dismiss]").click();
else if ((drawerComposer = $(".js-app-content.is-open .js-drawer-close:visible")).length === 1){
drawerComposer.click();
}
else{
$(".js-column-back").click();

View File

@@ -117,6 +117,36 @@
$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.
//

View File

@@ -15,7 +15,7 @@
try{
obj = eval("("+contents+")");
}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);
}
@@ -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);

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props')" />
<Import Project="packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props')" />
<Import Project="packages\CefSharp.WinForms.49.0.0-pre02\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.49.0.0-pre02\build\CefSharp.WinForms.props')" />
<Import Project="packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
@@ -11,12 +13,12 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TweetDck</RootNamespace>
<AssemblyName Condition=" '$(Configuration)' == 'Debug' ">TweetDick</AssemblyName>
<AssemblyName Condition=" '$(Configuration)' == 'Release Dick' ">TweetDick</AssemblyName>
<AssemblyName Condition=" '$(Configuration)' == 'Release Duck' ">TweetDuck</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<AssemblyName Condition=" '$(Configuration)' == 'Release' ">TweetDuck</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>ff8ce4f3</NuGetPackageImportStamp>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<NuGetPackageImportStamp>e83161d1</NuGetPackageImportStamp>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
@@ -41,24 +43,13 @@
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Dick|x86' ">
<OutputPath>bin\x86\Release Dick\</OutputPath>
<DefineConstants>
</DefineConstants>
<Optimize>true</Optimize>
<DebugType>none</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<UseVSHostingProcess>false</UseVSHostingProcess>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\icon.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Duck|x86' ">
<OutputPath>bin\x86\Release Duck\</OutputPath>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\x86\Release\</OutputPath>
<Optimize>true</Optimize>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
@@ -66,7 +57,12 @@
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<DefineConstants>DUCK</DefineConstants>
<DefineConstants>
</DefineConstants>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<AssemblyName>TweetDuck</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@@ -99,6 +95,7 @@
<Compile Include="Core\Controls\TabPanel.Designer.cs">
<DependentUpon>TabPanel.cs</DependentUpon>
</Compile>
<Compile Include="Core\Handling\BrowserProcessHandler.cs" />
<Compile Include="Core\Handling\ContextMenuBase.cs" />
<Compile Include="Core\Handling\ContextMenuBrowser.cs" />
<Compile Include="Core\FormBrowser.cs">
@@ -123,6 +120,12 @@
<Compile Include="Core\Other\FormAbout.Designer.cs">
<DependentUpon>FormAbout.cs</DependentUpon>
</Compile>
<Compile Include="Core\Other\FormMessage.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Core\Other\FormMessage.Designer.cs">
<DependentUpon>FormMessage.cs</DependentUpon>
</Compile>
<Compile Include="Core\Other\FormPlugins.cs">
<SubType>Form</SubType>
</Compile>
@@ -173,8 +176,10 @@
<Compile Include="Core\Other\Settings\TabSettingsUpdates.Designer.cs">
<DependentUpon>TabSettingsUpdates.cs</DependentUpon>
</Compile>
<Compile Include="Core\Utils\CommandLineArgs.cs" />
<Compile Include="Core\Utils\CommandLineArgsParser.cs" />
<Compile Include="Core\Utils\WindowState.cs" />
<Compile Include="Core\Utils\WindowsUtils.cs" />
<Compile Include="Migration\FormBackgroundWork.cs">
<SubType>Form</SubType>
</Compile>
@@ -188,6 +193,7 @@
<Compile Include="Core\Other\FormSettings.Designer.cs">
<DependentUpon>FormSettings.cs</DependentUpon>
</Compile>
<Compile Include="Migration\MigrationUtils.cs" />
<Compile Include="Plugins\Controls\PluginControl.cs">
<SubType>UserControl</SubType>
</Compile>
@@ -209,6 +215,7 @@
<Compile Include="Plugins\Events\PluginLoadEventArgs.cs" />
<Compile Include="Plugins\PluginManager.cs" />
<Compile Include="Plugins\PluginScriptGenerator.cs" />
<Compile Include="Reporter.cs" />
<Compile Include="Updates\FormUpdateDownload.cs">
<SubType>Form</SubType>
</Compile>
@@ -229,15 +236,8 @@
<Compile Include="Updates\UpdateCheckEventArgs.cs" />
<Compile Include="Updates\UpdateHandler.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\MigrationManager.cs" />
<Compile Include="Migration\Helpers\ProgramRegistrySearch.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
@@ -312,15 +312,13 @@
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\cef.redist.x86.3.2623.1396\build\cef.redist.x86.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.2623.1396\build\cef.redist.x86.targets'))" />
<Error Condition="!Exists('packages\cef.redist.x64.3.2623.1396\build\cef.redist.x64.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.2623.1396\build\cef.redist.x64.targets'))" />
<Error Condition="!Exists('packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.props'))" />
<Error Condition="!Exists('packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.targets'))" />
<Error Condition="!Exists('packages\CefSharp.WinForms.49.0.0-pre02\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.49.0.0-pre02\build\CefSharp.WinForms.props'))" />
<Error Condition="!Exists('packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets'))" />
<Error Condition="!Exists('packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets'))" />
<Error Condition="!Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props'))" />
<Error Condition="!Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets'))" />
<Error Condition="!Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props'))" />
<Error Condition="!Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets'))" />
</Target>
<Import Project="packages\cef.redist.x86.3.2623.1396\build\cef.redist.x86.targets" Condition="Exists('packages\cef.redist.x86.3.2623.1396\build\cef.redist.x86.targets')" />
<Import Project="packages\cef.redist.x64.3.2623.1396\build\cef.redist.x64.targets" Condition="Exists('packages\cef.redist.x64.3.2623.1396\build\cef.redist.x64.targets')" />
<Import Project="packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.targets')" />
<PropertyGroup>
<PostBuildEvent>del "$(TargetPath).config"
xcopy "$(ProjectDir)LICENSE.md" "$(TargetDir)" /Y
@@ -340,6 +338,10 @@ xcopy "$(ProjectDir)Resources\Plugins\*" "$(TargetDir)plugins\official\" /E /Y
rmdir "$(ProjectDir)\bin\Debug"
rmdir "$(ProjectDir)\bin\Release"</PostBuildEvent>
</PropertyGroup>
<Import Project="packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets" Condition="Exists('packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets')" />
<Import Project="packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets" Condition="Exists('packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets')" />
<Import Project="packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets')" />
<Import Project="packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets" Condition="Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
@@ -8,17 +8,14 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release Dick|x86 = Release Dick|x86
Release Duck|x86 = Release Duck|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2389A7CD-E0D3-4706-8294-092929A33A2D}.Debug|x86.ActiveCfg = Debug|x86
{2389A7CD-E0D3-4706-8294-092929A33A2D}.Debug|x86.Build.0 = Debug|x86
{2389A7CD-E0D3-4706-8294-092929A33A2D}.Debug|x86.Deploy.0 = Debug|x86
{2389A7CD-E0D3-4706-8294-092929A33A2D}.Release Dick|x86.ActiveCfg = Release Dick|x86
{2389A7CD-E0D3-4706-8294-092929A33A2D}.Release Dick|x86.Build.0 = Release Dick|x86
{2389A7CD-E0D3-4706-8294-092929A33A2D}.Release Duck|x86.ActiveCfg = Release Duck|x86
{2389A7CD-E0D3-4706-8294-092929A33A2D}.Release Duck|x86.Build.0 = Release Duck|x86
{2389A7CD-E0D3-4706-8294-092929A33A2D}.Release|x86.ActiveCfg = Release|x86
{2389A7CD-E0D3-4706-8294-092929A33A2D}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -90,7 +90,7 @@ namespace TweetDck.Updates{
}
}
else if (e.Error != null){
Program.Log(e.Error.ToString());
Program.Reporter.Log(e.Error.ToString());
if (MessageBox.Show("Could not download the update: "+e.Error.Message+"\r\n\r\nDo you want to open the website and try downloading the update manually?", "Update Has Failed", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1) == DialogResult.Yes){
BrowserUtils.OpenExternalBrowser(Program.Website);

View File

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