1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-05-29 11:34:07 +02:00

Refactor tweet screenshot code to a separate class and work around window disposal issues

This commit is contained in:
chylex 2016-12-24 20:35:13 +01:00
parent 2260dd419d
commit 12af79de05
4 changed files with 90 additions and 40 deletions

View File

@ -26,6 +26,12 @@ private static UserConfig Config{
public string UpdateInstallerPath { get; private set; }
public FormNotification BrowserNotificationForm{
get{
return notification;
}
}
private readonly ChromiumWebBrowser browser;
private readonly PluginManager plugins;
private readonly UpdateHandler updates;
@ -38,6 +44,7 @@ private static UserConfig Config{
private FormWindowState prevState;
private TweetScreenshotManager notificationScreenshotManager;
private SoundPlayer notificationSound;
public FormBrowser(PluginManager pluginManager, UpdaterSettings updaterSettings){
@ -73,6 +80,10 @@ public FormBrowser(PluginManager pluginManager, UpdaterSettings updaterSettings)
Disposed += (sender, args) => {
browser.Dispose();
if (notificationScreenshotManager != null){
notificationScreenshotManager.Dispose();
}
if (notificationSound != null){
notificationSound.Dispose();
}
@ -319,33 +330,11 @@ public void PlayNotificationSound(){
}
public void OnTweetScreenshotReady(string html, int width, int height){
FormNotification dummyWindow = CreateNotificationForm(NotificationFlags.DisableScripts | NotificationFlags.DisableContextMenu | NotificationFlags.TopMost);
if (notificationScreenshotManager == null){
notificationScreenshotManager = new TweetScreenshotManager(this);
}
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 = ControlExtensions.InvisibleLocation;
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();
notificationScreenshotManager.Trigger(html, width, height);
}
public void DisplayTooltip(string text){

View File

@ -28,7 +28,7 @@ public bool IsNotificationVisible{
}
}
private readonly Form owner;
private readonly Control owner;
private readonly PluginManager plugins;
private readonly ChromiumWebBrowser browser;
private readonly NotificationFlags flags;
@ -101,11 +101,6 @@ public FormNotification(FormBrowser owner, PluginManager pluginManager, Notifica
owner.FormClosed += (sender, args) => Close();
if (!flags.HasFlag(NotificationFlags.DisableScripts)){
notificationJS = ScriptLoader.LoadResource(NotificationScriptFile);
pluginJS = ScriptLoader.LoadResource(PluginManager.PluginNotificationScriptFile);
}
browser = new ChromiumWebBrowser("about:blank"){
MenuHandler = new ContextMenuNotification(this, !flags.HasFlag(NotificationFlags.DisableContextMenu)),
LifeSpanHandler = new LifeSpanHandler()
@ -117,8 +112,16 @@ public FormNotification(FormBrowser owner, PluginManager pluginManager, Notifica
browser.IsBrowserInitializedChanged += Browser_IsBrowserInitializedChanged;
browser.FrameLoadEnd += Browser_FrameLoadEnd;
browser.RegisterJsObject("$TD", new TweetDeckBridge(owner, this));
browser.RegisterAsyncJsObject("$TDP", plugins.Bridge);
if (!flags.HasFlag(NotificationFlags.DisableScripts)){
notificationJS = ScriptLoader.LoadResource(NotificationScriptFile);
browser.RegisterJsObject("$TD", new TweetDeckBridge(owner, this));
if (plugins != null){
pluginJS = ScriptLoader.LoadResource(PluginManager.PluginNotificationScriptFile);
browser.RegisterAsyncJsObject("$TDP", plugins.Bridge);
}
}
panelBrowser.Controls.Add(browser);
@ -210,7 +213,7 @@ private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
else if (notificationJS != null && browser.Address != "about:blank" && !flags.HasFlag(NotificationFlags.DisableScripts)){
ScriptLoader.ExecuteScript(e.Frame, notificationJS, NotificationScriptIdentifier);
if (plugins.HasAnyPlugin(PluginEnvironment.Notification)){
if (plugins != null && plugins.HasAnyPlugin(PluginEnvironment.Notification)){
ScriptLoader.ExecuteScript(e.Frame, pluginJS, PluginScriptIdentifier);
ScriptLoader.ExecuteFile(e.Frame, PluginManager.PluginGlobalScriptFile);
plugins.ExecutePlugins(e.Frame, PluginEnvironment.Notification, false);
@ -256,29 +259,32 @@ public void ShowNotificationForSettings(bool reset){
}
}
public void ShowNotificationForScreenshot(TweetNotification tweet, int width, int height, Action callback){
public void PrepareNotificationForScreenshot(Action callback){
browser.RegisterAsyncJsObject("$TD_NotificationScreenshot", new CallbackBridge(this, callback));
browser.FrameLoadEnd += (sender, args) => {
if (args.Frame.IsMain){
if (args.Frame.IsMain && browser.Address != "about:blank"){
ScriptLoader.ExecuteScript(args.Frame, "window.setTimeout(() => $TD_NotificationScreenshot.trigger(), 25)", "gen:screenshot");
}
};
}
public void LoadNotificationForScreenshot(TweetNotification tweet, int width, int height){
browser.LoadHtml(tweet.GenerateHtml(enableCustomCSS: false), "http://tweetdeck.twitter.com/?"+DateTime.Now.Ticks);
Location = ControlExtensions.InvisibleLocation;
ClientSize = new Size(width, height);
progressBarTimer.Visible = false;
panelBrowser.Height = height;
// TODO start a timer on 10 seconds to close the window if anything fails or takes too long
}
public void TakeScreenshot(){
public void TakeScreenshotAndHide(){
MoveToVisibleLocation();
Activate();
SendKeys.SendWait("%{PRTSC}");
Location = ControlExtensions.InvisibleLocation;
browser.LoadHtml("", "about:blank");
}
public void HideNotification(bool loadBlank){

View File

@ -0,0 +1,54 @@
using System;
using System.Drawing;
using TweetDck.Core.Controls;
using TweetDck.Core.Handling;
namespace TweetDck.Core.Utils.Notification{
class TweetScreenshotManager : IDisposable{
private readonly FormBrowser browser;
private readonly FormNotification screenshot;
public TweetScreenshotManager(FormBrowser browser){
this.browser = browser;
this.screenshot = new FormNotification(browser, null, NotificationFlags.DisableScripts | NotificationFlags.DisableContextMenu | NotificationFlags.TopMost){
CanMoveWindow = () => false
};
this.screenshot.PrepareNotificationForScreenshot(Callback);
}
public void Trigger(string html, int width, int height){
screenshot.LoadNotificationForScreenshot(new TweetNotification(html, string.Empty, 0), width, height);
screenshot.Show();
// TODO start a timer on 10 seconds to close the window if anything fails or takes too long
}
private void Callback(){
FormNotification notification = browser.BrowserNotificationForm;
Point? prevNotificationLocation = null;
bool prevFreezeTimer = false;
if (notification.IsNotificationVisible){
prevNotificationLocation = notification.Location;
prevFreezeTimer = notification.FreezeTimer;
notification.Location = ControlExtensions.InvisibleLocation;
notification.FreezeTimer = true;
}
screenshot.TakeScreenshotAndHide();
if (prevNotificationLocation.HasValue){
notification.Location = prevNotificationLocation.Value;
notification.FreezeTimer = prevFreezeTimer;
}
}
public void Dispose(){
screenshot.Dispose();
}
}
}

View File

@ -178,6 +178,7 @@
<Compile Include="Core\Utils\CommandLineArgs.cs" />
<Compile Include="Core\Utils\CommandLineArgsParser.cs" />
<Compile Include="Core\Utils\Notification\NotificationFlags.cs" />
<Compile Include="Core\Utils\Notification\TweetScreenshotManager.cs" />
<Compile Include="Core\Utils\WindowState.cs" />
<Compile Include="Core\Utils\WindowsUtils.cs" />
<Compile Include="Core\Handling\TweetDeckBridge.cs" />