mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-09-14 10:32:10 +02:00
Compare commits
54 Commits
Author | SHA1 | Date | |
---|---|---|---|
16180fd5d6 | |||
462aebb115 | |||
0cb3bd9cc6 | |||
2ef4f28740 | |||
b02fb0934f | |||
de363c982f | |||
f0132f59e5 | |||
dc32285454 | |||
e170172870 | |||
eba47a8196 | |||
907543a7cf | |||
e8dea023ac | |||
8cfb6ab4f5 | |||
c64d58143e | |||
991681e186 | |||
3c17c36f4f | |||
707b4b4ba2 | |||
413c7564aa | |||
453bf2dd82 | |||
5597d2aed0 | |||
3c43211b25 | |||
ee87841ec2 | |||
9e5a39e9fc | |||
8c21011ac7 | |||
5f5013f021 | |||
fe093475dc | |||
1c4e03ebea | |||
860b740db9 | |||
bd54da85a8 | |||
86165b3529 | |||
09d028a3af | |||
1cb261cb6f | |||
82934878cc | |||
996c460f57 | |||
33e704f1ab | |||
2c3849bc43 | |||
7de79786c9 | |||
d3d1fc808e | |||
1ab9e35c6e | |||
e6e4d0ba75 | |||
147c268ef8 | |||
ebd17e1544 | |||
039233c782 | |||
57484c8bf7 | |||
74fec18146 | |||
00341e984c | |||
c172e7aa3d | |||
1030555bb5 | |||
c53636c013 | |||
cf450447e5 | |||
81c29ab50c | |||
f99435ff6a | |||
39f554693d | |||
38539c4a9b |
@@ -3,7 +3,7 @@ using System.Diagnostics;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace TweetDick.Configuration{
|
namespace TweetDck.Configuration{
|
||||||
class LockManager{
|
class LockManager{
|
||||||
private readonly string file;
|
private readonly string file;
|
||||||
private FileStream lockStream;
|
private FileStream lockStream;
|
||||||
|
@@ -3,36 +3,47 @@ using System.Drawing;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Runtime.Serialization.Formatters.Binary;
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
using TweetDick.Core.Handling;
|
using TweetDck.Core.Handling;
|
||||||
|
|
||||||
namespace TweetDick.Configuration{
|
namespace TweetDck.Configuration{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
sealed class UserConfig{
|
sealed class UserConfig{
|
||||||
private static readonly IFormatter Formatter = new BinaryFormatter();
|
private static readonly IFormatter Formatter = new BinaryFormatter(){
|
||||||
|
Binder = new SerializationCompatibilityHandler()
|
||||||
|
};
|
||||||
|
|
||||||
|
private const int CurrentFileVersion = 1;
|
||||||
|
|
||||||
// START OF CONFIGURATION
|
// START OF CONFIGURATION
|
||||||
|
|
||||||
public bool IgnoreMigration { get; set; }
|
public bool IgnoreMigration { get; set; }
|
||||||
|
public bool IgnoreUninstallCheck { get; set; }
|
||||||
|
|
||||||
public bool IsMaximized { get; set; }
|
public bool IsMaximized { get; set; }
|
||||||
public Point WindowLocation { get; set; }
|
public Point WindowLocation { get; set; }
|
||||||
public Size WindowSize { get; set; }
|
public Size WindowSize { get; set; }
|
||||||
|
|
||||||
|
public bool MinimizeToTray { get; set; }
|
||||||
|
public bool DisplayNotificationTimer { get; set; }
|
||||||
|
|
||||||
public TweetNotification.Duration NotificationDuration { get; set; }
|
public TweetNotification.Duration NotificationDuration { get; set; }
|
||||||
public TweetNotification.Position NotificationPosition { get; set; }
|
public TweetNotification.Position NotificationPosition { get; set; }
|
||||||
public Point CustomNotificationPosition { get; set; }
|
public Point CustomNotificationPosition { get; set; }
|
||||||
public int NotificationEdgeDistance { get; set; }
|
public int NotificationEdgeDistance { get; set; }
|
||||||
public int NotificationDisplay { get; set; }
|
public int NotificationDisplay { get; set; }
|
||||||
|
|
||||||
|
public bool EnableUpdateCheck { get; set; }
|
||||||
|
public string DismissedUpdate { get; set; }
|
||||||
|
|
||||||
public bool IsCustomWindowLocationSet{
|
public bool IsCustomWindowLocationSet{
|
||||||
get{
|
get{
|
||||||
return WindowLocation.X != 32000;
|
return WindowLocation.X != -32000 && WindowLocation.X != 32000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsCustomNotificationPositionSet{
|
public bool IsCustomNotificationPositionSet{
|
||||||
get{
|
get{
|
||||||
return CustomNotificationPosition.X != 32000;
|
return CustomNotificationPosition.X != -32000 && CustomNotificationPosition.X != 32000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,15 +52,36 @@ namespace TweetDick.Configuration{
|
|||||||
[NonSerialized]
|
[NonSerialized]
|
||||||
private string file;
|
private string file;
|
||||||
|
|
||||||
|
private int fileVersion;
|
||||||
|
|
||||||
private UserConfig(string file){
|
private UserConfig(string file){
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
IsMaximized = true;
|
IsMaximized = true;
|
||||||
WindowLocation = new Point(32000,32000);
|
DisplayNotificationTimer = true;
|
||||||
|
WindowLocation = new Point(-32000,-32000);
|
||||||
NotificationDuration = TweetNotification.Duration.Medium;
|
NotificationDuration = TweetNotification.Duration.Medium;
|
||||||
NotificationPosition = TweetNotification.Position.TopRight;
|
NotificationPosition = TweetNotification.Position.TopRight;
|
||||||
CustomNotificationPosition = new Point(32000,32000);
|
CustomNotificationPosition = new Point(-32000,-32000);
|
||||||
NotificationEdgeDistance = 8;
|
NotificationEdgeDistance = 8;
|
||||||
|
EnableUpdateCheck = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpgradeFile(){
|
||||||
|
if (fileVersion == CurrentFileVersion){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if outdated, cycle through all versions
|
||||||
|
if (fileVersion == 0){
|
||||||
|
DisplayNotificationTimer = true;
|
||||||
|
EnableUpdateCheck = true;
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the version
|
||||||
|
fileVersion = CurrentFileVersion;
|
||||||
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Save(){
|
public bool Save(){
|
||||||
@@ -70,8 +102,8 @@ namespace TweetDick.Configuration{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}catch(Exception){
|
}catch(Exception e){
|
||||||
// TODO
|
Program.HandleException("Could not save the configuration file.",e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,11 +118,15 @@ namespace TweetDick.Configuration{
|
|||||||
config.file = file;
|
config.file = file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config != null){
|
||||||
|
config.UpgradeFile();
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}catch(FileNotFoundException){
|
}catch(FileNotFoundException){
|
||||||
}catch(Exception){
|
}catch(Exception e){
|
||||||
// TODO
|
Program.HandleException("Could not open the configuration file.",e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,5 +136,18 @@ namespace TweetDick.Configuration{
|
|||||||
private static string GetBackupFile(string file){
|
private static string GetBackupFile(string file){
|
||||||
return file+".bak";
|
return file+".bak";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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("{0}, {1}",typeName,assemblyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,4 +4,5 @@
|
|||||||
<package id="cef.redist.x86" 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.Common" version="49.0.0-pre02" targetFramework="net40-Client" />
|
||||||
<package id="CefSharp.WinForms" 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" />
|
||||||
</packages>
|
</packages>
|
32
Core/Controls/ControlExtensions.cs
Normal file
32
Core/Controls/ControlExtensions.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Controls{
|
||||||
|
static class ControlExtensions{
|
||||||
|
public static void InvokeSafe(this Form form, Action func){
|
||||||
|
if (form.InvokeRequired){
|
||||||
|
form.Invoke(func);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void MoveToCenter(this Form targetForm, Form parentForm){
|
||||||
|
targetForm.Location = new Point(parentForm.Location.X+parentForm.Width/2-targetForm.Width/2,parentForm.Location.Y+parentForm.Height/2-targetForm.Height/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetValueInstant(this ProgressBar bar, int value){
|
||||||
|
if (value == bar.Maximum){
|
||||||
|
bar.Value = value;
|
||||||
|
bar.Value = value-1;
|
||||||
|
bar.Value = value;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
bar.Value = value+1;
|
||||||
|
bar.Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
Core/Controls/FlatProgressBar.Designer.cs
generated
4
Core/Controls/FlatProgressBar.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDick.Core.Controls {
|
namespace TweetDck.Core.Controls {
|
||||||
partial class FlatProgressBar {
|
partial class FlatProgressBar {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
protected override void Dispose(bool disposing) {
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (brush != null)brush.Dispose();
|
||||||
|
|
||||||
if (disposing && (components != null)) {
|
if (disposing && (components != null)) {
|
||||||
components.Dispose();
|
components.Dispose();
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TweetDick.Core.Controls{
|
namespace TweetDck.Core.Controls{
|
||||||
public partial class FlatProgressBar : ProgressBar{
|
public partial class FlatProgressBar : ProgressBar{
|
||||||
private SolidBrush brush;
|
private SolidBrush brush;
|
||||||
|
|
||||||
@@ -11,15 +11,7 @@ namespace TweetDick.Core.Controls{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void SetValueInstant(int value){
|
public void SetValueInstant(int value){
|
||||||
if (value == Maximum){
|
ControlExtensions.SetValueInstant(this,value);
|
||||||
Value = value;
|
|
||||||
Value = value-1;
|
|
||||||
Value = value;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
Value = value+1;
|
|
||||||
Value = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPaint(PaintEventArgs e){
|
protected override void OnPaint(PaintEventArgs e){
|
||||||
|
2
Core/Controls/RichTextLabel.Designer.cs
generated
2
Core/Controls/RichTextLabel.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDick.Core.Controls {
|
namespace TweetDck.Core.Controls {
|
||||||
partial class RichTextLabel {
|
partial class RichTextLabel {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TweetDick.Core.Controls{
|
namespace TweetDck.Core.Controls{
|
||||||
public partial class RichTextLabel : RichTextBox{
|
public partial class RichTextLabel : RichTextBox{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wraps the body of a RTF formatted string with default tags and formatting.
|
/// Wraps the body of a RTF formatted string with default tags and formatting.
|
||||||
|
18
Core/FormBrowser.Designer.cs
generated
18
Core/FormBrowser.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDick.Core {
|
namespace TweetDck.Core {
|
||||||
sealed partial class FormBrowser {
|
sealed partial class FormBrowser {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -23,23 +23,33 @@
|
|||||||
/// the contents of this method with the code editor.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormBrowser));
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.trayIcon = new System.Windows.Forms.NotifyIcon(this.components);
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
|
// trayIcon
|
||||||
|
//
|
||||||
|
this.trayIcon.Icon = global::TweetDck.Properties.Resources.icon;
|
||||||
|
this.trayIcon.Click += new System.EventHandler(this.trayIcon_Click);
|
||||||
|
//
|
||||||
// FormBrowser
|
// FormBrowser
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.Icon = TweetDick.Properties.Resources.icon;
|
this.ClientSize = new System.Drawing.Size(284, 262);
|
||||||
this.Location = new System.Drawing.Point(32000, 32000);
|
this.Icon = global::TweetDck.Properties.Resources.icon;
|
||||||
|
this.Location = new System.Drawing.Point(-32000, -32000);
|
||||||
this.Name = "FormBrowser";
|
this.Name = "FormBrowser";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
||||||
this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd);
|
this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd);
|
||||||
|
this.Resize += new System.EventHandler(this.FormBrowser_Resize);
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.NotifyIcon trayIcon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
using System.Windows.Forms;
|
using System;
|
||||||
using CefSharp.WinForms;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using TweetDick.Configuration;
|
using System.Windows.Forms;
|
||||||
using CefSharp;
|
using CefSharp;
|
||||||
using TweetDick.Core.Handling;
|
using CefSharp.WinForms;
|
||||||
using TweetDick.Core.Other;
|
using TweetDck.Configuration;
|
||||||
using System.Drawing;
|
using TweetDck.Core.Handling;
|
||||||
using TweetDick.Resources;
|
using TweetDck.Core.Other;
|
||||||
|
using TweetDck.Resources;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
|
||||||
namespace TweetDick.Core{
|
namespace TweetDck.Core{
|
||||||
sealed partial class FormBrowser : Form{
|
sealed partial class FormBrowser : Form{
|
||||||
private static UserConfig Config{
|
private static UserConfig Config{
|
||||||
get{
|
get{
|
||||||
@@ -17,12 +18,17 @@ namespace TweetDick.Core{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string UpdateInstallerPath { get; private set; }
|
||||||
|
|
||||||
private readonly ChromiumWebBrowser browser;
|
private readonly ChromiumWebBrowser browser;
|
||||||
private readonly TweetDeckBridge bridge;
|
private readonly TweetDeckBridge bridge;
|
||||||
private readonly FormNotification notification;
|
private readonly FormNotification notification;
|
||||||
|
|
||||||
private FormSettings currentFormSettings;
|
private FormSettings currentFormSettings;
|
||||||
private FormAbout currentFormAbout;
|
private FormAbout currentFormAbout;
|
||||||
|
private bool isLoaded;
|
||||||
|
|
||||||
|
private FormWindowState prevState;
|
||||||
|
|
||||||
public FormBrowser(){
|
public FormBrowser(){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -31,29 +37,24 @@ namespace TweetDick.Core{
|
|||||||
|
|
||||||
bridge = new TweetDeckBridge(this);
|
bridge = new TweetDeckBridge(this);
|
||||||
|
|
||||||
browser = new ChromiumWebBrowser("https://tweetdeck.twitter.com/"){ MenuHandler = new ContextMenuHandler(this) };
|
browser = new ChromiumWebBrowser("https://tweetdeck.twitter.com/"){ MenuHandler = new ContextMenuBrowser(this) };
|
||||||
browser.LoadingStateChanged += Browser_LoadingStateChanged;
|
browser.LoadingStateChanged += Browser_LoadingStateChanged;
|
||||||
browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
||||||
browser.RegisterJsObject("$TD",bridge);
|
browser.RegisterJsObject("$TD",bridge);
|
||||||
|
|
||||||
Controls.Add(browser);
|
Controls.Add(browser);
|
||||||
|
|
||||||
notification = new FormNotification(this,bridge,true);
|
Disposed += (sender, args) => browser.Dispose();
|
||||||
|
|
||||||
|
notification = new FormNotification(this,bridge,true){ CanMoveWindow = () => false };
|
||||||
notification.Show();
|
notification.Show();
|
||||||
}
|
|
||||||
|
|
||||||
protected override void WndProc(ref Message m){
|
trayIcon.Text = Program.BrandName;
|
||||||
FormWindowState prevState = WindowState;
|
|
||||||
base.WndProc(ref m);
|
|
||||||
|
|
||||||
if (prevState != WindowState && m.Msg == 0x0014){ // WM_ERASEBKGND
|
|
||||||
FormBrowser_WindowStateChanged(this,new EventArgs());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowChildForm(Form form){
|
private void ShowChildForm(Form form){
|
||||||
form.Show(this);
|
form.Show(this);
|
||||||
form.Location = new Point(Location.X+Width/2-form.Width/2,Location.Y+Height/2-form.Height/2);
|
form.MoveToCenter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// window setup
|
// window setup
|
||||||
@@ -70,6 +71,9 @@ namespace TweetDick.Core{
|
|||||||
Size = Screen.PrimaryScreen.WorkingArea.Size;
|
Size = Screen.PrimaryScreen.WorkingArea.Size;
|
||||||
WindowState = FormWindowState.Maximized;
|
WindowState = FormWindowState.Maximized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prevState = WindowState;
|
||||||
|
isLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// active event handlers
|
// active event handlers
|
||||||
@@ -91,26 +95,47 @@ namespace TweetDick.Core{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FormBrowser_ResizeEnd(object sender, EventArgs e){ // also triggers when the window moves
|
private void FormBrowser_Resize(object sender, EventArgs e){
|
||||||
Config.WindowLocation = Location;
|
if (!isLoaded)return;
|
||||||
Config.WindowSize = Size;
|
|
||||||
Config.Save();
|
if (WindowState != prevState){
|
||||||
|
prevState = WindowState;
|
||||||
|
|
||||||
|
if (WindowState == FormWindowState.Minimized){
|
||||||
|
if (Config.MinimizeToTray){
|
||||||
|
Hide(); // hides taskbar too?! welp that works I guess
|
||||||
|
trayIcon.Visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
FormBrowser_ResizeEnd(sender,e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FormBrowser_WindowStateChanged(object sender, EventArgs e){
|
private void FormBrowser_ResizeEnd(object sender, EventArgs e){ // also triggers when the window moves
|
||||||
Config.IsMaximized = WindowState != FormWindowState.Normal;
|
if (!isLoaded)return;
|
||||||
FormBrowser_ResizeEnd(sender,e);
|
|
||||||
|
if (Location.X != -32000){
|
||||||
|
Config.IsMaximized = WindowState == FormWindowState.Maximized;
|
||||||
|
Config.WindowLocation = Location;
|
||||||
|
Config.WindowSize = Size;
|
||||||
|
Config.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trayIcon_Click(object sender, EventArgs e){
|
||||||
|
isLoaded = false;
|
||||||
|
Show();
|
||||||
|
SetupWindow();
|
||||||
|
|
||||||
|
trayIcon.Visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// callback handlers
|
// callback handlers
|
||||||
|
|
||||||
public void InvokeSafe(Action func){
|
public void InvokeSafe(Action func){
|
||||||
if (InvokeRequired){
|
ControlExtensions.InvokeSafe(this,func);
|
||||||
Invoke(func);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenSettings(){
|
public void OpenSettings(){
|
||||||
@@ -118,8 +143,21 @@ namespace TweetDick.Core{
|
|||||||
currentFormSettings.BringToFront();
|
currentFormSettings.BringToFront();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
bool prevEnableUpdateCheck = Config.EnableUpdateCheck;
|
||||||
|
|
||||||
currentFormSettings = new FormSettings(this);
|
currentFormSettings = new FormSettings(this);
|
||||||
currentFormSettings.FormClosed += (sender, args) => currentFormSettings = null;
|
|
||||||
|
currentFormSettings.FormClosed += (sender, args) => {
|
||||||
|
currentFormSettings = null;
|
||||||
|
|
||||||
|
if (!prevEnableUpdateCheck && Config.EnableUpdateCheck){
|
||||||
|
Config.DismissedUpdate = string.Empty;
|
||||||
|
Config.Save();
|
||||||
|
|
||||||
|
browser.ExecuteScriptAsync("TDGF_runUpdateCheck",new object[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ShowChildForm(currentFormSettings);
|
ShowChildForm(currentFormSettings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,5 +176,24 @@ namespace TweetDick.Core{
|
|||||||
public void OnTweetPopup(TweetNotification tweet){
|
public void OnTweetPopup(TweetNotification tweet){
|
||||||
notification.ShowNotification(tweet);
|
notification.ShowNotification(tweet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void BeginUpdateProcess(string versionTag, string downloadUrl){
|
||||||
|
Hide();
|
||||||
|
|
||||||
|
FormUpdateDownload downloadForm = new FormUpdateDownload(new UpdateInfo(versionTag,downloadUrl));
|
||||||
|
downloadForm.MoveToCenter(this);
|
||||||
|
downloadForm.ShowDialog();
|
||||||
|
|
||||||
|
if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Succeeded){
|
||||||
|
UpdateInstallerPath = downloadForm.InstallerPath;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
else if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Manual){
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
8
Core/FormNotification.Designer.cs
generated
8
Core/FormNotification.Designer.cs
generated
@@ -1,4 +1,6 @@
|
|||||||
namespace TweetDick.Core {
|
using TweetDck.Core.Controls;
|
||||||
|
|
||||||
|
namespace TweetDck.Core {
|
||||||
sealed partial class FormNotification {
|
sealed partial class FormNotification {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -26,7 +28,7 @@
|
|||||||
this.components = new System.ComponentModel.Container();
|
this.components = new System.ComponentModel.Container();
|
||||||
this.panelBrowser = new System.Windows.Forms.Panel();
|
this.panelBrowser = new System.Windows.Forms.Panel();
|
||||||
this.timerProgress = new System.Windows.Forms.Timer(this.components);
|
this.timerProgress = new System.Windows.Forms.Timer(this.components);
|
||||||
this.progressBarTimer = new TweetDick.Core.Controls.FlatProgressBar();
|
this.progressBarTimer = new FlatProgressBar();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// panelBrowser
|
// panelBrowser
|
||||||
@@ -65,7 +67,7 @@
|
|||||||
this.Controls.Add(this.progressBarTimer);
|
this.Controls.Add(this.progressBarTimer);
|
||||||
this.Controls.Add(this.panelBrowser);
|
this.Controls.Add(this.panelBrowser);
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||||
this.Location = new System.Drawing.Point(32000, 32000);
|
this.Location = new System.Drawing.Point(-32000, -32000);
|
||||||
this.Name = "FormNotification";
|
this.Name = "FormNotification";
|
||||||
this.ShowInTaskbar = false;
|
this.ShowInTaskbar = false;
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
||||||
|
@@ -1,15 +1,17 @@
|
|||||||
using System.Windows.Forms;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
using CefSharp;
|
using CefSharp;
|
||||||
using CefSharp.WinForms;
|
using CefSharp.WinForms;
|
||||||
using System.Drawing;
|
using TweetDck.Configuration;
|
||||||
using System;
|
using TweetDck.Core.Handling;
|
||||||
using System.Collections.Generic;
|
using TweetDck.Resources;
|
||||||
using TweetDick.Core.Handling;
|
|
||||||
using TweetDick.Configuration;
|
|
||||||
using TweetDick.Resources;
|
|
||||||
|
|
||||||
namespace TweetDick.Core{
|
namespace TweetDck.Core{
|
||||||
sealed partial class FormNotification : Form{
|
sealed partial class FormNotification : Form{
|
||||||
|
public Func<bool> CanMoveWindow = () => true;
|
||||||
|
|
||||||
private readonly Form owner;
|
private readonly Form owner;
|
||||||
private readonly ChromiumWebBrowser browser;
|
private readonly ChromiumWebBrowser browser;
|
||||||
|
|
||||||
@@ -31,7 +33,7 @@ namespace TweetDick.Core{
|
|||||||
|
|
||||||
notificationJS = ScriptLoader.LoadResource("notification.js");
|
notificationJS = ScriptLoader.LoadResource("notification.js");
|
||||||
|
|
||||||
browser = new ChromiumWebBrowser("about:blank"){ MenuHandler = new MenuHandlerEmpty() };
|
browser = new ChromiumWebBrowser("about:blank"){ MenuHandler = new ContextMenuNotification() };
|
||||||
browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
||||||
|
|
||||||
if (bridge != null){
|
if (bridge != null){
|
||||||
@@ -39,6 +41,8 @@ namespace TweetDick.Core{
|
|||||||
}
|
}
|
||||||
|
|
||||||
panelBrowser.Controls.Add(browser);
|
panelBrowser.Controls.Add(browser);
|
||||||
|
|
||||||
|
Disposed += (sender, args) => browser.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FormNotification(Form owner, bool autoHide) : this(owner,null,autoHide){}
|
public FormNotification(Form owner, bool autoHide) : this(owner,null,autoHide){}
|
||||||
@@ -49,6 +53,14 @@ namespace TweetDick.Core{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void WndProc(ref Message m){
|
||||||
|
if (m.Msg == 0x0112 && (m.WParam.ToInt32() & 0xFFF0) == 0xF010 && !CanMoveWindow()){ // WM_SYSCOMMAND, SC_MOVE
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.WndProc(ref m);
|
||||||
|
}
|
||||||
|
|
||||||
public void ShowNotification(TweetNotification notification){
|
public void ShowNotification(TweetNotification notification){
|
||||||
MoveToVisibleLocation();
|
MoveToVisibleLocation();
|
||||||
|
|
||||||
@@ -76,7 +88,7 @@ namespace TweetDick.Core{
|
|||||||
|
|
||||||
public void HideNotification(){
|
public void HideNotification(){
|
||||||
browser.LoadHtml("","about:blank");
|
browser.LoadHtml("","about:blank");
|
||||||
Location = new Point(32000,32000);
|
Location = new Point(-32000,-32000);
|
||||||
TopMost = false;
|
TopMost = false;
|
||||||
timerProgress.Stop();
|
timerProgress.Stop();
|
||||||
}
|
}
|
||||||
@@ -99,6 +111,15 @@ namespace TweetDick.Core{
|
|||||||
UserConfig config = Program.UserConfig;
|
UserConfig config = Program.UserConfig;
|
||||||
Screen screen = Screen.FromControl(owner);
|
Screen screen = Screen.FromControl(owner);
|
||||||
|
|
||||||
|
if (config.DisplayNotificationTimer){
|
||||||
|
ClientSize = new Size(ClientSize.Width,122);
|
||||||
|
progressBarTimer.Visible = true;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ClientSize = new Size(ClientSize.Width,118);
|
||||||
|
progressBarTimer.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (config.NotificationDisplay > 0 && config.NotificationDisplay <= Screen.AllScreens.Length){
|
if (config.NotificationDisplay > 0 && config.NotificationDisplay <= Screen.AllScreens.Length){
|
||||||
screen = Screen.AllScreens[config.NotificationDisplay-1];
|
screen = Screen.AllScreens[config.NotificationDisplay-1];
|
||||||
}
|
}
|
||||||
@@ -158,21 +179,5 @@ namespace TweetDick.Core{
|
|||||||
e.Cancel = true;
|
e.Cancel = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MenuHandlerEmpty : IContextMenuHandler{
|
|
||||||
public void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
|
||||||
model.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){}
|
|
||||||
|
|
||||||
public bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
110
Core/Handling/ContextMenuBase.cs
Normal file
110
Core/Handling/ContextMenuBase.cs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Handling{
|
||||||
|
abstract class ContextMenuBase : IContextMenuHandler{
|
||||||
|
private const int MenuOpenUrlInBrowser = 26500;
|
||||||
|
private const int MenuCopyUrl = 26501;
|
||||||
|
private const int MenuOpenImageInBrowser = 26502;
|
||||||
|
private const int MenuSaveImage = 26503;
|
||||||
|
private const int MenuCopyImageUrl = 26504;
|
||||||
|
|
||||||
|
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
||||||
|
RemoveSeparatorIfLast(model);
|
||||||
|
|
||||||
|
if (parameters.TypeFlags.HasFlag(ContextMenuType.Link)){
|
||||||
|
model.AddItem((CefMenuCommand)MenuOpenUrlInBrowser,"Open in browser");
|
||||||
|
model.AddItem((CefMenuCommand)MenuCopyUrl,"Copy link address");
|
||||||
|
model.AddSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents){
|
||||||
|
model.AddItem((CefMenuCommand)MenuOpenImageInBrowser,"Open image in browser");
|
||||||
|
model.AddItem((CefMenuCommand)MenuSaveImage,"Save image as...");
|
||||||
|
model.AddItem((CefMenuCommand)MenuCopyImageUrl,"Copy image URL");
|
||||||
|
model.AddSeparator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
||||||
|
switch((int)commandId){
|
||||||
|
case MenuOpenUrlInBrowser:
|
||||||
|
BrowserUtils.OpenExternalBrowser(parameters.LinkUrl);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MenuCopyUrl:
|
||||||
|
Clipboard.SetText(parameters.UnfilteredLinkUrl,TextDataFormat.Text);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MenuOpenImageInBrowser:
|
||||||
|
BrowserUtils.OpenExternalBrowser(parameters.SourceUrl);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MenuSaveImage:
|
||||||
|
string fileName = GetImageFileName(parameters.SourceUrl);
|
||||||
|
string extension = Path.GetExtension(fileName);
|
||||||
|
string saveTarget;
|
||||||
|
|
||||||
|
using(SaveFileDialog dialog = new SaveFileDialog{
|
||||||
|
AutoUpgradeEnabled = true,
|
||||||
|
OverwritePrompt = true,
|
||||||
|
Title = "Save image",
|
||||||
|
FileName = fileName,
|
||||||
|
Filter = "Image ("+(string.IsNullOrEmpty(extension) ? "unknown" : extension)+")|*.*"
|
||||||
|
}){
|
||||||
|
saveTarget = dialog.ShowDialog() == DialogResult.OK ? dialog.FileName : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveTarget != null){
|
||||||
|
BrowserUtils.DownloadFileAsync(parameters.SourceUrl,saveTarget,ex => {
|
||||||
|
MessageBox.Show("An error occurred while downloading the image: "+ex.Message,Program.BrandName+" Has Failed :(",MessageBoxButtons.OK,MessageBoxIcon.Error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MenuCopyImageUrl:
|
||||||
|
Clipboard.SetText(parameters.SourceUrl,TextDataFormat.Text);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){}
|
||||||
|
|
||||||
|
public virtual bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void RemoveSeparatorIfFirst(IMenuModel model){
|
||||||
|
if (model.Count > 0 && model.GetTypeAt(model.Count-1) == MenuItemType.Separator){
|
||||||
|
model.RemoveAt(model.Count-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void RemoveSeparatorIfLast(IMenuModel model){
|
||||||
|
if (model.Count > 0 && model.GetTypeAt(model.Count-1) == MenuItemType.Separator){
|
||||||
|
model.RemoveAt(model.Count-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetImageFileName(string url){
|
||||||
|
// twimg adds a colon after file extension
|
||||||
|
int dot = url.LastIndexOf('.');
|
||||||
|
|
||||||
|
if (dot != -1){
|
||||||
|
int colon = url.IndexOf(':',dot);
|
||||||
|
|
||||||
|
if (colon != -1){
|
||||||
|
url = url.Substring(0,colon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return file name
|
||||||
|
return BrowserUtils.GetFileNameFromUrl(url) ?? "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,38 +1,41 @@
|
|||||||
using CefSharp;
|
using CefSharp;
|
||||||
|
|
||||||
namespace TweetDick.Core.Handling{
|
namespace TweetDck.Core.Handling{
|
||||||
class ContextMenuHandler : IContextMenuHandler{
|
class ContextMenuBrowser : ContextMenuBase{
|
||||||
private const int MenuSettings = 26500;
|
private const int MenuSettings = 26600;
|
||||||
private const int MenuAbout = 26501;
|
private const int MenuAbout = 26601;
|
||||||
|
|
||||||
private readonly FormBrowser form;
|
private readonly FormBrowser form;
|
||||||
|
|
||||||
public ContextMenuHandler(FormBrowser form){
|
public ContextMenuBrowser(FormBrowser form){
|
||||||
this.form = form;
|
this.form = form;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
||||||
model.Remove(CefMenuCommand.Back);
|
model.Remove(CefMenuCommand.Back);
|
||||||
model.Remove(CefMenuCommand.Forward);
|
model.Remove(CefMenuCommand.Forward);
|
||||||
model.Remove(CefMenuCommand.Print);
|
model.Remove(CefMenuCommand.Print);
|
||||||
model.Remove(CefMenuCommand.ViewSource);
|
model.Remove(CefMenuCommand.ViewSource);
|
||||||
|
|
||||||
if (model.Count > 0 && model.GetTypeAt(model.Count-1) == MenuItemType.Separator){
|
RemoveSeparatorIfFirst(model);
|
||||||
model.RemoveAt(model.Count-1);
|
|
||||||
}
|
base.OnBeforeContextMenu(browserControl,browser,frame,parameters,model);
|
||||||
|
|
||||||
model.AddItem(CefMenuCommand.Reload,"Reload");
|
model.AddItem(CefMenuCommand.Reload,"Reload");
|
||||||
model.AddSeparator();
|
model.AddSeparator();
|
||||||
|
|
||||||
if (TweetNotification.IsReady){
|
if (TweetNotification.IsReady){
|
||||||
model.AddItem((CefMenuCommand)MenuSettings,"Settings");
|
model.AddItem((CefMenuCommand)MenuSettings,"Settings");
|
||||||
model.AddSeparator();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model.AddItem((CefMenuCommand)MenuAbout,"About "+Program.BrandName);
|
model.AddItem((CefMenuCommand)MenuAbout,"About "+Program.BrandName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
||||||
|
if (base.OnContextMenuCommand(browserControl,browser,frame,parameters,commandId,eventFlags)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
switch((int)commandId){
|
switch((int)commandId){
|
||||||
case MenuSettings:
|
case MenuSettings:
|
||||||
form.InvokeSafe(() => {
|
form.InvokeSafe(() => {
|
||||||
@@ -51,11 +54,5 @@ namespace TweetDick.Core.Handling{
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){}
|
|
||||||
|
|
||||||
public bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
16
Core/Handling/ContextMenuNotification.cs
Normal file
16
Core/Handling/ContextMenuNotification.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using CefSharp;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Handling{
|
||||||
|
class ContextMenuNotification : ContextMenuBase{
|
||||||
|
public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
||||||
|
model.Clear();
|
||||||
|
|
||||||
|
base.OnBeforeContextMenu(browserControl,browser,frame,parameters,model);
|
||||||
|
RemoveSeparatorIfLast(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
using System.Diagnostics;
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDick.Core.Handling{
|
namespace TweetDck.Core.Handling{
|
||||||
class TweetDeckBridge{
|
class TweetDeckBridge{
|
||||||
private readonly FormBrowser form;
|
private readonly FormBrowser form;
|
||||||
|
|
||||||
@@ -10,6 +10,24 @@ namespace TweetDick.Core.Handling{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string VersionTag{
|
||||||
|
get{
|
||||||
|
return Program.VersionTag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateCheckEnabled{
|
||||||
|
get{
|
||||||
|
return Program.UserConfig.EnableUpdateCheck;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DismissedVersionTag{
|
||||||
|
get{
|
||||||
|
return Program.UserConfig.DismissedUpdate ?? string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public TweetDeckBridge(FormBrowser form){
|
public TweetDeckBridge(FormBrowser form){
|
||||||
this.form = form;
|
this.form = form;
|
||||||
}
|
}
|
||||||
@@ -38,12 +56,25 @@ namespace TweetDick.Core.Handling{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnUpdateAccepted(string versionTag, string downloadUrl){
|
||||||
|
form.InvokeSafe(() => {
|
||||||
|
form.BeginUpdateProcess(versionTag,downloadUrl);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnUpdateDismissed(string versionTag){
|
||||||
|
form.InvokeSafe(() => {
|
||||||
|
Program.UserConfig.DismissedUpdate = versionTag;
|
||||||
|
Program.UserConfig.Save();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void OpenBrowser(string url){
|
public void OpenBrowser(string url){
|
||||||
Process.Start(url);
|
BrowserUtils.OpenExternalBrowser(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Log(string data){
|
public void Log(string data){
|
||||||
Debug.WriteLine(data);
|
System.Diagnostics.Debug.WriteLine(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace TweetDick.Core.Handling{
|
namespace TweetDck.Core.Handling{
|
||||||
sealed class TweetNotification{
|
sealed class TweetNotification{
|
||||||
private static string FontSizeClass { get; set; }
|
private static string FontSizeClass { get; set; }
|
||||||
private static string HeadTag { get; set; }
|
private static string HeadTag { get; set; }
|
||||||
@@ -17,10 +17,10 @@ namespace TweetDick.Core.Handling{
|
|||||||
StringBuilder build = new StringBuilder();
|
StringBuilder build = new StringBuilder();
|
||||||
build.Append(@"<article><div class='js-stream-item-content item-box js-show-detail'><div class='js-tweet tweet'>");
|
build.Append(@"<article><div class='js-stream-item-content item-box js-show-detail'><div class='js-tweet tweet'>");
|
||||||
build.Append(@"<header class='tweet-header'>");
|
build.Append(@"<header class='tweet-header'>");
|
||||||
build.Append(@"<time class='tweet-timestamp js-timestamp pull-right txt-mute'><a target='_blank' rel='url' href='https://twitter.com/chylexMC' class='txt-small'>0s</a></time>");
|
build.Append(@"<time class='tweet-timestamp js-timestamp pull-right txt-mute'><a target='_blank' rel='url' href='https://twitter.com/chylexmc' class='txt-small'>0s</a></time>");
|
||||||
build.Append(@"<a target='_blank' rel='user' href='https://twitter.com/chylexMC' class='account-link link-complex block'>");
|
build.Append(@"<a target='_blank' rel='user' href='https://twitter.com/chylexmc' class='account-link link-complex block'>");
|
||||||
build.Append(@"<div class='obj-left item-img tweet-img'><img width='48' height='48' alt='chylexMC's avatar' src='https://pbs.twimg.com/profile_images/645532929930608642/J56NBJVY_normal.png' class='tweet-avatar avatar pull-right'></div>");
|
build.Append(@"<div class='obj-left item-img tweet-img'><img width='48' height='48' alt='chylexmc's avatar' src='https://pbs.twimg.com/profile_images/645532929930608642/J56NBJVY_normal.png' class='tweet-avatar avatar pull-right'></div>");
|
||||||
build.Append(@"<div class='nbfc'><span class='account-inline txt-ellipsis'><b class='fullname link-complex-target'>chylex</b> <span class='username txt-mute'>@chylexMC</span></span></div>");
|
build.Append(@"<div class='nbfc'><span class='account-inline txt-ellipsis'><b class='fullname link-complex-target'>chylex</b> <span class='username txt-mute'>@chylexmc</span></span></div>");
|
||||||
build.Append(@"</a>");
|
build.Append(@"</a>");
|
||||||
build.Append(@"</header>");
|
build.Append(@"</header>");
|
||||||
build.Append(@"<div class='tweet-body'><p class='js-tweet-text tweet-text with-linebreaks'>This is an example tweet, which lets you test the location and duration of popup notifications.</p></div>");
|
build.Append(@"<div class='tweet-body'><p class='js-tweet-text tweet-text with-linebreaks'>This is an example tweet, which lets you test the location and duration of popup notifications.</p></div>");
|
||||||
|
7
Core/Other/FormAbout.Designer.cs
generated
7
Core/Other/FormAbout.Designer.cs
generated
@@ -1,4 +1,6 @@
|
|||||||
namespace TweetDick.Core.Other {
|
using TweetDck.Core.Controls;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other {
|
||||||
sealed partial class FormAbout {
|
sealed partial class FormAbout {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -23,7 +25,7 @@
|
|||||||
/// the contents of this method with the code editor.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.labelAbout = new TweetDick.Core.Controls.RichTextLabel();
|
this.labelAbout = new TweetDck.Core.Controls.RichTextLabel();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// labelAbout
|
// labelAbout
|
||||||
@@ -41,6 +43,7 @@
|
|||||||
this.labelAbout.TabIndex = 0;
|
this.labelAbout.TabIndex = 0;
|
||||||
this.labelAbout.TabStop = false;
|
this.labelAbout.TabStop = false;
|
||||||
this.labelAbout.Text = "";
|
this.labelAbout.Text = "";
|
||||||
|
this.labelAbout.Click += new System.EventHandler(this.labelAbout_Click);
|
||||||
//
|
//
|
||||||
// FormAbout
|
// FormAbout
|
||||||
//
|
//
|
||||||
|
@@ -1,20 +1,43 @@
|
|||||||
using System.Text;
|
using System;
|
||||||
|
using System.Text;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDick.Core.Controls;
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDick.Core.Other{
|
namespace TweetDck.Core.Other{
|
||||||
sealed partial class FormAbout : Form{
|
sealed partial class FormAbout : Form{
|
||||||
|
private const string GitHubLink = "https://github.com/chylex/TweetDuck";
|
||||||
|
|
||||||
public FormAbout(){
|
public FormAbout(){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Text = "About "+Program.BrandName;
|
Text = "About "+Program.BrandName+" "+Program.VersionTag;
|
||||||
|
|
||||||
StringBuilder build = new StringBuilder();
|
StringBuilder build = new StringBuilder();
|
||||||
build.Append(@"\fs22").Append(Program.BrandName).Append(@" was created by chylex as a replacement to the discontinued TweetDeck client for Windows, and is released under the MIT license.\par ");
|
build.Append(@"\fs22").Append(Program.BrandName).Append(@" was created by chylex as a replacement to the discontinued TweetDeck client for Windows, and is released under the MIT license.\par ");
|
||||||
build.Append(@"Official Website: ").Append(RichTextLabel.AddLink(Program.Website)).Append(@"\line ");
|
build.Append(@"Official Website: ").Append(RichTextLabel.AddLink(Program.Website)).Append(@"\line ");
|
||||||
build.Append(@"Source Code: ").Append(RichTextLabel.AddLink("https://github.com/chylex/TweetDick"));
|
build.Append(@"Source Code: ").Append(RichTextLabel.AddLink(GitHubLink));
|
||||||
|
|
||||||
labelAbout.Rtf = RichTextLabel.Wrap(build.ToString());
|
labelAbout.Rtf = RichTextLabel.Wrap(build.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void labelAbout_Click(object sender, EventArgs e){ // LinkClicked isn't working so fuck that
|
||||||
|
if (Cursor.Current != Cursors.Hand)return;
|
||||||
|
|
||||||
|
// I don't even give a fuck, someone else PR a proper fix please
|
||||||
|
int index = labelAbout.GetCharIndexFromPosition(((MouseEventArgs)e).Location);
|
||||||
|
|
||||||
|
if (IsClickingOn(index,Program.Website)){
|
||||||
|
BrowserUtils.OpenExternalBrowser(Program.Website);
|
||||||
|
}
|
||||||
|
else if (IsClickingOn(index,GitHubLink)){
|
||||||
|
BrowserUtils.OpenExternalBrowser(GitHubLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsClickingOn(int index, string substringSearch){
|
||||||
|
int substringIndex = labelAbout.Text.IndexOf(substringSearch,StringComparison.Ordinal);
|
||||||
|
return index >= substringIndex && index <= substringIndex+substringSearch.Length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
Core/Other/FormBackgroundWork.Designer.cs
generated
4
Core/Other/FormBackgroundWork.Designer.cs
generated
@@ -1,6 +1,6 @@
|
|||||||
using TweetDick.Core.Controls;
|
using TweetDck.Core.Controls;
|
||||||
|
|
||||||
namespace TweetDick.Core.Other {
|
namespace TweetDck.Core.Other {
|
||||||
partial class FormBackgroundWork {
|
partial class FormBackgroundWork {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDick.Core.Controls;
|
using TweetDck.Core.Controls;
|
||||||
|
|
||||||
namespace TweetDick.Core.Other{
|
namespace TweetDck.Core.Other{
|
||||||
partial class FormBackgroundWork : Form{
|
partial class FormBackgroundWork : Form{
|
||||||
public FormBackgroundWork(){
|
public FormBackgroundWork(){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
126
Core/Other/FormSettings.Designer.cs
generated
126
Core/Other/FormSettings.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDick.Core.Other {
|
namespace TweetDck.Core.Other {
|
||||||
sealed partial class FormSettings {
|
sealed partial class FormSettings {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
/// the contents of this method with the code editor.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormSettings));
|
|
||||||
this.groupNotificationLocation = new System.Windows.Forms.GroupBox();
|
this.groupNotificationLocation = new System.Windows.Forms.GroupBox();
|
||||||
this.labelDisplay = new System.Windows.Forms.Label();
|
this.labelDisplay = new System.Windows.Forms.Label();
|
||||||
this.comboBoxDisplay = new System.Windows.Forms.ComboBox();
|
this.comboBoxDisplay = new System.Windows.Forms.ComboBox();
|
||||||
@@ -34,16 +33,23 @@
|
|||||||
this.radioLocBL = new System.Windows.Forms.RadioButton();
|
this.radioLocBL = new System.Windows.Forms.RadioButton();
|
||||||
this.radioLocTR = new System.Windows.Forms.RadioButton();
|
this.radioLocTR = new System.Windows.Forms.RadioButton();
|
||||||
this.radioLocTL = new System.Windows.Forms.RadioButton();
|
this.radioLocTL = new System.Windows.Forms.RadioButton();
|
||||||
|
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
|
||||||
|
this.tableColumn2Panel = new System.Windows.Forms.Panel();
|
||||||
|
this.groupUserInterface = new System.Windows.Forms.GroupBox();
|
||||||
|
this.checkNotificationTimer = new System.Windows.Forms.CheckBox();
|
||||||
|
this.checkMinimizeTray = new System.Windows.Forms.CheckBox();
|
||||||
this.groupNotificationDuration = new System.Windows.Forms.GroupBox();
|
this.groupNotificationDuration = new System.Windows.Forms.GroupBox();
|
||||||
this.radioDurVeryLong = new System.Windows.Forms.RadioButton();
|
this.radioDurVeryLong = new System.Windows.Forms.RadioButton();
|
||||||
this.radioDurLong = new System.Windows.Forms.RadioButton();
|
this.radioDurLong = new System.Windows.Forms.RadioButton();
|
||||||
this.radioDurMedium = new System.Windows.Forms.RadioButton();
|
this.radioDurMedium = new System.Windows.Forms.RadioButton();
|
||||||
this.radioDurShort = new System.Windows.Forms.RadioButton();
|
this.radioDurShort = new System.Windows.Forms.RadioButton();
|
||||||
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
|
this.checkUpdateNotifications = new System.Windows.Forms.CheckBox();
|
||||||
this.groupNotificationLocation.SuspendLayout();
|
this.groupNotificationLocation.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).BeginInit();
|
||||||
this.groupNotificationDuration.SuspendLayout();
|
|
||||||
this.tableLayout.SuspendLayout();
|
this.tableLayout.SuspendLayout();
|
||||||
|
this.tableColumn2Panel.SuspendLayout();
|
||||||
|
this.groupUserInterface.SuspendLayout();
|
||||||
|
this.groupNotificationDuration.SuspendLayout();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// groupNotificationLocation
|
// groupNotificationLocation
|
||||||
@@ -181,6 +187,70 @@
|
|||||||
this.radioLocTL.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
this.radioLocTL.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
||||||
this.radioLocTL.Click += new System.EventHandler(this.radioLoc_Click);
|
this.radioLocTL.Click += new System.EventHandler(this.radioLoc_Click);
|
||||||
//
|
//
|
||||||
|
// tableLayout
|
||||||
|
//
|
||||||
|
this.tableLayout.ColumnCount = 2;
|
||||||
|
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||||
|
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||||
|
this.tableLayout.Controls.Add(this.tableColumn2Panel, 1, 0);
|
||||||
|
this.tableLayout.Controls.Add(this.groupNotificationLocation, 0, 0);
|
||||||
|
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.tableLayout.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.FixedSize;
|
||||||
|
this.tableLayout.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.tableLayout.Name = "tableLayout";
|
||||||
|
this.tableLayout.Padding = new System.Windows.Forms.Padding(3);
|
||||||
|
this.tableLayout.RowCount = 1;
|
||||||
|
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
|
this.tableLayout.Size = new System.Drawing.Size(384, 282);
|
||||||
|
this.tableLayout.TabIndex = 2;
|
||||||
|
//
|
||||||
|
// tableColumn2Panel
|
||||||
|
//
|
||||||
|
this.tableColumn2Panel.Controls.Add(this.groupUserInterface);
|
||||||
|
this.tableColumn2Panel.Controls.Add(this.groupNotificationDuration);
|
||||||
|
this.tableColumn2Panel.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.tableColumn2Panel.Location = new System.Drawing.Point(192, 3);
|
||||||
|
this.tableColumn2Panel.Margin = new System.Windows.Forms.Padding(0);
|
||||||
|
this.tableColumn2Panel.Name = "tableColumn2Panel";
|
||||||
|
this.tableColumn2Panel.Size = new System.Drawing.Size(189, 276);
|
||||||
|
this.tableColumn2Panel.TabIndex = 3;
|
||||||
|
//
|
||||||
|
// groupUserInterface
|
||||||
|
//
|
||||||
|
this.groupUserInterface.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.groupUserInterface.Controls.Add(this.checkUpdateNotifications);
|
||||||
|
this.groupUserInterface.Controls.Add(this.checkNotificationTimer);
|
||||||
|
this.groupUserInterface.Controls.Add(this.checkMinimizeTray);
|
||||||
|
this.groupUserInterface.Location = new System.Drawing.Point(3, 128);
|
||||||
|
this.groupUserInterface.Name = "groupUserInterface";
|
||||||
|
this.groupUserInterface.Size = new System.Drawing.Size(183, 145);
|
||||||
|
this.groupUserInterface.TabIndex = 3;
|
||||||
|
this.groupUserInterface.TabStop = false;
|
||||||
|
this.groupUserInterface.Text = "User Interface";
|
||||||
|
//
|
||||||
|
// checkNotificationTimer
|
||||||
|
//
|
||||||
|
this.checkNotificationTimer.AutoSize = true;
|
||||||
|
this.checkNotificationTimer.Location = new System.Drawing.Point(6, 43);
|
||||||
|
this.checkNotificationTimer.Name = "checkNotificationTimer";
|
||||||
|
this.checkNotificationTimer.Size = new System.Drawing.Size(145, 17);
|
||||||
|
this.checkNotificationTimer.TabIndex = 4;
|
||||||
|
this.checkNotificationTimer.Text = "Display Notification Timer";
|
||||||
|
this.checkNotificationTimer.UseVisualStyleBackColor = true;
|
||||||
|
this.checkNotificationTimer.CheckedChanged += new System.EventHandler(this.checkNotificationTimer_CheckedChanged);
|
||||||
|
//
|
||||||
|
// checkMinimizeTray
|
||||||
|
//
|
||||||
|
this.checkMinimizeTray.AutoSize = true;
|
||||||
|
this.checkMinimizeTray.Location = new System.Drawing.Point(6, 20);
|
||||||
|
this.checkMinimizeTray.Name = "checkMinimizeTray";
|
||||||
|
this.checkMinimizeTray.Size = new System.Drawing.Size(102, 17);
|
||||||
|
this.checkMinimizeTray.TabIndex = 0;
|
||||||
|
this.checkMinimizeTray.Text = "Minimize to Tray";
|
||||||
|
this.checkMinimizeTray.UseVisualStyleBackColor = true;
|
||||||
|
this.checkMinimizeTray.CheckedChanged += new System.EventHandler(this.checkMinimizeTray_CheckedChanged);
|
||||||
|
//
|
||||||
// groupNotificationDuration
|
// groupNotificationDuration
|
||||||
//
|
//
|
||||||
this.groupNotificationDuration.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
this.groupNotificationDuration.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
@@ -189,10 +259,10 @@
|
|||||||
this.groupNotificationDuration.Controls.Add(this.radioDurLong);
|
this.groupNotificationDuration.Controls.Add(this.radioDurLong);
|
||||||
this.groupNotificationDuration.Controls.Add(this.radioDurMedium);
|
this.groupNotificationDuration.Controls.Add(this.radioDurMedium);
|
||||||
this.groupNotificationDuration.Controls.Add(this.radioDurShort);
|
this.groupNotificationDuration.Controls.Add(this.radioDurShort);
|
||||||
this.groupNotificationDuration.Location = new System.Drawing.Point(195, 6);
|
this.groupNotificationDuration.Location = new System.Drawing.Point(3, 3);
|
||||||
this.groupNotificationDuration.Name = "groupNotificationDuration";
|
this.groupNotificationDuration.Name = "groupNotificationDuration";
|
||||||
this.groupNotificationDuration.Size = new System.Drawing.Size(183, 118);
|
this.groupNotificationDuration.Size = new System.Drawing.Size(183, 119);
|
||||||
this.groupNotificationDuration.TabIndex = 1;
|
this.groupNotificationDuration.TabIndex = 2;
|
||||||
this.groupNotificationDuration.TabStop = false;
|
this.groupNotificationDuration.TabStop = false;
|
||||||
this.groupNotificationDuration.Text = "Notification Duration";
|
this.groupNotificationDuration.Text = "Notification Duration";
|
||||||
//
|
//
|
||||||
@@ -248,22 +318,16 @@
|
|||||||
this.radioDurShort.CheckedChanged += new System.EventHandler(this.radioDur_CheckedChanged);
|
this.radioDurShort.CheckedChanged += new System.EventHandler(this.radioDur_CheckedChanged);
|
||||||
this.radioDurShort.Click += new System.EventHandler(this.radioDur_Click);
|
this.radioDurShort.Click += new System.EventHandler(this.radioDur_Click);
|
||||||
//
|
//
|
||||||
// tableLayout
|
// checkUpdateNotifications
|
||||||
//
|
//
|
||||||
this.tableLayout.ColumnCount = 2;
|
this.checkUpdateNotifications.AutoSize = true;
|
||||||
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 67);
|
||||||
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
this.checkUpdateNotifications.Name = "checkUpdateNotifications";
|
||||||
this.tableLayout.Controls.Add(this.groupNotificationLocation, 0, 0);
|
this.checkUpdateNotifications.Size = new System.Drawing.Size(122, 17);
|
||||||
this.tableLayout.Controls.Add(this.groupNotificationDuration, 1, 0);
|
this.checkUpdateNotifications.TabIndex = 5;
|
||||||
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
|
this.checkUpdateNotifications.Text = "Update Notifications";
|
||||||
this.tableLayout.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.FixedSize;
|
this.checkUpdateNotifications.UseVisualStyleBackColor = true;
|
||||||
this.tableLayout.Location = new System.Drawing.Point(0, 0);
|
this.checkUpdateNotifications.CheckedChanged += new System.EventHandler(this.checkUpdateNotifications_CheckedChanged);
|
||||||
this.tableLayout.Name = "tableLayout";
|
|
||||||
this.tableLayout.Padding = new System.Windows.Forms.Padding(3);
|
|
||||||
this.tableLayout.RowCount = 1;
|
|
||||||
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
|
||||||
this.tableLayout.Size = new System.Drawing.Size(384, 282);
|
|
||||||
this.tableLayout.TabIndex = 2;
|
|
||||||
//
|
//
|
||||||
// FormSettings
|
// FormSettings
|
||||||
//
|
//
|
||||||
@@ -272,7 +336,7 @@
|
|||||||
this.ClientSize = new System.Drawing.Size(384, 282);
|
this.ClientSize = new System.Drawing.Size(384, 282);
|
||||||
this.Controls.Add(this.tableLayout);
|
this.Controls.Add(this.tableLayout);
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
this.Icon = TweetDick.Properties.Resources.icon;
|
this.Icon = global::TweetDck.Properties.Resources.icon;
|
||||||
this.MaximizeBox = false;
|
this.MaximizeBox = false;
|
||||||
this.MinimizeBox = false;
|
this.MinimizeBox = false;
|
||||||
this.Name = "FormSettings";
|
this.Name = "FormSettings";
|
||||||
@@ -281,9 +345,12 @@
|
|||||||
this.groupNotificationLocation.ResumeLayout(false);
|
this.groupNotificationLocation.ResumeLayout(false);
|
||||||
this.groupNotificationLocation.PerformLayout();
|
this.groupNotificationLocation.PerformLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).EndInit();
|
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).EndInit();
|
||||||
|
this.tableLayout.ResumeLayout(false);
|
||||||
|
this.tableColumn2Panel.ResumeLayout(false);
|
||||||
|
this.groupUserInterface.ResumeLayout(false);
|
||||||
|
this.groupUserInterface.PerformLayout();
|
||||||
this.groupNotificationDuration.ResumeLayout(false);
|
this.groupNotificationDuration.ResumeLayout(false);
|
||||||
this.groupNotificationDuration.PerformLayout();
|
this.groupNotificationDuration.PerformLayout();
|
||||||
this.tableLayout.ResumeLayout(false);
|
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -298,13 +365,18 @@
|
|||||||
private System.Windows.Forms.RadioButton radioLocTL;
|
private System.Windows.Forms.RadioButton radioLocTL;
|
||||||
private System.Windows.Forms.Label labelEdgeDistance;
|
private System.Windows.Forms.Label labelEdgeDistance;
|
||||||
private System.Windows.Forms.TrackBar trackBarEdgeDistance;
|
private System.Windows.Forms.TrackBar trackBarEdgeDistance;
|
||||||
|
private System.Windows.Forms.Label labelDisplay;
|
||||||
|
private System.Windows.Forms.ComboBox comboBoxDisplay;
|
||||||
|
private System.Windows.Forms.TableLayoutPanel tableLayout;
|
||||||
|
private System.Windows.Forms.Panel tableColumn2Panel;
|
||||||
|
private System.Windows.Forms.GroupBox groupUserInterface;
|
||||||
private System.Windows.Forms.GroupBox groupNotificationDuration;
|
private System.Windows.Forms.GroupBox groupNotificationDuration;
|
||||||
private System.Windows.Forms.RadioButton radioDurVeryLong;
|
private System.Windows.Forms.RadioButton radioDurVeryLong;
|
||||||
private System.Windows.Forms.RadioButton radioDurLong;
|
private System.Windows.Forms.RadioButton radioDurLong;
|
||||||
private System.Windows.Forms.RadioButton radioDurMedium;
|
private System.Windows.Forms.RadioButton radioDurMedium;
|
||||||
private System.Windows.Forms.RadioButton radioDurShort;
|
private System.Windows.Forms.RadioButton radioDurShort;
|
||||||
private System.Windows.Forms.Label labelDisplay;
|
private System.Windows.Forms.CheckBox checkMinimizeTray;
|
||||||
private System.Windows.Forms.ComboBox comboBoxDisplay;
|
private System.Windows.Forms.CheckBox checkNotificationTimer;
|
||||||
private System.Windows.Forms.TableLayoutPanel tableLayout;
|
private System.Windows.Forms.CheckBox checkUpdateNotifications;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,9 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDick.Configuration;
|
using TweetDck.Configuration;
|
||||||
using TweetDick.Core.Handling;
|
using TweetDck.Core.Handling;
|
||||||
|
|
||||||
namespace TweetDick.Core.Other{
|
namespace TweetDck.Core.Other{
|
||||||
sealed partial class FormSettings : Form{
|
sealed partial class FormSettings : Form{
|
||||||
private static UserConfig Config{
|
private static UserConfig Config{
|
||||||
get{
|
get{
|
||||||
@@ -20,8 +20,7 @@ namespace TweetDick.Core.Other{
|
|||||||
|
|
||||||
Text = Program.BrandName+" Settings";
|
Text = Program.BrandName+" Settings";
|
||||||
|
|
||||||
notification = new FormNotification(browserForm,false);
|
notification = new FormNotification(browserForm,false){ CanMoveWindow = () => radioLocCustom.Checked };
|
||||||
notification.Show(this);
|
|
||||||
|
|
||||||
notification.Move += (sender, args) => {
|
notification.Move += (sender, args) => {
|
||||||
if (radioLocCustom.Checked){
|
if (radioLocCustom.Checked){
|
||||||
@@ -29,6 +28,8 @@ namespace TweetDick.Core.Other{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
notification.Show(this);
|
||||||
|
|
||||||
switch(Config.NotificationPosition){
|
switch(Config.NotificationPosition){
|
||||||
case TweetNotification.Position.TopLeft: radioLocTL.Checked = true; break;
|
case TweetNotification.Position.TopLeft: radioLocTL.Checked = true; break;
|
||||||
case TweetNotification.Position.TopRight: radioLocTR.Checked = true; break;
|
case TweetNotification.Position.TopRight: radioLocTR.Checked = true; break;
|
||||||
@@ -53,6 +54,9 @@ namespace TweetDick.Core.Other{
|
|||||||
comboBoxDisplay.SelectedIndex = Math.Min(comboBoxDisplay.Items.Count-1,Config.NotificationDisplay);
|
comboBoxDisplay.SelectedIndex = Math.Min(comboBoxDisplay.Items.Count-1,Config.NotificationDisplay);
|
||||||
|
|
||||||
trackBarEdgeDistance.Value = Config.NotificationEdgeDistance;
|
trackBarEdgeDistance.Value = Config.NotificationEdgeDistance;
|
||||||
|
checkMinimizeTray.Checked = Config.MinimizeToTray;
|
||||||
|
checkNotificationTimer.Checked = Config.DisplayNotificationTimer;
|
||||||
|
checkUpdateNotifications.Checked = Config.EnableUpdateCheck;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FormSettings_FormClosing(object sender, FormClosingEventArgs e){
|
private void FormSettings_FormClosing(object sender, FormClosingEventArgs e){
|
||||||
@@ -114,5 +118,24 @@ namespace TweetDick.Core.Other{
|
|||||||
|
|
||||||
notification.ShowNotificationForSettings(true);
|
notification.ShowNotificationForSettings(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkMinimizeTray_CheckedChanged(object sender, EventArgs e){
|
||||||
|
if (!isLoaded)return;
|
||||||
|
|
||||||
|
Config.MinimizeToTray = checkMinimizeTray.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkNotificationTimer_CheckedChanged(object sender, EventArgs e){
|
||||||
|
if (!isLoaded)return;
|
||||||
|
|
||||||
|
Config.DisplayNotificationTimer = checkNotificationTimer.Checked;
|
||||||
|
notification.ShowNotificationForSettings(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkUpdateNotifications_CheckedChanged(object sender, EventArgs e){
|
||||||
|
if (!isLoaded)return;
|
||||||
|
|
||||||
|
Config.EnableUpdateCheck = checkUpdateNotifications.Checked;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
103
Core/Other/FormUpdateDownload.Designer.cs
generated
Normal file
103
Core/Other/FormUpdateDownload.Designer.cs
generated
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
namespace TweetDck.Core.Other {
|
||||||
|
partial class FormUpdateDownload {
|
||||||
|
/// <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.progressDownload = new System.Windows.Forms.ProgressBar();
|
||||||
|
this.btnCancel = new System.Windows.Forms.Button();
|
||||||
|
this.labelDescription = new System.Windows.Forms.Label();
|
||||||
|
this.labelStatus = new System.Windows.Forms.Label();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// progressDownload
|
||||||
|
//
|
||||||
|
this.progressDownload.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.progressDownload.Location = new System.Drawing.Point(12, 32);
|
||||||
|
this.progressDownload.MarqueeAnimationSpeed = 40;
|
||||||
|
this.progressDownload.Maximum = 1000;
|
||||||
|
this.progressDownload.Name = "progressDownload";
|
||||||
|
this.progressDownload.Size = new System.Drawing.Size(361, 23);
|
||||||
|
this.progressDownload.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
|
||||||
|
this.progressDownload.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// btnCancel
|
||||||
|
//
|
||||||
|
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnCancel.AutoSize = true;
|
||||||
|
this.btnCancel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||||
|
this.btnCancel.Location = new System.Drawing.Point(317, 61);
|
||||||
|
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);
|
||||||
|
this.btnCancel.TabIndex = 1;
|
||||||
|
this.btnCancel.Text = "Cancel";
|
||||||
|
this.btnCancel.UseVisualStyleBackColor = true;
|
||||||
|
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||||
|
//
|
||||||
|
// labelDescription
|
||||||
|
//
|
||||||
|
this.labelDescription.AutoSize = true;
|
||||||
|
this.labelDescription.Location = new System.Drawing.Point(9, 13);
|
||||||
|
this.labelDescription.Margin = new System.Windows.Forms.Padding(3, 0, 3, 3);
|
||||||
|
this.labelDescription.Name = "labelDescription";
|
||||||
|
this.labelDescription.Size = new System.Drawing.Size(0, 13);
|
||||||
|
this.labelDescription.TabIndex = 2;
|
||||||
|
//
|
||||||
|
// labelStatus
|
||||||
|
//
|
||||||
|
this.labelStatus.AutoSize = true;
|
||||||
|
this.labelStatus.Location = new System.Drawing.Point(9, 62);
|
||||||
|
this.labelStatus.Name = "labelStatus";
|
||||||
|
this.labelStatus.Size = new System.Drawing.Size(0, 13);
|
||||||
|
this.labelStatus.TabIndex = 3;
|
||||||
|
//
|
||||||
|
// FormUpdateDownload
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(385, 96);
|
||||||
|
this.Controls.Add(this.labelStatus);
|
||||||
|
this.Controls.Add(this.labelDescription);
|
||||||
|
this.Controls.Add(this.btnCancel);
|
||||||
|
this.Controls.Add(this.progressDownload);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
|
this.Icon = global::TweetDck.Properties.Resources.icon;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.Name = "FormUpdateDownload";
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
||||||
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormUpdateDownload_FormClosing);
|
||||||
|
this.Shown += new System.EventHandler(this.FormUpdateDownload_Shown);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.ProgressBar progressDownload;
|
||||||
|
private System.Windows.Forms.Button btnCancel;
|
||||||
|
private System.Windows.Forms.Label labelDescription;
|
||||||
|
private System.Windows.Forms.Label labelStatus;
|
||||||
|
}
|
||||||
|
}
|
108
Core/Other/FormUpdateDownload.cs
Normal file
108
Core/Other/FormUpdateDownload.cs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDck.Core.Controls;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Other{
|
||||||
|
sealed partial class FormUpdateDownload : Form{
|
||||||
|
public string InstallerPath{
|
||||||
|
get{
|
||||||
|
return Path.Combine(Path.GetTempPath(),updateInfo.FileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Status{
|
||||||
|
Waiting, Failed, Cancelled, Manual, Succeeded
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status UpdateStatus { get; private set; }
|
||||||
|
|
||||||
|
private readonly WebClient webClient;
|
||||||
|
private readonly UpdateInfo updateInfo;
|
||||||
|
|
||||||
|
public FormUpdateDownload(UpdateInfo info){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.webClient = new WebClient{ Proxy = null };
|
||||||
|
this.webClient.Headers[HttpRequestHeader.UserAgent] = BrowserUtils.HeaderUserAgent;
|
||||||
|
|
||||||
|
this.updateInfo = info;
|
||||||
|
this.UpdateStatus = Status.Waiting;
|
||||||
|
|
||||||
|
Disposed += (sender, args) => webClient.Dispose();
|
||||||
|
|
||||||
|
webClient.DownloadProgressChanged += webClient_DownloadProgressChanged;
|
||||||
|
webClient.DownloadFileCompleted += webClient_DownloadFileCompleted;
|
||||||
|
|
||||||
|
Text = "Updating "+Program.BrandName;
|
||||||
|
labelDescription.Text = "Downloading version "+info.VersionTag+"...";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FormUpdateDownload_Shown(object sender, EventArgs e){
|
||||||
|
webClient.DownloadFileAsync(new Uri(updateInfo.DownloadUrl),InstallerPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCancel_Click(object sender, EventArgs e){
|
||||||
|
webClient.CancelAsync();
|
||||||
|
btnCancel.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FormUpdateDownload_FormClosing(object sender, FormClosingEventArgs e){
|
||||||
|
if (UpdateStatus == Status.Waiting){
|
||||||
|
e.Cancel = true;
|
||||||
|
webClient.CancelAsync();
|
||||||
|
UpdateStatus = e.CloseReason == CloseReason.UserClosing ? Status.Cancelled : Status.Manual; // manual will exit the app
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e){
|
||||||
|
this.InvokeSafe(() => {
|
||||||
|
if (e.TotalBytesToReceive == -1){
|
||||||
|
if (progressDownload.Style != ProgressBarStyle.Marquee){
|
||||||
|
progressDownload.Style = ProgressBarStyle.Continuous;
|
||||||
|
progressDownload.SetValueInstant(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
labelStatus.Text = (e.BytesReceived/(1024.0*1024.0)).ToString("0.0")+" MB";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (progressDownload.Style != ProgressBarStyle.Continuous){
|
||||||
|
progressDownload.Style = ProgressBarStyle.Continuous;
|
||||||
|
}
|
||||||
|
|
||||||
|
progressDownload.SetValueInstant(e.ProgressPercentage*10);
|
||||||
|
labelStatus.Text = (e.BytesReceived/(1024.0*1024.0)).ToString("0.0")+" / "+(e.TotalBytesToReceive/(1024.0*1024.0)).ToString("0.0")+" MB";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e){
|
||||||
|
this.InvokeSafe(() => {
|
||||||
|
if (e.Cancelled){
|
||||||
|
if (UpdateStatus == Status.Waiting){
|
||||||
|
UpdateStatus = Status.Cancelled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (e.Error != null){
|
||||||
|
Program.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);
|
||||||
|
UpdateStatus = Status.Manual;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
UpdateStatus = Status.Failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
UpdateStatus = Status.Succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
Close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
Core/Utils/BrowserUtils.cs
Normal file
51
Core/Utils/BrowserUtils.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
static class BrowserUtils{
|
||||||
|
public static string HeaderAcceptLanguage{
|
||||||
|
get{
|
||||||
|
string culture = CultureInfo.CurrentCulture.Name;
|
||||||
|
|
||||||
|
if (culture == "en"){
|
||||||
|
return "en-us,en";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return culture.ToLowerInvariant()+",en;q=0.9";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string HeaderUserAgent{
|
||||||
|
get{
|
||||||
|
return Program.BrandName+" "+Application.ProductVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OpenExternalBrowser(string url){ // TODO implement mailto
|
||||||
|
Process.Start(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetFileNameFromUrl(string url){
|
||||||
|
string file = Path.GetFileName(new Uri(url).AbsolutePath);
|
||||||
|
return string.IsNullOrEmpty(file) ? null : file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DownloadFileAsync(string url, string target, Action<Exception> onFailure){
|
||||||
|
WebClient client = new WebClient{ Proxy = null };
|
||||||
|
client.Headers[HttpRequestHeader.UserAgent] = HeaderUserAgent;
|
||||||
|
|
||||||
|
client.DownloadFileCompleted += (sender, args) => {
|
||||||
|
if (args.Error != null){
|
||||||
|
onFailure(args.Error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
client.DownloadFileAsync(new Uri(url),target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
Core/Utils/UpdateInfo.cs
Normal file
17
Core/Utils/UpdateInfo.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace TweetDck.Core.Utils{
|
||||||
|
class UpdateInfo{
|
||||||
|
public readonly string VersionTag;
|
||||||
|
public readonly string DownloadUrl;
|
||||||
|
|
||||||
|
public string FileName{
|
||||||
|
get{
|
||||||
|
return BrowserUtils.GetFileNameFromUrl(DownloadUrl) ?? Program.BrandName+".Update.exe";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdateInfo(string versionTag, string downloadUrl){
|
||||||
|
this.VersionTag = versionTag;
|
||||||
|
this.DownloadUrl = downloadUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
Migration/FormMigrationQuestion.Designer.cs
generated
4
Migration/FormMigrationQuestion.Designer.cs
generated
@@ -1,6 +1,6 @@
|
|||||||
using TweetDick.Core.Controls;
|
using TweetDck.Core.Controls;
|
||||||
|
|
||||||
namespace TweetDick.Migration {
|
namespace TweetDck.Migration {
|
||||||
partial class FormMigrationQuestion {
|
partial class FormMigrationQuestion {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDick.Core.Controls;
|
using TweetDck.Core.Controls;
|
||||||
|
|
||||||
namespace TweetDick.Migration{
|
namespace TweetDck.Migration{
|
||||||
partial class FormMigrationQuestion : Form{
|
partial class FormMigrationQuestion : Form{
|
||||||
public MigrationDecision Decision { get; private set; }
|
public MigrationDecision Decision { get; private set; }
|
||||||
|
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using Shell32;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Shell32;
|
||||||
|
|
||||||
namespace TweetDick.Migration.Helpers{
|
namespace TweetDck.Migration.Helpers{
|
||||||
sealed class LnkEditor{
|
sealed class LnkEditor{
|
||||||
private readonly ShellLinkObject obj;
|
private readonly ShellLinkObject obj;
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace TweetDick.Migration.Helpers{
|
namespace TweetDck.Migration.Helpers{
|
||||||
static class ProgramProcessSearch{
|
static class ProgramProcessSearch{
|
||||||
public static Process FindProcessWithWindowByName(string name){
|
public static Process FindProcessWithWindowByName(string name){
|
||||||
try{
|
try{
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
|
||||||
namespace TweetDick.Migration.Helpers{
|
namespace TweetDck.Migration.Helpers{
|
||||||
static class ProgramRegistrySearch{
|
static class ProgramRegistrySearch{
|
||||||
public static string FindByDisplayName(string displayName){
|
public static string FindByDisplayName(string displayName){
|
||||||
Predicate<RegistryKey> predicate = key => displayName.Equals(key.GetValue("DisplayName") as string,StringComparison.OrdinalIgnoreCase);
|
Predicate<RegistryKey> predicate = key => displayName.Equals(key.GetValue("DisplayName") as string,StringComparison.OrdinalIgnoreCase);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDick.Migration{
|
namespace TweetDck.Migration{
|
||||||
enum MigrationDecision{
|
enum MigrationDecision{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copies the important files and then deletes the TweetDeck folder.
|
/// Copies the important files and then deletes the TweetDeck folder.
|
||||||
|
@@ -1,21 +1,26 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDick.Core.Other;
|
using Microsoft.Win32;
|
||||||
using TweetDick.Migration.Helpers;
|
using TweetDck.Core.Other;
|
||||||
|
using TweetDck.Migration.Helpers;
|
||||||
|
|
||||||
namespace TweetDick.Migration{
|
namespace TweetDck.Migration{
|
||||||
static class MigrationManager{
|
static class MigrationManager{
|
||||||
private static readonly string TweetDeckPathParent = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),"twitter");
|
private static readonly string TweetDeckPathParent = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),"twitter");
|
||||||
private static readonly string TweetDeckPath = Path.Combine(TweetDeckPathParent,"TweetDeck");
|
private static readonly string TweetDeckPath = Path.Combine(TweetDeckPathParent,"TweetDeck");
|
||||||
|
|
||||||
public static void Run(){
|
public static void Run(){
|
||||||
if (!Program.UserConfig.IgnoreMigration && Directory.Exists(TweetDeckPath)){
|
if (!Program.UserConfig.IgnoreMigration && Directory.Exists(TweetDeckPath)){
|
||||||
FormMigrationQuestion formQuestion = new FormMigrationQuestion();
|
MigrationDecision decision;
|
||||||
MigrationDecision decision = formQuestion.ShowDialog() == DialogResult.OK ? formQuestion.Decision : MigrationDecision.AskLater;
|
|
||||||
|
using(FormMigrationQuestion formQuestion = new FormMigrationQuestion()){
|
||||||
|
decision = formQuestion.ShowDialog() == DialogResult.OK ? formQuestion.Decision : MigrationDecision.AskLater;
|
||||||
|
}
|
||||||
|
|
||||||
switch(decision){
|
switch(decision){
|
||||||
case MigrationDecision.MigratePurge:
|
case MigrationDecision.MigratePurge:
|
||||||
@@ -25,12 +30,13 @@ namespace TweetDick.Migration{
|
|||||||
|
|
||||||
formWait.ShowWorkDialog(() => {
|
formWait.ShowWorkDialog(() => {
|
||||||
if (!BeginMigration(decision,ex => formWait.Invoke(new Action(() => {
|
if (!BeginMigration(decision,ex => formWait.Invoke(new Action(() => {
|
||||||
if (ex != null){
|
|
||||||
MessageBox.Show(ex.ToString()); // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
formWait.Close();
|
formWait.Close();
|
||||||
|
|
||||||
|
if (ex != null){
|
||||||
|
Program.HandleException("An unexpected exception has occurred during the migration process.",ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Program.UserConfig.IgnoreMigration = true;
|
Program.UserConfig.IgnoreMigration = true;
|
||||||
Program.UserConfig.Save();
|
Program.UserConfig.Save();
|
||||||
})))){
|
})))){
|
||||||
@@ -46,6 +52,17 @@ namespace TweetDick.Migration{
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!Program.UserConfig.IgnoreUninstallCheck){
|
||||||
|
string guid = ProgramRegistrySearch.FindByDisplayName("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);
|
||||||
|
CleanupTweetDeck();
|
||||||
|
}
|
||||||
|
|
||||||
|
Program.UserConfig.IgnoreUninstallCheck = true;
|
||||||
|
Program.UserConfig.Save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool BeginMigration(MigrationDecision decision, Action<Exception> onFinished){
|
private static bool BeginMigration(MigrationDecision decision, Action<Exception> onFinished){
|
||||||
@@ -98,14 +115,10 @@ namespace TweetDick.Migration{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (decision == MigrationDecision.MigratePurge){
|
if (decision == MigrationDecision.MigratePurge){
|
||||||
// update the lnk files wherever possible (desktop icons, pinned taskbar)
|
// update the lnk files wherever possible (desktop icons, pinned taskbar, start menu)
|
||||||
string[] locations = {
|
foreach(string location in GetLnkDirectories()){
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
|
if (location == string.Empty)continue;
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory),
|
|
||||||
Environment.ExpandEnvironmentVariables(@"%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar")
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach(string location in locations){
|
|
||||||
string linkFile = Path.Combine(location,"TweetDeck.lnk");
|
string linkFile = Path.Combine(location,"TweetDeck.lnk");
|
||||||
|
|
||||||
if (File.Exists(linkFile)){
|
if (File.Exists(linkFile)){
|
||||||
@@ -115,7 +128,18 @@ namespace TweetDick.Migration{
|
|||||||
lnk.SetComment(Program.BrandName); // TODO add a tagline
|
lnk.SetComment(Program.BrandName); // TODO add a tagline
|
||||||
lnk.Save();
|
lnk.Save();
|
||||||
|
|
||||||
File.Move(linkFile,Path.Combine(location,Program.BrandName+".lnk"));
|
string renamed = Path.Combine(location,Program.BrandName+".lnk");
|
||||||
|
|
||||||
|
try{
|
||||||
|
if (!File.Exists(renamed)){
|
||||||
|
File.Move(linkFile,renamed);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
File.Delete(linkFile);
|
||||||
|
}
|
||||||
|
}catch{
|
||||||
|
// eh, too bad
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,13 +149,12 @@ namespace TweetDick.Migration{
|
|||||||
string guid = ProgramRegistrySearch.FindByDisplayName("TweetDeck");
|
string guid = ProgramRegistrySearch.FindByDisplayName("TweetDeck");
|
||||||
|
|
||||||
if (guid != null){
|
if (guid != null){
|
||||||
Process uninstaller = Process.Start("msiexec.exe","/x"+guid+" /quiet /qn");
|
RunUninstaller(guid,5000);
|
||||||
|
|
||||||
if (uninstaller != null){
|
|
||||||
uninstaller.WaitForExit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// registry cleanup
|
||||||
|
CleanupTweetDeck();
|
||||||
|
|
||||||
// migration finished like a boss
|
// migration finished like a boss
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -149,5 +172,41 @@ namespace TweetDick.Migration{
|
|||||||
}catch(DirectoryNotFoundException){
|
}catch(DirectoryNotFoundException){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> GetLnkDirectories(){
|
||||||
|
yield return Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
|
||||||
|
yield return Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory);
|
||||||
|
yield return Environment.ExpandEnvironmentVariables(@"%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar");
|
||||||
|
|
||||||
|
/* already handled by the installer
|
||||||
|
string startMenu = Environment.GetFolderPath(Environment.SpecialFolder.StartMenu);
|
||||||
|
string[] sub = Directory.GetDirectories(startMenu);
|
||||||
|
|
||||||
|
if (sub.Length > 0){
|
||||||
|
yield return Path.Combine(startMenu,sub[0],"TweetDeck");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
Registry.CurrentUser.DeleteSubKey(@"Software\Twitter"); // only if empty
|
||||||
|
}catch(Exception){
|
||||||
|
// not found or too bad
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
82
Program.cs
82
Program.cs
@@ -1,14 +1,18 @@
|
|||||||
using CefSharp;
|
using System;
|
||||||
using System;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDick.Configuration;
|
using CefSharp;
|
||||||
using TweetDick.Core;
|
using TweetDck.Configuration;
|
||||||
using TweetDick.Migration;
|
using TweetDck.Core;
|
||||||
|
using TweetDck.Migration;
|
||||||
|
using TweetDck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDick{
|
[assembly: CLSCompliant(true)]
|
||||||
|
namespace TweetDck{
|
||||||
static class Program{
|
static class Program{
|
||||||
#if DUCK
|
#if DUCK
|
||||||
public const string BrandName = "TweetDuck";
|
public const string BrandName = "TweetDuck";
|
||||||
@@ -18,28 +22,19 @@ namespace TweetDick{
|
|||||||
public const string Website = "http://tweetdick.chylex.com";
|
public const string Website = "http://tweetdick.chylex.com";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
public const string VersionTag = "1.1";
|
||||||
|
|
||||||
public static readonly string StoragePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),BrandName);
|
public static readonly string StoragePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),BrandName);
|
||||||
private static readonly LockManager LockManager;
|
private static readonly LockManager LockManager = new LockManager(Path.Combine(StoragePath,".lock"));
|
||||||
|
|
||||||
public static UserConfig UserConfig { get; private set; }
|
public static UserConfig UserConfig { get; private set; }
|
||||||
|
|
||||||
private static string HeaderAcceptLanguage{
|
public static string LogFile{
|
||||||
get{
|
get{
|
||||||
string culture = CultureInfo.CurrentCulture.Name;
|
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"td-log.txt");
|
||||||
|
|
||||||
if (culture == "en"){
|
|
||||||
return "en-us,en";
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return culture.ToLowerInvariant()+",en;q=0.9";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Program(){
|
|
||||||
LockManager = new LockManager(Path.Combine(StoragePath,".lock"));
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
|
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
|
||||||
public static extern IntPtr LoadLibrary(string name);
|
public static extern IntPtr LoadLibrary(string name);
|
||||||
|
|
||||||
@@ -73,8 +68,8 @@ namespace TweetDick{
|
|||||||
};
|
};
|
||||||
|
|
||||||
Cef.Initialize(new CefSettings{
|
Cef.Initialize(new CefSettings{
|
||||||
AcceptLanguageList = HeaderAcceptLanguage,
|
AcceptLanguageList = BrowserUtils.HeaderAcceptLanguage,
|
||||||
UserAgent = BrandName+" "+Application.ProductVersion,
|
UserAgent = BrowserUtils.HeaderUserAgent,
|
||||||
Locale = CultureInfo.CurrentCulture.TwoLetterISOLanguageName,
|
Locale = CultureInfo.CurrentCulture.TwoLetterISOLanguageName,
|
||||||
CachePath = StoragePath,
|
CachePath = StoragePath,
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
@@ -82,13 +77,54 @@ namespace TweetDick{
|
|||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AppDomain.CurrentDomain.UnhandledException += (sender, args) => {
|
||||||
|
Exception ex = args.ExceptionObject as Exception;
|
||||||
|
|
||||||
|
if (ex != null){
|
||||||
|
HandleException("An unhandled exception has occurred.",ex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Application.ApplicationExit += (sender, args) => {
|
Application.ApplicationExit += (sender, args) => {
|
||||||
UserConfig.Save();
|
UserConfig.Save();
|
||||||
LockManager.Unlock();
|
LockManager.Unlock();
|
||||||
Cef.Shutdown();
|
Cef.Shutdown();
|
||||||
};
|
};
|
||||||
|
|
||||||
Application.Run(new FormBrowser());
|
FormBrowser mainForm = new FormBrowser();
|
||||||
|
Application.Run(mainForm);
|
||||||
|
|
||||||
|
if (mainForm.UpdateInstallerPath != null){
|
||||||
|
Cef.Shutdown();
|
||||||
|
|
||||||
|
Process.Start(mainForm.UpdateInstallerPath,"/SP- /SILENT /NOICONS /CLOSEAPPLICATIONS");
|
||||||
|
Application.Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleException(string message, Exception e){
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void 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")).Append("]\r\n");
|
||||||
|
build.Append(data).Append("\r\n\r\n");
|
||||||
|
|
||||||
|
try{
|
||||||
|
File.AppendAllText(LogFile,build.ToString(),Encoding.UTF8);
|
||||||
|
}catch{
|
||||||
|
// oops
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using TweetDick;
|
using System.Resources;
|
||||||
|
using TweetDck;
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
// General Information about an assembly is controlled through the following
|
||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle(Program.BrandName)]
|
[assembly: AssemblyTitle("TweetDeck client for Windows")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("TweetDeck client for Windows")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct(Program.BrandName)]
|
[assembly: AssemblyProduct(Program.BrandName)]
|
||||||
@@ -32,5 +33,7 @@ using TweetDick;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.9.1.0")]
|
[assembly: AssemblyVersion("1.1.0.0")]
|
||||||
[assembly: AssemblyFileVersion("0.9.1.0")]
|
[assembly: AssemblyFileVersion("1.1.0.0")]
|
||||||
|
|
||||||
|
[assembly: NeutralResourcesLanguageAttribute("en")]
|
4
Properties/Resources.Designer.cs
generated
4
Properties/Resources.Designer.cs
generated
@@ -8,7 +8,7 @@
|
|||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace TweetDick.Properties {
|
namespace TweetDck.Properties {
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ namespace TweetDick.Properties {
|
|||||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
get {
|
get {
|
||||||
if (object.ReferenceEquals(resourceMan, null)) {
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TweetDick.Properties.Resources", typeof(Resources).Assembly);
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TweetDck.Properties.Resources", typeof(Resources).Assembly);
|
||||||
resourceMan = temp;
|
resourceMan = temp;
|
||||||
}
|
}
|
||||||
return resourceMan;
|
return resourceMan;
|
||||||
|
13
README.md
Normal file
13
README.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# 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.
|
||||||
|
```
|
||||||
|
PM> Install-Package CefSharp.WinForms -Pre
|
||||||
|
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**.
|
@@ -3,11 +3,11 @@ using System.IO;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TweetDick.Resources{
|
namespace TweetDck.Resources{
|
||||||
static class ScriptLoader{
|
static class ScriptLoader{
|
||||||
public static string LoadResource(string name){
|
public static string LoadResource(string name){
|
||||||
try{
|
try{
|
||||||
return File.ReadAllText(name,Encoding.UTF8);
|
return File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,name),Encoding.UTF8);
|
||||||
}catch(Exception ex){
|
}catch(Exception ex){
|
||||||
MessageBox.Show("Unfortunately, "+Program.BrandName+" could not load the "+name+" file. The program will continue running with limited functionality.\r\n\r\n"+ex.Message,Program.BrandName+" Has Failed :(",MessageBoxButtons.OK,MessageBoxIcon.Error);
|
MessageBox.Show("Unfortunately, "+Program.BrandName+" could not load the "+name+" file. The program will continue running with limited functionality.\r\n\r\n"+ex.Message,Program.BrandName+" Has Failed :(",MessageBoxButtons.OK,MessageBoxIcon.Error);
|
||||||
return null;
|
return null;
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
var fontSizeClasses = [ "txt-base-smallest", "txt-base-small", "txt-base-medium", "txt-base-large", "txt-base-largest" ];
|
var fontSizeClasses = [ "txt-base-smallest", "txt-base-small", "txt-base-medium", "txt-base-large", "txt-base-largest" ];
|
||||||
|
|
||||||
//
|
//
|
||||||
// Variable: Says whether TweetDick events was initialized.
|
// Variable: Says whether TweetD*ck events was initialized.
|
||||||
//
|
//
|
||||||
var isInitialized = false;
|
var isInitialized = false;
|
||||||
|
|
||||||
@@ -15,24 +15,29 @@
|
|||||||
var prevFontSizeClass;
|
var prevFontSizeClass;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Function: Initializes TweetDick events. Called after the website app is loaded.
|
// Variable: Current timeout ID for update checking.
|
||||||
//
|
//
|
||||||
var initializeTweetDick = function(){
|
var updateCheckTimeoutID;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Function: Initializes TweetD*ck events. Called after the website app is loaded.
|
||||||
|
//
|
||||||
|
var initializeTweetDck = function(){
|
||||||
// Settings button hook
|
// Settings button hook
|
||||||
$("[data-action='settings-menu']").click(function(){
|
$("[data-action='settings-menu']").click(function(){
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
var menu = $(".js-dropdown-content").children("ul").first();
|
var menu = $(".js-dropdown-content").children("ul").first();
|
||||||
if (menu.length == 0)return;
|
if (menu.length === 0)return;
|
||||||
|
|
||||||
menu.children(".drp-h-divider").last().after('<li class="is-selectable" data-std><a href="#" data-action>'+$TD.brandName+'</a></li><li class="drp-h-divider"></li>');
|
menu.children(".drp-h-divider").last().after('<li class="is-selectable" data-std><a href="#" data-action>'+$TD.brandName+'</a></li><li class="drp-h-divider"></li>');
|
||||||
|
|
||||||
var tweetDickBtn = menu.children("[data-std]").first();
|
var tweetDckBtn = menu.children("[data-std]").first();
|
||||||
|
|
||||||
tweetDickBtn.on("click","a",function(){
|
tweetDckBtn.on("click","a",function(){
|
||||||
$TD.openSettingsMenu();
|
$TD.openSettingsMenu();
|
||||||
});
|
});
|
||||||
|
|
||||||
tweetDickBtn.hover(function(){
|
tweetDckBtn.hover(function(){
|
||||||
$(this).addClass("is-selected");
|
$(this).addClass("is-selected");
|
||||||
},function(){
|
},function(){
|
||||||
$(this).removeClass("is-selected");
|
$(this).removeClass("is-selected");
|
||||||
@@ -57,7 +62,7 @@
|
|||||||
refreshColumnObservers();
|
refreshColumnObservers();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Popup notifications
|
// Force popup notification settings
|
||||||
window.TD.controller.notifications.hasNotifications = function(){
|
window.TD.controller.notifications.hasNotifications = function(){
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -66,6 +71,9 @@
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Run update check
|
||||||
|
runUpdateCheck();
|
||||||
|
|
||||||
// Finish init
|
// Finish init
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
};
|
};
|
||||||
@@ -83,7 +91,7 @@
|
|||||||
mid = mid.children(".js-column-scroller").first();
|
mid = mid.children(".js-column-scroller").first();
|
||||||
|
|
||||||
var container = mid.children(".js-chirp-container").first();
|
var container = mid.children(".js-chirp-container").first();
|
||||||
if (container.length == 0)return;
|
if (container.length === 0)return;
|
||||||
|
|
||||||
var scroller = container.parent();
|
var scroller = container.parent();
|
||||||
|
|
||||||
@@ -100,7 +108,7 @@
|
|||||||
|
|
||||||
Array.prototype.forEach.call(mutations,function(mutation){
|
Array.prototype.forEach.call(mutations,function(mutation){
|
||||||
Array.prototype.forEach.call(mutation.addedNodes,function(node){
|
Array.prototype.forEach.call(mutation.addedNodes,function(node){
|
||||||
if (node.tagName != "ARTICLE")return;
|
if (node.tagName !== "ARTICLE")return;
|
||||||
|
|
||||||
onNewTweet(column,node);
|
onNewTweet(column,node);
|
||||||
});
|
});
|
||||||
@@ -119,13 +127,20 @@
|
|||||||
var html = $(tweet.outerHTML);
|
var html = $(tweet.outerHTML);
|
||||||
var body = html.find(".tweet-body").first();
|
var body = html.find(".tweet-body").first();
|
||||||
|
|
||||||
|
if (html.find(".icon-reply").length > 0){
|
||||||
|
return; // ignore sent messages
|
||||||
|
}
|
||||||
|
|
||||||
body.children("div.js-quote-detail").each(function(){
|
body.children("div.js-quote-detail").each(function(){
|
||||||
$(this).html("(quoted tweet)");
|
$(this).html("(quoted tweet)");
|
||||||
});
|
});
|
||||||
|
|
||||||
body.children().not("p,div.js-quote-detail").remove();
|
body.children().not("p,span,div.js-quote-detail").remove();
|
||||||
|
|
||||||
$TD.onTweetPopup(html.html(),html.find(".js-tweet-text:first").text().length); // TODO column & remove pic links from text()
|
var characters = html.find(".js-tweet-text:first").text().length;
|
||||||
|
if (characters == 0)return;
|
||||||
|
|
||||||
|
$TD.onTweetPopup(html.html(),characters); // TODO column & remove pic links from text()
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -155,7 +170,115 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Block: Observe the app <div> element and initialize TweetDick whenever possible.
|
// Function: Creates the update notification element. Removes the old one if already exists.
|
||||||
|
//
|
||||||
|
var createUpdateNotificationElement = function(version, download){
|
||||||
|
var ele = $("#tweetdck-update");
|
||||||
|
var existed = ele.length > 0;
|
||||||
|
|
||||||
|
if (existed > 0){
|
||||||
|
ele.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
var html = [
|
||||||
|
"<div id='tweetdck-update'>",
|
||||||
|
"<p class='tdu-title'>"+$TD.brandName+" Update</p>",
|
||||||
|
"<p class='tdu-info'>Version "+version+" is now available.</p>",
|
||||||
|
"<div class='tdu-buttons'>",
|
||||||
|
"<button class='btn btn-positive tdu-btn-download'><span class='label'>Download</button>",
|
||||||
|
"<button class='btn btn-negative tdu-btn-dismiss'><span class='label'>Dismiss</button>",
|
||||||
|
"</div>",
|
||||||
|
"</div>"
|
||||||
|
];
|
||||||
|
|
||||||
|
$("h1.app-title").after(html.join(""));
|
||||||
|
|
||||||
|
ele = $("#tweetdck-update");
|
||||||
|
|
||||||
|
var buttonDiv = ele.children("div.tdu-buttons").first();
|
||||||
|
|
||||||
|
ele.css({
|
||||||
|
color: "#fff",
|
||||||
|
backgroundColor: "rgb(32,94,138)",
|
||||||
|
position: "absolute",
|
||||||
|
left: "4px",
|
||||||
|
bottom: "4px",
|
||||||
|
width: "192px",
|
||||||
|
height: "86px",
|
||||||
|
display: existed ? "block" : "none",
|
||||||
|
borderRadius: "2px"
|
||||||
|
});
|
||||||
|
|
||||||
|
ele.children("p.tdu-title").first().css({
|
||||||
|
fontSize: "17px",
|
||||||
|
fontWeight: "bold",
|
||||||
|
textAlign: "center",
|
||||||
|
letterSpacing: "0.2px",
|
||||||
|
margin: "4px auto 2px"
|
||||||
|
});
|
||||||
|
|
||||||
|
ele.children("p.tdu-info").first().css({
|
||||||
|
fontSize: "12px",
|
||||||
|
textAlign: "center",
|
||||||
|
margin: "2px auto 6px"
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonDiv.css({
|
||||||
|
textAlign: "center"
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonDiv.children().css({
|
||||||
|
margin: "0 4px",
|
||||||
|
minHeight: "25px",
|
||||||
|
boxShadow: "1px 1px 1px rgba(17,17,17,0.5)"
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonDiv.find("span").css({
|
||||||
|
verticalAlign: "baseline"
|
||||||
|
});
|
||||||
|
|
||||||
|
ele.find("span.tdu-data-tag").first().css({
|
||||||
|
cursor: "pointer",
|
||||||
|
textDecoration: "underline"
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonDiv.children(".tdu-btn-download").click(function(){
|
||||||
|
ele.remove();
|
||||||
|
$TD.onUpdateAccepted(version,download);
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonDiv.children(".tdu-btn-dismiss").click(function(){
|
||||||
|
$TD.onUpdateDismissed(version);
|
||||||
|
ele.slideUp(function(){ ele.remove(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!existed){
|
||||||
|
ele.slideDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ele;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Function: Runs an update check and updates all DOM elements appropriately
|
||||||
|
//
|
||||||
|
var runUpdateCheck = function(){
|
||||||
|
clearTimeout(updateCheckTimeoutID);
|
||||||
|
updateCheckTimeoutID = setTimeout(runUpdateCheck,1000*60*60); // 1 hour
|
||||||
|
|
||||||
|
if (!$TD.updateCheckEnabled)return;
|
||||||
|
|
||||||
|
$.getJSON("https://api.github.com/repos/chylex/"+$TD.brandName+"/releases/latest",function(response){
|
||||||
|
var tagName = response.tag_name;
|
||||||
|
|
||||||
|
if (tagName != $TD.versionTag && tagName != $TD.dismissedVersionTag && response.assets.length > 0){
|
||||||
|
createUpdateNotificationElement(tagName,response.assets[0].browser_download_url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Block: Observe the app <div> element and initialize TweetD*ck whenever possible.
|
||||||
//
|
//
|
||||||
var app = $("body").children(".js-app");
|
var app = $("body").children(".js-app");
|
||||||
|
|
||||||
@@ -164,7 +287,7 @@
|
|||||||
isInitialized = false;
|
isInitialized = false;
|
||||||
}
|
}
|
||||||
else if (!isInitialized && !app.hasClass("is-hidden")){
|
else if (!isInitialized && !app.hasClass("is-hidden")){
|
||||||
initializeTweetDick();
|
initializeTweetDck();
|
||||||
}
|
}
|
||||||
}).observe(app[0],{
|
}).observe(app[0],{
|
||||||
attributes: true,
|
attributes: true,
|
||||||
@@ -213,8 +336,9 @@
|
|||||||
if (urlWait)return;
|
if (urlWait)return;
|
||||||
|
|
||||||
var me = $(this);
|
var me = $(this);
|
||||||
|
var rel = me.attr("rel");
|
||||||
|
|
||||||
if (!me.is(".link-complex") && !(me.attr("rel") == "mediaPreview" && me.closest("#open-modal").length == 0)){
|
if (!me.is(".link-complex") && !(rel === "mediaPreview" && me.closest("#open-modal").length === 0) && rel !== "list"){
|
||||||
$TD.openBrowser(me.attr("href"));
|
$TD.openBrowser(me.attr("href"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,4 +353,21 @@
|
|||||||
onUrlOpened();
|
onUrlOpened();
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Block: Hook into mp4 video element clicking
|
||||||
|
//
|
||||||
|
$(document.body).delegate("video.js-media-gif","click",function(e){
|
||||||
|
var src = $(this).attr("src");
|
||||||
|
|
||||||
|
if (src.endsWith(".mp4")){
|
||||||
|
$TD.openBrowser(src);
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Block: Setup global functions.
|
||||||
|
//
|
||||||
|
window.TDGF_runUpdateCheck = runUpdateCheck;
|
||||||
})($,$TD);
|
})($,$TD);
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<ProjectGuid>{2389A7CD-E0D3-4706-8294-092929A33A2D}</ProjectGuid>
|
<ProjectGuid>{2389A7CD-E0D3-4706-8294-092929A33A2D}</ProjectGuid>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>TweetDick</RootNamespace>
|
<RootNamespace>TweetDck</RootNamespace>
|
||||||
<AssemblyName Condition=" '$(Configuration)' == 'Debug' ">TweetDick</AssemblyName>
|
<AssemblyName Condition=" '$(Configuration)' == 'Debug' ">TweetDick</AssemblyName>
|
||||||
<AssemblyName Condition=" '$(Configuration)' == 'Release Dick' ">TweetDick</AssemblyName>
|
<AssemblyName Condition=" '$(Configuration)' == 'Release Dick' ">TweetDick</AssemblyName>
|
||||||
<AssemblyName Condition=" '$(Configuration)' == 'Release Duck' ">TweetDuck</AssemblyName>
|
<AssemblyName Condition=" '$(Configuration)' == 'Release Duck' ">TweetDuck</AssemblyName>
|
||||||
@@ -77,13 +77,15 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Configuration\LockManager.cs" />
|
<Compile Include="Configuration\LockManager.cs" />
|
||||||
<Compile Include="Configuration\UserConfig.cs" />
|
<Compile Include="Configuration\UserConfig.cs" />
|
||||||
|
<Compile Include="Core\Controls\ControlExtensions.cs" />
|
||||||
<Compile Include="Core\Controls\FlatProgressBar.cs">
|
<Compile Include="Core\Controls\FlatProgressBar.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Core\Controls\FlatProgressBar.Designer.cs">
|
<Compile Include="Core\Controls\FlatProgressBar.Designer.cs">
|
||||||
<DependentUpon>FlatProgressBar.cs</DependentUpon>
|
<DependentUpon>FlatProgressBar.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Core\Handling\ContextMenuHandler.cs" />
|
<Compile Include="Core\Handling\ContextMenuBase.cs" />
|
||||||
|
<Compile Include="Core\Handling\ContextMenuBrowser.cs" />
|
||||||
<Compile Include="Core\FormBrowser.cs">
|
<Compile Include="Core\FormBrowser.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -96,6 +98,7 @@
|
|||||||
<Compile Include="Core\FormNotification.Designer.cs">
|
<Compile Include="Core\FormNotification.Designer.cs">
|
||||||
<DependentUpon>FormNotification.cs</DependentUpon>
|
<DependentUpon>FormNotification.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Core\Handling\ContextMenuNotification.cs" />
|
||||||
<Compile Include="Core\Handling\TweetNotification.cs" />
|
<Compile Include="Core\Handling\TweetNotification.cs" />
|
||||||
<Compile Include="Core\Controls\RichTextLabel.cs">
|
<Compile Include="Core\Controls\RichTextLabel.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
@@ -122,6 +125,14 @@
|
|||||||
<Compile Include="Core\Other\FormSettings.Designer.cs">
|
<Compile Include="Core\Other\FormSettings.Designer.cs">
|
||||||
<DependentUpon>FormSettings.cs</DependentUpon>
|
<DependentUpon>FormSettings.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Core\Other\FormUpdateDownload.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Core\Other\FormUpdateDownload.Designer.cs">
|
||||||
|
<DependentUpon>FormUpdateDownload.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Core\Utils\BrowserUtils.cs" />
|
||||||
|
<Compile Include="Core\Utils\UpdateInfo.cs" />
|
||||||
<Compile Include="Migration\FormMigrationQuestion.cs">
|
<Compile Include="Migration\FormMigrationQuestion.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -220,7 +231,9 @@
|
|||||||
xcopy "$(ProjectDir)LICENSE" "$(TargetDir)" /Y
|
xcopy "$(ProjectDir)LICENSE" "$(TargetDir)" /Y
|
||||||
del "$(TargetDir)LICENSE.txt"
|
del "$(TargetDir)LICENSE.txt"
|
||||||
ren "$(TargetDir)LICENSE" "LICENSE.txt"
|
ren "$(TargetDir)LICENSE" "LICENSE.txt"
|
||||||
xcopy "$(ProjectDir)Libraries\CEFSHARP-LICENSE.txt" "$(TargetDir)" /Y</PostBuildEvent>
|
xcopy "$(ProjectDir)Libraries\CEFSHARP-LICENSE.txt" "$(TargetDir)" /Y
|
||||||
|
xcopy "$(ProjectDir)packages\Microsoft.VC120.CRT.JetBrains.12.0.21005.2\DotFiles\msvcp120.dll" "$(TargetDir)" /Y
|
||||||
|
xcopy "$(ProjectDir)packages\Microsoft.VC120.CRT.JetBrains.12.0.21005.2\DotFiles\msvcr120.dll" "$(TargetDir)" /Y</PostBuildEvent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- 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.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio 2013
|
# Visual Studio 2013
|
||||||
VisualStudioVersion = 12.0.40629.0
|
VisualStudioVersion = 12.0.40629.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDick", "TweetDick.csproj", "{2389A7CD-E0D3-4706-8294-092929A33A2D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDck", "TweetDck.csproj", "{2389A7CD-E0D3-4706-8294-092929A33A2D}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
4
_postbuild.bat
Normal file
4
_postbuild.bat
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
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"
|
Reference in New Issue
Block a user