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

Compare commits

..

8 Commits
1.15 ... 1.15.1

22 changed files with 219 additions and 218 deletions

View File

@@ -7,7 +7,6 @@ namespace TweetDuck.Configuration{
public const string ArgDataFolder = "-datafolder"; public const string ArgDataFolder = "-datafolder";
public const string ArgLogging = "-log"; public const string ArgLogging = "-log";
public const string ArgIgnoreGDPR = "-nogdpr"; public const string ArgIgnoreGDPR = "-nogdpr";
public const string ArgNotificationScrollWA = "-nscrollwa";
// internal args // internal args
public const string ArgRestart = "-restart"; public const string ArgRestart = "-restart";

View 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;
}
}
}

View File

@@ -17,7 +17,6 @@ using TweetDuck.Plugins;
using TweetDuck.Plugins.Enums; using TweetDuck.Plugins.Enums;
using TweetDuck.Plugins.Events; using TweetDuck.Plugins.Events;
using TweetDuck.Updates; using TweetDuck.Updates;
using TweetDuck.Updates.Events;
namespace TweetDuck.Core{ namespace TweetDuck.Core{
sealed partial class FormBrowser : Form, AnalyticsFile.IProvider{ sealed partial class FormBrowser : Form, AnalyticsFile.IProvider{
@@ -50,6 +49,7 @@ namespace TweetDuck.Core{
private readonly UpdateHandler updates; private readonly UpdateHandler updates;
private readonly FormNotificationTweet notification; private readonly FormNotificationTweet notification;
private readonly ContextMenu contextMenu; private readonly ContextMenu contextMenu;
private readonly UpdateBridge updateBridge;
private bool isLoaded; private bool isLoaded;
private FormWindowState prevState; private FormWindowState prevState;
@@ -62,7 +62,7 @@ namespace TweetDuck.Core{
InitializeComponent(); InitializeComponent();
Text = Program.BrandName; Text = Program.BrandName;
this.plugins = new PluginManager(Program.PluginPath, Program.PluginConfigFilePath); this.plugins = new PluginManager(Program.PluginPath, Program.PluginConfigFilePath);
this.plugins.Reloaded += plugins_Reloaded; this.plugins.Reloaded += plugins_Reloaded;
this.plugins.Executed += plugins_Executed; this.plugins.Executed += plugins_Executed;
@@ -71,7 +71,15 @@ namespace TweetDuck.Core{
this.notification = new FormNotificationTweet(this, plugins); this.notification = new FormNotificationTweet(this, plugins);
this.notification.Show(); 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.contextMenu = ContextMenuBrowser.CreateMenu(this);
this.plugins.Register(browser, PluginEnvironment.Browser, this, true); this.plugins.Register(browser, PluginEnvironment.Browser, this, true);
@@ -103,11 +111,6 @@ namespace TweetDuck.Core{
UpdateFormIcon(); 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){ if (Config.AllowDataCollection){
analytics = new AnalyticsManager(this, plugins, Program.AnalyticsFilePath); analytics = new AnalyticsManager(this, plugins, Program.AnalyticsFilePath);
} }
@@ -207,7 +210,7 @@ namespace TweetDuck.Core{
private void FormBrowser_FormClosed(object sender, FormClosedEventArgs e){ private void FormBrowser_FormClosed(object sender, FormClosedEventArgs e){
if (isLoaded && UpdateInstallerPath == null){ if (isLoaded && UpdateInstallerPath == null){
updates.CleanupDownload(); updateBridge.Cleanup();
} }
} }
@@ -252,7 +255,7 @@ namespace TweetDuck.Core{
string tag = update.VersionTag; string tag = update.VersionTag;
if (tag != Program.VersionTag && tag != Config.DismissedUpdate){ if (tag != Program.VersionTag && tag != Config.DismissedUpdate){
updates.PrepareUpdate(update); update.BeginSilentDownload();
browser.ShowUpdateNotification(tag, update.ReleaseNotes); browser.ShowUpdateNotification(tag, update.ReleaseNotes);
} }
else{ else{
@@ -268,38 +271,61 @@ namespace TweetDuck.Core{
ignoreUpdateCheckError = true; ignoreUpdateCheckError = true;
} }
private void updates_UpdateAccepted(object sender, UpdateEventArgs e){ private void updateBridge_UpdateAccepted(object sender, UpdateInfo update){
this.InvokeAsyncSafe(() => { FormManager.CloseAllDialogs();
FormManager.CloseAllDialogs();
if (!string.IsNullOrEmpty(Config.DismissedUpdate)){ if (!string.IsNullOrEmpty(Config.DismissedUpdate)){
Config.DismissedUpdate = null; Config.DismissedUpdate = null;
Config.Save(); 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 => { downloadForm.VisibleChanged += (sender2, args2) => {
UpdateDownloadStatus status = update.DownloadStatus; downloadForm.MoveToCenter(this);
Hide();
};
if (status == UpdateDownloadStatus.Done){ downloadForm.FormClosed += (sender2, args2) => {
UpdateInstallerPath = update.InstallerPath; if (downloadForm.DialogResult != DialogResult.OK){
ForceClose(); 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); downloadForm.Dispose();
ForceClose(); OnFinished();
} };
else{
Show(); downloadForm.Show();
} }
});
});
} }
private void updates_UpdateDismissed(object sender, UpdateEventArgs e){ private void updateBridge_UpdateDelayed(object sender, UpdateInfo update){
this.InvokeAsyncSafe(() => { // stops the timer
Config.DismissedUpdate = e.UpdateInfo.VersionTag; }
Config.Save();
}); private void updateBridge_UpdateDismissed(object sender, UpdateInfo update){
Config.DismissedUpdate = update.VersionTag;
Config.Save();
} }
protected override void WndProc(ref Message m){ protected override void WndProc(ref Message m){

View File

@@ -2,7 +2,6 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using TweetDuck.Configuration;
using TweetDuck.Core.Bridge; using TweetDuck.Core.Bridge;
using TweetDuck.Core.Controls; using TweetDuck.Core.Controls;
using TweetDuck.Core.Handling; using TweetDuck.Core.Handling;
@@ -132,14 +131,7 @@ namespace TweetDuck.Core.Notification{
int eventType = wParam.ToInt32(); int eventType = wParam.ToInt32();
if (eventType == NativeMethods.WM_MOUSEWHEEL && IsCursorOverBrowser){ if (eventType == NativeMethods.WM_MOUSEWHEEL && IsCursorOverBrowser){
if (Arguments.HasFlag(Arguments.ArgNotificationScrollWA)){ browser.SendMouseWheelEvent(0, 0, 0, BrowserUtils.Scale(NativeMethods.GetMouseHookData(lParam), Program.UserConfig.NotificationScrollSpeed*0.01), CefEventFlags.None);
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);
}
return NativeMethods.HOOK_HANDLED; return NativeMethods.HOOK_HANDLED;
} }
else if (eventType == NativeMethods.WM_XBUTTONDOWN && DesktopBounds.Contains(Cursor.Position)){ else if (eventType == NativeMethods.WM_XBUTTONDOWN && DesktopBounds.Contains(Cursor.Position)){

View File

@@ -7,7 +7,6 @@ using TweetDuck.Core.Handling.General;
using TweetDuck.Core.Other.Settings.Dialogs; using TweetDuck.Core.Other.Settings.Dialogs;
using TweetDuck.Core.Utils; using TweetDuck.Core.Utils;
using TweetDuck.Updates; using TweetDuck.Updates;
using TweetDuck.Updates.Events;
namespace TweetDuck.Core.Other.Settings{ namespace TweetDuck.Core.Other.Settings{
sealed partial class TabSettingsGeneral : BaseTabSettings{ sealed partial class TabSettingsGeneral : BaseTabSettings{
@@ -210,11 +209,6 @@ namespace TweetDuck.Core.Other.Settings{
btnCheckUpdates.Enabled = false; btnCheckUpdates.Enabled = false;
updateCheckEventId = updates.Check(true); 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){ private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){

View File

@@ -9,7 +9,6 @@ using TweetDuck.Core.Bridge;
using TweetDuck.Core.Controls; using TweetDuck.Core.Controls;
using TweetDuck.Core.Handling; using TweetDuck.Core.Handling;
using TweetDuck.Core.Handling.General; using TweetDuck.Core.Handling.General;
using TweetDuck.Core.Management;
using TweetDuck.Core.Notification; using TweetDuck.Core.Notification;
using TweetDuck.Core.Other.Interfaces; using TweetDuck.Core.Other.Interfaces;
using TweetDuck.Core.Utils; using TweetDuck.Core.Utils;
@@ -40,7 +39,7 @@ namespace TweetDuck.Core{
private string prevSoundNotificationPath = null; private string prevSoundNotificationPath = null;
public TweetDeckBrowser(FormBrowser owner, TweetDeckBridge bridge){ public TweetDeckBrowser(FormBrowser owner, TweetDeckBridge tdBridge, UpdateBridge updateBridge){
RequestHandlerBrowser requestHandler = new RequestHandlerBrowser(); RequestHandlerBrowser requestHandler = new RequestHandlerBrowser();
this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){ this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){
@@ -58,7 +57,8 @@ namespace TweetDuck.Core{
this.browser.FrameLoadEnd += browser_FrameLoadEnd; this.browser.FrameLoadEnd += browser_FrameLoadEnd;
this.browser.LoadError += browser_LoadError; 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.BrowserSettings.BackgroundColor = (uint)TwitterUtils.BackgroundColor.ToArgb();
this.browser.Dock = DockStyle.None; this.browser.Dock = DockStyle.None;
@@ -146,25 +146,28 @@ namespace TweetDuck.Core{
private void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){ private void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
IFrame frame = e.Frame; IFrame frame = e.Frame;
if (frame.IsMain && TwitterUtils.IsTweetDeckWebsite(frame)){ if (frame.IsMain){
UpdateProperties(); if (TwitterUtils.IsTweetDeckWebsite(frame)){
TweetDeckBridge.RestoreSessionData(frame); UpdateProperties();
ScriptLoader.ExecuteFile(frame, "code.js", browser); 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); 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);
}
} }
} }

View File

@@ -22,7 +22,17 @@ namespace TweetDuck.Core.Utils{
args["disable-gpu-vsync"] = "1"; 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"; args["disable-smooth-scrolling"] = "1";
} }

View File

@@ -76,22 +76,14 @@ namespace TweetDuck.Core.Utils{
string firstImageLink = GetMediaLink(urls[0], quality); string firstImageLink = GetMediaLink(urls[0], quality);
int qualityIndex = firstImageLink.IndexOf(':', firstImageLink.LastIndexOf('/')); int qualityIndex = firstImageLink.IndexOf(':', firstImageLink.LastIndexOf('/'));
string file = GetImageFileName(firstImageLink); string filename = GetImageFileName(firstImageLink);
string ext = Path.GetExtension(file); // includes dot string ext = Path.GetExtension(filename); // includes dot
string[] fileNameParts = qualityIndex == -1 ? new string[]{
Path.ChangeExtension(file, null)
} : new string[]{
username,
Path.ChangeExtension(file, null),
firstImageLink.Substring(qualityIndex+1)
};
using(SaveFileDialog dialog = new SaveFileDialog{ using(SaveFileDialog dialog = new SaveFileDialog{
AutoUpgradeEnabled = true, AutoUpgradeEnabled = true,
OverwritePrompt = urls.Length == 1, OverwritePrompt = urls.Length == 1,
Title = "Save Image", 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}") Filter = (urls.Length == 1 ? "Image" : "Images")+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
}){ }){
if (dialog.ShowDialog() == DialogResult.OK){ if (dialog.ShowDialog() == DialogResult.OK){
@@ -122,12 +114,12 @@ namespace TweetDuck.Core.Utils{
AutoUpgradeEnabled = true, AutoUpgradeEnabled = true,
OverwritePrompt = true, OverwritePrompt = true,
Title = "Save Video", 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}") Filter = "Video"+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
}){ }){
if (dialog.ShowDialog() == DialogResult.OK){ if (dialog.ShowDialog() == DialogResult.OK){
BrowserUtils.DownloadFileAsync(url, dialog.FileName, null, ex => { 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);
}); });
} }
} }

View File

@@ -19,7 +19,7 @@ namespace TweetDuck{
public const string BrandName = "TweetDuck"; public const string BrandName = "TweetDuck";
public const string Website = "https://tweetduck.chylex.com"; 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 string ProgramPath = AppDomain.CurrentDomain.BaseDirectory;
public static readonly bool IsPortable = File.Exists(Path.Combine(ProgramPath, "makeportable")); public static readonly bool IsPortable = File.Exists(Path.Combine(ProgramPath, "makeportable"));

View File

@@ -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 .s-minimal .mdl-header{border-bottom:1px solid #e1e8ed}
html.dark .lst-launcher .top-row{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 .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 .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-col-settings{background-color:#fff;border-left:1px solid #E1E8ED}
html.dark .mdl-links{color:#8899a6} html.dark .mdl-links{color:#8899a6}

View File

@@ -6,8 +6,10 @@
z-index: 9999; z-index: 9999;
color: #fff; color: #fff;
background-color: rgb(32, 94, 138); background-color: rgb(32, 94, 138);
font-family: Helvetica, Arial, Verdana, sans-serif;
text-align: center; text-align: center;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5); text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
line-height: 1.28578;
transition: transform 400ms cubic-bezier(.02, .01, .47, 1); transition: transform 400ms cubic-bezier(.02, .01, .47, 1);
} }
@@ -67,6 +69,8 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.5);
font-family: Helvetica, Arial, Verdana, sans-serif;
line-height: 1.28578;
z-index: 9998; z-index: 9998;
} }
@@ -82,14 +86,16 @@
overflow-y: auto; overflow-y: auto;
transform: translateX(-50%) translateY(-50%); transform: translateX(-50%) translateY(-50%);
font-size: 14px; font-size: 14px;
color: #000; color: #2f2f2f;
background-color: #fff; background-color: #fff;
box-sizing: border-box; box-sizing: border-box;
} }
#tweetduck-changelog h2 { #tweetduck-changelog h2 {
margin: 0 0 7px; margin: 0 0 8px;
color: #5c6973;
font-size: 23px; font-size: 23px;
line-height: 1.28578;
} }
#tweetduck-changelog h2 + br { #tweetduck-changelog h2 + br {
@@ -98,7 +104,9 @@
#tweetduck-changelog h3 { #tweetduck-changelog h3 {
margin: 0 0 5px 7px; margin: 0 0 5px 7px;
color: #065b9c;
font-size: 18px; font-size: 18px;
line-height: 1.28578;
} }
#tweetduck-changelog p { #tweetduck-changelog p {

View File

@@ -42,7 +42,7 @@ button, .btn, .mdl, .mdl-content, .popover, .lst-modal, .tooltip-inner {
border-radius: 1px !important; 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; border-radius: 1px !important;
} }
@@ -100,6 +100,15 @@ button {
margin-bottom: 0 !important; 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 */ /* Hide TweetDeck logo */
/***********************/ /***********************/

View File

@@ -132,13 +132,16 @@
// //
// Block: Check updates on startup. // Block: Check updates on startup.
// //
if ("$" in window && typeof $._data === "function" && "TD" in $._data(document, "events")){ const triggerCheck = function(){
$(document).one("TD.ready", function(){
$TDU.triggerUpdateCheck();
});
}
else{
$TDU.triggerUpdateCheck(); $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);
} }
// //

View File

@@ -58,6 +58,7 @@
<Compile Include="Configuration\SystemConfig.cs" /> <Compile Include="Configuration\SystemConfig.cs" />
<Compile Include="Configuration\UserConfig.cs" /> <Compile Include="Configuration\UserConfig.cs" />
<Compile Include="Core\Bridge\PropertyBridge.cs" /> <Compile Include="Core\Bridge\PropertyBridge.cs" />
<Compile Include="Core\Bridge\UpdateBridge.cs" />
<Compile Include="Core\Controls\ControlExtensions.cs" /> <Compile Include="Core\Controls\ControlExtensions.cs" />
<Compile Include="Core\Controls\FlatButton.cs"> <Compile Include="Core\Controls\FlatButton.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
@@ -283,7 +284,7 @@
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="Reporter.cs" /> <Compile Include="Reporter.cs" />
<Compile Include="Updates\Events\UpdateCheckEventArgs.cs" /> <Compile Include="Updates\UpdateCheckEventArgs.cs" />
<Compile Include="Updates\FormUpdateDownload.cs"> <Compile Include="Updates\FormUpdateDownload.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@@ -306,7 +307,6 @@
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources\ScriptLoader.cs" /> <Compile Include="Resources\ScriptLoader.cs" />
<Compile Include="Updates\Events\UpdateEventArgs.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5"> <BootstrapperPackage Include="Microsoft.Net.Client.3.5">

View File

@@ -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;
}
}
}

View File

@@ -20,7 +20,7 @@ namespace TweetDuck.Updates{
} }
private void timerDownloadCheck_Tick(object sender, EventArgs e){ private void timerDownloadCheck_Tick(object sender, EventArgs e){
if (updateInfo.DownloadStatus.IsFinished()){ if (updateInfo.DownloadStatus.IsFinished(false)){
timerDownloadCheck.Stop(); timerDownloadCheck.Stop();
DialogResult = DialogResult.OK; DialogResult = DialogResult.OK;
Close(); Close();

View File

@@ -1,7 +1,7 @@
using System; using System;
using TweetDuck.Data; using TweetDuck.Data;
namespace TweetDuck.Updates.Events{ namespace TweetDuck.Updates{
sealed class UpdateCheckEventArgs : EventArgs{ sealed class UpdateCheckEventArgs : EventArgs{
public int EventId { get; } public int EventId { get; }
public Result<UpdateInfo> Result { get; } public Result<UpdateInfo> Result { get; }

View File

@@ -9,8 +9,8 @@
} }
public static class UpdateDownloadStatusExtensions{ public static class UpdateDownloadStatusExtensions{
public static bool IsFinished(this UpdateDownloadStatus status){ public static bool IsFinished(this UpdateDownloadStatus status, bool canRetry){
return status == UpdateDownloadStatus.AssetMissing || status == UpdateDownloadStatus.Done || status == UpdateDownloadStatus.Failed; return status == UpdateDownloadStatus.AssetMissing || status == UpdateDownloadStatus.Done || (status == UpdateDownloadStatus.Failed && !canRetry);
} }
} }
} }

View File

@@ -1,38 +1,24 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Other.Interfaces;
using TweetDuck.Data; using TweetDuck.Data;
using TweetDuck.Updates.Events;
using Timer = System.Windows.Forms.Timer; using Timer = System.Windows.Forms.Timer;
namespace TweetDuck.Updates{ namespace TweetDuck.Updates{
sealed class UpdateHandler : IDisposable{ sealed class UpdateHandler : IDisposable{
public const int CheckCodeUpdatesDisabled = -1; public const int CheckCodeUpdatesDisabled = -1;
public const int CheckCodeNotOnTweetDeck = -2;
private readonly UpdateCheckClient client; private readonly UpdateCheckClient client;
private readonly TaskScheduler scheduler; private readonly TaskScheduler scheduler;
private readonly ITweetDeckBrowser browser;
private readonly Timer timer; private readonly Timer timer;
public event EventHandler<UpdateEventArgs> UpdateAccepted;
public event EventHandler<UpdateEventArgs> UpdateDelayed;
public event EventHandler<UpdateEventArgs> UpdateDismissed;
public event EventHandler<UpdateCheckEventArgs> CheckFinished; public event EventHandler<UpdateCheckEventArgs> CheckFinished;
private ushort lastEventId; private ushort lastEventId;
private UpdateInfo lastUpdateInfo;
public UpdateHandler(ITweetDeckBrowser browser, string installerFolder){ public UpdateHandler(string installerFolder){
this.client = new UpdateCheckClient(installerFolder); this.client = new UpdateCheckClient(installerFolder);
this.scheduler = TaskScheduler.FromCurrentSynchronizationContext(); this.scheduler = TaskScheduler.FromCurrentSynchronizationContext();
this.browser = browser;
this.browser.RegisterBridge("$TDU", new Bridge(this));
this.timer = new Timer(); this.timer = new Timer();
this.timer.Tick += timer_Tick; this.timer.Tick += timer_Tick;
} }
@@ -68,10 +54,6 @@ namespace TweetDuck.Updates{
public int Check(bool force){ public int Check(bool force){
if (Program.UserConfig.EnableUpdateCheck || force){ if (Program.UserConfig.EnableUpdateCheck || force){
if (!browser.IsTweetDeckWebsite){
return CheckCodeNotOnTweetDeck;
}
int nextEventId = unchecked(++lastEventId); int nextEventId = unchecked(++lastEventId);
Task<UpdateInfo> checkTask = client.Check(); Task<UpdateInfo> checkTask = client.Check();
@@ -84,46 +66,6 @@ namespace TweetDuck.Updates{
return CheckCodeUpdatesDisabled; 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){ private void HandleUpdateCheckSuccessful(int eventId, UpdateInfo info){
CheckFinished?.Invoke(this, new UpdateCheckEventArgs(eventId, new Result<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){ private void HandleUpdateCheckFailed(int eventId, Exception exception){
CheckFinished?.Invoke(this, new UpdateCheckEventArgs(eventId, new Result<UpdateInfo>(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();
}
}
} }
} }

View File

@@ -26,6 +26,11 @@ namespace TweetDuck.Updates{
} }
public void BeginSilentDownload(){ public void BeginSilentDownload(){
if (File.Exists(InstallerPath)){
DownloadStatus = UpdateDownloadStatus.Done;
return;
}
if (DownloadStatus == UpdateDownloadStatus.None || DownloadStatus == UpdateDownloadStatus.Failed){ if (DownloadStatus == UpdateDownloadStatus.None || DownloadStatus == UpdateDownloadStatus.Failed){
DownloadStatus = UpdateDownloadStatus.InProgress; DownloadStatus = UpdateDownloadStatus.InProgress;

View File

@@ -18,6 +18,9 @@ namespace TweetDuck.Video{
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow(); public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern bool SetProcessDPIAware();
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct RECT{ public struct RECT{
public int Left; public int Left;

View File

@@ -5,7 +5,7 @@ using System.Windows.Forms;
namespace TweetDuck.Video{ namespace TweetDuck.Video{
static class Program{ static class Program{
internal const string Version = "1.2.2.2"; internal const string Version = "1.3";
// referenced in VideoPlayer // referenced in VideoPlayer
// set by task manager -- public const int CODE_PROCESS_KILLED = 1; // set by task manager -- public const int CODE_PROCESS_KILLED = 1;
@@ -19,6 +19,7 @@ namespace TweetDuck.Video{
private static int Main(string[] args){ private static int Main(string[] args){
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
NativeMethods.SetProcessDPIAware();
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;