mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-08-18 13:31:41 +02:00
.github
.idea
Application
Browser
Adapters
Handling
Notification
Screenshot
FormNotificationBase.Designer.cs
FormNotificationBase.cs
FormNotificationExample.cs
FormNotificationMain.Designer.cs
FormNotificationMain.cs
FormNotificationTweet.Designer.cs
FormNotificationTweet.cs
SoundNotification.cs
FormBrowser.Designer.cs
FormBrowser.cs
FormBrowser.resx
TrayIcon.Designer.cs
TrayIcon.cs
TweetDeckBrowser.cs
Configuration
Controls
Dialogs
Management
Plugins
Properties
Resources
Updates
Utils
bld
lib
subprocess
video
.gitattributes
.gitignore
LICENSE.md
Program.cs
README.md
Reporter.cs
TweetDuck.csproj
TweetDuck.sln
TweetDuck.sln.DotSettings
Version.cs
app.config
packages.config
252 lines
7.7 KiB
C#
252 lines
7.7 KiB
C#
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using CefSharp.WinForms;
|
|
using TweetDuck.Browser.Adapters;
|
|
using TweetDuck.Browser.Handling;
|
|
using TweetDuck.Configuration;
|
|
using TweetDuck.Controls;
|
|
using TweetDuck.Utils;
|
|
using TweetLib.Browser.Interfaces;
|
|
using TweetLib.Core.Features.Notifications;
|
|
using TweetLib.Core.Features.Twitter;
|
|
using TweetLib.Core.Systems.Configuration;
|
|
|
|
namespace TweetDuck.Browser.Notification {
|
|
abstract partial class FormNotificationBase : Form {
|
|
protected static UserConfig Config => Program.Config.User;
|
|
|
|
protected delegate NotificationBrowser CreateBrowserImplFunc(FormNotificationBase form, IBrowserComponent browserComponent);
|
|
|
|
protected virtual Point PrimaryLocation {
|
|
get {
|
|
Screen screen;
|
|
|
|
if (Config.NotificationDisplay > 0 && Config.NotificationDisplay <= Screen.AllScreens.Length) {
|
|
screen = Screen.AllScreens[Config.NotificationDisplay - 1];
|
|
}
|
|
else {
|
|
screen = Screen.FromControl(owner);
|
|
}
|
|
|
|
int edgeDist = Config.NotificationEdgeDistance;
|
|
|
|
switch (Config.NotificationPosition) {
|
|
case DesktopNotification.Position.TopLeft:
|
|
return new Point(screen.WorkingArea.X + edgeDist, screen.WorkingArea.Y + edgeDist);
|
|
|
|
case DesktopNotification.Position.TopRight:
|
|
return new Point(screen.WorkingArea.X + screen.WorkingArea.Width - edgeDist - Width, screen.WorkingArea.Y + edgeDist);
|
|
|
|
case DesktopNotification.Position.BottomLeft:
|
|
return new Point(screen.WorkingArea.X + edgeDist, screen.WorkingArea.Y + screen.WorkingArea.Height - edgeDist - Height);
|
|
|
|
case DesktopNotification.Position.BottomRight:
|
|
return new Point(screen.WorkingArea.X + screen.WorkingArea.Width - edgeDist - Width, screen.WorkingArea.Y + screen.WorkingArea.Height - edgeDist - Height);
|
|
|
|
case DesktopNotification.Position.Custom:
|
|
if (!Config.IsCustomNotificationPositionSet) {
|
|
Config.CustomNotificationPosition = new Point(screen.WorkingArea.X + screen.WorkingArea.Width - edgeDist - Width, screen.WorkingArea.Y + edgeDist);
|
|
Config.Save();
|
|
}
|
|
|
|
return Config.CustomNotificationPosition;
|
|
}
|
|
|
|
return Location;
|
|
}
|
|
}
|
|
|
|
protected bool IsNotificationVisible => Location != ControlExtensions.InvisibleLocation;
|
|
protected virtual bool CanDragWindow => true;
|
|
|
|
public new Point Location {
|
|
get {
|
|
return base.Location;
|
|
}
|
|
|
|
set {
|
|
Visible = (base.Location = value) != ControlExtensions.InvisibleLocation;
|
|
FormBorderStyle = NotificationBorderStyle;
|
|
}
|
|
}
|
|
|
|
protected virtual FormBorderStyle NotificationBorderStyle {
|
|
get {
|
|
if (WindowsUtils.ShouldAvoidToolWindow && Visible) { // Visible = workaround for alt+tab
|
|
return FormBorderStyle.FixedSingle;
|
|
}
|
|
else {
|
|
return FormBorderStyle.FixedToolWindow;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override bool ShowWithoutActivation => true;
|
|
|
|
protected float DpiScale { get; }
|
|
protected double SizeScale => DpiScale * Config.ZoomLevel / 100.0;
|
|
|
|
private readonly FormBrowser owner;
|
|
|
|
protected readonly IBrowserComponent browserComponent;
|
|
private readonly NotificationBrowser browserImpl;
|
|
|
|
#pragma warning disable IDE0069 // Disposable fields should be disposed
|
|
protected readonly ChromiumWebBrowser browser;
|
|
#pragma warning restore IDE0069 // Disposable fields should be disposed
|
|
|
|
private readonly ResourceHandlerNotification resourceHandler = new ResourceHandlerNotification();
|
|
|
|
private DesktopNotification currentNotification;
|
|
private int pauseCounter;
|
|
|
|
public string CurrentTweetUrl => currentNotification?.TweetUrl;
|
|
public string CurrentQuoteUrl => currentNotification?.QuoteUrl;
|
|
|
|
protected bool IsPaused => pauseCounter > 0;
|
|
protected internal bool IsCursorOverBrowser => browser.Bounds.Contains(PointToClient(Cursor.Position));
|
|
|
|
public bool FreezeTimer { get; set; }
|
|
public bool ContextMenuOpen { get; set; }
|
|
|
|
protected FormNotificationBase(FormBrowser owner, CreateBrowserImplFunc createBrowserImpl) {
|
|
InitializeComponent();
|
|
|
|
this.owner = owner;
|
|
this.owner.FormClosed += owner_FormClosed;
|
|
|
|
this.browser = new ChromiumWebBrowser(NotificationBrowser.BlankURL) {
|
|
RequestHandler = new RequestHandlerBase(false)
|
|
};
|
|
|
|
this.browserComponent = new ComponentImpl(browser, this);
|
|
this.browserImpl = createBrowserImpl(this, browserComponent);
|
|
|
|
this.browser.Dock = DockStyle.None;
|
|
this.browser.ClientSize = ClientSize;
|
|
|
|
Controls.Add(browser);
|
|
|
|
Disposed += (sender, args) => {
|
|
this.owner.FormClosed -= owner_FormClosed;
|
|
this.browserImpl.Dispose();
|
|
this.browser.Dispose();
|
|
};
|
|
|
|
DpiScale = this.GetDPIScale();
|
|
|
|
// ReSharper disable once VirtualMemberCallInContructor
|
|
UpdateTitle();
|
|
}
|
|
|
|
protected sealed class ComponentImpl : CefBrowserComponent {
|
|
private readonly FormNotificationBase owner;
|
|
|
|
public ComponentImpl(ChromiumWebBrowser browser, FormNotificationBase owner) : base(browser) {
|
|
this.owner = owner;
|
|
}
|
|
|
|
protected override ContextMenuBase SetupContextMenu(IContextMenuHandler handler) {
|
|
return new ContextMenuNotification(owner, handler);
|
|
}
|
|
|
|
protected override CefResourceHandlerFactory SetupResourceHandlerFactory(IResourceRequestHandler handler) {
|
|
var registry = new CefResourceHandlerRegistry();
|
|
registry.RegisterStatic(NotificationBrowser.BlankURL, string.Empty);
|
|
registry.RegisterDynamic(TwitterUrls.TweetDeck, owner.resourceHandler);
|
|
return new CefResourceHandlerFactory(handler, registry);
|
|
}
|
|
}
|
|
|
|
protected override void Dispose(bool disposing) {
|
|
if (disposing) {
|
|
components?.Dispose();
|
|
resourceHandler.Dispose();
|
|
}
|
|
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
protected override void WndProc(ref Message m) {
|
|
if (m.Msg == 0x0112 && (m.WParam.ToInt32() & 0xFFF0) == 0xF010 && !CanDragWindow) { // WM_SYSCOMMAND, SC_MOVE
|
|
return;
|
|
}
|
|
|
|
base.WndProc(ref m);
|
|
}
|
|
|
|
// event handlers
|
|
|
|
private void owner_FormClosed(object sender, FormClosedEventArgs e) {
|
|
Close();
|
|
}
|
|
|
|
// notification methods
|
|
|
|
public virtual void HideNotification() {
|
|
browser.Load(NotificationBrowser.BlankURL);
|
|
DisplayTooltip(null);
|
|
|
|
Location = ControlExtensions.InvisibleLocation;
|
|
currentNotification = null;
|
|
}
|
|
|
|
public virtual void FinishCurrentNotification() {}
|
|
|
|
public virtual void PauseNotification() {
|
|
if (pauseCounter++ == 0 && IsNotificationVisible) {
|
|
Location = ControlExtensions.InvisibleLocation;
|
|
}
|
|
}
|
|
|
|
public virtual void ResumeNotification() {
|
|
if (pauseCounter > 0) {
|
|
--pauseCounter;
|
|
}
|
|
}
|
|
|
|
protected virtual void LoadTweet(DesktopNotification tweet) {
|
|
currentNotification = tweet;
|
|
resourceHandler.SetHTML(browserImpl.GetTweetHTML(tweet));
|
|
|
|
browser.Load(TwitterUrls.TweetDeck);
|
|
DisplayTooltip(null);
|
|
}
|
|
|
|
protected virtual void SetNotificationSize(int width, int height) {
|
|
browser.ClientSize = ClientSize = new Size(BrowserUtils.Scale(width, SizeScale), BrowserUtils.Scale(height, SizeScale));
|
|
}
|
|
|
|
protected virtual void UpdateTitle() {
|
|
string title = currentNotification?.ColumnTitle;
|
|
Text = string.IsNullOrEmpty(title) || !Config.DisplayNotificationColumn ? Program.BrandName : $"{Program.BrandName} - {title}";
|
|
}
|
|
|
|
public void ShowTweetDetail() {
|
|
if (currentNotification != null && owner.ShowTweetDetail(currentNotification.ColumnId, currentNotification.ChirpId, currentNotification.TweetUrl)) {
|
|
FinishCurrentNotification();
|
|
}
|
|
}
|
|
|
|
public void MoveToVisibleLocation() {
|
|
bool needsReactivating = Location == ControlExtensions.InvisibleLocation;
|
|
Location = PrimaryLocation;
|
|
|
|
if (needsReactivating) {
|
|
NativeMethods.SetFormPos(this, NativeMethods.HWND_TOPMOST, NativeMethods.SWP_NOACTIVATE);
|
|
}
|
|
}
|
|
|
|
public void DisplayTooltip(string text) {
|
|
if (string.IsNullOrEmpty(text)) {
|
|
toolTip.Hide(this);
|
|
}
|
|
else {
|
|
Point position = PointToClient(Cursor.Position);
|
|
position.Offset(20, 5);
|
|
toolTip.Show(text, this, position);
|
|
}
|
|
}
|
|
}
|
|
}
|