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

Refactor context menu handling and make adding new types of context easier

This commit is contained in:
chylex 2017-08-27 18:18:30 +02:00
parent 588bb9a093
commit 442d74d0cb
5 changed files with 110 additions and 100 deletions

View File

@ -3,6 +3,7 @@
using System.Windows.Forms;
using CefSharp;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Handling;
using TweetDuck.Core.Notification;
using TweetDuck.Core.Other;
using TweetDuck.Core.Utils;
@ -10,8 +11,6 @@
namespace TweetDuck.Core.Bridge{
sealed class TweetDeckBridge{
public static string LastRightClickedLink = string.Empty;
public static string LastRightClickedImage = string.Empty;
public static string LastHighlightedTweet = string.Empty;
public static string LastHighlightedQuotedTweet = string.Empty;
public static string LastHighlightedTweetAuthor = string.Empty;
@ -19,7 +18,7 @@ sealed class TweetDeckBridge{
public static Dictionary<string, string> SessionData = new Dictionary<string, string>(2);
public static void ResetStaticProperties(){
LastRightClickedLink = LastRightClickedImage = LastHighlightedTweet = LastHighlightedQuotedTweet = LastHighlightedTweetAuthor = string.Empty;
LastHighlightedTweet = LastHighlightedQuotedTweet = LastHighlightedTweetAuthor = string.Empty;
LastHighlightedTweetImages = StringUtils.EmptyArray;
}
@ -56,12 +55,8 @@ public void LoadNotificationHeadContents(string headContents){
});
}
public void SetLastRightClickedLink(string link){
form.InvokeAsyncSafe(() => LastRightClickedLink = link);
}
public void SetLastRightClickedImage(string link){
form.InvokeAsyncSafe(() => LastRightClickedImage = link);
public void SetLastRightClickInfo(string type, string link){
form.InvokeAsyncSafe(() => ContextMenuBase.SetContextInfo(type, link));
}
public void SetLastHighlightedTweet(string link, string quotedLink, string author, string imageList){

View File

@ -6,29 +6,35 @@
using TweetDuck.Core.Bridge;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Utils;
using System.Collections.Generic;
namespace TweetDuck.Core.Handling{
abstract class ContextMenuBase : IContextMenuHandler{
protected static readonly bool HasDevTools = File.Exists(Path.Combine(Program.ProgramPath, "devtools_resources.pak"));
private static TwitterUtils.ImageQuality ImageQuality => Program.UserConfig.TwitterImageQuality;
private static KeyValuePair<string, string> ContextInfo;
private static bool IsLink => ContextInfo.Key == "link";
private static bool IsImage => ContextInfo.Key == "image";
private static bool IsVideo => ContextInfo.Key == "video";
private static string GetLink(IContextMenuParams parameters){
return string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedLink) ? parameters.UnfilteredLinkUrl : TweetDeckBridge.LastRightClickedLink;
public static void SetContextInfo(string type, string link){
ContextInfo = new KeyValuePair<string, string>(string.IsNullOrEmpty(link) ? null : type, link);
}
private static string GetImage(IContextMenuParams parameters){
return string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedImage) ? parameters.SourceUrl : TweetDeckBridge.LastRightClickedImage;
private static string GetMediaLink(IContextMenuParams parameters){
return IsImage || IsVideo ? ContextInfo.Value : parameters.SourceUrl;
}
private const int MenuOpenLinkUrl = 26500;
private const int MenuCopyLinkUrl = 26501;
private const int MenuCopyUsername = 26502;
private const int MenuOpenImageUrl = 26503;
private const int MenuCopyImageUrl = 26504;
private const int MenuSaveImage = 26505;
private const int MenuSaveAllImages = 26506;
private const int MenuOpenDevTools = 26599;
private const CefMenuCommand MenuOpenLinkUrl = (CefMenuCommand)26500;
private const CefMenuCommand MenuCopyLinkUrl = (CefMenuCommand)26501;
private const CefMenuCommand MenuCopyUsername = (CefMenuCommand)26502;
private const CefMenuCommand MenuOpenMediaUrl = (CefMenuCommand)26503;
private const CefMenuCommand MenuCopyMediaUrl = (CefMenuCommand)26504;
private const CefMenuCommand MenuSaveMedia = (CefMenuCommand)26505;
private const CefMenuCommand MenuSaveTweetImages = (CefMenuCommand)26506;
private const CefMenuCommand MenuOpenDevTools = (CefMenuCommand)26599;
private readonly Form form;
@ -40,36 +46,46 @@ protected ContextMenuBase(Form form){
}
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
bool hasTweetImage = !string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedImage);
lastHighlightedTweetAuthor = TweetDeckBridge.LastHighlightedTweetAuthor;
lastHighlightedTweetImageList = TweetDeckBridge.LastHighlightedTweetImages;
if (!TwitterUtils.IsTweetDeckWebsite(frame) || browser.IsLoading){
lastHighlightedTweetAuthor = string.Empty;
lastHighlightedTweetImageList = StringUtils.EmptyArray;
ContextInfo = default(KeyValuePair<string, string>);
}
else{
lastHighlightedTweetAuthor = TweetDeckBridge.LastHighlightedTweetAuthor;
lastHighlightedTweetImageList = TweetDeckBridge.LastHighlightedTweetImages;
}
if (parameters.TypeFlags.HasFlag(ContextMenuType.Link) && !parameters.UnfilteredLinkUrl.EndsWith("tweetdeck.twitter.com/#", StringComparison.Ordinal) && !hasTweetImage){
bool hasTweetImage = IsImage;
bool hasTweetVideo = IsVideo;
string TextOpen(string name) => "Open "+name+" in browser";
string TextCopy(string name) => "Copy "+name+" address";
string TextSave(string name) => "Save "+name+" as...";
if (parameters.TypeFlags.HasFlag(ContextMenuType.Link) && !parameters.UnfilteredLinkUrl.EndsWith("tweetdeck.twitter.com/#", StringComparison.Ordinal) && !hasTweetImage && !hasTweetVideo){
if (TwitterUtils.RegexAccount.IsMatch(parameters.UnfilteredLinkUrl)){
model.AddItem((CefMenuCommand)MenuOpenLinkUrl, "Open account in browser");
model.AddItem((CefMenuCommand)MenuCopyLinkUrl, "Copy account address");
model.AddItem((CefMenuCommand)MenuCopyUsername, "Copy account username");
model.AddItem(MenuOpenLinkUrl, TextOpen("account"));
model.AddItem(MenuCopyLinkUrl, TextCopy("account"));
model.AddItem(MenuCopyUsername, "Copy account username");
}
else{
model.AddItem((CefMenuCommand)MenuOpenLinkUrl, "Open link in browser");
model.AddItem((CefMenuCommand)MenuCopyLinkUrl, "Copy link address");
model.AddItem(MenuOpenLinkUrl, TextOpen("link"));
model.AddItem(MenuCopyLinkUrl, TextCopy("link"));
}
model.AddSeparator();
}
if ((parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents) || hasTweetImage){
model.AddItem((CefMenuCommand)MenuOpenImageUrl, "Open image in browser");
model.AddItem((CefMenuCommand)MenuCopyImageUrl, "Copy image address");
model.AddItem((CefMenuCommand)MenuSaveImage, "Save image as...");
if (hasTweetVideo){
}
else if ((parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents) || hasTweetImage){
model.AddItem(MenuOpenMediaUrl, TextOpen("image"));
model.AddItem(MenuCopyMediaUrl, TextCopy("image"));
model.AddItem(MenuSaveMedia, TextSave("image"));
if (lastHighlightedTweetImageList.Length > 1){
model.AddItem((CefMenuCommand)MenuSaveAllImages, "Save all images as...");
model.AddItem(MenuSaveTweetImages, TextSave("all images"));
}
model.AddSeparator();
@ -77,35 +93,36 @@ public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser bro
}
public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
switch((int)commandId){
switch(commandId){
case MenuOpenLinkUrl:
BrowserUtils.OpenExternalBrowser(parameters.LinkUrl);
break;
case MenuCopyLinkUrl:
SetClipboardText(GetLink(parameters));
break;
case MenuOpenImageUrl:
BrowserUtils.OpenExternalBrowser(TwitterUtils.GetImageLink(GetImage(parameters), ImageQuality));
break;
case MenuSaveImage:
TwitterUtils.DownloadImage(GetImage(parameters), lastHighlightedTweetAuthor, ImageQuality);
break;
case MenuSaveAllImages:
TwitterUtils.DownloadImages(lastHighlightedTweetImageList, lastHighlightedTweetAuthor, ImageQuality);
break;
case MenuCopyImageUrl:
SetClipboardText(TwitterUtils.GetImageLink(GetImage(parameters), ImageQuality));
SetClipboardText(IsLink ? ContextInfo.Value : parameters.UnfilteredLinkUrl);
break;
case MenuCopyUsername:
Match match = TwitterUtils.RegexAccount.Match(parameters.UnfilteredLinkUrl);
SetClipboardText(match.Success ? match.Groups[1].Value : parameters.UnfilteredLinkUrl);
break;
case MenuOpenMediaUrl:
BrowserUtils.OpenExternalBrowser(TwitterUtils.GetImageLink(GetMediaLink(parameters), ImageQuality));
break;
case MenuCopyMediaUrl:
SetClipboardText(TwitterUtils.GetImageLink(GetMediaLink(parameters), ImageQuality));
break;
case MenuSaveMedia:
TwitterUtils.DownloadImage(GetMediaLink(parameters), lastHighlightedTweetAuthor, ImageQuality);
break;
case MenuSaveTweetImages:
TwitterUtils.DownloadImages(lastHighlightedTweetImageList, lastHighlightedTweetAuthor, ImageQuality);
break;
case MenuOpenDevTools:
browserControl.ShowDevTools();
@ -116,8 +133,7 @@ public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser br
}
public virtual void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){
TweetDeckBridge.LastRightClickedLink = string.Empty;
TweetDeckBridge.LastRightClickedImage = string.Empty;
ContextInfo = default(KeyValuePair<string, string>);
}
public virtual bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback){
@ -129,7 +145,7 @@ protected void SetClipboardText(string text){
}
protected static void AddDebugMenuItems(IMenuModel model){
model.AddItem((CefMenuCommand)MenuOpenDevTools, "Open dev tools");
model.AddItem(MenuOpenDevTools, "Open dev tools");
}
protected static void RemoveSeparatorIfLast(IMenuModel model){

View File

@ -6,17 +6,17 @@
namespace TweetDuck.Core.Handling{
class ContextMenuBrowser : ContextMenuBase{
private const int MenuGlobal = 26600;
private const int MenuMute = 26601;
private const int MenuSettings = 26602;
private const int MenuPlugins = 26003;
private const int MenuAbout = 26604;
private const CefMenuCommand MenuGlobal = (CefMenuCommand)26600;
private const CefMenuCommand MenuMute = (CefMenuCommand)26601;
private const CefMenuCommand MenuSettings = (CefMenuCommand)26602;
private const CefMenuCommand MenuPlugins = (CefMenuCommand)26003;
private const CefMenuCommand MenuAbout = (CefMenuCommand)26604;
private const int MenuOpenTweetUrl = 26610;
private const int MenuCopyTweetUrl = 26611;
private const int MenuOpenQuotedTweetUrl = 26612;
private const int MenuCopyQuotedTweetUrl = 26613;
private const int MenuScreenshotTweet = 26614;
private const CefMenuCommand MenuOpenTweetUrl = (CefMenuCommand)26610;
private const CefMenuCommand MenuCopyTweetUrl = (CefMenuCommand)26611;
private const CefMenuCommand MenuOpenQuotedTweetUrl = (CefMenuCommand)26612;
private const CefMenuCommand MenuCopyQuotedTweetUrl = (CefMenuCommand)26613;
private const CefMenuCommand MenuScreenshotTweet = (CefMenuCommand)26614;
private const string TitleReloadBrowser = "Reload browser";
private const string TitleMuteNotifications = "Mute notifications";
@ -55,14 +55,14 @@ public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser br
}
if (!string.IsNullOrEmpty(lastHighlightedTweet) && (parameters.TypeFlags & (ContextMenuType.Editable | ContextMenuType.Selection)) == 0){
model.AddItem((CefMenuCommand)MenuOpenTweetUrl, "Open tweet in browser");
model.AddItem((CefMenuCommand)MenuCopyTweetUrl, "Copy tweet address");
model.AddItem((CefMenuCommand)MenuScreenshotTweet, "Screenshot tweet to clipboard");
model.AddItem(MenuOpenTweetUrl, "Open tweet in browser");
model.AddItem(MenuCopyTweetUrl, "Copy tweet address");
model.AddItem(MenuScreenshotTweet, "Screenshot tweet to clipboard");
if (!string.IsNullOrEmpty(lastHighlightedQuotedTweet)){
model.AddSeparator();
model.AddItem((CefMenuCommand)MenuOpenQuotedTweetUrl, "Open quoted tweet in browser");
model.AddItem((CefMenuCommand)MenuCopyQuotedTweetUrl, "Copy quoted tweet address");
model.AddItem(MenuOpenQuotedTweetUrl, "Open quoted tweet in browser");
model.AddItem(MenuCopyQuotedTweetUrl, "Copy quoted tweet address");
}
model.AddSeparator();
@ -71,16 +71,16 @@ public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser br
if ((parameters.TypeFlags & (ContextMenuType.Editable | ContextMenuType.Selection)) == 0){
AddSeparator(model);
IMenuModel globalMenu = model.Count == 0 ? model : model.AddSubMenu((CefMenuCommand)MenuGlobal, Program.BrandName);
IMenuModel globalMenu = model.Count == 0 ? model : model.AddSubMenu(MenuGlobal, Program.BrandName);
globalMenu.AddItem(CefMenuCommand.Reload, TitleReloadBrowser);
globalMenu.AddCheckItem((CefMenuCommand)MenuMute, TitleMuteNotifications);
globalMenu.SetChecked((CefMenuCommand)MenuMute, Program.UserConfig.MuteNotifications);
globalMenu.AddCheckItem(MenuMute, TitleMuteNotifications);
globalMenu.SetChecked(MenuMute, Program.UserConfig.MuteNotifications);
globalMenu.AddSeparator();
globalMenu.AddItem((CefMenuCommand)MenuSettings, TitleSettings);
globalMenu.AddItem((CefMenuCommand)MenuPlugins, TitlePlugins);
globalMenu.AddItem((CefMenuCommand)MenuAbout, TitleAboutProgram);
globalMenu.AddItem(MenuSettings, TitleSettings);
globalMenu.AddItem(MenuPlugins, TitlePlugins);
globalMenu.AddItem(MenuAbout, TitleAboutProgram);
if (HasDevTools){
globalMenu.AddSeparator();
@ -96,8 +96,8 @@ public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser b
return true;
}
switch((int)commandId){
case (int)CefMenuCommand.Reload:
switch(commandId){
case CefMenuCommand.Reload:
form.InvokeAsyncSafe(form.ReloadToTweetDeck);
return true;

View File

@ -4,11 +4,11 @@
namespace TweetDuck.Core.Handling{
class ContextMenuNotification : ContextMenuBase{
private const int MenuViewDetail = 26600;
private const int MenuSkipTweet = 26601;
private const int MenuFreeze = 26602;
private const int MenuCopyTweetUrl = 26603;
private const int MenuCopyQuotedTweetUrl = 26604;
private const CefMenuCommand MenuViewDetail = (CefMenuCommand)26600;
private const CefMenuCommand MenuSkipTweet = (CefMenuCommand)26601;
private const CefMenuCommand MenuFreeze = (CefMenuCommand)26602;
private const CefMenuCommand MenuCopyTweetUrl = (CefMenuCommand)26603;
private const CefMenuCommand MenuCopyQuotedTweetUrl = (CefMenuCommand)26604;
private readonly FormNotificationBase form;
private readonly bool enableCustomMenu;
@ -29,17 +29,17 @@ public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser br
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
if (enableCustomMenu){
model.AddItem((CefMenuCommand)MenuViewDetail, "View detail");
model.AddItem((CefMenuCommand)MenuSkipTweet, "Skip tweet");
model.AddCheckItem((CefMenuCommand)MenuFreeze, "Freeze");
model.SetChecked((CefMenuCommand)MenuFreeze, form.FreezeTimer);
model.AddSeparator();
model.AddItem(MenuViewDetail, "View detail");
model.AddItem(MenuSkipTweet, "Skip tweet");
model.AddCheckItem(MenuFreeze, "Freeze");
model.SetChecked(MenuFreeze, form.FreezeTimer);
if (!string.IsNullOrEmpty(form.CurrentTweetUrl)){
model.AddItem((CefMenuCommand)MenuCopyTweetUrl, "Copy tweet address");
model.AddSeparator();
model.AddItem(MenuCopyTweetUrl, "Copy tweet address");
if (!string.IsNullOrEmpty(form.CurrentQuoteUrl)){
model.AddItem((CefMenuCommand)MenuCopyQuotedTweetUrl, "Copy quoted tweet address");
model.AddItem(MenuCopyQuotedTweetUrl, "Copy quoted tweet address");
}
}
}
@ -59,7 +59,7 @@ public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser b
return true;
}
switch((int)commandId){
switch(commandId){
case MenuSkipTweet:
form.InvokeAsyncSafe(form.FinishCurrentNotification);
return true;

View File

@ -376,17 +376,16 @@
// Block: Allow bypassing of t.co and include media previews in context menus.
//
$(document.body).delegate("a", "contextmenu", function(){
$TD.setLastRightClickedLink($(this).attr("data-full-url") || "");
});
$(document.body).delegate("a.js-media-image-link", "contextmenu", function(){
let me = $(this)[0];
if (me.firstElementChild){
$TD.setLastRightClickedImage(me.firstElementChild.getAttribute("src"));
if (me.classList.contains("js-media-image-link") && highlightedTweetObj){
let media = (highlightedTweetObj.quotedTweet || highlightedTweetObj).getMedia().find(media => media.mediaId === me.getAttribute("data-media-entity-id"));
$TD.setLastRightClickInfo("image", media.large());
}
}
else{
$TD.setLastRightClickedImage(me.style.backgroundImage.replace(/url\(['"]?(.*?)['"]?\)/, "$1"));
$TD.setLastRightClickInfo("link", me.getAttribute("data-full-url"));
}
});