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

Compare commits

...

8 Commits
1.16 ... 1.16.1

13 changed files with 118 additions and 49 deletions

View File

@@ -15,6 +15,7 @@ using TweetDuck.Core.Other.Settings.Dialogs;
using TweetDuck.Core.Utils; using TweetDuck.Core.Utils;
using TweetDuck.Plugins; using TweetDuck.Plugins;
using TweetDuck.Plugins.Events; using TweetDuck.Plugins.Events;
using TweetDuck.Resources;
using TweetDuck.Updates; using TweetDuck.Updates;
namespace TweetDuck.Core{ namespace TweetDuck.Core{
@@ -365,7 +366,11 @@ namespace TweetDuck.Core{
public void ReloadToTweetDeck(){ public void ReloadToTweetDeck(){
#if DEBUG #if DEBUG
Resources.ScriptLoader.HotSwap(); ScriptLoader.HotSwap();
#else
if (ModifierKeys.HasFlag(Keys.Shift)){
ScriptLoader.ClearCache();
}
#endif #endif
ignoreUpdateCheckError = false; ignoreUpdateCheckError = false;

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows.Forms; using System.Windows.Forms;
using CefSharp; using CefSharp;
@@ -123,33 +122,11 @@ namespace TweetDuck.Core.Handling{
break; break;
case MenuViewImage: { case MenuViewImage: {
void ViewImage(string path){
string ext = Path.GetExtension(path);
if (TwitterUtils.ValidImageExtensions.Contains(ext)){
WindowsUtils.OpenAssociatedProgram(path);
}
else{
FormMessage.Error("Image Download", "Invalid file extension "+ext, FormMessage.OK);
}
}
string url = Context.MediaUrl; string url = Context.MediaUrl;
string file = Path.Combine(BrowserCache.CacheFolder, TwitterUtils.GetImageFileName(url) ?? Path.GetRandomFileName());
control.InvokeAsyncSafe(() => { control.InvokeAsyncSafe(() => {
if (File.Exists(file)){ TwitterUtils.ViewImage(url, ImageQuality);
ViewImage(file); analytics.AnalyticsFile.ViewedImages.Trigger();
}
else{
analytics.AnalyticsFile.ViewedImages.Trigger();
BrowserUtils.DownloadFileAsync(TwitterUtils.GetMediaLink(url, ImageQuality), file, () => {
ViewImage(file);
}, ex => {
FormMessage.Error("Image Download", "An error occurred while downloading the image: "+ex.Message, FormMessage.OK);
});
}
}); });
break; break;

View File

@@ -59,7 +59,7 @@ namespace TweetDuck.Core.Notification{
build.Append("<style type='text/css'>").Append(customCSS).Append("</style>"); build.Append("<style type='text/css'>").Append(customCSS).Append("</style>");
} }
build.Append("</head><body class='scroll-styled-v"); build.Append("</head><body class='scroll-styled-v system-font-stack");
if (!string.IsNullOrEmpty(bodyClasses)){ if (!string.IsNullOrEmpty(bodyClasses)){
build.Append(' ').Append(bodyClasses); build.Append(' ').Append(bodyClasses);

View File

@@ -207,9 +207,13 @@ namespace TweetDuck.Core.Utils{
return client; return client;
} }
public static WebClient DownloadFileAsync(string url, string target, Action onSuccess, Action<Exception> onFailure){ public static WebClient DownloadFileAsync(string url, string target, string cookie, Action onSuccess, Action<Exception> onFailure){
WebClient client = CreateWebClient(); WebClient client = CreateWebClient();
if (cookie != null){
client.Headers[HttpRequestHeader.Cookie] = cookie;
}
client.DownloadFileCompleted += (sender, args) => { client.DownloadFileCompleted += (sender, args) => {
if (args.Cancelled){ if (args.Cancelled){
try{ try{

View File

@@ -4,8 +4,12 @@ using System.Drawing;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows.Forms; using System.Windows.Forms;
using TweetDuck.Core.Management;
using TweetDuck.Core.Other; using TweetDuck.Core.Other;
using TweetDuck.Data; using TweetDuck.Data;
using System.Linq;
using System.Threading.Tasks;
using Cookie = CefSharp.Cookie;
namespace TweetDuck.Core.Utils{ namespace TweetDuck.Core.Utils{
static class TwitterUtils{ static class TwitterUtils{
@@ -48,7 +52,10 @@ namespace TweetDuck.Core.Utils{
if (quality == ImageQuality.Orig){ if (quality == ImageQuality.Orig){
string result = ExtractMediaBaseLink(url); string result = ExtractMediaBaseLink(url);
if (result != url || url.Contains("//pbs.twimg.com/media/")){ if (url.Contains("//ton.twitter.com/") && url.Contains("/ton/data/dm/")){
result += ":large";
}
else if (result != url || url.Contains("//pbs.twimg.com/media/")){
result += ":orig"; result += ":orig";
} }
@@ -62,6 +69,32 @@ namespace TweetDuck.Core.Utils{
public static string GetImageFileName(string url){ public static string GetImageFileName(string url){
return BrowserUtils.GetFileNameFromUrl(ExtractMediaBaseLink(url)); return BrowserUtils.GetFileNameFromUrl(ExtractMediaBaseLink(url));
} }
public static void ViewImage(string url, ImageQuality quality){
void ViewImageInternal(string path){
string ext = Path.GetExtension(path);
if (ValidImageExtensions.Contains(ext)){
WindowsUtils.OpenAssociatedProgram(path);
}
else{
FormMessage.Error("Image Download", "Invalid file extension "+ext, FormMessage.OK);
}
}
string file = Path.Combine(BrowserCache.CacheFolder, GetImageFileName(url) ?? Path.GetRandomFileName());
if (WindowsUtils.FileExistsAndNotEmpty(file)){
ViewImageInternal(file);
}
else{
DownloadFileAuth(GetMediaLink(url, quality), file, () => {
ViewImageInternal(file);
}, ex => {
FormMessage.Error("Image Download", "An error occurred while downloading the image: "+ex.Message, FormMessage.OK);
});
}
}
public static void DownloadImage(string url, string username, ImageQuality quality){ public static void DownloadImage(string url, string username, ImageQuality quality){
DownloadImages(new string[]{ url }, username, quality); DownloadImages(new string[]{ url }, username, quality);
@@ -91,14 +124,14 @@ namespace TweetDuck.Core.Utils{
} }
if (urls.Length == 1){ if (urls.Length == 1){
BrowserUtils.DownloadFileAsync(firstImageLink, dialog.FileName, null, OnFailure); DownloadFileAuth(firstImageLink, dialog.FileName, null, OnFailure);
} }
else{ else{
string pathBase = Path.ChangeExtension(dialog.FileName, null); string pathBase = Path.ChangeExtension(dialog.FileName, null);
string pathExt = Path.GetExtension(dialog.FileName); string pathExt = Path.GetExtension(dialog.FileName);
for(int index = 0; index < urls.Length; index++){ for(int index = 0; index < urls.Length; index++){
BrowserUtils.DownloadFileAsync(GetMediaLink(urls[index], quality), $"{pathBase} {index+1}{pathExt}", null, OnFailure); DownloadFileAuth(GetMediaLink(urls[index], quality), $"{pathBase} {index+1}{pathExt}", null, OnFailure);
} }
} }
} }
@@ -117,11 +150,33 @@ namespace TweetDuck.Core.Utils{
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 => { DownloadFileAuth(url, dialog.FileName, null, ex => {
FormMessage.Error("Video Download", "An error occurred while downloading the video: "+ex.Message, FormMessage.OK); FormMessage.Error("Video Download", "An error occurred while downloading the video: "+ex.Message, FormMessage.OK);
}); });
} }
} }
} }
private static void DownloadFileAuth(string url, string target, Action onSuccess, Action<Exception> onFailure){
const string AuthCookieName = "auth_token";
TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();
using(ICookieManager cookies = Cef.GetGlobalCookieManager()){
cookies.VisitUrlCookiesAsync(url, true).ContinueWith(task => {
string cookieStr = null;
if (task.Status == TaskStatus.RanToCompletion){
Cookie found = task.Result?.Find(cookie => cookie.Name == AuthCookieName); // the list may be null
if (found != null){
cookieStr = $"{found.Name}={found.Value}";
}
}
BrowserUtils.DownloadFileAsync(url, target, cookieStr, onSuccess, onFailure);
}, scheduler);
}
}
} }
} }

View File

@@ -66,6 +66,14 @@ namespace TweetDuck.Core.Utils{
} }
} }
public static bool FileExistsAndNotEmpty(string path){
try{
return new FileInfo(path).Length > 0;
}catch{
return false;
}
}
public static bool OpenAssociatedProgram(string file, string arguments = "", bool runElevated = false){ public static bool OpenAssociatedProgram(string file, string arguments = "", bool runElevated = false){
try{ try{
using(Process.Start(new ProcessStartInfo{ using(Process.Start(new ProcessStartInfo{

View File

@@ -20,7 +20,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.16"; public const string VersionTag = "1.16.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

@@ -111,15 +111,17 @@ enabled(){
// styles // styles
this.css = window.TDPF_createCustomStyle(this); this.css = window.TDPF_createCustomStyle(this);
this.css.insert(".js-app-add-column.is-hidden + .clear-columns-btn-all-parent { display: none; }"); this.css.insert(".js-app-add-column.is-hidden + .clear-columns-btn-all-parent { display: none; }");
this.css.insert(".column-header-links { min-width: 51px !important; }");
this.css.insert("[data-td-icon='icon-message'] .column-header-links { min-width: 110px !important; }");
this.css.insert(".column-navigator-overflow .clear-columns-btn-all-parent { display: none !important; }"); this.css.insert(".column-navigator-overflow .clear-columns-btn-all-parent { display: none !important; }");
this.css.insert(".column-navigator-overflow { bottom: 224px !important; }"); this.css.insert(".column-navigator-overflow { bottom: 224px !important; }");
this.css.insert("[data-action='td-clearcolumns-dosingle'] { padding: 3px 0 !important; }");
this.css.insert("[data-action='clear'].btn-options-tray { display: none !important; }"); this.css.insert(".column-header-links { min-width: 51px !important; }");
this.css.insert("[data-td-icon='icon-schedule'] .td-clear-column-shortcut { display: none; }"); this.css.insert(".column[data-td-icon='icon-message'] .column-header-links { min-width: 110px !important; }");
this.css.insert("[data-td-icon='icon-custom-timeline'] .td-clear-column-shortcut { display: none; }"); this.css.insert(".btn-options-tray[data-action='clear'] { display: none !important; }");
this.css.insert(".column[data-td-icon='icon-schedule'] a[data-action='td-clearcolumns-dosingle'] { display: none; }");
this.css.insert(".column[data-td-icon='icon-custom-timeline'] a[data-action='td-clearcolumns-dosingle'] { display: none; }");
} }
ready(){ ready(){

View File

@@ -14,6 +14,7 @@ enabled(){
themeColorTweaks: true, themeColorTweaks: true,
revertIcons: true, revertIcons: true,
showCharacterCount: true, showCharacterCount: true,
forceArialFont: true,
increaseQuoteTextSize: false, increaseQuoteTextSize: false,
smallComposeTextSize: false, smallComposeTextSize: false,
optimizeAnimations: true, optimizeAnimations: true,
@@ -430,6 +431,10 @@ enabled(){
this.css.insert("#tduck .tweet-actions > li:nth-child(4) { margin-right: 2px !important }"); this.css.insert("#tduck .tweet-actions > li:nth-child(4) { margin-right: 2px !important }");
} }
if (this.config.forceArialFont){
this.css.insert("#tduck .system-font-stack { font-family: Arial, sans-serif; font-weight: 400 }");
}
if (this.config.increaseQuoteTextSize){ if (this.config.increaseQuoteTextSize){
this.css.insert(".quoted-tweet { font-size: 1em !important }"); this.css.insert(".quoted-tweet { font-size: 1em !important }");
} }
@@ -595,6 +600,10 @@ ${iconData.map(entry => `#tduck .icon-${entry[0]}:before{content:\"\\f0${entry[1
html[data-td-font] { font-size: ${this.config.fontSize} !important } html[data-td-font] { font-size: ${this.config.fontSize} !important }
.avatar { border-radius: ${this.config.avatarRadius}% !important } .avatar { border-radius: ${this.config.avatarRadius}% !important }
${this.config.forceArialFont ? `
#tduck .system-font-stack { font-family: Arial, sans-serif; font-weight: 400 }
` : ``}
${this.config.increaseQuoteTextSize ? ` ${this.config.increaseQuoteTextSize ? `
.quoted-tweet { font-size: 1em !important } .quoted-tweet { font-size: 1em !important }
` : ``} ` : ``}

View File

@@ -69,6 +69,10 @@
<option value="custom-px">Custom</option> <option value="custom-px">Custom</option>
<option value="change-custom-px">Change custom value...</option> <option value="change-custom-px">Change custom value...</option>
</select> </select>
<label class="checkbox">
<input data-td-key="forceArialFont" class="js-theme-checkbox touch-larger-label" type="checkbox">
Use Arial as default font
</label>
<label class="checkbox"> <label class="checkbox">
<input data-td-key="increaseQuoteTextSize" class="js-theme-checkbox touch-larger-label" type="checkbox"> <input data-td-key="increaseQuoteTextSize" class="js-theme-checkbox touch-larger-label" type="checkbox">
Increase quoted tweet font size Increase quoted tweet font size

View File

@@ -80,6 +80,10 @@ namespace TweetDuck.Resources{
} }
} }
public static void ClearCache(){
CachedData.Clear();
}
private static void ShowLoadError(Control sync, string message){ private static void ShowLoadError(Control sync, string message){
sync?.InvokeSafe(() => FormMessage.Error("Resource Error", message, FormMessage.OK)); sync?.InvokeSafe(() => FormMessage.Error("Resource Error", message, FormMessage.OK));
} }
@@ -128,7 +132,7 @@ namespace TweetDuck.Resources{
sw.Stop(); sw.Stop();
Debug.WriteLine("Finished rebuild script in "+sw.ElapsedMilliseconds+" ms"); Debug.WriteLine("Finished rebuild script in "+sw.ElapsedMilliseconds+" ms");
CachedData.Clear(); ClearCache();
// Force update plugin manager setup scripts // Force update plugin manager setup scripts

View File

@@ -253,9 +253,9 @@ a[data-full-url] {
bottom: 0 !important; bottom: 0 !important;
} }
/**********************************************************/ /**************************************************************************/
/* Prevent column icons from being hidden by column title */ /* Prevent column icons from being hidden by column title & fix alignment */
/**********************************************************/ /**************************************************************************/
.column-header-title { .column-header-title {
overflow: hidden !important; overflow: hidden !important;
@@ -270,9 +270,10 @@ a[data-full-url] {
.column-header-links { .column-header-links {
max-width: 100% !important; max-width: 100% !important;
text-align: right;
} }
[data-td-icon="icon-message"] .column-header-links { .column[data-td-icon="icon-message"] .column-header-links {
min-width: 86px; min-width: 86px;
} }
@@ -455,18 +456,18 @@ a:not(.tweet-detail-action) .reply-triangle {
/* Fix cut off usernames in Messages column */ /* Fix cut off usernames in Messages column */
/********************************************/ /********************************************/
[data-td-icon="icon-message"].is-shifted-1 .column-title-container { .column[data-td-icon="icon-message"].is-shifted-1 .column-title-container {
height: 100%; height: 100%;
border-bottom-color: transparent; border-bottom-color: transparent;
} }
#tduck [data-td-icon="icon-message"].is-shifted-1 .column-title-items { #tduck .column[data-td-icon="icon-message"].is-shifted-1 .column-title-items {
height: 100%; height: 100%;
margin-left: 4px !important; margin-left: 4px !important;
padding-top: 1px; padding-top: 1px;
} }
[data-td-icon="icon-message"].is-shifted-1 .username { .column[data-td-icon="icon-message"].is-shifted-1 .username {
vertical-align: bottom; vertical-align: bottom;
} }

View File

@@ -26,7 +26,7 @@ namespace TweetDuck.Updates{
} }
public void BeginSilentDownload(){ public void BeginSilentDownload(){
if (File.Exists(InstallerPath)){ if (WindowsUtils.FileExistsAndNotEmpty(InstallerPath)){
DownloadStatus = UpdateDownloadStatus.Done; DownloadStatus = UpdateDownloadStatus.Done;
return; return;
} }
@@ -48,7 +48,7 @@ namespace TweetDuck.Updates{
return; return;
} }
currentDownload = BrowserUtils.DownloadFileAsync(downloadUrl, InstallerPath, () => { currentDownload = BrowserUtils.DownloadFileAsync(downloadUrl, InstallerPath, null, () => {
DownloadStatus = UpdateDownloadStatus.Done; DownloadStatus = UpdateDownloadStatus.Done;
currentDownload = null; currentDownload = null;
}, e => { }, e => {