mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-09-14 19:32:10 +02:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
90414ae579 | |||
41c8caa2a4 | |||
15305ecabe | |||
50090effd4 | |||
6dffdcd1ed | |||
db9daf2714 | |||
502ac4ebc1 | |||
3f44f3bab4 |
@@ -7,7 +7,6 @@ namespace TweetDuck.Configuration{
|
||||
public const string ArgDataFolder = "-datafolder";
|
||||
public const string ArgLogging = "-log";
|
||||
public const string ArgIgnoreGDPR = "-nogdpr";
|
||||
public const string ArgNotificationScrollWA = "-nscrollwa";
|
||||
|
||||
// internal args
|
||||
public const string ArgRestart = "-restart";
|
||||
|
68
Core/Bridge/UpdateBridge.cs
Normal file
68
Core/Bridge/UpdateBridge.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using TweetDuck.Core.Controls;
|
||||
using TweetDuck.Updates;
|
||||
|
||||
namespace TweetDuck.Core.Bridge{
|
||||
class UpdateBridge{
|
||||
private readonly UpdateHandler updates;
|
||||
private readonly Control sync;
|
||||
|
||||
private UpdateInfo nextUpdate = null;
|
||||
|
||||
public event EventHandler<UpdateInfo> UpdateAccepted;
|
||||
public event EventHandler<UpdateInfo> UpdateDelayed;
|
||||
public event EventHandler<UpdateInfo> UpdateDismissed;
|
||||
|
||||
public UpdateBridge(UpdateHandler updates, Control sync){
|
||||
this.sync = sync;
|
||||
|
||||
this.updates = updates;
|
||||
this.updates.CheckFinished += updates_CheckFinished;
|
||||
}
|
||||
|
||||
internal void Cleanup(){
|
||||
updates.CheckFinished -= updates_CheckFinished;
|
||||
nextUpdate?.DeleteInstaller();
|
||||
}
|
||||
|
||||
private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
||||
UpdateInfo foundUpdate = e.Result.HasValue ? e.Result.Value : null;
|
||||
|
||||
if (nextUpdate != null && !nextUpdate.Equals(foundUpdate)){
|
||||
nextUpdate.DeleteInstaller();
|
||||
}
|
||||
|
||||
nextUpdate = foundUpdate;
|
||||
}
|
||||
|
||||
private void HandleInteractionEvent(EventHandler<UpdateInfo> eventHandler){
|
||||
UpdateInfo tmpInfo = nextUpdate;
|
||||
|
||||
if (tmpInfo != null){
|
||||
sync.InvokeAsyncSafe(() => eventHandler?.Invoke(this, tmpInfo));
|
||||
}
|
||||
}
|
||||
|
||||
// Bridge methods
|
||||
|
||||
public void TriggerUpdateCheck(){
|
||||
updates.Check(false);
|
||||
}
|
||||
|
||||
public void OnUpdateAccepted(){
|
||||
HandleInteractionEvent(UpdateAccepted);
|
||||
}
|
||||
|
||||
public void OnUpdateDelayed(){
|
||||
HandleInteractionEvent(UpdateDelayed);
|
||||
}
|
||||
|
||||
public void OnUpdateDismissed(){
|
||||
HandleInteractionEvent(UpdateDismissed);
|
||||
|
||||
nextUpdate?.DeleteInstaller();
|
||||
nextUpdate = null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -17,7 +17,6 @@ using TweetDuck.Plugins;
|
||||
using TweetDuck.Plugins.Enums;
|
||||
using TweetDuck.Plugins.Events;
|
||||
using TweetDuck.Updates;
|
||||
using TweetDuck.Updates.Events;
|
||||
|
||||
namespace TweetDuck.Core{
|
||||
sealed partial class FormBrowser : Form, AnalyticsFile.IProvider{
|
||||
@@ -50,6 +49,7 @@ namespace TweetDuck.Core{
|
||||
private readonly UpdateHandler updates;
|
||||
private readonly FormNotificationTweet notification;
|
||||
private readonly ContextMenu contextMenu;
|
||||
private readonly UpdateBridge updateBridge;
|
||||
|
||||
private bool isLoaded;
|
||||
private FormWindowState prevState;
|
||||
@@ -62,7 +62,7 @@ namespace TweetDuck.Core{
|
||||
InitializeComponent();
|
||||
|
||||
Text = Program.BrandName;
|
||||
|
||||
|
||||
this.plugins = new PluginManager(Program.PluginPath, Program.PluginConfigFilePath);
|
||||
this.plugins.Reloaded += plugins_Reloaded;
|
||||
this.plugins.Executed += plugins_Executed;
|
||||
@@ -71,7 +71,15 @@ namespace TweetDuck.Core{
|
||||
this.notification = new FormNotificationTweet(this, plugins);
|
||||
this.notification.Show();
|
||||
|
||||
this.browser = new TweetDeckBrowser(this, new TweetDeckBridge.Browser(this, notification));
|
||||
this.updates = new UpdateHandler(Program.InstallerPath);
|
||||
this.updates.CheckFinished += updates_CheckFinished;
|
||||
|
||||
this.updateBridge = new UpdateBridge(updates, this);
|
||||
this.updateBridge.UpdateAccepted += updateBridge_UpdateAccepted;
|
||||
this.updateBridge.UpdateDelayed += updateBridge_UpdateDelayed;
|
||||
this.updateBridge.UpdateDismissed += updateBridge_UpdateDismissed;
|
||||
|
||||
this.browser = new TweetDeckBrowser(this, new TweetDeckBridge.Browser(this, notification), updateBridge);
|
||||
this.contextMenu = ContextMenuBrowser.CreateMenu(this);
|
||||
|
||||
this.plugins.Register(browser, PluginEnvironment.Browser, this, true);
|
||||
@@ -103,11 +111,6 @@ namespace TweetDuck.Core{
|
||||
UpdateFormIcon();
|
||||
}
|
||||
|
||||
this.updates = new UpdateHandler(browser, Program.InstallerPath);
|
||||
this.updates.CheckFinished += updates_CheckFinished;
|
||||
this.updates.UpdateAccepted += updates_UpdateAccepted;
|
||||
this.updates.UpdateDismissed += updates_UpdateDismissed;
|
||||
|
||||
if (Config.AllowDataCollection){
|
||||
analytics = new AnalyticsManager(this, plugins, Program.AnalyticsFilePath);
|
||||
}
|
||||
@@ -207,7 +210,7 @@ namespace TweetDuck.Core{
|
||||
|
||||
private void FormBrowser_FormClosed(object sender, FormClosedEventArgs e){
|
||||
if (isLoaded && UpdateInstallerPath == null){
|
||||
updates.CleanupDownload();
|
||||
updateBridge.Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +255,7 @@ namespace TweetDuck.Core{
|
||||
string tag = update.VersionTag;
|
||||
|
||||
if (tag != Program.VersionTag && tag != Config.DismissedUpdate){
|
||||
updates.PrepareUpdate(update);
|
||||
update.BeginSilentDownload();
|
||||
browser.ShowUpdateNotification(tag, update.ReleaseNotes);
|
||||
}
|
||||
else{
|
||||
@@ -268,38 +271,61 @@ namespace TweetDuck.Core{
|
||||
ignoreUpdateCheckError = true;
|
||||
}
|
||||
|
||||
private void updates_UpdateAccepted(object sender, UpdateEventArgs e){
|
||||
this.InvokeAsyncSafe(() => {
|
||||
FormManager.CloseAllDialogs();
|
||||
private void updateBridge_UpdateAccepted(object sender, UpdateInfo update){
|
||||
FormManager.CloseAllDialogs();
|
||||
|
||||
if (!string.IsNullOrEmpty(Config.DismissedUpdate)){
|
||||
Config.DismissedUpdate = null;
|
||||
Config.Save();
|
||||
if (!string.IsNullOrEmpty(Config.DismissedUpdate)){
|
||||
Config.DismissedUpdate = null;
|
||||
Config.Save();
|
||||
}
|
||||
|
||||
void OnFinished(){
|
||||
UpdateDownloadStatus status = update.DownloadStatus;
|
||||
|
||||
if (status == UpdateDownloadStatus.Done){
|
||||
UpdateInstallerPath = update.InstallerPath;
|
||||
ForceClose();
|
||||
}
|
||||
else if (status != UpdateDownloadStatus.Canceled && FormMessage.Error("Update Has Failed", "Could not automatically download the update: "+(update.DownloadError?.Message ?? "unknown error")+"\n\nWould you like to open the website and try downloading the update manually?", FormMessage.Yes, FormMessage.No)){
|
||||
BrowserUtils.OpenExternalBrowser(Program.Website);
|
||||
ForceClose();
|
||||
}
|
||||
else{
|
||||
Show();
|
||||
}
|
||||
}
|
||||
|
||||
if (update.DownloadStatus.IsFinished(true)){
|
||||
OnFinished();
|
||||
}
|
||||
else{
|
||||
FormUpdateDownload downloadForm = new FormUpdateDownload(update);
|
||||
|
||||
updates.BeginUpdateDownload(this, e.UpdateInfo, update => {
|
||||
UpdateDownloadStatus status = update.DownloadStatus;
|
||||
downloadForm.VisibleChanged += (sender2, args2) => {
|
||||
downloadForm.MoveToCenter(this);
|
||||
Hide();
|
||||
};
|
||||
|
||||
if (status == UpdateDownloadStatus.Done){
|
||||
UpdateInstallerPath = update.InstallerPath;
|
||||
ForceClose();
|
||||
downloadForm.FormClosed += (sender2, args2) => {
|
||||
if (downloadForm.DialogResult != DialogResult.OK){
|
||||
update.CancelDownload();
|
||||
}
|
||||
else if (status != UpdateDownloadStatus.Canceled && FormMessage.Error("Update Has Failed", "Could not automatically download the update: "+(update.DownloadError?.Message ?? "unknown error")+"\n\nWould you like to open the website and try downloading the update manually?", FormMessage.Yes, FormMessage.No)){
|
||||
BrowserUtils.OpenExternalBrowser(Program.Website);
|
||||
ForceClose();
|
||||
}
|
||||
else{
|
||||
Show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
downloadForm.Dispose();
|
||||
OnFinished();
|
||||
};
|
||||
|
||||
downloadForm.Show();
|
||||
}
|
||||
}
|
||||
|
||||
private void updates_UpdateDismissed(object sender, UpdateEventArgs e){
|
||||
this.InvokeAsyncSafe(() => {
|
||||
Config.DismissedUpdate = e.UpdateInfo.VersionTag;
|
||||
Config.Save();
|
||||
});
|
||||
private void updateBridge_UpdateDelayed(object sender, UpdateInfo update){
|
||||
// stops the timer
|
||||
}
|
||||
|
||||
private void updateBridge_UpdateDismissed(object sender, UpdateInfo update){
|
||||
Config.DismissedUpdate = update.VersionTag;
|
||||
Config.Save();
|
||||
}
|
||||
|
||||
protected override void WndProc(ref Message m){
|
||||
|
@@ -2,7 +2,6 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using TweetDuck.Configuration;
|
||||
using TweetDuck.Core.Bridge;
|
||||
using TweetDuck.Core.Controls;
|
||||
using TweetDuck.Core.Handling;
|
||||
@@ -132,14 +131,7 @@ namespace TweetDuck.Core.Notification{
|
||||
int eventType = wParam.ToInt32();
|
||||
|
||||
if (eventType == NativeMethods.WM_MOUSEWHEEL && IsCursorOverBrowser){
|
||||
if (Arguments.HasFlag(Arguments.ArgNotificationScrollWA)){
|
||||
int delta = BrowserUtils.Scale(NativeMethods.GetMouseHookData(lParam), Program.UserConfig.NotificationScrollSpeed*0.01);
|
||||
browser.ExecuteScriptAsync("window.scrollBy", 0, -Math.Round(delta/0.72));
|
||||
}
|
||||
else{
|
||||
browser.SendMouseWheelEvent(0, 0, 0, BrowserUtils.Scale(NativeMethods.GetMouseHookData(lParam), Program.UserConfig.NotificationScrollSpeed*0.01), CefEventFlags.None);
|
||||
}
|
||||
|
||||
browser.SendMouseWheelEvent(0, 0, 0, BrowserUtils.Scale(NativeMethods.GetMouseHookData(lParam), Program.UserConfig.NotificationScrollSpeed*0.01), CefEventFlags.None);
|
||||
return NativeMethods.HOOK_HANDLED;
|
||||
}
|
||||
else if (eventType == NativeMethods.WM_XBUTTONDOWN && DesktopBounds.Contains(Cursor.Position)){
|
||||
|
@@ -7,7 +7,6 @@ using TweetDuck.Core.Handling.General;
|
||||
using TweetDuck.Core.Other.Settings.Dialogs;
|
||||
using TweetDuck.Core.Utils;
|
||||
using TweetDuck.Updates;
|
||||
using TweetDuck.Updates.Events;
|
||||
|
||||
namespace TweetDuck.Core.Other.Settings{
|
||||
sealed partial class TabSettingsGeneral : BaseTabSettings{
|
||||
@@ -210,11 +209,6 @@ namespace TweetDuck.Core.Other.Settings{
|
||||
|
||||
btnCheckUpdates.Enabled = false;
|
||||
updateCheckEventId = updates.Check(true);
|
||||
|
||||
if (updateCheckEventId == UpdateHandler.CheckCodeNotOnTweetDeck){
|
||||
FormMessage.Error("Update Check", "Updates can only be checked once TweetDeck is fully loaded.", FormMessage.OK);
|
||||
btnCheckUpdates.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
||||
|
@@ -9,7 +9,6 @@ using TweetDuck.Core.Bridge;
|
||||
using TweetDuck.Core.Controls;
|
||||
using TweetDuck.Core.Handling;
|
||||
using TweetDuck.Core.Handling.General;
|
||||
using TweetDuck.Core.Management;
|
||||
using TweetDuck.Core.Notification;
|
||||
using TweetDuck.Core.Other.Interfaces;
|
||||
using TweetDuck.Core.Utils;
|
||||
@@ -40,7 +39,7 @@ namespace TweetDuck.Core{
|
||||
|
||||
private string prevSoundNotificationPath = null;
|
||||
|
||||
public TweetDeckBrowser(FormBrowser owner, TweetDeckBridge bridge){
|
||||
public TweetDeckBrowser(FormBrowser owner, TweetDeckBridge tdBridge, UpdateBridge updateBridge){
|
||||
RequestHandlerBrowser requestHandler = new RequestHandlerBrowser();
|
||||
|
||||
this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){
|
||||
@@ -58,7 +57,8 @@ namespace TweetDuck.Core{
|
||||
this.browser.FrameLoadEnd += browser_FrameLoadEnd;
|
||||
this.browser.LoadError += browser_LoadError;
|
||||
|
||||
this.browser.RegisterAsyncJsObject("$TD", bridge);
|
||||
this.browser.RegisterAsyncJsObject("$TD", tdBridge);
|
||||
this.browser.RegisterAsyncJsObject("$TDU", updateBridge);
|
||||
|
||||
this.browser.BrowserSettings.BackgroundColor = (uint)TwitterUtils.BackgroundColor.ToArgb();
|
||||
this.browser.Dock = DockStyle.None;
|
||||
@@ -146,25 +146,28 @@ namespace TweetDuck.Core{
|
||||
private void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
||||
IFrame frame = e.Frame;
|
||||
|
||||
if (frame.IsMain && TwitterUtils.IsTweetDeckWebsite(frame)){
|
||||
UpdateProperties();
|
||||
TweetDeckBridge.RestoreSessionData(frame);
|
||||
ScriptLoader.ExecuteFile(frame, "code.js", browser);
|
||||
if (frame.IsMain){
|
||||
if (TwitterUtils.IsTweetDeckWebsite(frame)){
|
||||
UpdateProperties();
|
||||
TweetDeckBridge.RestoreSessionData(frame);
|
||||
ScriptLoader.ExecuteFile(frame, "code.js", browser);
|
||||
|
||||
InjectBrowserCSS();
|
||||
ReinjectCustomCSS(Program.UserConfig.CustomBrowserCSS);
|
||||
UserConfig_SoundNotificationInfoChanged(null, EventArgs.Empty);
|
||||
|
||||
TweetDeckBridge.ResetStaticProperties();
|
||||
|
||||
if (Arguments.HasFlag(Arguments.ArgIgnoreGDPR)){
|
||||
ScriptLoader.ExecuteScript(frame, "TD.storage.Account.prototype.requiresConsent = function(){ return false; }", "gen:gdpr");
|
||||
}
|
||||
|
||||
if (Program.UserConfig.FirstRun){
|
||||
ScriptLoader.ExecuteFile(frame, "introduction.js", browser);
|
||||
}
|
||||
}
|
||||
|
||||
ScriptLoader.ExecuteFile(frame, "update.js", browser);
|
||||
|
||||
InjectBrowserCSS();
|
||||
ReinjectCustomCSS(Program.UserConfig.CustomBrowserCSS);
|
||||
UserConfig_SoundNotificationInfoChanged(null, EventArgs.Empty);
|
||||
|
||||
TweetDeckBridge.ResetStaticProperties();
|
||||
|
||||
if (Arguments.HasFlag(Arguments.ArgIgnoreGDPR)){
|
||||
ScriptLoader.ExecuteScript(frame, "TD.storage.Account.prototype.requiresConsent = function(){ return false; }", "gen:gdpr");
|
||||
}
|
||||
|
||||
if (Program.UserConfig.FirstRun){
|
||||
ScriptLoader.ExecuteFile(frame, "introduction.js", browser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -22,7 +22,17 @@ namespace TweetDuck.Core.Utils{
|
||||
args["disable-gpu-vsync"] = "1";
|
||||
}
|
||||
|
||||
if (!Program.UserConfig.EnableSmoothScrolling){
|
||||
if (Program.UserConfig.EnableSmoothScrolling){
|
||||
args["disable-threaded-scrolling"] = "1";
|
||||
|
||||
if (args.TryGetValue("disable-features", out string disabledFeatures)){
|
||||
args["disable-features"] = "TouchpadAndWheelScrollLatching,"+disabledFeatures;
|
||||
}
|
||||
else{
|
||||
args["disable-features"] = "TouchpadAndWheelScrollLatching";
|
||||
}
|
||||
}
|
||||
else{
|
||||
args["disable-smooth-scrolling"] = "1";
|
||||
}
|
||||
|
||||
|
@@ -76,22 +76,14 @@ namespace TweetDuck.Core.Utils{
|
||||
string firstImageLink = GetMediaLink(urls[0], quality);
|
||||
int qualityIndex = firstImageLink.IndexOf(':', firstImageLink.LastIndexOf('/'));
|
||||
|
||||
string file = GetImageFileName(firstImageLink);
|
||||
string ext = Path.GetExtension(file); // includes dot
|
||||
|
||||
string[] fileNameParts = qualityIndex == -1 ? new string[]{
|
||||
Path.ChangeExtension(file, null)
|
||||
} : new string[]{
|
||||
username,
|
||||
Path.ChangeExtension(file, null),
|
||||
firstImageLink.Substring(qualityIndex+1)
|
||||
};
|
||||
string filename = GetImageFileName(firstImageLink);
|
||||
string ext = Path.GetExtension(filename); // includes dot
|
||||
|
||||
using(SaveFileDialog dialog = new SaveFileDialog{
|
||||
AutoUpgradeEnabled = true,
|
||||
OverwritePrompt = urls.Length == 1,
|
||||
Title = "Save Image",
|
||||
FileName = $"{string.Join(" ", fileNameParts.Where(part => !string.IsNullOrEmpty(part)))}{ext}",
|
||||
FileName = qualityIndex == -1 ? filename : $"{username} {Path.ChangeExtension(filename, null)} {firstImageLink.Substring(qualityIndex+1)}".Trim()+ext,
|
||||
Filter = (urls.Length == 1 ? "Image" : "Images")+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
|
||||
}){
|
||||
if (dialog.ShowDialog() == DialogResult.OK){
|
||||
@@ -122,12 +114,12 @@ namespace TweetDuck.Core.Utils{
|
||||
AutoUpgradeEnabled = true,
|
||||
OverwritePrompt = true,
|
||||
Title = "Save Video",
|
||||
FileName = string.IsNullOrEmpty(username) ? filename : $"{username} {filename}",
|
||||
FileName = string.IsNullOrEmpty(username) ? filename : $"{username} {filename}".TrimStart(),
|
||||
Filter = "Video"+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
|
||||
}){
|
||||
if (dialog.ShowDialog() == DialogResult.OK){
|
||||
BrowserUtils.DownloadFileAsync(url, dialog.FileName, null, ex => {
|
||||
FormMessage.Error("Image Download", "An error occurred while downloading the image: "+ex.Message, FormMessage.OK);
|
||||
FormMessage.Error("Video Download", "An error occurred while downloading the video: "+ex.Message, FormMessage.OK);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ namespace TweetDuck{
|
||||
public const string BrandName = "TweetDuck";
|
||||
public const string Website = "https://tweetduck.chylex.com";
|
||||
|
||||
public const string VersionTag = "1.15";
|
||||
public const string VersionTag = "1.15.1";
|
||||
|
||||
public static readonly string ProgramPath = AppDomain.CurrentDomain.BaseDirectory;
|
||||
public static readonly bool IsPortable = File.Exists(Path.Combine(ProgramPath, "makeportable"));
|
||||
|
@@ -391,7 +391,7 @@ html.dark .mdl-column-rhs{border-left:1px solid #ccd6dd;background:#fff}
|
||||
html.dark .s-minimal .mdl-header{border-bottom:1px solid #e1e8ed}
|
||||
html.dark .lst-launcher .top-row{border-bottom:1px solid #e1e8ed}
|
||||
html.dark .lst-launcher .is-disabled a,html.dark .lst-launcher .is-disabled a:hover,html.dark .lst-launcher .is-disabled a:focus,html.dark .lst-launcher .is-disabled a:active{background:#fff}
|
||||
html.dark .lst-launcher a:hover,html.dark .lst-launcher a:focus,html.dark .lst-launcher a:active{background:#f2f9ff;border:1px solid #bbddf5}
|
||||
html.dark .lst-launcher a:hover,html.dark .lst-launcher a:focus,html.dark .lst-launcher a:active{background:#f2f9ff}
|
||||
html.dark .lst-profile a,html.dark .lst-profile a:hover,html.dark .lst-profile a:focus,html.dark .lst-profile a:active{color:#657786}
|
||||
html.dark .mdl-col-settings{background-color:#fff;border-left:1px solid #E1E8ED}
|
||||
html.dark .mdl-links{color:#8899a6}
|
||||
|
@@ -6,8 +6,10 @@
|
||||
z-index: 9999;
|
||||
color: #fff;
|
||||
background-color: rgb(32, 94, 138);
|
||||
font-family: Helvetica, Arial, Verdana, sans-serif;
|
||||
text-align: center;
|
||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
|
||||
line-height: 1.28578;
|
||||
transition: transform 400ms cubic-bezier(.02, .01, .47, 1);
|
||||
}
|
||||
|
||||
@@ -67,6 +69,8 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
font-family: Helvetica, Arial, Verdana, sans-serif;
|
||||
line-height: 1.28578;
|
||||
z-index: 9998;
|
||||
}
|
||||
|
||||
@@ -82,14 +86,16 @@
|
||||
overflow-y: auto;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
font-size: 14px;
|
||||
color: #000;
|
||||
color: #2f2f2f;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#tweetduck-changelog h2 {
|
||||
margin: 0 0 7px;
|
||||
margin: 0 0 8px;
|
||||
color: #5c6973;
|
||||
font-size: 23px;
|
||||
line-height: 1.28578;
|
||||
}
|
||||
|
||||
#tweetduck-changelog h2 + br {
|
||||
@@ -98,7 +104,9 @@
|
||||
|
||||
#tweetduck-changelog h3 {
|
||||
margin: 0 0 5px 7px;
|
||||
color: #065b9c;
|
||||
font-size: 18px;
|
||||
line-height: 1.28578;
|
||||
}
|
||||
|
||||
#tweetduck-changelog p {
|
||||
|
@@ -42,7 +42,7 @@ button, .btn, .mdl, .mdl-content, .popover, .lst-modal, .tooltip-inner {
|
||||
border-radius: 1px !important;
|
||||
}
|
||||
|
||||
.media-item, .media-preview, .media-image, .js-media-added .br--4 {
|
||||
.media-item, .media-preview, .media-image, .js-media-added .br--4, #tduck .compose-message-recipient img {
|
||||
border-radius: 1px !important;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,15 @@ button {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
#tduck .lst-launcher a {
|
||||
border: 1px solid transparent !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
#tduck .lst-launcher a:hover, #tduck .lst-launcher a:focus, #tduck .lst-launcher a:active {
|
||||
border-color: #bbddf5 !important;
|
||||
}
|
||||
|
||||
/***********************/
|
||||
/* Hide TweetDeck logo */
|
||||
/***********************/
|
||||
|
@@ -132,13 +132,16 @@
|
||||
//
|
||||
// Block: Check updates on startup.
|
||||
//
|
||||
if ("$" in window && typeof $._data === "function" && "TD" in $._data(document, "events")){
|
||||
$(document).one("TD.ready", function(){
|
||||
$TDU.triggerUpdateCheck();
|
||||
});
|
||||
}
|
||||
else{
|
||||
const triggerCheck = function(){
|
||||
$TDU.triggerUpdateCheck();
|
||||
};
|
||||
|
||||
try{
|
||||
throw false if !($._data(document, "events").TD.some(obj => obj.namespace === "ready"));
|
||||
|
||||
$(document).one("TD.ready", triggerCheck);
|
||||
}catch(err){
|
||||
setTimeout(triggerCheck, 500);
|
||||
}
|
||||
|
||||
//
|
||||
|
@@ -58,6 +58,7 @@
|
||||
<Compile Include="Configuration\SystemConfig.cs" />
|
||||
<Compile Include="Configuration\UserConfig.cs" />
|
||||
<Compile Include="Core\Bridge\PropertyBridge.cs" />
|
||||
<Compile Include="Core\Bridge\UpdateBridge.cs" />
|
||||
<Compile Include="Core\Controls\ControlExtensions.cs" />
|
||||
<Compile Include="Core\Controls\FlatButton.cs">
|
||||
<SubType>Component</SubType>
|
||||
@@ -283,7 +284,7 @@
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Reporter.cs" />
|
||||
<Compile Include="Updates\Events\UpdateCheckEventArgs.cs" />
|
||||
<Compile Include="Updates\UpdateCheckEventArgs.cs" />
|
||||
<Compile Include="Updates\FormUpdateDownload.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -306,7 +307,6 @@
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Resources\ScriptLoader.cs" />
|
||||
<Compile Include="Updates\Events\UpdateEventArgs.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
|
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace TweetDuck.Updates.Events{
|
||||
sealed class UpdateEventArgs : EventArgs{
|
||||
public UpdateInfo UpdateInfo { get; }
|
||||
|
||||
public UpdateEventArgs(UpdateInfo updateInfo){
|
||||
this.UpdateInfo = updateInfo;
|
||||
}
|
||||
}
|
||||
}
|
@@ -20,7 +20,7 @@ namespace TweetDuck.Updates{
|
||||
}
|
||||
|
||||
private void timerDownloadCheck_Tick(object sender, EventArgs e){
|
||||
if (updateInfo.DownloadStatus.IsFinished()){
|
||||
if (updateInfo.DownloadStatus.IsFinished(false)){
|
||||
timerDownloadCheck.Stop();
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
|
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using TweetDuck.Data;
|
||||
|
||||
namespace TweetDuck.Updates.Events{
|
||||
namespace TweetDuck.Updates{
|
||||
sealed class UpdateCheckEventArgs : EventArgs{
|
||||
public int EventId { get; }
|
||||
public Result<UpdateInfo> Result { get; }
|
@@ -9,8 +9,8 @@
|
||||
}
|
||||
|
||||
public static class UpdateDownloadStatusExtensions{
|
||||
public static bool IsFinished(this UpdateDownloadStatus status){
|
||||
return status == UpdateDownloadStatus.AssetMissing || status == UpdateDownloadStatus.Done || status == UpdateDownloadStatus.Failed;
|
||||
public static bool IsFinished(this UpdateDownloadStatus status, bool canRetry){
|
||||
return status == UpdateDownloadStatus.AssetMissing || status == UpdateDownloadStatus.Done || (status == UpdateDownloadStatus.Failed && !canRetry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,38 +1,24 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using TweetDuck.Core.Controls;
|
||||
using TweetDuck.Core.Other.Interfaces;
|
||||
using TweetDuck.Data;
|
||||
using TweetDuck.Updates.Events;
|
||||
using Timer = System.Windows.Forms.Timer;
|
||||
|
||||
namespace TweetDuck.Updates{
|
||||
sealed class UpdateHandler : IDisposable{
|
||||
public const int CheckCodeUpdatesDisabled = -1;
|
||||
public const int CheckCodeNotOnTweetDeck = -2;
|
||||
|
||||
private readonly UpdateCheckClient client;
|
||||
private readonly TaskScheduler scheduler;
|
||||
private readonly ITweetDeckBrowser browser;
|
||||
private readonly Timer timer;
|
||||
|
||||
public event EventHandler<UpdateEventArgs> UpdateAccepted;
|
||||
public event EventHandler<UpdateEventArgs> UpdateDelayed;
|
||||
public event EventHandler<UpdateEventArgs> UpdateDismissed;
|
||||
|
||||
public event EventHandler<UpdateCheckEventArgs> CheckFinished;
|
||||
|
||||
private ushort lastEventId;
|
||||
private UpdateInfo lastUpdateInfo;
|
||||
|
||||
public UpdateHandler(ITweetDeckBrowser browser, string installerFolder){
|
||||
public UpdateHandler(string installerFolder){
|
||||
this.client = new UpdateCheckClient(installerFolder);
|
||||
this.scheduler = TaskScheduler.FromCurrentSynchronizationContext();
|
||||
|
||||
this.browser = browser;
|
||||
this.browser.RegisterBridge("$TDU", new Bridge(this));
|
||||
|
||||
this.timer = new Timer();
|
||||
this.timer.Tick += timer_Tick;
|
||||
}
|
||||
@@ -68,10 +54,6 @@ namespace TweetDuck.Updates{
|
||||
|
||||
public int Check(bool force){
|
||||
if (Program.UserConfig.EnableUpdateCheck || force){
|
||||
if (!browser.IsTweetDeckWebsite){
|
||||
return CheckCodeNotOnTweetDeck;
|
||||
}
|
||||
|
||||
int nextEventId = unchecked(++lastEventId);
|
||||
Task<UpdateInfo> checkTask = client.Check();
|
||||
|
||||
@@ -84,46 +66,6 @@ namespace TweetDuck.Updates{
|
||||
return CheckCodeUpdatesDisabled;
|
||||
}
|
||||
|
||||
public void PrepareUpdate(UpdateInfo info){
|
||||
CleanupDownload();
|
||||
lastUpdateInfo = info;
|
||||
lastUpdateInfo.BeginSilentDownload();
|
||||
}
|
||||
|
||||
public void BeginUpdateDownload(Form ownerForm, UpdateInfo updateInfo, Action<UpdateInfo> onFinished){
|
||||
UpdateDownloadStatus status = updateInfo.DownloadStatus;
|
||||
|
||||
if (status == UpdateDownloadStatus.Done || status == UpdateDownloadStatus.AssetMissing){
|
||||
onFinished(updateInfo);
|
||||
}
|
||||
else{
|
||||
FormUpdateDownload downloadForm = new FormUpdateDownload(updateInfo);
|
||||
|
||||
downloadForm.VisibleChanged += (sender, args) => {
|
||||
downloadForm.MoveToCenter(ownerForm);
|
||||
ownerForm.Hide();
|
||||
};
|
||||
|
||||
downloadForm.FormClosed += (sender, args) => {
|
||||
if (downloadForm.DialogResult != DialogResult.OK){
|
||||
updateInfo.CancelDownload();
|
||||
}
|
||||
|
||||
downloadForm.Dispose();
|
||||
onFinished(updateInfo);
|
||||
};
|
||||
|
||||
downloadForm.Show();
|
||||
}
|
||||
}
|
||||
|
||||
public void CleanupDownload(){
|
||||
if (lastUpdateInfo != null){
|
||||
lastUpdateInfo.DeleteInstaller();
|
||||
lastUpdateInfo = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleUpdateCheckSuccessful(int eventId, UpdateInfo info){
|
||||
CheckFinished?.Invoke(this, new UpdateCheckEventArgs(eventId, new Result<UpdateInfo>(info)));
|
||||
}
|
||||
@@ -131,48 +73,5 @@ namespace TweetDuck.Updates{
|
||||
private void HandleUpdateCheckFailed(int eventId, Exception exception){
|
||||
CheckFinished?.Invoke(this, new UpdateCheckEventArgs(eventId, new Result<UpdateInfo>(exception)));
|
||||
}
|
||||
|
||||
private void TriggerUpdateAcceptedEvent(){
|
||||
if (lastUpdateInfo != null){
|
||||
UpdateAccepted?.Invoke(this, new UpdateEventArgs(lastUpdateInfo));
|
||||
}
|
||||
}
|
||||
|
||||
private void TriggerUpdateDelayedEvent(){
|
||||
if (lastUpdateInfo != null){
|
||||
UpdateDelayed?.Invoke(this, new UpdateEventArgs(lastUpdateInfo));
|
||||
}
|
||||
}
|
||||
|
||||
private void TriggerUpdateDismissedEvent(){
|
||||
if (lastUpdateInfo != null){
|
||||
UpdateDismissed?.Invoke(this, new UpdateEventArgs(lastUpdateInfo));
|
||||
CleanupDownload();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Bridge{
|
||||
private readonly UpdateHandler owner;
|
||||
|
||||
public Bridge(UpdateHandler owner){
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public void TriggerUpdateCheck(){
|
||||
owner.Check(false);
|
||||
}
|
||||
|
||||
public void OnUpdateAccepted(){
|
||||
owner.TriggerUpdateAcceptedEvent();
|
||||
}
|
||||
|
||||
public void OnUpdateDelayed(){
|
||||
owner.TriggerUpdateDelayedEvent();
|
||||
}
|
||||
|
||||
public void OnUpdateDismissed(){
|
||||
owner.TriggerUpdateDismissedEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -26,6 +26,11 @@ namespace TweetDuck.Updates{
|
||||
}
|
||||
|
||||
public void BeginSilentDownload(){
|
||||
if (File.Exists(InstallerPath)){
|
||||
DownloadStatus = UpdateDownloadStatus.Done;
|
||||
return;
|
||||
}
|
||||
|
||||
if (DownloadStatus == UpdateDownloadStatus.None || DownloadStatus == UpdateDownloadStatus.Failed){
|
||||
DownloadStatus = UpdateDownloadStatus.InProgress;
|
||||
|
||||
|
@@ -18,6 +18,9 @@ namespace TweetDuck.Video{
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetForegroundWindow();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool SetProcessDPIAware();
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RECT{
|
||||
public int Left;
|
||||
|
@@ -5,7 +5,7 @@ using System.Windows.Forms;
|
||||
|
||||
namespace TweetDuck.Video{
|
||||
static class Program{
|
||||
internal const string Version = "1.2.2.2";
|
||||
internal const string Version = "1.3";
|
||||
|
||||
// referenced in VideoPlayer
|
||||
// set by task manager -- public const int CODE_PROCESS_KILLED = 1;
|
||||
@@ -19,6 +19,7 @@ namespace TweetDuck.Video{
|
||||
private static int Main(string[] args){
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
NativeMethods.SetProcessDPIAware();
|
||||
|
||||
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
|
||||
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
|
||||
|
Reference in New Issue
Block a user