mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-10-08 22:27:02 +02:00
Configuration
Core
Bridge
Controls
Handling
Filters
General
ContextMenuBase.cs
ContextMenuBrowser.cs
ContextMenuGuide.cs
ContextMenuNotification.cs
DragHandlerBrowser.cs
KeyboardHandlerBrowser.cs
KeyboardHandlerNotification.cs
RequestHandlerBase.cs
RequestHandlerBrowser.cs
ResourceHandlerFactory.cs
ResourceHandlerNotification.cs
Management
Notification
Other
Utils
FormBrowser.Designer.cs
FormBrowser.cs
FormBrowser.resx
FormManager.cs
TweetDeckBrowser.cs
Data
Plugins
Properties
Resources
Updates
bld
lib
subprocess
video
.gitattributes
.gitignore
LICENSE.md
Program.cs
README.md
Reporter.cs
TweetDuck.csproj
TweetDuck.sln
TweetDuck.sln.DotSettings
packages.config
230 lines
10 KiB
C#
230 lines
10 KiB
C#
using System;
|
|
using System.Text.RegularExpressions;
|
|
using System.Windows.Forms;
|
|
using CefSharp;
|
|
using TweetDuck.Core.Controls;
|
|
using TweetDuck.Core.Utils;
|
|
using System.Linq;
|
|
using TweetDuck.Configuration;
|
|
using TweetDuck.Core.Bridge;
|
|
using TweetDuck.Core.Management;
|
|
using TweetDuck.Core.Notification;
|
|
using TweetDuck.Core.Other;
|
|
using TweetDuck.Core.Other.Analytics;
|
|
using TweetDuck.Resources;
|
|
|
|
namespace TweetDuck.Core.Handling{
|
|
abstract class ContextMenuBase : IContextMenuHandler{
|
|
protected static UserConfig Config => Program.Config.User;
|
|
|
|
private static TwitterUtils.ImageQuality ImageQuality => Config.TwitterImageQuality;
|
|
|
|
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 MenuSearchInBrowser = (CefMenuCommand)26508;
|
|
private const CefMenuCommand MenuReadApplyROT13 = (CefMenuCommand)26509;
|
|
private const CefMenuCommand MenuOpenDevTools = (CefMenuCommand)26599;
|
|
|
|
protected ContextInfo.ContextData Context { get; private set; }
|
|
|
|
private readonly AnalyticsFile.IProvider analytics;
|
|
|
|
protected ContextMenuBase(AnalyticsFile.IProvider analytics){
|
|
this.analytics = analytics;
|
|
}
|
|
|
|
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
|
if (!TwitterUtils.IsTweetDeckWebsite(frame) || browser.IsLoading){
|
|
Context = TweetDeckBridge.ContextInfo.Reset();
|
|
}
|
|
else{
|
|
Context = TweetDeckBridge.ContextInfo.Create(parameters);
|
|
}
|
|
|
|
if (parameters.TypeFlags.HasFlag(ContextMenuType.Selection) && !parameters.TypeFlags.HasFlag(ContextMenuType.Editable)){
|
|
model.AddItem(MenuSearchInBrowser, "Search in browser");
|
|
model.AddSeparator();
|
|
model.AddItem(MenuReadApplyROT13, "Apply ROT13");
|
|
model.AddSeparator();
|
|
}
|
|
|
|
string TextOpen(string name) => "Open "+name+" in browser";
|
|
string TextCopy(string name) => "Copy "+name+" address";
|
|
string TextSave(string name) => "Save "+name+" as...";
|
|
|
|
if (Context.Types.HasFlag(ContextInfo.ContextType.Link) && !Context.UnsafeLinkUrl.EndsWith("tweetdeck.twitter.com/#", StringComparison.Ordinal)){
|
|
if (TwitterUtils.RegexAccount.IsMatch(Context.UnsafeLinkUrl)){
|
|
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 (Context.Types.HasFlag(ContextInfo.ContextType.Video)){
|
|
model.AddItem(MenuOpenMediaUrl, TextOpen("video"));
|
|
model.AddItem(MenuCopyMediaUrl, TextCopy("video"));
|
|
model.AddItem(MenuSaveMedia, TextSave("video"));
|
|
model.AddSeparator();
|
|
}
|
|
else if (Context.Types.HasFlag(ContextInfo.ContextType.Image) && Context.MediaUrl != TweetNotification.AppLogo.Url){
|
|
model.AddItem(MenuViewImage, "View image in photo viewer");
|
|
model.AddItem(MenuOpenMediaUrl, TextOpen("image"));
|
|
model.AddItem(MenuCopyMediaUrl, TextCopy("image"));
|
|
model.AddItem(MenuSaveMedia, TextSave("image"));
|
|
|
|
if (Context.Chirp.Images.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){
|
|
Control control = browserControl.AsControl();
|
|
|
|
switch(commandId){
|
|
case MenuOpenLinkUrl:
|
|
OpenBrowser(control, Context.LinkUrl);
|
|
break;
|
|
|
|
case MenuCopyLinkUrl:
|
|
SetClipboardText(control, Context.UnsafeLinkUrl);
|
|
break;
|
|
|
|
case MenuCopyUsername: {
|
|
string url = Context.UnsafeLinkUrl;
|
|
Match match = TwitterUtils.RegexAccount.Match(url);
|
|
|
|
SetClipboardText(control, match.Success ? match.Groups[1].Value : url);
|
|
control.InvokeAsyncSafe(analytics.AnalyticsFile.CopiedUsernames.Trigger);
|
|
break;
|
|
}
|
|
|
|
case MenuOpenMediaUrl:
|
|
OpenBrowser(control, TwitterUtils.GetMediaLink(Context.MediaUrl, ImageQuality));
|
|
break;
|
|
|
|
case MenuCopyMediaUrl:
|
|
SetClipboardText(control, TwitterUtils.GetMediaLink(Context.MediaUrl, ImageQuality));
|
|
break;
|
|
|
|
case MenuViewImage: {
|
|
string url = Context.MediaUrl;
|
|
|
|
control.InvokeAsyncSafe(() => {
|
|
TwitterUtils.ViewImage(url, ImageQuality);
|
|
analytics.AnalyticsFile.ViewedImages.Trigger();
|
|
});
|
|
|
|
break;
|
|
}
|
|
|
|
case MenuSaveMedia: {
|
|
bool isVideo = Context.Types.HasFlag(ContextInfo.ContextType.Video);
|
|
string url = Context.MediaUrl;
|
|
string username = Context.Chirp.Authors.LastOrDefault();
|
|
|
|
control.InvokeAsyncSafe(() => {
|
|
if (isVideo){
|
|
TwitterUtils.DownloadVideo(url, username);
|
|
analytics.AnalyticsFile.DownloadedVideos.Trigger();
|
|
}
|
|
else{
|
|
TwitterUtils.DownloadImage(url, username, ImageQuality);
|
|
analytics.AnalyticsFile.DownloadedImages.Trigger();
|
|
}
|
|
});
|
|
|
|
break;
|
|
}
|
|
|
|
case MenuSaveTweetImages: {
|
|
string[] urls = Context.Chirp.Images;
|
|
string username = Context.Chirp.Authors.LastOrDefault();
|
|
|
|
control.InvokeAsyncSafe(() => {
|
|
TwitterUtils.DownloadImages(urls, username, ImageQuality);
|
|
analytics.AnalyticsFile.DownloadedImages.Trigger();
|
|
});
|
|
|
|
break;
|
|
}
|
|
|
|
case MenuReadApplyROT13:
|
|
string selection = parameters.SelectionText;
|
|
control.InvokeAsyncSafe(() => FormMessage.Information("ROT13", StringUtils.ConvertRot13(selection), FormMessage.OK));
|
|
control.InvokeAsyncSafe(analytics.AnalyticsFile.UsedROT13.Trigger);
|
|
return true;
|
|
|
|
case MenuSearchInBrowser:
|
|
string query = parameters.SelectionText;
|
|
control.InvokeAsyncSafe(() => BrowserUtils.OpenExternalSearch(query));
|
|
DeselectAll(frame);
|
|
break;
|
|
|
|
case MenuOpenDevTools:
|
|
browserControl.ShowDevTools();
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public virtual void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){
|
|
Context = TweetDeckBridge.ContextInfo.Reset();
|
|
}
|
|
|
|
public virtual bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback){
|
|
return false;
|
|
}
|
|
|
|
protected static void DeselectAll(IFrame frame){
|
|
ScriptLoader.ExecuteScript(frame, "window.getSelection().removeAllRanges()", "gen:deselect");
|
|
}
|
|
|
|
protected static void OpenBrowser(Control control, string url){
|
|
control.InvokeAsyncSafe(() => BrowserUtils.OpenExternalBrowser(url));
|
|
}
|
|
|
|
protected static void SetClipboardText(Control control, string text){
|
|
control.InvokeAsyncSafe(() => WindowsUtils.SetClipboard(text, TextDataFormat.UnicodeText));
|
|
}
|
|
|
|
protected static void InsertSelectionSearchItem(IMenuModel model, CefMenuCommand insertCommand, string insertLabel){
|
|
model.InsertItemAt(model.GetIndexOf(MenuSearchInBrowser)+1, insertCommand, insertLabel);
|
|
}
|
|
|
|
protected static void AddDebugMenuItems(IMenuModel model){
|
|
if (BrowserUtils.HasDevTools){
|
|
AddSeparator(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();
|
|
}
|
|
}
|
|
}
|
|
}
|