From 04a78a02d3daa51ea6f471e9dc328f5a2af345bb Mon Sep 17 00:00:00 2001 From: chylex <info@chylex.com> Date: Wed, 16 Nov 2016 18:33:01 +0100 Subject: [PATCH 01/11] Add NotificationFlags for easier configuration of the notification window --- Core/FormBrowser.cs | 6 +++--- Core/FormNotification.cs | 20 +++++++++++--------- Core/Other/FormSettings.cs | 3 ++- Core/Utils/NotificationFlags.cs | 11 +++++++++++ TweetDck.csproj | 1 + 5 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 Core/Utils/NotificationFlags.cs diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs index 05c4ded1..02657219 100644 --- a/Core/FormBrowser.cs +++ b/Core/FormBrowser.cs @@ -44,7 +44,7 @@ public FormBrowser(PluginManager pluginManager){ this.plugins.Reloaded += plugins_Reloaded; this.plugins.PluginChangedState += plugins_PluginChangedState; - FormNotification notification = CreateNotificationForm(true); + FormNotification notification = CreateNotificationForm(NotificationFlags.AutoHide); notification.CanMoveWindow = () => false; notification.Show(); @@ -87,8 +87,8 @@ private void ForceClose(){ Close(); } - public FormNotification CreateNotificationForm(bool autoHide){ - return new FormNotification(this, plugins, autoHide); + public FormNotification CreateNotificationForm(NotificationFlags flags){ + return new FormNotification(this, plugins, flags); } // window setup diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs index 091ddea8..09505292 100644 --- a/Core/FormNotification.cs +++ b/Core/FormNotification.cs @@ -25,7 +25,7 @@ sealed partial class FormNotification : Form{ private readonly ChromiumWebBrowser browser; private readonly Queue<TweetNotification> tweetQueue = new Queue<TweetNotification>(4); - private readonly bool autoHide; + private readonly NotificationFlags flags; private int timeLeft, totalTime; private readonly NativeMethods.HookProc mouseHookDelegate; @@ -82,22 +82,24 @@ private static int BaseClientHeight{ } } - public FormNotification(FormBrowser owner, PluginManager pluginManager, bool autoHide){ + public FormNotification(FormBrowser owner, PluginManager pluginManager, NotificationFlags flags){ InitializeComponent(); Text = Program.BrandName; this.owner = owner; this.plugins = pluginManager; - this.autoHide = autoHide; + this.flags = flags; owner.FormClosed += (sender, args) => Close(); - notificationJS = ScriptLoader.LoadResource(NotificationScriptFile); - pluginJS = ScriptLoader.LoadResource(PluginManager.PluginNotificationScriptFile); + if (!flags.HasFlag(NotificationFlags.DisableScripts)){ + notificationJS = ScriptLoader.LoadResource(NotificationScriptFile); + pluginJS = ScriptLoader.LoadResource(PluginManager.PluginNotificationScriptFile); + } browser = new ChromiumWebBrowser("about:blank"){ - MenuHandler = new ContextMenuNotification(this, autoHide), + MenuHandler = new ContextMenuNotification(this, !flags.HasFlag(NotificationFlags.DisableContextMenu)), LifeSpanHandler = new LifeSpanHandler() }; @@ -112,7 +114,7 @@ public FormNotification(FormBrowser owner, PluginManager pluginManager, bool aut panelBrowser.Controls.Add(browser); - if (autoHide){ + if (flags.HasFlag(NotificationFlags.AutoHide)){ Program.UserConfig.MuteToggled += Config_MuteToggled; Disposed += (sender, args) => Program.UserConfig.MuteToggled -= Config_MuteToggled; } @@ -197,7 +199,7 @@ private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){ Initialized(this, new EventArgs()); } } - else if (notificationJS != null && browser.Address != "about:blank"){ + else if (notificationJS != null && browser.Address != "about:blank" && !flags.HasFlag(NotificationFlags.DisableScripts)){ ScriptLoader.ExecuteScript(e.Frame, notificationJS, NotificationScriptIdentifier); if (plugins.HasAnyPlugin(PluginEnvironment.Notification)){ @@ -269,7 +271,7 @@ public void FinishCurrentTweet(){ if (tweetQueue.Count > 0){ LoadNextNotification(); } - else if (autoHide){ + else if (flags.HasFlag(NotificationFlags.AutoHide)){ HideNotification(true); } else{ diff --git a/Core/Other/FormSettings.cs b/Core/Other/FormSettings.cs index 4dcdd191..905d552c 100644 --- a/Core/Other/FormSettings.cs +++ b/Core/Other/FormSettings.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Windows.Forms; using TweetDck.Core.Other.Settings; +using TweetDck.Core.Utils; using TweetDck.Plugins; using TweetDck.Updates; @@ -17,7 +18,7 @@ public FormSettings(FormBrowser browserForm, PluginManager plugins, UpdateHandle this.tabPanel.SetupTabPanel(100); this.tabPanel.AddButton("General", SelectTab<TabSettingsGeneral>); - this.tabPanel.AddButton("Notifications", () => SelectTab(() => new TabSettingsNotifications(browserForm.CreateNotificationForm(false)))); + this.tabPanel.AddButton("Notifications", () => SelectTab(() => new TabSettingsNotifications(browserForm.CreateNotificationForm(NotificationFlags.DisableContextMenu)))); this.tabPanel.AddButton("Updates", () => SelectTab(() => new TabSettingsUpdates(updates))); this.tabPanel.AddButton("Advanced", () => SelectTab(() => new TabSettingsAdvanced(browserForm.ReloadBrowser, plugins))); this.tabPanel.SelectTab(tabPanel.Buttons.First()); diff --git a/Core/Utils/NotificationFlags.cs b/Core/Utils/NotificationFlags.cs new file mode 100644 index 00000000..2fb722ef --- /dev/null +++ b/Core/Utils/NotificationFlags.cs @@ -0,0 +1,11 @@ +using System; + +namespace TweetDck.Core.Utils{ + [Flags] + public enum NotificationFlags{ + None = 0, + AutoHide = 1, + DisableScripts = 2, + DisableContextMenu = 4 + } +} diff --git a/TweetDck.csproj b/TweetDck.csproj index cb9b90a3..045d0c35 100644 --- a/TweetDck.csproj +++ b/TweetDck.csproj @@ -178,6 +178,7 @@ </Compile> <Compile Include="Core\Utils\CommandLineArgs.cs" /> <Compile Include="Core\Utils\CommandLineArgsParser.cs" /> + <Compile Include="Core\Utils\NotificationFlags.cs" /> <Compile Include="Core\Utils\WindowState.cs" /> <Compile Include="Core\Utils\WindowsUtils.cs" /> <Compile Include="Core\Handling\TweetDeckBridge.cs" /> From 7a1e7637ffc93d62585b62abb98734c3719bc00f Mon Sep 17 00:00:00 2001 From: chylex <info@chylex.com> Date: Wed, 16 Nov 2016 18:33:30 +0100 Subject: [PATCH 02/11] Add a parameter to toggle custom CSS in TweetNotification.GenerateHtml --- Core/Handling/TweetNotification.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Core/Handling/TweetNotification.cs b/Core/Handling/TweetNotification.cs index f8d70612..d3c327f6 100644 --- a/Core/Handling/TweetNotification.cs +++ b/Core/Handling/TweetNotification.cs @@ -99,16 +99,20 @@ public int GetDisplayDuration(int value){ return 2000+Math.Max(1000, value*characters); } - public string GenerateHtml(){ + public string GenerateHtml(bool enableCustomCSS = true){ StringBuilder build = new StringBuilder(); build.Append("<!DOCTYPE html>"); build.Append("<html class='os-windows txt-base-").Append(FontSizeClass ?? DefaultFontSizeClass).Append("'>"); - build.Append("<head>").Append(HeadTag ?? DefaultHeadTag).Append("<style type='text/css'>").Append(CustomCSS).Append("</style>"); + build.Append("<head>").Append(HeadTag ?? DefaultHeadTag); - if (!string.IsNullOrEmpty(Program.UserConfig.CustomNotificationCSS)){ - build.Append("<style type='text/css'>").Append(Program.UserConfig.CustomNotificationCSS).Append("</style>"); - } + if (enableCustomCSS){ + build.Append("<style type='text/css'>").Append(CustomCSS).Append("</style>"); + if (!string.IsNullOrEmpty(Program.UserConfig.CustomNotificationCSS)){ + build.Append("<style type='text/css'>").Append(Program.UserConfig.CustomNotificationCSS).Append("</style>"); + } + } + build.Append("</head>"); build.Append("<body class='hearty'").Append(isExample ? " td-example-notification" : "").Append("><div class='app-columns-container'><div class='column scroll-styled-v' style='width:100%;overflow-y:auto'>"); build.Append(html); From c3db3ce0f233634fb5fb5612eab624892e1f9750 Mon Sep 17 00:00:00 2001 From: chylex <info@chylex.com> Date: Wed, 16 Nov 2016 18:39:30 +0100 Subject: [PATCH 03/11] Push WIP tweet screenshot functionality --- Core/FormBrowser.cs | 15 ++++++++++++ Core/FormNotification.cs | 38 ++++++++++++++++++++++++++++- Core/Handling/ContextMenuBrowser.cs | 6 +++++ Core/Handling/TweetDeckBridge.cs | 4 +++ Resources/Scripts/code.js | 18 ++++++++++++++ 5 files changed, 80 insertions(+), 1 deletion(-) 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. // From a1b483d20ad414b223f899022e55e53e4e852398 Mon Sep 17 00:00:00 2001 From: chylex <info@chylex.com> Date: Fri, 23 Dec 2016 13:40:30 +0100 Subject: [PATCH 04/11] Implement printscreen simulation and a timeout to screenshot notification --- Core/FormBrowser.cs | 6 ++++-- Core/FormNotification.cs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs index 47b58faf..342fd46c 100644 --- a/Core/FormBrowser.cs +++ b/Core/FormBrowser.cs @@ -295,8 +295,10 @@ 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.Activate(); + SendKeys.SendWait("%{PRTSC}"); + dummyWindow.Close(); + // dummyWindow.Dispose(); // TODO something freezes the program sometimes }); dummyWindow.Show(); diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs index 3b9d3bef..0636e7f5 100644 --- a/Core/FormNotification.cs +++ b/Core/FormNotification.cs @@ -254,7 +254,7 @@ public void ShowNotificationForScreenshot(TweetNotification tweet, int width, in browser.FrameLoadEnd += (sender, args) => { if (args.Frame.IsMain){ - args.Frame.ExecuteJavaScriptAsync("$TD_NotificationScreenshot.trigger()"); + ScriptLoader.ExecuteScript(args.Frame, "window.setTimeout(() => $TD_NotificationScreenshot.trigger(), 25)", "gen:screenshot"); } }; From 7f7c5ab35b597c4ad3f6b650dcead9e562bf19fa Mon Sep 17 00:00:00 2001 From: chylex <info@chylex.com> Date: Fri, 23 Dec 2016 14:07:47 +0100 Subject: [PATCH 05/11] Update CefSharp to 53.0.1 --- Configuration/packages.config | 8 ++++---- TweetDck.csproj | 30 ++++++++++++++---------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/Configuration/packages.config b/Configuration/packages.config index d299e8fe..02c2fd46 100644 --- a/Configuration/packages.config +++ b/Configuration/packages.config @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <packages xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> - <package id="cef.redist.x64" version="3.2785.1478" targetFramework="net452" /> - <package id="cef.redist.x86" version="3.2785.1478" targetFramework="net452" /> - <package id="CefSharp.Common" version="53.0.0-pre01" targetFramework="net452" /> - <package id="CefSharp.WinForms" version="53.0.0-pre01" targetFramework="net452" /> + <package id="cef.redist.x64" version="3.2785.1486" targetFramework="net452" /> + <package id="cef.redist.x86" version="3.2785.1486" targetFramework="net452" /> + <package id="CefSharp.Common" version="53.0.1" targetFramework="net452" /> + <package id="CefSharp.WinForms" version="53.0.1" targetFramework="net452" /> <package id="Microsoft.VC120.CRT.JetBrains" version="12.0.21005.2" targetFramework="net452" /> </packages> \ No newline at end of file diff --git a/TweetDck.csproj b/TweetDck.csproj index 045d0c35..af6c8f59 100644 --- a/TweetDck.csproj +++ b/TweetDck.csproj @@ -1,9 +1,7 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props')" /> - <Import Project="packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props')" /> - <Import Project="packages\CefSharp.WinForms.49.0.0-pre02\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.49.0.0-pre02\build\CefSharp.WinForms.props')" /> - <Import Project="packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.props')" /> + <Import Project="packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props')" /> + <Import Project="packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> @@ -16,7 +14,7 @@ <AssemblyName Condition=" '$(Configuration)' == 'Release' ">TweetDuck</AssemblyName> <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> - <NuGetPackageImportStamp>e83161d1</NuGetPackageImportStamp> + <NuGetPackageImportStamp>783c0e30</NuGetPackageImportStamp> <TargetFrameworkProfile> </TargetFrameworkProfile> <PublishUrl>publish\</PublishUrl> @@ -305,12 +303,12 @@ <PropertyGroup> <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> </PropertyGroup> - <Error Condition="!Exists('packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets'))" /> - <Error Condition="!Exists('packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets'))" /> - <Error Condition="!Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props'))" /> - <Error Condition="!Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets'))" /> - <Error Condition="!Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props'))" /> - <Error Condition="!Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets'))" /> + <Error Condition="!Exists('packages\cef.redist.x86.3.2785.1486\build\cef.redist.x86.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.2785.1486\build\cef.redist.x86.targets'))" /> + <Error Condition="!Exists('packages\cef.redist.x64.3.2785.1486\build\cef.redist.x64.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.2785.1486\build\cef.redist.x64.targets'))" /> + <Error Condition="!Exists('packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props'))" /> + <Error Condition="!Exists('packages\CefSharp.Common.53.0.1\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.53.0.1\build\CefSharp.Common.targets'))" /> + <Error Condition="!Exists('packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props'))" /> + <Error Condition="!Exists('packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.targets'))" /> </Target> <PropertyGroup> <PostBuildEvent>del "$(TargetPath).config" @@ -331,10 +329,10 @@ xcopy "$(ProjectDir)Resources\Plugins\*" "$(TargetDir)plugins\official\" /E /Y rmdir "$(ProjectDir)\bin\Debug" rmdir "$(ProjectDir)\bin\Release"</PostBuildEvent> </PropertyGroup> - <Import Project="packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets" Condition="Exists('packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets')" /> - <Import Project="packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets" Condition="Exists('packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets')" /> - <Import Project="packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets')" /> - <Import Project="packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets" Condition="Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets')" /> + <Import Project="packages\cef.redist.x86.3.2785.1486\build\cef.redist.x86.targets" Condition="Exists('packages\cef.redist.x86.3.2785.1486\build\cef.redist.x86.targets')" /> + <Import Project="packages\cef.redist.x64.3.2785.1486\build\cef.redist.x64.targets" Condition="Exists('packages\cef.redist.x64.3.2785.1486\build\cef.redist.x64.targets')" /> + <Import Project="packages\CefSharp.Common.53.0.1\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.53.0.1\build\CefSharp.Common.targets')" /> + <Import Project="packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.targets" Condition="Exists('packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.targets')" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> From 61359c2faa9e952d63ffbcc9ac485917ef2564c2 Mon Sep 17 00:00:00 2001 From: chylex <info@chylex.com> Date: Fri, 23 Dec 2016 14:26:59 +0100 Subject: [PATCH 06/11] Refactor NotificationFlags and inner screenshot bridge class to a separate namespace --- Core/FormBrowser.cs | 1 + Core/FormNotification.cs | 15 ++------------- Core/Other/FormSettings.cs | 2 +- Core/Utils/Notification/CallbackBridge.cs | 19 +++++++++++++++++++ .../{ => Notification}/NotificationFlags.cs | 2 +- 5 files changed, 24 insertions(+), 15 deletions(-) create mode 100644 Core/Utils/Notification/CallbackBridge.cs rename Core/Utils/{ => Notification}/NotificationFlags.cs (79%) diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs index 342fd46c..6d868c79 100644 --- a/Core/FormBrowser.cs +++ b/Core/FormBrowser.cs @@ -9,6 +9,7 @@ using TweetDck.Core.Controls; using System.Drawing; using TweetDck.Core.Utils; +using TweetDck.Core.Utils.Notification; using TweetDck.Updates; using TweetDck.Plugins; using TweetDck.Plugins.Enums; diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs index 0636e7f5..0c5c504c 100644 --- a/Core/FormNotification.cs +++ b/Core/FormNotification.cs @@ -9,6 +9,7 @@ using TweetDck.Core.Handling; using TweetDck.Resources; using TweetDck.Core.Utils; +using TweetDck.Core.Utils.Notification; using TweetDck.Plugins; using TweetDck.Plugins.Enums; @@ -250,7 +251,7 @@ 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.RegisterAsyncJsObject("$TD_NotificationScreenshot", new CallbackBridge(this, callback)); browser.FrameLoadEnd += (sender, args) => { if (args.Frame.IsMain){ @@ -272,18 +273,6 @@ public void ShowNotificationForScreenshot(TweetNotification tweet, int width, in // 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/Other/FormSettings.cs b/Core/Other/FormSettings.cs index 905d552c..55b1a144 100644 --- a/Core/Other/FormSettings.cs +++ b/Core/Other/FormSettings.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Windows.Forms; using TweetDck.Core.Other.Settings; -using TweetDck.Core.Utils; +using TweetDck.Core.Utils.Notification; using TweetDck.Plugins; using TweetDck.Updates; diff --git a/Core/Utils/Notification/CallbackBridge.cs b/Core/Utils/Notification/CallbackBridge.cs new file mode 100644 index 00000000..6c6c2fbf --- /dev/null +++ b/Core/Utils/Notification/CallbackBridge.cs @@ -0,0 +1,19 @@ +using System; +using System.Windows.Forms; +using TweetDck.Core.Controls; + +namespace TweetDck.Core.Utils.Notification{ + sealed class CallbackBridge{ + private readonly Control owner; + private readonly Action safeCallback; + + public CallbackBridge(Control owner, Action safeCallback){ + this.owner = owner; + this.safeCallback = safeCallback; + } + + public void Trigger(){ + owner.InvokeSafe(safeCallback); + } + } +} diff --git a/Core/Utils/NotificationFlags.cs b/Core/Utils/Notification/NotificationFlags.cs similarity index 79% rename from Core/Utils/NotificationFlags.cs rename to Core/Utils/Notification/NotificationFlags.cs index 2fb722ef..6efa12e9 100644 --- a/Core/Utils/NotificationFlags.cs +++ b/Core/Utils/Notification/NotificationFlags.cs @@ -1,6 +1,6 @@ using System; -namespace TweetDck.Core.Utils{ +namespace TweetDck.Core.Utils.Notification{ [Flags] public enum NotificationFlags{ None = 0, From 3a37ee719b66c7a4c7cb17fd77bbe560e77ccbbd Mon Sep 17 00:00:00 2001 From: chylex <info@chylex.com> Date: Fri, 23 Dec 2016 14:29:23 +0100 Subject: [PATCH 07/11] Fix csproj file after previous refactor commit --- TweetDck.csproj | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/TweetDck.csproj b/TweetDck.csproj index af6c8f59..833d59a8 100644 --- a/TweetDck.csproj +++ b/TweetDck.csproj @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props')" /> <Import Project="packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props')" /> @@ -174,9 +174,10 @@ <Compile Include="Core\Other\Settings\TabSettingsUpdates.Designer.cs"> <DependentUpon>TabSettingsUpdates.cs</DependentUpon> </Compile> + <Compile Include="Core\Utils\Notification\CallbackBridge.cs" /> <Compile Include="Core\Utils\CommandLineArgs.cs" /> <Compile Include="Core\Utils\CommandLineArgsParser.cs" /> - <Compile Include="Core\Utils\NotificationFlags.cs" /> + <Compile Include="Core\Utils\Notification\NotificationFlags.cs" /> <Compile Include="Core\Utils\WindowState.cs" /> <Compile Include="Core\Utils\WindowsUtils.cs" /> <Compile Include="Core\Handling\TweetDeckBridge.cs" /> From 9b983de8c9e59b8d33c6546cf9b69e5c7063a3b1 Mon Sep 17 00:00:00 2001 From: chylex <info@chylex.com> Date: Fri, 23 Dec 2016 14:52:48 +0100 Subject: [PATCH 08/11] Ensure notification window visibility when taking screenshots, refactor MoveToVisibleLocation --- Core/FormBrowser.cs | 4 ++-- Core/FormNotification.cs | 49 ++++++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs index 6d868c79..36828a61 100644 --- a/Core/FormBrowser.cs +++ b/Core/FormBrowser.cs @@ -296,8 +296,8 @@ 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, () => { - dummyWindow.Activate(); - SendKeys.SendWait("%{PRTSC}"); + dummyWindow.TakeScreenshot(); + dummyWindow.Hide(); dummyWindow.Close(); // dummyWindow.Dispose(); // TODO something freezes the program sometimes }); diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs index 0c5c504c..8a3c00da 100644 --- a/Core/FormNotification.cs +++ b/Core/FormNotification.cs @@ -246,7 +246,7 @@ public void ShowNotificationForSettings(bool reset){ LoadTweet(TweetNotification.ExampleTweet); } else{ - MoveToVisibleLocation(); + PrepareAndDisplayWindow(); } } @@ -261,18 +261,20 @@ public void ShowNotificationForScreenshot(TweetNotification tweet, int width, in browser.LoadHtml(tweet.GenerateHtml(false), "http://tweetdeck.twitter.com/?"+DateTime.Now.Ticks); + Location = new Point(-32000, -32000); 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 } + public void TakeScreenshot(){ + MoveToVisibleLocation(); + Activate(); + SendKeys.SendWait("%{PRTSC}"); + } + public void HideNotification(bool loadBlank){ if (loadBlank || Program.UserConfig.NotificationLegacyLoad){ browser.LoadHtml("", "about:blank"); @@ -288,7 +290,7 @@ public void HideNotification(bool loadBlank){ public void OnNotificationReady(){ UpdateTitle(); - MoveToVisibleLocation(); + PrepareAndDisplayWindow(); timerProgress.Start(); } @@ -326,21 +328,6 @@ private void LoadTweet(TweetNotification tweet){ private void MoveToVisibleLocation(){ UserConfig config = Program.UserConfig; - if (RequiresResize){ - RequiresResize = false; - - if (config.DisplayNotificationTimer){ - ClientSize = new Size(BaseClientWidth, BaseClientHeight+4); - progressBarTimer.Visible = true; - } - else{ - ClientSize = new Size(BaseClientWidth, BaseClientHeight); - progressBarTimer.Visible = false; - } - - panelBrowser.Height = BaseClientHeight; - } - Screen screen = Screen.FromControl(owner); if (config.NotificationDisplay > 0 && config.NotificationDisplay <= Screen.AllScreens.Length){ @@ -380,7 +367,25 @@ private void MoveToVisibleLocation(){ if (needsReactivating){ NativeMethods.SetFormPos(this, NativeMethods.HWND_TOPMOST, NativeMethods.SWP_NOACTIVATE); } + } + private void PrepareAndDisplayWindow(){ + if (RequiresResize){ + RequiresResize = false; + + if (Program.UserConfig.DisplayNotificationTimer){ + ClientSize = new Size(BaseClientWidth, BaseClientHeight+4); + progressBarTimer.Visible = true; + } + else{ + ClientSize = new Size(BaseClientWidth, BaseClientHeight); + progressBarTimer.Visible = false; + } + + panelBrowser.Height = BaseClientHeight; + } + + MoveToVisibleLocation(); StartMouseHook(); } From 68fa3294d46178819f13e91f569b613e5c25f5cc Mon Sep 17 00:00:00 2001 From: chylex <info@chylex.com> Date: Fri, 23 Dec 2016 14:56:16 +0100 Subject: [PATCH 09/11] Update CefSharp version in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e21fcb48..c6f6e77a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ The program was build using Visual Studio 2013. After opening the solution, make sure you have **CefSharp.WinForms** and **Microsoft.VC120.CRT.JetBrains** included - if not, download them using NuGet. For **CefSharp**, you will need version 53 or newer currently available as a pre-release. ``` -PM> Install-Package CefSharp.WinForms -Pre -Version 53.0.0-pre01 +PM> Install-Package CefSharp.WinForms -Version 53.0.1 PM> Install-Package Microsoft.VC120.CRT.JetBrains ``` From cac6d1f889a21efe761978bf1314dbf0da457aeb Mon Sep 17 00:00:00 2001 From: chylex <info@chylex.com> Date: Fri, 23 Dec 2016 15:13:34 +0100 Subject: [PATCH 10/11] Swap notification windows when taking a screenshot, and make screenshot window unmovable --- Core/FormBrowser.cs | 26 ++++++++++++++++++++++---- Core/FormNotification.cs | 7 ++++++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs index 36828a61..d8af3be1 100644 --- a/Core/FormBrowser.cs +++ b/Core/FormBrowser.cs @@ -28,6 +28,7 @@ private static UserConfig Config{ private readonly ChromiumWebBrowser browser; private readonly PluginManager plugins; private readonly UpdateHandler updates; + private readonly FormNotification notification; private FormSettings currentFormSettings; private FormAbout currentFormAbout; @@ -45,9 +46,9 @@ public FormBrowser(PluginManager pluginManager){ this.plugins.Reloaded += plugins_Reloaded; this.plugins.PluginChangedState += plugins_PluginChangedState; - FormNotification notification = CreateNotificationForm(NotificationFlags.AutoHide); - notification.CanMoveWindow = () => false; - notification.Show(); + this.notification = CreateNotificationForm(NotificationFlags.AutoHide); + this.notification.CanMoveWindow = () => false; + this.notification.Show(); this.browser = new ChromiumWebBrowser("https://tweetdeck.twitter.com/"){ MenuHandler = new ContextMenuBrowser(this), @@ -296,12 +297,29 @@ 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, () => { + Point? prevNotificationLocation = null; + bool prevFreezeTimer = false; + + if (notification.IsNotificationVisible){ + prevNotificationLocation = notification.Location; + prevFreezeTimer = notification.FreezeTimer; + + notification.Location = new Point(-32000, -32000); + notification.FreezeTimer = true; + } + dummyWindow.TakeScreenshot(); dummyWindow.Hide(); dummyWindow.Close(); // dummyWindow.Dispose(); // TODO something freezes the program sometimes - }); + if (prevNotificationLocation.HasValue){ + notification.Location = prevNotificationLocation.Value; + notification.FreezeTimer = prevFreezeTimer; + } + }); + + dummyWindow.CanMoveWindow = () => false; dummyWindow.Show(); } diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs index 8a3c00da..e2f04dce 100644 --- a/Core/FormNotification.cs +++ b/Core/FormNotification.cs @@ -5,7 +5,6 @@ using CefSharp; using CefSharp.WinForms; using TweetDck.Configuration; -using TweetDck.Core.Controls; using TweetDck.Core.Handling; using TweetDck.Resources; using TweetDck.Core.Utils; @@ -22,6 +21,12 @@ sealed partial class FormNotification : Form{ public Func<bool> CanMoveWindow = () => true; + public bool IsNotificationVisible{ + get{ + return Location.X != -32000; + } + } + private readonly Form owner; private readonly PluginManager plugins; private readonly ChromiumWebBrowser browser; From 02e8dc34404666bc359ab24a0b9e2e4c1fedb983 Mon Sep 17 00:00:00 2001 From: chylex <info@chylex.com> Date: Fri, 23 Dec 2016 15:29:33 +0100 Subject: [PATCH 11/11] Fix screenshot script modifying original elements and missing html classes --- Resources/Scripts/code.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Resources/Scripts/code.js b/Resources/Scripts/code.js index af79c688..2591971b 100644 --- a/Resources/Scripts/code.js +++ b/Resources/Scripts/code.js @@ -316,8 +316,14 @@ window.TDGF_triggerScreenshot = function(){ if (selectedTweet){ + var realWidth = selectedTweet.width(); + var realHeight = selectedTweet.height()-selectedTweet.find("footer").last().height(); + + selectedTweet = selectedTweet.clone(); + selectedTweet.children().first().addClass($(document.documentElement).attr("class")); selectedTweet.find("footer").last().remove(); - $TD.screenshotTweet(selectedTweet.html(), selectedTweet.width(), selectedTweet.height()); + + $TD.screenshotTweet(selectedTweet.html(), realWidth, realHeight); } }; })();