diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs index 02657219..47b58faf 100644 --- a/Core/FormBrowser.cs +++ b/Core/FormBrowser.cs @@ -291,6 +291,17 @@ public void OnTweetNotification(){ } } + public void OnTweetScreenshotReady(string html, int width, int height){ + FormNotification dummyWindow = CreateNotificationForm(NotificationFlags.DisableScripts | NotificationFlags.DisableContextMenu); + + dummyWindow.ShowNotificationForScreenshot(new TweetNotification(html, string.Empty, 0), width, height, () => { + // TODO DrawToBitmap does not work here + dummyWindow.Dispose(); // TODO something freezes the program sometimes + }); + + dummyWindow.Show(); + } + public void DisplayTooltip(string text){ if (string.IsNullOrEmpty(text)){ toolTip.Hide(this); @@ -310,6 +321,10 @@ public void OnImagePastedFinish(){ browser.ExecuteScriptAsync("TDGF_tryPasteImageFinish()"); } + public void TriggerTweetScreenshot(){ + browser.ExecuteScriptAsync("TDGF_triggerScreenshot()"); + } + public void ReloadBrowser(){ browser.ExecuteScriptAsync("window.location.reload()"); } diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs index 09505292..3b9d3bef 100644 --- a/Core/FormNotification.cs +++ b/Core/FormNotification.cs @@ -5,6 +5,7 @@ using CefSharp; using CefSharp.WinForms; using TweetDck.Configuration; +using TweetDck.Core.Controls; using TweetDck.Core.Handling; using TweetDck.Resources; using TweetDck.Core.Utils; @@ -23,9 +24,9 @@ sealed partial class FormNotification : Form{ private readonly Form owner; private readonly PluginManager plugins; private readonly ChromiumWebBrowser browser; + private readonly NotificationFlags flags; private readonly Queue<TweetNotification> tweetQueue = new Queue<TweetNotification>(4); - private readonly NotificationFlags flags; private int timeLeft, totalTime; private readonly NativeMethods.HookProc mouseHookDelegate; @@ -248,6 +249,41 @@ public void ShowNotificationForSettings(bool reset){ } } + public void ShowNotificationForScreenshot(TweetNotification tweet, int width, int height, Action callback){ + browser.RegisterAsyncJsObject("$TD_NotificationScreenshot", new ScreenshotBridge(() => this.InvokeSafe(callback))); + + browser.FrameLoadEnd += (sender, args) => { + if (args.Frame.IsMain){ + args.Frame.ExecuteJavaScriptAsync("$TD_NotificationScreenshot.trigger()"); + } + }; + + browser.LoadHtml(tweet.GenerateHtml(false), "http://tweetdeck.twitter.com/?"+DateTime.Now.Ticks); + + ClientSize = new Size(width, height); + progressBarTimer.Visible = false; + panelBrowser.Height = height; + + // TODO + + Screen screen = Screen.FromControl(this); + Location = new Point(screen.WorkingArea.X+8, screen.WorkingArea.Y+8); + + // TODO start a timer on 10 seconds to close the window if anything fails or takes too long + } + + private sealed class ScreenshotBridge{ + private readonly Action safeCallback; + + public ScreenshotBridge(Action safeCallback){ + this.safeCallback = safeCallback; + } + + public void Trigger(){ + safeCallback(); + } + } + public void HideNotification(bool loadBlank){ if (loadBlank || Program.UserConfig.NotificationLegacyLoad){ browser.LoadHtml("", "about:blank"); diff --git a/Core/Handling/ContextMenuBrowser.cs b/Core/Handling/ContextMenuBrowser.cs index d4c29cbf..00afd2e2 100644 --- a/Core/Handling/ContextMenuBrowser.cs +++ b/Core/Handling/ContextMenuBrowser.cs @@ -15,6 +15,7 @@ class ContextMenuBrowser : ContextMenuBase{ private const int MenuCopyTweetUrl = 26611; private const int MenuOpenQuotedTweetUrl = 26612; private const int MenuCopyQuotedTweetUrl = 26613; + private const int MenuScreenshotTweet = 26614; private readonly FormBrowser form; @@ -45,6 +46,7 @@ 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"); if (!string.IsNullOrEmpty(lastHighlightedQuotedTweet)){ model.AddSeparator(); @@ -109,6 +111,10 @@ public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser b Clipboard.SetText(lastHighlightedTweet, TextDataFormat.UnicodeText); return true; + case MenuScreenshotTweet: + form.InvokeSafe(form.TriggerTweetScreenshot); + return true; + case MenuOpenQuotedTweetUrl: BrowserUtils.OpenExternalBrowser(lastHighlightedQuotedTweet); return true; diff --git a/Core/Handling/TweetDeckBridge.cs b/Core/Handling/TweetDeckBridge.cs index 6d645876..b4669bc6 100644 --- a/Core/Handling/TweetDeckBridge.cs +++ b/Core/Handling/TweetDeckBridge.cs @@ -154,6 +154,10 @@ public void ClickUploadImage(int offsetX, int offsetY){ }); } + public void ScreenshotTweet(string html, int width, int height){ + form.InvokeSafe(() => form.OnTweetScreenshotReady(html, width, height)); + } + public void OpenBrowser(string url){ BrowserUtils.OpenExternalBrowser(url); } diff --git a/Resources/Scripts/code.js b/Resources/Scripts/code.js index 71b454fc..af79c688 100644 --- a/Resources/Scripts/code.js +++ b/Resources/Scripts/code.js @@ -304,6 +304,24 @@ }); })(); + // + // Block: Screenshot tweet to clipboard. + // + (function(){ + var selectedTweet; + + app.delegate("article.js-stream-item", "contextmenu", function(){ + selectedTweet = $(this); + }); + + window.TDGF_triggerScreenshot = function(){ + if (selectedTweet){ + selectedTweet.find("footer").last().remove(); + $TD.screenshotTweet(selectedTweet.html(), selectedTweet.width(), selectedTweet.height()); + } + }; + })(); + // // Block: Paste images when tweeting. //