1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-04-18 15:15:48 +02:00

Add "Save all images as..." context menu option for tweets with multiple images

This commit is contained in:
chylex 2017-07-21 12:14:15 +02:00
parent cb24a859f4
commit b35e4d4d01
4 changed files with 59 additions and 20 deletions
Core
Resources/Scripts

View File

@ -10,9 +10,11 @@ sealed class TweetDeckBridge{
public static string LastRightClickedImage = string.Empty; public static string LastRightClickedImage = string.Empty;
public static string LastHighlightedTweet = string.Empty; public static string LastHighlightedTweet = string.Empty;
public static string LastHighlightedQuotedTweet = string.Empty; public static string LastHighlightedQuotedTweet = string.Empty;
public static string[] LastHighlightedTweetImages = new string[0];
public static void ResetStaticProperties(){ public static void ResetStaticProperties(){
LastRightClickedLink = LastRightClickedImage = LastHighlightedTweet = LastHighlightedQuotedTweet = string.Empty; LastRightClickedLink = LastRightClickedImage = LastHighlightedTweet = LastHighlightedQuotedTweet = string.Empty;
LastHighlightedTweetImages = new string[0];
} }
private readonly FormBrowser form; private readonly FormBrowser form;
@ -43,10 +45,11 @@ public void SetLastRightClickedImage(string link){
form.InvokeAsyncSafe(() => LastRightClickedImage = link); form.InvokeAsyncSafe(() => LastRightClickedImage = link);
} }
public void SetLastHighlightedTweet(string link, string quotedLink){ public void SetLastHighlightedTweet(string link, string quotedLink, string imageList){
form.InvokeAsyncSafe(() => { form.InvokeAsyncSafe(() => {
LastHighlightedTweet = link; LastHighlightedTweet = link;
LastHighlightedQuotedTweet = quotedLink; LastHighlightedQuotedTweet = quotedLink;
LastHighlightedTweetImages = imageList.Split(';');
}); });
} }

View File

@ -25,12 +25,15 @@ private static string GetImage(IContextMenuParams parameters){
private const int MenuOpenLinkUrl = 26500; private const int MenuOpenLinkUrl = 26500;
private const int MenuCopyLinkUrl = 26501; private const int MenuCopyLinkUrl = 26501;
private const int MenuCopyUsername = 26502; private const int MenuCopyUsername = 26502;
private const int MenuOpenImage = 26503; private const int MenuOpenImageUrl = 26503;
private const int MenuSaveImage = 26504; private const int MenuCopyImageUrl = 26504;
private const int MenuCopyImageUrl = 26505; private const int MenuSaveImage = 26505;
private const int MenuSaveAllImages = 26506;
private const int MenuOpenDevTools = 26599; private const int MenuOpenDevTools = 26599;
private readonly Form form; private readonly Form form;
private string[] lastHighlightedTweetImageList;
protected ContextMenuBase(Form form){ protected ContextMenuBase(Form form){
this.form = form; this.form = form;
@ -38,6 +41,7 @@ protected ContextMenuBase(Form form){
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){ public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
bool hasTweetImage = !string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedImage); bool hasTweetImage = !string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedImage);
lastHighlightedTweetImageList = TweetDeckBridge.LastHighlightedTweetImages;
if (parameters.TypeFlags.HasFlag(ContextMenuType.Link) && !parameters.UnfilteredLinkUrl.EndsWith("tweetdeck.twitter.com/#", StringComparison.Ordinal) && !hasTweetImage){ if (parameters.TypeFlags.HasFlag(ContextMenuType.Link) && !parameters.UnfilteredLinkUrl.EndsWith("tweetdeck.twitter.com/#", StringComparison.Ordinal) && !hasTweetImage){
if (RegexTwitterAccount.Value.IsMatch(parameters.UnfilteredLinkUrl)){ if (RegexTwitterAccount.Value.IsMatch(parameters.UnfilteredLinkUrl)){
@ -54,9 +58,14 @@ public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser bro
} }
if ((parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents) || hasTweetImage){ if ((parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents) || hasTweetImage){
model.AddItem((CefMenuCommand)MenuOpenImage, "Open image in browser"); model.AddItem((CefMenuCommand)MenuOpenImageUrl, "Open image in browser");
model.AddItem((CefMenuCommand)MenuSaveImage, "Save image as...");
model.AddItem((CefMenuCommand)MenuCopyImageUrl, "Copy image address"); model.AddItem((CefMenuCommand)MenuCopyImageUrl, "Copy image address");
model.AddItem((CefMenuCommand)MenuSaveImage, "Save image as...");
if (lastHighlightedTweetImageList.Length > 1){
model.AddItem((CefMenuCommand)MenuSaveAllImages, "Save all images as...");
}
model.AddSeparator(); model.AddSeparator();
} }
} }
@ -71,7 +80,7 @@ public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser br
SetClipboardText(GetLink(parameters)); SetClipboardText(GetLink(parameters));
break; break;
case MenuOpenImage: case MenuOpenImageUrl:
BrowserUtils.OpenExternalBrowser(TwitterUtils.GetImageLink(GetImage(parameters), ImageQuality)); BrowserUtils.OpenExternalBrowser(TwitterUtils.GetImageLink(GetImage(parameters), ImageQuality));
break; break;
@ -79,6 +88,10 @@ public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser br
TwitterUtils.DownloadImage(GetImage(parameters), ImageQuality); TwitterUtils.DownloadImage(GetImage(parameters), ImageQuality);
break; break;
case MenuSaveAllImages:
TwitterUtils.DownloadImages(lastHighlightedTweetImageList, ImageQuality);
break;
case MenuCopyImageUrl: case MenuCopyImageUrl:
SetClipboardText(TwitterUtils.GetImageLink(GetImage(parameters), ImageQuality)); SetClipboardText(TwitterUtils.GetImageLink(GetImage(parameters), ImageQuality));
break; break;

View File

@ -1,4 +1,5 @@
using CefSharp; using System;
using CefSharp;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
@ -46,22 +47,42 @@ public static string GetImageLink(string url, ImageQuality quality){
return url; return url;
} }
} }
public static void DownloadImage(string url, ImageQuality quality){ public static void DownloadImage(string url, ImageQuality quality){
string file = BrowserUtils.GetFileNameFromUrl(ExtractImageBaseLink(url)); DownloadImages(new string[]{ url }, quality);
}
public static void DownloadImages(string[] urls, ImageQuality quality){
if (urls.Length == 0){
return;
}
string file = BrowserUtils.GetFileNameFromUrl(ExtractImageBaseLink(urls[0]));
string ext = Path.GetExtension(file); // includes dot string ext = Path.GetExtension(file); // includes dot
using(SaveFileDialog dialog = new SaveFileDialog{ using(SaveFileDialog dialog = new SaveFileDialog{
AutoUpgradeEnabled = true, AutoUpgradeEnabled = true,
OverwritePrompt = true, OverwritePrompt = urls.Length == 1,
Title = "Save image", Title = "Save image",
FileName = file, FileName = file,
Filter = string.IsNullOrEmpty(ext) ? "Image (unknown)|*.*" : $"Image (*{ext})|*{ext}" Filter = (urls.Length == 1 ? "Image" : "Images")+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
}){ }){
if (dialog.ShowDialog() == DialogResult.OK){ if (dialog.ShowDialog() == DialogResult.OK){
BrowserUtils.DownloadFileAsync(GetImageLink(url, quality), dialog.FileName, null, ex => { void OnFailure(Exception ex){
FormMessage.Error("Image Download", "An error occurred while downloading the image: "+ex.Message, FormMessage.OK); FormMessage.Error("Image Download", "An error occurred while downloading the image: "+ex.Message, FormMessage.OK);
}); }
if (urls.Length == 1){
BrowserUtils.DownloadFileAsync(GetImageLink(urls[0], quality), dialog.FileName, null, OnFailure);
}
else{
string pathBase = Path.ChangeExtension(dialog.FileName, null);
string pathExt = Path.GetExtension(dialog.FileName);
for(int index = 0; index < urls.Length; index++){
BrowserUtils.DownloadFileAsync(GetImageLink(urls[index], quality), pathBase+(index+1)+pathExt, null, OnFailure);
}
}
} }
} }
} }

View File

@ -363,12 +363,12 @@
return !!highlightedColumnObj; return !!highlightedColumnObj;
}; };
var updateHighlightedTweet = function(ele, obj, link, embeddedLink){ var updateHighlightedTweet = function(ele, obj, link, embeddedLink, imageList){
highlightedTweetEle = ele; highlightedTweetEle = ele;
highlightedTweetObj = obj; highlightedTweetObj = obj;
if (lastTweet !== link){ if (lastTweet !== link){
$TD.setLastHighlightedTweet(link, embeddedLink); $TD.setLastHighlightedTweet(link, embeddedLink, imageList);
lastTweet = link; lastTweet = link;
} }
}; };
@ -398,16 +398,18 @@
if (tweet.chirpType === TD.services.ChirpBase.TWEET){ if (tweet.chirpType === TD.services.ChirpBase.TWEET){
var link = tweet.getChirpURL(); var link = tweet.getChirpURL();
var embedded = tweet.quotedTweet ? tweet.quotedTweet.getChirpURL() : ""; var embedded = tweet.quotedTweet ? tweet.quotedTweet.getChirpURL() : "";
var images = tweet.hasImage() ? tweet.getMedia().filter(item => !item.isAnimatedGif).map(item => item.entity.media_url_https+":small").join(";") : "";
updateHighlightedTweet(me, tweet, link || "", embedded || ""); // TODO maybe handle embedded images too?
updateHighlightedTweet(me, tweet, link || "", embedded || "", images);
} }
else{ else{
updateHighlightedTweet(me, tweet, "", ""); updateHighlightedTweet(me, tweet, "", "", "");
} }
} }
} }
else if (e.type === "mouseleave"){ else if (e.type === "mouseleave"){
updateHighlightedTweet(null, null, "", ""); updateHighlightedTweet(null, null, "", "", "");
} }
}); });
})(); })();