using System; using System.IO; using System.Text.RegularExpressions; using System.Windows.Forms; using CefSharp; using TweetDuck.Core.Bridge; using TweetDuck.Core.Controls; using TweetDuck.Core.Utils; using System.Collections.Generic; using System.Linq; using TweetDuck.Core.Other; namespace TweetDuck.Core.Handling{ abstract class ContextMenuBase : IContextMenuHandler{ public 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"; public static void SetContextInfo(string type, string link){ ContextInfo = new KeyValuePair<string, string>(string.IsNullOrEmpty(link) ? null : type, link); } private static string GetMediaLink(IContextMenuParams parameters){ return IsImage || IsVideo ? ContextInfo.Value : parameters.SourceUrl; } private const CefMenuCommand MenuOpenLinkUrl = (CefMenuCommand)26500; private const CefMenuCommand MenuCopyLinkUrl = (CefMenuCommand)26501; private const CefMenuCommand MenuCopyUsername = (CefMenuCommand)26502; private const CefMenuCommand MenuViewImage = (CefMenuCommand)26503; private const CefMenuCommand MenuOpenMediaUrl = (CefMenuCommand)26504; private const CefMenuCommand MenuCopyMediaUrl = (CefMenuCommand)26505; private const CefMenuCommand MenuSaveMedia = (CefMenuCommand)26506; private const CefMenuCommand MenuSaveTweetImages = (CefMenuCommand)26507; private const CefMenuCommand MenuOpenDevTools = (CefMenuCommand)26599; private string[] lastHighlightedTweetAuthors; private string[] lastHighlightedTweetImageList; public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){ if (!TwitterUtils.IsTweetDeckWebsite(frame) || browser.IsLoading){ lastHighlightedTweetAuthors = StringUtils.EmptyArray; lastHighlightedTweetImageList = StringUtils.EmptyArray; ContextInfo = default(KeyValuePair<string, string>); } else{ lastHighlightedTweetAuthors = TweetDeckBridge.LastHighlightedTweetAuthorsArray; lastHighlightedTweetImageList = TweetDeckBridge.LastHighlightedTweetImagesArray; } 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(MenuOpenLinkUrl, TextOpen("account")); model.AddItem(MenuCopyLinkUrl, TextCopy("account")); model.AddItem(MenuCopyUsername, "Copy account username"); } else{ model.AddItem(MenuOpenLinkUrl, TextOpen("link")); model.AddItem(MenuCopyLinkUrl, TextCopy("link")); } model.AddSeparator(); } if (hasTweetVideo){ model.AddItem(MenuOpenMediaUrl, TextOpen("video")); model.AddItem(MenuCopyMediaUrl, TextCopy("video")); model.AddItem(MenuSaveMedia, TextSave("video")); model.AddSeparator(); } else if ((parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents) || hasTweetImage){ model.AddItem(MenuViewImage, "View image in photo viewer"); model.AddItem(MenuOpenMediaUrl, TextOpen("image")); model.AddItem(MenuCopyMediaUrl, TextCopy("image")); model.AddItem(MenuSaveMedia, TextSave("image")); if (lastHighlightedTweetImageList.Length > 1){ model.AddItem(MenuSaveTweetImages, TextSave("all images")); } model.AddSeparator(); } } public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){ switch(commandId){ case MenuOpenLinkUrl: OpenBrowser(browserControl.AsControl(), IsLink ? ContextInfo.Value : parameters.LinkUrl); break; case MenuCopyLinkUrl: SetClipboardText(browserControl.AsControl(), IsLink ? ContextInfo.Value : parameters.UnfilteredLinkUrl); break; case MenuCopyUsername: Match match = TwitterUtils.RegexAccount.Match(parameters.UnfilteredLinkUrl); SetClipboardText(browserControl.AsControl(), match.Success ? match.Groups[1].Value : parameters.UnfilteredLinkUrl); break; case MenuOpenMediaUrl: OpenBrowser(browserControl.AsControl(), TwitterUtils.GetMediaLink(GetMediaLink(parameters), ImageQuality)); break; case MenuCopyMediaUrl: SetClipboardText(browserControl.AsControl(), TwitterUtils.GetMediaLink(GetMediaLink(parameters), ImageQuality)); break; case MenuViewImage: string url = GetMediaLink(parameters); string file = Path.Combine(BrowserCache.CacheFolder, TwitterUtils.GetImageFileName(url)); void ViewFile(){ string ext = Path.GetExtension(file); if (TwitterUtils.ValidImageExtensions.Contains(ext)){ WindowsUtils.OpenAssociatedProgram(file); } else{ FormMessage.Error("Image Download", "Invalid file extension "+ext, FormMessage.OK); } } if (File.Exists(file)){ ViewFile(); } else{ BrowserUtils.DownloadFileAsync(TwitterUtils.GetMediaLink(url, ImageQuality), file, ViewFile, ex => { FormMessage.Error("Image Download", "An error occurred while downloading the image: "+ex.Message, FormMessage.OK); }); } break; case MenuSaveMedia: if (IsVideo){ TwitterUtils.DownloadVideo(GetMediaLink(parameters), lastHighlightedTweetAuthors.LastOrDefault()); } else{ TwitterUtils.DownloadImage(GetMediaLink(parameters), lastHighlightedTweetAuthors.LastOrDefault(), ImageQuality); } break; case MenuSaveTweetImages: TwitterUtils.DownloadImages(lastHighlightedTweetImageList, lastHighlightedTweetAuthors.LastOrDefault(), ImageQuality); break; case MenuOpenDevTools: browserControl.ShowDevTools(); break; } return false; } public virtual void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){ ContextInfo = default(KeyValuePair<string, string>); } public virtual bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback){ return false; } protected void OpenBrowser(Control control, string url){ control.InvokeAsyncSafe(() => BrowserUtils.OpenExternalBrowser(url)); } protected void SetClipboardText(Control control, string text){ control.InvokeAsyncSafe(() => WindowsUtils.SetClipboard(text, TextDataFormat.UnicodeText)); } protected static void AddDebugMenuItems(IMenuModel model){ model.AddItem(MenuOpenDevTools, "Open dev tools"); } protected static void RemoveSeparatorIfLast(IMenuModel model){ if (model.Count > 0 && model.GetTypeAt(model.Count-1) == MenuItemType.Separator){ model.RemoveAt(model.Count-1); } } protected static void AddSeparator(IMenuModel model){ if (model.Count > 0 && model.GetTypeAt(model.Count-1) != MenuItemType.Separator){ // do not add separators if there is nothing to separate model.AddSeparator(); } } } }