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

Refactor & optimize context menu, send last tweet info only on right-click

This commit is contained in:
chylex 2018-03-02 05:24:45 +01:00
parent d5bf8ec558
commit 8fbb639430
6 changed files with 132 additions and 101 deletions

View File

@ -3,7 +3,7 @@
using System.Windows.Forms;
using CefSharp;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Handling;
using TweetDuck.Core.Management;
using TweetDuck.Core.Notification;
using TweetDuck.Core.Other;
using TweetDuck.Core.Utils;
@ -13,20 +13,12 @@ namespace TweetDuck.Core.Bridge{
class TweetDeckBridge{
public static string FontSize { get; private set; }
public static string NotificationHeadLayout { get; private set; }
public static string LastHighlightedTweetUrl = string.Empty;
public static string LastHighlightedQuoteUrl = string.Empty;
private static string LastHighlightedTweetAuthors = string.Empty;
private static string LastHighlightedTweetImages = string.Empty;
public static string[] LastHighlightedTweetAuthorsArray => LastHighlightedTweetAuthors.Split(';');
public static string[] LastHighlightedTweetImagesArray => LastHighlightedTweetImages.Split(';');
public static readonly ContextInfo ContextInfo = new ContextInfo();
private static readonly Dictionary<string, string> SessionData = new Dictionary<string, string>(2);
public static void ResetStaticProperties(){
FontSize = NotificationHeadLayout = null;
LastHighlightedTweetUrl = LastHighlightedQuoteUrl = LastHighlightedTweetAuthors = LastHighlightedTweetImages = string.Empty;
}
public static void RestoreSessionData(IFrame frame){
@ -72,13 +64,8 @@ public void LoadNotificationLayout(string fontSize, string headLayout){
});
}
public void SetLastHighlightedTweet(string tweetUrl, string quoteUrl, string authors, string imageList){
form.InvokeAsyncSafe(() => {
LastHighlightedTweetUrl = tweetUrl;
LastHighlightedQuoteUrl = quoteUrl;
LastHighlightedTweetAuthors = authors;
LastHighlightedTweetImages = imageList;
});
public void SetRightClickedChirp(string tweetUrl, string quoteUrl, string chirpAuthors, string chirpImages){
ContextInfo.SetChirp(tweetUrl, quoteUrl, chirpAuthors, chirpImages);
}
public void DisplayTooltip(string text){
@ -112,8 +99,8 @@ public void ShowTweetDetail(){
// Global
public void SetLastRightClickInfo(string type, string link){
form.InvokeAsyncSafe(() => ContextMenuBase.SetContextInfo(type, link));
public void SetLastRightClickInfo(string type, string url){
ContextInfo.SetLink(type, url);
}
public void OnTweetPopup(string columnId, string chirpId, string columnName, string tweetHtml, int tweetCharacters, string tweetUrl, string quoteUrl){

View File

@ -3,11 +3,10 @@
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.Bridge;
using TweetDuck.Core.Management;
using TweetDuck.Core.Notification;
using TweetDuck.Core.Other;
@ -18,19 +17,6 @@ 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;
@ -42,8 +28,8 @@ private static string GetMediaLink(IContextMenuParams parameters){
private const CefMenuCommand MenuSaveTweetImages = (CefMenuCommand)26507;
private const CefMenuCommand MenuOpenDevTools = (CefMenuCommand)26599;
private string[] lastHighlightedTweetAuthors;
private string[] lastHighlightedTweetImageList;
protected ContextInfo.LinkInfo LastLink { get; private set; }
protected ContextInfo.ChirpInfo LastChirp { get; private set; }
private readonly AnalyticsFile.IProvider analytics;
@ -51,19 +37,23 @@ protected ContextMenuBase(AnalyticsFile.IProvider analytics){
this.analytics = analytics;
}
private void ResetContextInfo(){
LastLink = default(ContextInfo.LinkInfo);
LastChirp = default(ContextInfo.ChirpInfo);
TweetDeckBridge.ContextInfo.Reset();
}
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>);
ResetContextInfo();
}
else{
lastHighlightedTweetAuthors = TweetDeckBridge.LastHighlightedTweetAuthorsArray;
lastHighlightedTweetImageList = TweetDeckBridge.LastHighlightedTweetImagesArray;
LastLink = TweetDeckBridge.ContextInfo.Link;
LastChirp = TweetDeckBridge.ContextInfo.Chirp;
}
bool hasTweetImage = IsImage;
bool hasTweetVideo = IsVideo;
bool hasTweetImage = LastLink.IsImage;
bool hasTweetVideo = LastLink.IsVideo;
string TextOpen(string name) => "Open "+name+" in browser";
string TextCopy(string name) => "Copy "+name+" address";
@ -95,7 +85,7 @@ public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser bro
model.AddItem(MenuCopyMediaUrl, TextCopy("image"));
model.AddItem(MenuSaveMedia, TextSave("image"));
if (lastHighlightedTweetImageList.Length > 1){
if (LastChirp.Images.Length > 1){
model.AddItem(MenuSaveTweetImages, TextSave("all images"));
}
@ -108,11 +98,11 @@ public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser br
switch(commandId){
case MenuOpenLinkUrl:
OpenBrowser(control, IsLink ? ContextInfo.Value : parameters.LinkUrl);
OpenBrowser(control, LastLink.GetUrl(parameters, true));
break;
case MenuCopyLinkUrl:
SetClipboardText(control, IsLink ? ContextInfo.Value : parameters.UnfilteredLinkUrl);
SetClipboardText(control, LastLink.GetUrl(parameters, false));
break;
case MenuCopyUsername:
@ -122,35 +112,37 @@ public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser br
break;
case MenuOpenMediaUrl:
OpenBrowser(control, TwitterUtils.GetMediaLink(GetMediaLink(parameters), ImageQuality));
OpenBrowser(control, TwitterUtils.GetMediaLink(LastLink.GetMediaSource(parameters), ImageQuality));
break;
case MenuCopyMediaUrl:
SetClipboardText(control, TwitterUtils.GetMediaLink(GetMediaLink(parameters), ImageQuality));
SetClipboardText(control, TwitterUtils.GetMediaLink(LastLink.GetMediaSource(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);
void ViewImage(string path){
string ext = Path.GetExtension(path);
if (TwitterUtils.ValidImageExtensions.Contains(ext)){
WindowsUtils.OpenAssociatedProgram(file);
WindowsUtils.OpenAssociatedProgram(path);
}
else{
FormMessage.Error("Image Download", "Invalid file extension "+ext, FormMessage.OK);
}
}
string url = LastLink.GetMediaSource(parameters);
string file = Path.Combine(BrowserCache.CacheFolder, TwitterUtils.GetImageFileName(url));
if (File.Exists(file)){
ViewFile();
ViewImage(file);
}
else{
control.InvokeAsyncSafe(analytics.AnalyticsFile.ViewedImages.Trigger);
BrowserUtils.DownloadFileAsync(TwitterUtils.GetMediaLink(url, ImageQuality), file, ViewFile, ex => {
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);
});
}
@ -158,20 +150,20 @@ void ViewFile(){
break;
case MenuSaveMedia:
if (IsVideo){
if (LastLink.IsVideo){
control.InvokeAsyncSafe(analytics.AnalyticsFile.DownloadedVideos.Trigger);
TwitterUtils.DownloadVideo(GetMediaLink(parameters), lastHighlightedTweetAuthors.LastOrDefault());
TwitterUtils.DownloadVideo(LastLink.GetMediaSource(parameters), LastChirp.Authors.LastOrDefault());
}
else{
control.InvokeAsyncSafe(analytics.AnalyticsFile.DownloadedImages.Trigger);
TwitterUtils.DownloadImage(GetMediaLink(parameters), lastHighlightedTweetAuthors.LastOrDefault(), ImageQuality);
TwitterUtils.DownloadImage(LastLink.GetMediaSource(parameters), LastChirp.Authors.LastOrDefault(), ImageQuality);
}
break;
case MenuSaveTweetImages:
control.InvokeAsyncSafe(analytics.AnalyticsFile.DownloadedImages.Trigger);
TwitterUtils.DownloadImages(lastHighlightedTweetImageList, lastHighlightedTweetAuthors.LastOrDefault(), ImageQuality);
TwitterUtils.DownloadImages(LastChirp.Images, LastChirp.Authors.LastOrDefault(), ImageQuality);
break;
case MenuOpenDevTools:
@ -183,7 +175,7 @@ void ViewFile(){
}
public virtual void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){
ContextInfo = default(KeyValuePair<string, string>);
ResetContextInfo();
}
public virtual bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback){

View File

@ -1,8 +1,6 @@
using CefSharp;
using System.Windows.Forms;
using TweetDuck.Core.Bridge;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Utils;
namespace TweetDuck.Core.Handling{
sealed class ContextMenuBrowser : ContextMenuBase{
@ -26,10 +24,7 @@ sealed class ContextMenuBrowser : ContextMenuBase{
private const string TitleAboutProgram = "About "+Program.BrandName;
private readonly FormBrowser form;
private string lastHighlightedTweetUrl;
private string lastHighlightedQuoteUrl;
public ContextMenuBrowser(FormBrowser form) : base(form){
this.form = form;
}
@ -52,20 +47,12 @@ public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser br
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
lastHighlightedTweetUrl = TweetDeckBridge.LastHighlightedTweetUrl;
lastHighlightedQuoteUrl = TweetDeckBridge.LastHighlightedQuoteUrl;
if (!TwitterUtils.IsTweetDeckWebsite(frame) || browser.IsLoading){
lastHighlightedTweetUrl = string.Empty;
lastHighlightedQuoteUrl = string.Empty;
}
if (!string.IsNullOrEmpty(lastHighlightedTweetUrl) && (parameters.TypeFlags & (ContextMenuType.Editable | ContextMenuType.Selection)) == 0){
if (!string.IsNullOrEmpty(LastChirp.TweetUrl) && (parameters.TypeFlags & (ContextMenuType.Editable | ContextMenuType.Selection)) == 0){
model.AddItem(MenuOpenTweetUrl, "Open tweet in browser");
model.AddItem(MenuCopyTweetUrl, "Copy tweet address");
model.AddItem(MenuScreenshotTweet, "Screenshot tweet to clipboard");
if (!string.IsNullOrEmpty(lastHighlightedQuoteUrl)){
if (!string.IsNullOrEmpty(LastChirp.QuoteUrl)){
model.AddSeparator();
model.AddItem(MenuOpenQuotedTweetUrl, "Open quoted tweet in browser");
model.AddItem(MenuCopyQuotedTweetUrl, "Copy quoted tweet address");
@ -126,11 +113,11 @@ public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser b
return true;
case MenuOpenTweetUrl:
OpenBrowser(form, lastHighlightedTweetUrl);
OpenBrowser(form, LastChirp.TweetUrl);
return true;
case MenuCopyTweetUrl:
SetClipboardText(form, lastHighlightedTweetUrl);
SetClipboardText(form, LastChirp.TweetUrl);
return true;
case MenuScreenshotTweet:
@ -138,11 +125,11 @@ public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser b
return true;
case MenuOpenQuotedTweetUrl:
OpenBrowser(form, lastHighlightedQuoteUrl);
OpenBrowser(form, LastChirp.QuoteUrl);
return true;
case MenuCopyQuotedTweetUrl:
SetClipboardText(form, lastHighlightedQuoteUrl);
SetClipboardText(form, LastChirp.QuoteUrl);
return true;
case MenuInputApplyROT13:

View File

@ -0,0 +1,68 @@
using CefSharp;
using TweetDuck.Core.Utils;
namespace TweetDuck.Core.Management{
sealed class ContextInfo{
public LinkInfo Link { get; private set; }
public ChirpInfo Chirp { get; private set; }
public ContextInfo(){
Reset();
}
public void SetLink(string type, string url){
Link = new LinkInfo(string.IsNullOrEmpty(type) ? null : type, url);
}
public void SetChirp(string tweetUrl, string quoteUrl, string chirpAuthors, string chirpImages){
Chirp = new ChirpInfo(tweetUrl, quoteUrl, chirpAuthors, chirpImages);
}
public void Reset(){
Link = new LinkInfo();
Chirp = new ChirpInfo();
}
// Data structures
public struct LinkInfo{
public bool IsLink => type == "link";
public bool IsImage => type == "image";
public bool IsVideo => type == "video";
public string GetUrl(IContextMenuParams parameters, bool safe){
return IsLink ? url : (safe ? parameters.LinkUrl : parameters.UnfilteredLinkUrl);
}
public string GetMediaSource(IContextMenuParams parameters){
return IsImage || IsVideo ? url : parameters.SourceUrl;
}
private readonly string type;
private readonly string url;
public LinkInfo(string type, string url){
this.type = type;
this.url = url;
}
}
public struct ChirpInfo{
public string TweetUrl { get; }
public string QuoteUrl { get; }
public string[] Authors => chirpAuthors?.Split(';') ?? StringUtils.EmptyArray;
public string[] Images => chirpImages?.Split(';') ?? StringUtils.EmptyArray;
private readonly string chirpAuthors;
private readonly string chirpImages;
public ChirpInfo(string tweetUrl, string quoteUrl, string chirpAuthors, string chirpImages){
this.TweetUrl = tweetUrl;
this.QuoteUrl = quoteUrl;
this.chirpAuthors = chirpAuthors;
this.chirpImages = chirpImages;
}
}
}
}

View File

@ -595,22 +595,15 @@
// Block: Update highlighted column and tweet for context menu and other functionality.
//
(function(){
var lastTweet = "";
const updateHighlightedColumn = function(ele){
highlightedColumnEle = ele;
highlightedColumnObj = ele ? TD.controller.columnManager.get(ele.attr("data-column")) : null;
return !!highlightedColumnObj;
};
const updateHighlightedTweet = function(ele, obj, tweetUrl, quoteUrl, authors, imageList){
const updateHighlightedTweet = function(ele, obj){
highlightedTweetEle = ele;
highlightedTweetObj = obj;
if (lastTweet !== tweetUrl){
$TD.setLastHighlightedTweet(tweetUrl, quoteUrl, authors, imageList);
lastTweet = tweetUrl;
}
};
const processMedia = function(chirp){
@ -626,6 +619,19 @@
mouseleave: function(){
updateHighlightedColumn(null);
},
contextmenu: function(){
let tweet = highlightedTweetObj;
if (tweet && tweet.chirpType === TD.services.ChirpBase.TWEET){
let tweetUrl = tweet.getChirpURL();
let quoteUrl = tweet.quotedTweet ? tweet.quotedTweet.getChirpURL() : "";
let chirpAuthors = tweet.quotedTweet ? [ tweet.getMainUser().screenName, tweet.quotedTweet.getMainUser().screenName ].join(";") : tweet.getMainUser().screenName;
let chirpImages = tweet.hasImage() ? processMedia(tweet) : tweet.quotedTweet && tweet.quotedTweet.hasImage() ? processMedia(tweet.quotedTweet) : "";
$TD.setRightClickedChirp(tweetUrl || "", quoteUrl || "", chirpAuthors, chirpImages);
}
}
});
@ -637,21 +643,11 @@
let tweet = highlightedColumnObj.findChirp(me.attr("data-tweet-id")) || highlightedColumnObj.findChirp(me.attr("data-key"));
return if !tweet;
if (tweet.chirpType === TD.services.ChirpBase.TWEET){
let tweetUrl = tweet.getChirpURL();
let quoteUrl = tweet.quotedTweet ? tweet.quotedTweet.getChirpURL() : "";
let authors = tweet.quotedTweet ? [ tweet.getMainUser().screenName, tweet.quotedTweet.getMainUser().screenName ].join(";") : tweet.getMainUser().screenName;
let imageList = tweet.hasImage() ? processMedia(tweet) : tweet.quotedTweet && tweet.quotedTweet.hasImage() ? processMedia(tweet.quotedTweet) : "";
updateHighlightedTweet(me, tweet, tweetUrl || "", quoteUrl || "", authors, imageList);
}
else{
updateHighlightedTweet(me, tweet, "", "", "", "");
}
updateHighlightedTweet(me, tweet);
},
mouseleave: function(){
updateHighlightedTweet(null, null, "", "", "", "");
updateHighlightedTweet(null, null);
}
});
})();

View File

@ -108,6 +108,7 @@
<Compile Include="Core\Handling\RequestHandlerBrowser.cs" />
<Compile Include="Core\Handling\ResourceHandlerNotification.cs" />
<Compile Include="Core\ITweetDeckBrowser.cs" />
<Compile Include="Core\Management\ContextInfo.cs" />
<Compile Include="Core\Notification\Example\FormNotificationExample.cs">
<SubType>Form</SubType>
</Compile>