mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-09-14 10:32:10 +02:00
Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
7944a24d3c | |||
cc8459c759 | |||
10074ff92c | |||
173f25bebc | |||
31680fc4ae | |||
e937d43614 | |||
20e29a7975 | |||
ef815dabce | |||
1fb133e6b8 | |||
50b58cd6a6 | |||
01485d7ef9 | |||
b17c6a5ac7 | |||
d2ed2b4a00 | |||
710a7524a1 | |||
2be46464d6 | |||
8d536a6734 | |||
250d502238 | |||
e8de7266d0 | |||
9414f372d7 | |||
b0f9de67cf | |||
9b082e114e | |||
816a5334ac | |||
15a4e10da9 | |||
01b9302b0c | |||
442126a11a | |||
a9c140c0fc | |||
97ad7a3e68 | |||
7d737eefb6 | |||
4ac05b38d3 | |||
651bbbb672 |
@@ -7,6 +7,7 @@ namespace TweetDuck.Configuration{
|
||||
public const string ArgDataFolder = "-datafolder";
|
||||
public const string ArgLogging = "-log";
|
||||
public const string ArgIgnoreGDPR = "-nogdpr";
|
||||
public const string ArgFreeze = "-freeze";
|
||||
|
||||
// internal args
|
||||
public const string ArgRestart = "-restart";
|
||||
|
@@ -34,7 +34,7 @@ namespace TweetDuck.Configuration.Instance{
|
||||
LoadInternal(attempt > 0);
|
||||
|
||||
if (firstException != null){ // silently log exception that caused a backup restore
|
||||
Program.Reporter.Log(firstException.ToString());
|
||||
Program.Reporter.LogImportant(firstException.ToString());
|
||||
}
|
||||
|
||||
return;
|
||||
|
@@ -124,7 +124,7 @@ namespace TweetDuck.Configuration{
|
||||
try{
|
||||
File.Delete(file);
|
||||
}catch(Exception e){
|
||||
Program.Reporter.Log(e.ToString());
|
||||
Program.Reporter.LogImportant(e.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ namespace TweetDuck.Configuration{
|
||||
public Size PluginsWindowSize { get; set; } = Size.Empty;
|
||||
|
||||
public bool ExpandLinksOnHover { get; set; } = true;
|
||||
public bool FocusDmInput { get; set; } = true;
|
||||
public bool OpenSearchInFirstColumn { get; set; } = true;
|
||||
public bool KeepLikeFollowDialogsOpen { get; set; } = true;
|
||||
public bool BestImageQuality { get; set; } = true;
|
||||
|
@@ -17,6 +17,7 @@ namespace TweetDuck.Core.Bridge{
|
||||
build.Append("x.expandLinksOnHover=").Append(Bool(config.ExpandLinksOnHover));
|
||||
|
||||
if (environment == Environment.Browser){
|
||||
build.Append("x.focusDmInput=").Append(Bool(config.FocusDmInput));
|
||||
build.Append("x.openSearchInFirstColumn=").Append(Bool(config.OpenSearchInFirstColumn));
|
||||
build.Append("x.keepLikeFollowDialogsOpen=").Append(Bool(config.KeepLikeFollowDialogsOpen));
|
||||
build.Append("x.muteNotifications=").Append(Bool(config.MuteNotifications));
|
||||
|
@@ -494,7 +494,7 @@ namespace TweetDuck.Core{
|
||||
FormManager.TryFind<FormSettings>()?.Close();
|
||||
|
||||
using(DialogSettingsManage dialog = new DialogSettingsManage(plugins, true)){
|
||||
if (dialog.ShowDialog() == DialogResult.OK && !dialog.IsRestarting){
|
||||
if (!dialog.IsDisposed && dialog.ShowDialog() == DialogResult.OK && !dialog.IsRestarting){ // needs disposal check because the dialog may be closed in constructor
|
||||
BrowserProcessHandler.UpdatePrefs();
|
||||
FormManager.TryFind<FormPlugins>()?.Close();
|
||||
plugins.Reload(); // also reloads the browser
|
||||
|
47
Core/Handling/KeyboardHandlerBase.cs
Normal file
47
Core/Handling/KeyboardHandlerBase.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System.Windows.Forms;
|
||||
using CefSharp;
|
||||
using TweetDuck.Core.Controls;
|
||||
using TweetDuck.Core.Other;
|
||||
using TweetDuck.Core.Utils;
|
||||
|
||||
namespace TweetDuck.Core.Handling{
|
||||
class KeyboardHandlerBase : IKeyboardHandler{
|
||||
protected virtual bool HandleRawKey(IWebBrowser browserControl, IBrowser browser, Keys key, CefEventFlags modifiers){
|
||||
if (modifiers == (CefEventFlags.ControlDown | CefEventFlags.ShiftDown) && key == Keys.I){
|
||||
if (BrowserUtils.HasDevTools){
|
||||
browser.ShowDevTools();
|
||||
}
|
||||
else{
|
||||
browserControl.AsControl().InvokeSafe(() => {
|
||||
string extraMessage;
|
||||
|
||||
if (Program.IsPortable){
|
||||
extraMessage = "Please download the portable installer, select the folder with your current installation of TweetDuck Portable, and tick 'Install dev tools' during the installation process.";
|
||||
}
|
||||
else{
|
||||
extraMessage = "Please download the installer, and tick 'Install dev tools' during the installation process. The installer will automatically find and update your current installation of TweetDuck.";
|
||||
}
|
||||
|
||||
FormMessage.Information("Dev Tools", "You do not have dev tools installed. "+extraMessage, FormMessage.OK);
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IKeyboardHandler.OnPreKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut){
|
||||
if (type == KeyType.RawKeyDown && !browser.FocusedFrame.Url.StartsWith("chrome-devtools://")){
|
||||
return HandleRawKey(browserControl, browser, (Keys)windowsKeyCode, modifiers);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IKeyboardHandler.OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,19 +2,19 @@
|
||||
using CefSharp;
|
||||
|
||||
namespace TweetDuck.Core.Handling{
|
||||
sealed class KeyboardHandlerBrowser : IKeyboardHandler{
|
||||
sealed class KeyboardHandlerBrowser : KeyboardHandlerBase{
|
||||
private readonly FormBrowser form;
|
||||
|
||||
public KeyboardHandlerBrowser(FormBrowser form){
|
||||
this.form = form;
|
||||
}
|
||||
|
||||
bool IKeyboardHandler.OnPreKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut){
|
||||
return type == KeyType.RawKeyDown && form.ProcessBrowserKey((Keys)windowsKeyCode);
|
||||
}
|
||||
protected override bool HandleRawKey(IWebBrowser browserControl, IBrowser browser, Keys key, CefEventFlags modifiers){
|
||||
if (base.HandleRawKey(browserControl, browser, key, modifiers)){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IKeyboardHandler.OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey){
|
||||
return false;
|
||||
return form.ProcessBrowserKey(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ using TweetDuck.Core.Controls;
|
||||
using TweetDuck.Core.Notification;
|
||||
|
||||
namespace TweetDuck.Core.Handling {
|
||||
sealed class KeyboardHandlerNotification : IKeyboardHandler{
|
||||
sealed class KeyboardHandlerNotification : KeyboardHandlerBase{
|
||||
private readonly FormNotificationBase notification;
|
||||
|
||||
public KeyboardHandlerNotification(FormNotificationBase notification){
|
||||
@@ -15,31 +15,30 @@ namespace TweetDuck.Core.Handling {
|
||||
notification.InvokeAsyncSafe(notification.AnalyticsFile.NotificationKeyboardShortcuts.Trigger);
|
||||
}
|
||||
|
||||
bool IKeyboardHandler.OnPreKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut){
|
||||
if (type == KeyType.RawKeyDown && !browser.FocusedFrame.Url.StartsWith("chrome-devtools://")){
|
||||
switch((Keys)windowsKeyCode){
|
||||
case Keys.Enter:
|
||||
notification.InvokeAsyncSafe(notification.FinishCurrentNotification);
|
||||
TriggerKeyboardShortcutAnalytics();
|
||||
return true;
|
||||
|
||||
case Keys.Escape:
|
||||
notification.InvokeAsyncSafe(notification.HideNotification);
|
||||
TriggerKeyboardShortcutAnalytics();
|
||||
return true;
|
||||
|
||||
case Keys.Space:
|
||||
notification.InvokeAsyncSafe(() => notification.FreezeTimer = !notification.FreezeTimer);
|
||||
TriggerKeyboardShortcutAnalytics();
|
||||
return true;
|
||||
}
|
||||
protected override bool HandleRawKey(IWebBrowser browserControl, IBrowser browser, Keys key, CefEventFlags modifiers){
|
||||
if (base.HandleRawKey(browserControl, browser, key, modifiers)){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
switch(key){
|
||||
case Keys.Enter:
|
||||
notification.InvokeAsyncSafe(notification.FinishCurrentNotification);
|
||||
TriggerKeyboardShortcutAnalytics();
|
||||
return true;
|
||||
|
||||
bool IKeyboardHandler.OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey){
|
||||
return false;
|
||||
case Keys.Escape:
|
||||
notification.InvokeAsyncSafe(notification.HideNotification);
|
||||
TriggerKeyboardShortcutAnalytics();
|
||||
return true;
|
||||
|
||||
case Keys.Space:
|
||||
notification.InvokeAsyncSafe(() => notification.FreezeTimer = !notification.FreezeTimer);
|
||||
TriggerKeyboardShortcutAnalytics();
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,20 +1,45 @@
|
||||
// Uncomment to force TweetDeck to load a predefined version of the vendor/bundle scripts and stylesheets
|
||||
// #define FREEZE_TWEETDECK_RESOURCES
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using CefSharp;
|
||||
using CefSharp.Handler;
|
||||
using TweetDuck.Core.Handling.General;
|
||||
using TweetDuck.Core.Utils;
|
||||
|
||||
#if FREEZE_TWEETDECK_RESOURCES
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
#endif
|
||||
|
||||
namespace TweetDuck.Core.Handling{
|
||||
class RequestHandlerBase : DefaultRequestHandler{
|
||||
private static readonly Regex TweetDeckResourceUrl = new Regex(@"/dist/(.*?)\.(.*?)\.(css|js)$", RegexOptions.Compiled);
|
||||
private static readonly SortedList<string, string> TweetDeckHashes = new SortedList<string, string>(4);
|
||||
|
||||
public static void LoadResourceRewriteRules(string rules){
|
||||
if (string.IsNullOrEmpty(rules)){
|
||||
return;
|
||||
}
|
||||
|
||||
TweetDeckHashes.Clear();
|
||||
|
||||
foreach(string rule in rules.Replace(" ", "").ToLower().Split(',')){
|
||||
string[] split = rule.Split('=');
|
||||
|
||||
if (split.Length == 2){
|
||||
string key = split[0];
|
||||
string hash = split[1];
|
||||
|
||||
if (hash.All(chr => char.IsDigit(chr) || (chr >= 'a' && chr <= 'f'))){
|
||||
TweetDeckHashes.Add(key, hash);
|
||||
}
|
||||
else{
|
||||
throw new ArgumentException("Invalid hash characters: "+rule);
|
||||
}
|
||||
}
|
||||
else{
|
||||
throw new ArgumentException("A rule must have exactly one '=' character: "+rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly bool autoReload;
|
||||
|
||||
public RequestHandlerBase(bool autoReload){
|
||||
@@ -34,34 +59,18 @@ namespace TweetDuck.Core.Handling{
|
||||
|
||||
return base.OnBeforeResourceLoad(browserControl, browser, frame, request, callback);
|
||||
}
|
||||
|
||||
public override void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status){
|
||||
if (autoReload){
|
||||
browser.Reload();
|
||||
}
|
||||
}
|
||||
|
||||
#if FREEZE_TWEETDECK_RESOURCES
|
||||
private static readonly Regex TweetDeckResourceUrl = new Regex(@"/dist/(.*?)\.(.*?)\.(css|js)$", RegexOptions.Compiled);
|
||||
|
||||
private static readonly SortedList<string, string> TweetDeckHashes = new SortedList<string, string>(2){
|
||||
{ "vendor.js", "d897f6b9ed" },
|
||||
{ "bundle.js", "851d3877b9" },
|
||||
{ "vendor.css", "ce7cdd10b6" },
|
||||
{ "bundle.css", "c339f07047" }
|
||||
};
|
||||
|
||||
public override bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response){
|
||||
if (request.ResourceType == ResourceType.Script || request.ResourceType == ResourceType.Stylesheet){
|
||||
if ((request.ResourceType == ResourceType.Script || request.ResourceType == ResourceType.Stylesheet) && TweetDeckHashes.Count > 0){
|
||||
string url = request.Url;
|
||||
Match match = TweetDeckResourceUrl.Match(url);
|
||||
|
||||
if (match.Success && TweetDeckHashes.TryGetValue($"{match.Groups[1]}.{match.Groups[3]}", out string hash)){
|
||||
if (match.Groups[2].Value == hash){
|
||||
Debug.WriteLine($"Accepting {url}");
|
||||
Program.Reporter.LogVerbose("[RequestHandlerBase] Accepting " + url);
|
||||
}
|
||||
else{
|
||||
Debug.WriteLine($"Rewriting {url} hash to {hash}");
|
||||
Program.Reporter.LogVerbose("[RequestHandlerBase] Replacing " + url + " hash with " + hash);
|
||||
request.Url = TweetDeckResourceUrl.Replace(url, $"/dist/$1.{hash}.$3");
|
||||
return true;
|
||||
}
|
||||
@@ -70,6 +79,11 @@ namespace TweetDuck.Core.Handling{
|
||||
|
||||
return base.OnResourceResponse(browserControl, browser, frame, request, response);
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status){
|
||||
if (autoReload){
|
||||
browser.Reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -13,7 +13,12 @@ namespace TweetDuck.Core.Handling{
|
||||
public RequestHandlerBrowser() : base(true){}
|
||||
|
||||
public override CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback){
|
||||
if (request.ResourceType == ResourceType.Script){
|
||||
if (request.ResourceType == ResourceType.MainFrame){
|
||||
if (request.Url.EndsWith("//twitter.com/")){
|
||||
request.Url = TwitterUtils.TweetDeckURL; // redirect plain twitter.com requests, fixes bugs with login 2FA
|
||||
}
|
||||
}
|
||||
else if (request.ResourceType == ResourceType.Script){
|
||||
string url = request.Url;
|
||||
|
||||
if (url.Contains("analytics.")){
|
||||
|
@@ -40,7 +40,7 @@ namespace TweetDuck.Core.Management{
|
||||
|
||||
if ((process = Process.Start(new ProcessStartInfo{
|
||||
FileName = Path.Combine(Program.ProgramPath, "TweetDuck.Video.exe"),
|
||||
Arguments = $"{owner.Handle} {Config.VideoPlayerVolume} \"{url}\" \"{pipe.GenerateToken()}\"",
|
||||
Arguments = $"{owner.Handle} {(int)Math.Floor(100F*owner.GetDPIScale())} {Config.VideoPlayerVolume} \"{url}\" \"{pipe.GenerateToken()}\"",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true
|
||||
})) != null){
|
||||
@@ -135,7 +135,7 @@ namespace TweetDuck.Core.Management{
|
||||
|
||||
private void process_OutputDataReceived(object sender, DataReceivedEventArgs e){
|
||||
if (!string.IsNullOrEmpty(e.Data)){
|
||||
Program.Reporter.Log("[VideoPlayer] "+e.Data);
|
||||
Program.Reporter.LogVerbose("[VideoPlayer] "+e.Data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -70,6 +70,7 @@ namespace TweetDuck.Core.Other{
|
||||
this.browser = new ChromiumWebBrowser(url){
|
||||
MenuHandler = new ContextMenuGuide(owner),
|
||||
JsDialogHandler = new JavaScriptDialogHandler(),
|
||||
KeyboardHandler = new KeyboardHandlerBase(),
|
||||
LifeSpanHandler = new LifeSpanHandler(),
|
||||
RequestHandler = new RequestHandlerBase(true),
|
||||
ResourceHandlerFactory = resourceHandlerFactory
|
||||
|
@@ -33,6 +33,7 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
|
||||
|
||||
private readonly PluginManager plugins;
|
||||
private readonly Dictionary<CheckBox, ProfileManager.Items> checkBoxMap = new Dictionary<CheckBox, ProfileManager.Items>(4);
|
||||
private readonly bool openImportImmediately;
|
||||
|
||||
private State currentState;
|
||||
private ProfileManager importManager;
|
||||
@@ -51,6 +52,8 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
|
||||
this.checkBoxMap[cbSession] = ProfileManager.Items.Session;
|
||||
this.checkBoxMap[cbPluginData] = ProfileManager.Items.PluginData;
|
||||
|
||||
this.openImportImmediately = openImportImmediately;
|
||||
|
||||
if (openImportImmediately){
|
||||
radioImport.Checked = true;
|
||||
btnContinue_Click(null, EventArgs.Empty);
|
||||
@@ -88,6 +91,10 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
|
||||
Filter = "TweetDuck Profile (*.tdsettings)|*.tdsettings"
|
||||
}){
|
||||
if (dialog.ShowDialog() != DialogResult.OK){
|
||||
if (openImportImmediately){
|
||||
Close();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
71
Core/Other/Settings/TabSettingsGeneral.Designer.cs
generated
71
Core/Other/Settings/TabSettingsGeneral.Designer.cs
generated
@@ -39,6 +39,7 @@
|
||||
this.checkAnimatedAvatars = new System.Windows.Forms.CheckBox();
|
||||
this.labelUpdates = new System.Windows.Forms.Label();
|
||||
this.flowPanelLeft = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.checkFocusDmInput = new System.Windows.Forms.CheckBox();
|
||||
this.checkKeepLikeFollowDialogsOpen = new System.Windows.Forms.CheckBox();
|
||||
this.labelTray = new System.Windows.Forms.Label();
|
||||
this.comboBoxTrayType = new System.Windows.Forms.ComboBox();
|
||||
@@ -82,11 +83,11 @@
|
||||
//
|
||||
this.checkUpdateNotifications.AutoSize = true;
|
||||
this.checkUpdateNotifications.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||
this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 393);
|
||||
this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 409);
|
||||
this.checkUpdateNotifications.Margin = new System.Windows.Forms.Padding(6, 6, 3, 2);
|
||||
this.checkUpdateNotifications.Name = "checkUpdateNotifications";
|
||||
this.checkUpdateNotifications.Size = new System.Drawing.Size(182, 19);
|
||||
this.checkUpdateNotifications.TabIndex = 13;
|
||||
this.checkUpdateNotifications.TabIndex = 14;
|
||||
this.checkUpdateNotifications.Text = "Check Updates Automatically";
|
||||
this.checkUpdateNotifications.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -94,12 +95,12 @@
|
||||
//
|
||||
this.btnCheckUpdates.AutoSize = true;
|
||||
this.btnCheckUpdates.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||
this.btnCheckUpdates.Location = new System.Drawing.Point(5, 417);
|
||||
this.btnCheckUpdates.Location = new System.Drawing.Point(5, 433);
|
||||
this.btnCheckUpdates.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||
this.btnCheckUpdates.Name = "btnCheckUpdates";
|
||||
this.btnCheckUpdates.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.btnCheckUpdates.Size = new System.Drawing.Size(128, 25);
|
||||
this.btnCheckUpdates.TabIndex = 14;
|
||||
this.btnCheckUpdates.TabIndex = 15;
|
||||
this.btnCheckUpdates.Text = "Check Updates Now";
|
||||
this.btnCheckUpdates.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -119,11 +120,11 @@
|
||||
//
|
||||
this.checkBestImageQuality.AutoSize = true;
|
||||
this.checkBestImageQuality.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||
this.checkBestImageQuality.Location = new System.Drawing.Point(6, 98);
|
||||
this.checkBestImageQuality.Location = new System.Drawing.Point(6, 122);
|
||||
this.checkBestImageQuality.Margin = new System.Windows.Forms.Padding(6, 3, 3, 2);
|
||||
this.checkBestImageQuality.Name = "checkBestImageQuality";
|
||||
this.checkBestImageQuality.Size = new System.Drawing.Size(125, 19);
|
||||
this.checkBestImageQuality.TabIndex = 4;
|
||||
this.checkBestImageQuality.TabIndex = 5;
|
||||
this.checkBestImageQuality.Text = "Best Image Quality";
|
||||
this.checkBestImageQuality.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -131,11 +132,11 @@
|
||||
//
|
||||
this.checkOpenSearchInFirstColumn.AutoSize = true;
|
||||
this.checkOpenSearchInFirstColumn.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||
this.checkOpenSearchInFirstColumn.Location = new System.Drawing.Point(6, 50);
|
||||
this.checkOpenSearchInFirstColumn.Location = new System.Drawing.Point(6, 74);
|
||||
this.checkOpenSearchInFirstColumn.Margin = new System.Windows.Forms.Padding(6, 3, 3, 2);
|
||||
this.checkOpenSearchInFirstColumn.Name = "checkOpenSearchInFirstColumn";
|
||||
this.checkOpenSearchInFirstColumn.Size = new System.Drawing.Size(245, 19);
|
||||
this.checkOpenSearchInFirstColumn.TabIndex = 2;
|
||||
this.checkOpenSearchInFirstColumn.TabIndex = 3;
|
||||
this.checkOpenSearchInFirstColumn.Text = "Add Search Columns Before First Column";
|
||||
this.checkOpenSearchInFirstColumn.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -158,11 +159,11 @@
|
||||
//
|
||||
this.labelZoom.AutoSize = true;
|
||||
this.labelZoom.Font = new System.Drawing.Font("Segoe UI Semibold", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.labelZoom.Location = new System.Drawing.Point(3, 155);
|
||||
this.labelZoom.Location = new System.Drawing.Point(3, 179);
|
||||
this.labelZoom.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||
this.labelZoom.Name = "labelZoom";
|
||||
this.labelZoom.Size = new System.Drawing.Size(39, 15);
|
||||
this.labelZoom.TabIndex = 6;
|
||||
this.labelZoom.TabIndex = 7;
|
||||
this.labelZoom.Text = "Zoom";
|
||||
//
|
||||
// zoomUpdateTimer
|
||||
@@ -185,21 +186,21 @@
|
||||
//
|
||||
this.panelZoom.Controls.Add(this.trackBarZoom);
|
||||
this.panelZoom.Controls.Add(this.labelZoomValue);
|
||||
this.panelZoom.Location = new System.Drawing.Point(0, 171);
|
||||
this.panelZoom.Location = new System.Drawing.Point(0, 195);
|
||||
this.panelZoom.Margin = new System.Windows.Forms.Padding(0, 1, 0, 0);
|
||||
this.panelZoom.Name = "panelZoom";
|
||||
this.panelZoom.Size = new System.Drawing.Size(300, 35);
|
||||
this.panelZoom.TabIndex = 7;
|
||||
this.panelZoom.TabIndex = 8;
|
||||
//
|
||||
// checkAnimatedAvatars
|
||||
//
|
||||
this.checkAnimatedAvatars.AutoSize = true;
|
||||
this.checkAnimatedAvatars.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||
this.checkAnimatedAvatars.Location = new System.Drawing.Point(6, 122);
|
||||
this.checkAnimatedAvatars.Location = new System.Drawing.Point(6, 146);
|
||||
this.checkAnimatedAvatars.Margin = new System.Windows.Forms.Padding(6, 3, 3, 2);
|
||||
this.checkAnimatedAvatars.Name = "checkAnimatedAvatars";
|
||||
this.checkAnimatedAvatars.Size = new System.Drawing.Size(158, 19);
|
||||
this.checkAnimatedAvatars.TabIndex = 5;
|
||||
this.checkAnimatedAvatars.TabIndex = 6;
|
||||
this.checkAnimatedAvatars.Text = "Enable Animated Avatars";
|
||||
this.checkAnimatedAvatars.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -207,11 +208,11 @@
|
||||
//
|
||||
this.labelUpdates.AutoSize = true;
|
||||
this.labelUpdates.Font = new System.Drawing.Font("Segoe UI Semibold", 10.5F, System.Drawing.FontStyle.Bold);
|
||||
this.labelUpdates.Location = new System.Drawing.Point(0, 367);
|
||||
this.labelUpdates.Margin = new System.Windows.Forms.Padding(0, 30, 0, 1);
|
||||
this.labelUpdates.Location = new System.Drawing.Point(0, 383);
|
||||
this.labelUpdates.Margin = new System.Windows.Forms.Padding(0, 27, 0, 1);
|
||||
this.labelUpdates.Name = "labelUpdates";
|
||||
this.labelUpdates.Size = new System.Drawing.Size(69, 19);
|
||||
this.labelUpdates.TabIndex = 12;
|
||||
this.labelUpdates.TabIndex = 13;
|
||||
this.labelUpdates.Text = "UPDATES";
|
||||
//
|
||||
// flowPanelLeft
|
||||
@@ -220,6 +221,7 @@
|
||||
| System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.flowPanelLeft.Controls.Add(this.labelUI);
|
||||
this.flowPanelLeft.Controls.Add(this.checkExpandLinks);
|
||||
this.flowPanelLeft.Controls.Add(this.checkFocusDmInput);
|
||||
this.flowPanelLeft.Controls.Add(this.checkOpenSearchInFirstColumn);
|
||||
this.flowPanelLeft.Controls.Add(this.checkKeepLikeFollowDialogsOpen);
|
||||
this.flowPanelLeft.Controls.Add(this.checkBestImageQuality);
|
||||
@@ -240,15 +242,27 @@
|
||||
this.flowPanelLeft.TabIndex = 0;
|
||||
this.flowPanelLeft.WrapContents = false;
|
||||
//
|
||||
// checkFocusDmInput
|
||||
//
|
||||
this.checkFocusDmInput.AutoSize = true;
|
||||
this.checkFocusDmInput.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||
this.checkFocusDmInput.Location = new System.Drawing.Point(6, 50);
|
||||
this.checkFocusDmInput.Margin = new System.Windows.Forms.Padding(6, 3, 3, 2);
|
||||
this.checkFocusDmInput.Name = "checkFocusDmInput";
|
||||
this.checkFocusDmInput.Size = new System.Drawing.Size(282, 19);
|
||||
this.checkFocusDmInput.TabIndex = 2;
|
||||
this.checkFocusDmInput.Text = "Focus Input Field When Opening Direct Message";
|
||||
this.checkFocusDmInput.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// checkKeepLikeFollowDialogsOpen
|
||||
//
|
||||
this.checkKeepLikeFollowDialogsOpen.AutoSize = true;
|
||||
this.checkKeepLikeFollowDialogsOpen.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||
this.checkKeepLikeFollowDialogsOpen.Location = new System.Drawing.Point(6, 74);
|
||||
this.checkKeepLikeFollowDialogsOpen.Location = new System.Drawing.Point(6, 98);
|
||||
this.checkKeepLikeFollowDialogsOpen.Margin = new System.Windows.Forms.Padding(6, 3, 3, 2);
|
||||
this.checkKeepLikeFollowDialogsOpen.Name = "checkKeepLikeFollowDialogsOpen";
|
||||
this.checkKeepLikeFollowDialogsOpen.Size = new System.Drawing.Size(190, 19);
|
||||
this.checkKeepLikeFollowDialogsOpen.TabIndex = 3;
|
||||
this.checkKeepLikeFollowDialogsOpen.TabIndex = 4;
|
||||
this.checkKeepLikeFollowDialogsOpen.Text = "Keep Like/Follow Dialogs Open";
|
||||
this.checkKeepLikeFollowDialogsOpen.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -256,11 +270,11 @@
|
||||
//
|
||||
this.labelTray.AutoSize = true;
|
||||
this.labelTray.Font = new System.Drawing.Font("Segoe UI Semibold", 10.5F, System.Drawing.FontStyle.Bold);
|
||||
this.labelTray.Location = new System.Drawing.Point(0, 236);
|
||||
this.labelTray.Margin = new System.Windows.Forms.Padding(0, 30, 0, 1);
|
||||
this.labelTray.Location = new System.Drawing.Point(0, 255);
|
||||
this.labelTray.Margin = new System.Windows.Forms.Padding(0, 25, 0, 1);
|
||||
this.labelTray.Name = "labelTray";
|
||||
this.labelTray.Size = new System.Drawing.Size(99, 19);
|
||||
this.labelTray.TabIndex = 8;
|
||||
this.labelTray.TabIndex = 9;
|
||||
this.labelTray.Text = "SYSTEM TRAY";
|
||||
//
|
||||
// comboBoxTrayType
|
||||
@@ -268,32 +282,32 @@
|
||||
this.comboBoxTrayType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.comboBoxTrayType.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||
this.comboBoxTrayType.FormattingEnabled = true;
|
||||
this.comboBoxTrayType.Location = new System.Drawing.Point(5, 260);
|
||||
this.comboBoxTrayType.Location = new System.Drawing.Point(5, 279);
|
||||
this.comboBoxTrayType.Margin = new System.Windows.Forms.Padding(5, 4, 3, 3);
|
||||
this.comboBoxTrayType.Name = "comboBoxTrayType";
|
||||
this.comboBoxTrayType.Size = new System.Drawing.Size(144, 23);
|
||||
this.comboBoxTrayType.TabIndex = 9;
|
||||
this.comboBoxTrayType.TabIndex = 10;
|
||||
//
|
||||
// labelTrayIcon
|
||||
//
|
||||
this.labelTrayIcon.AutoSize = true;
|
||||
this.labelTrayIcon.Font = new System.Drawing.Font("Segoe UI Semibold", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.labelTrayIcon.Location = new System.Drawing.Point(3, 295);
|
||||
this.labelTrayIcon.Location = new System.Drawing.Point(3, 314);
|
||||
this.labelTrayIcon.Margin = new System.Windows.Forms.Padding(3, 9, 3, 0);
|
||||
this.labelTrayIcon.Name = "labelTrayIcon";
|
||||
this.labelTrayIcon.Size = new System.Drawing.Size(56, 15);
|
||||
this.labelTrayIcon.TabIndex = 10;
|
||||
this.labelTrayIcon.TabIndex = 11;
|
||||
this.labelTrayIcon.Text = "Tray Icon";
|
||||
//
|
||||
// checkTrayHighlight
|
||||
//
|
||||
this.checkTrayHighlight.AutoSize = true;
|
||||
this.checkTrayHighlight.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||
this.checkTrayHighlight.Location = new System.Drawing.Point(6, 316);
|
||||
this.checkTrayHighlight.Location = new System.Drawing.Point(6, 335);
|
||||
this.checkTrayHighlight.Margin = new System.Windows.Forms.Padding(6, 6, 3, 2);
|
||||
this.checkTrayHighlight.Name = "checkTrayHighlight";
|
||||
this.checkTrayHighlight.Size = new System.Drawing.Size(114, 19);
|
||||
this.checkTrayHighlight.TabIndex = 11;
|
||||
this.checkTrayHighlight.TabIndex = 12;
|
||||
this.checkTrayHighlight.Text = "Enable Highlight";
|
||||
this.checkTrayHighlight.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -548,5 +562,6 @@
|
||||
private System.Windows.Forms.Label labelTranslationTarget;
|
||||
private System.Windows.Forms.ComboBox comboBoxTranslationTarget;
|
||||
private System.Windows.Forms.CheckBox checkHardwareAcceleration;
|
||||
private System.Windows.Forms.CheckBox checkFocusDmInput;
|
||||
}
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@ namespace TweetDuck.Core.Other.Settings{
|
||||
// user interface
|
||||
|
||||
toolTip.SetToolTip(checkExpandLinks, "Expands links inside the tweets. If disabled,\r\nthe full links show up in a tooltip instead.");
|
||||
toolTip.SetToolTip(checkFocusDmInput, "Places cursor into Direct Message input\r\nfield when opening a conversation.");
|
||||
toolTip.SetToolTip(checkOpenSearchInFirstColumn, "By default, TweetDeck adds Search columns at the end.\r\nThis option makes them appear before the first column instead.");
|
||||
toolTip.SetToolTip(checkKeepLikeFollowDialogsOpen, "Allows liking and following from multiple accounts at once,\r\ninstead of automatically closing the dialog after taking an action.");
|
||||
toolTip.SetToolTip(checkBestImageQuality, "When right-clicking a tweet image, the context menu options\r\nwill use links to the original image size (:orig in the URL).");
|
||||
@@ -42,6 +43,7 @@ namespace TweetDuck.Core.Other.Settings{
|
||||
toolTip.SetToolTip(trackBarZoom, toolTip.GetToolTip(labelZoomValue));
|
||||
|
||||
checkExpandLinks.Checked = Config.ExpandLinksOnHover;
|
||||
checkFocusDmInput.Checked = Config.FocusDmInput;
|
||||
checkOpenSearchInFirstColumn.Checked = Config.OpenSearchInFirstColumn;
|
||||
checkKeepLikeFollowDialogsOpen.Checked = Config.KeepLikeFollowDialogsOpen;
|
||||
checkBestImageQuality.Checked = Config.BestImageQuality;
|
||||
@@ -127,6 +129,7 @@ namespace TweetDuck.Core.Other.Settings{
|
||||
|
||||
public override void OnReady(){
|
||||
checkExpandLinks.CheckedChanged += checkExpandLinks_CheckedChanged;
|
||||
checkFocusDmInput.CheckedChanged += checkFocusDmInput_CheckedChanged;
|
||||
checkOpenSearchInFirstColumn.CheckedChanged += checkOpenSearchInFirstColumn_CheckedChanged;
|
||||
checkKeepLikeFollowDialogsOpen.CheckedChanged += checkKeepLikeFollowDialogsOpen_CheckedChanged;
|
||||
checkBestImageQuality.CheckedChanged += checkBestImageQuality_CheckedChanged;
|
||||
@@ -160,6 +163,10 @@ namespace TweetDuck.Core.Other.Settings{
|
||||
Config.ExpandLinksOnHover = checkExpandLinks.Checked;
|
||||
}
|
||||
|
||||
private void checkFocusDmInput_CheckedChanged(object sender, EventArgs e){
|
||||
Config.FocusDmInput = checkFocusDmInput.Checked;
|
||||
}
|
||||
|
||||
private void checkOpenSearchInFirstColumn_CheckedChanged(object sender, EventArgs e){
|
||||
Config.OpenSearchInFirstColumn = checkOpenSearchInFirstColumn.Checked;
|
||||
}
|
||||
|
@@ -19,6 +19,9 @@ namespace TweetDuck.Core{
|
||||
sealed class TweetDeckBrowser : IDisposable{
|
||||
private static UserConfig Config => Program.Config.User;
|
||||
|
||||
private const string ErrorUrl = "http://td/error";
|
||||
private const string TwitterStyleUrl = "https://abs.twimg.com/tduck/css";
|
||||
|
||||
public bool Ready { get; private set; }
|
||||
|
||||
public bool Enabled{
|
||||
@@ -119,10 +122,15 @@ namespace TweetDuck.Core{
|
||||
|
||||
if (frame.IsMain){
|
||||
if (TwitterUtils.IsTwitterWebsite(frame)){
|
||||
string css = ScriptLoader.LoadResource("styles/twitter.css", browser);
|
||||
resourceHandlerFactory.RegisterHandler(TwitterStyleUrl, ResourceHandler.FromString(css, mimeType: "text/css"));
|
||||
|
||||
ScriptLoader.ExecuteFile(frame, "twitter.js", browser);
|
||||
}
|
||||
|
||||
frame.ExecuteJavaScriptAsync(TwitterUtils.BackgroundColorOverride);
|
||||
if (!TwitterUtils.IsTwitterLogin2FactorWebsite(frame)){
|
||||
frame.ExecuteJavaScriptAsync(TwitterUtils.BackgroundColorOverride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +159,10 @@ namespace TweetDuck.Core{
|
||||
|
||||
ScriptLoader.ExecuteFile(frame, "update.js", browser);
|
||||
}
|
||||
|
||||
if (frame.Url == ErrorUrl){
|
||||
resourceHandlerFactory.UnregisterHandler(ErrorUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private void browser_LoadError(object sender, LoadErrorEventArgs e){
|
||||
@@ -162,7 +174,8 @@ namespace TweetDuck.Core{
|
||||
string errorPage = ScriptLoader.LoadResourceSilent("pages/error.html");
|
||||
|
||||
if (errorPage != null){
|
||||
browser.LoadHtml(errorPage.Replace("{err}", BrowserUtils.GetErrorName(e.ErrorCode)), "http://td/error");
|
||||
resourceHandlerFactory.RegisterHandler(ErrorUrl, ResourceHandler.FromString(errorPage.Replace("{err}", BrowserUtils.GetErrorName(e.ErrorCode))));
|
||||
browser.Load(ErrorUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ namespace TweetDuck.Core.Utils{
|
||||
public const string TweetDeckURL = "https://tweetdeck.twitter.com";
|
||||
|
||||
public static readonly Color BackgroundColor = Color.FromArgb(28, 99, 153);
|
||||
public const string BackgroundColorOverride = "setTimeout(function f(){let h=document.head;if(!h){setTimeout(f,5);return;}let e=document.createElement('style');e.innerHTML='body,body::before{background:#1c6399!important}';h.appendChild(e);},1)";
|
||||
public const string BackgroundColorOverride = "setTimeout(function f(){let h=document.head;if(!h){setTimeout(f,5);return;}let e=document.createElement('style');e.innerHTML='body,body::before{background:#1c6399!important;margin:0}';h.appendChild(e);},1)";
|
||||
|
||||
public static readonly ResourceLink LoadingSpinner = new ResourceLink("https://ton.twimg.com/tduck/spinner", ResourceHandler.FromByteArray(Properties.Resources.spinner, "image/apng"));
|
||||
|
||||
@@ -43,6 +43,10 @@ namespace TweetDuck.Core.Utils{
|
||||
return frame.Url.Contains("//twitter.com/");
|
||||
}
|
||||
|
||||
public static bool IsTwitterLogin2FactorWebsite(IFrame frame){
|
||||
return frame.Url.Contains("//twitter.com/account/login_verification");
|
||||
}
|
||||
|
||||
private static string ExtractMediaBaseLink(string url){
|
||||
int slash = url.LastIndexOf('/');
|
||||
return slash == -1 ? url : StringUtils.ExtractBefore(url, ':', slash);
|
||||
|
10
Program.cs
10
Program.cs
@@ -9,6 +9,7 @@ using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using TweetDuck.Configuration;
|
||||
using TweetDuck.Core;
|
||||
using TweetDuck.Core.Handling;
|
||||
using TweetDuck.Core.Handling.General;
|
||||
using TweetDuck.Core.Other;
|
||||
using TweetDuck.Core.Management;
|
||||
@@ -20,7 +21,7 @@ namespace TweetDuck{
|
||||
public const string BrandName = "TweetDuck";
|
||||
public const string Website = "https://tweetduck.chylex.com";
|
||||
|
||||
public const string VersionTag = "1.17";
|
||||
public const string VersionTag = "1.17.4";
|
||||
|
||||
public static readonly string ProgramPath = AppDomain.CurrentDomain.BaseDirectory;
|
||||
public static readonly bool IsPortable = File.Exists(Path.Combine(ProgramPath, "makeportable"));
|
||||
@@ -129,6 +130,13 @@ namespace TweetDuck{
|
||||
BrowserCache.TryClearNow();
|
||||
}
|
||||
|
||||
try{
|
||||
RequestHandlerBase.LoadResourceRewriteRules(Arguments.GetValue(Arguments.ArgFreeze, null));
|
||||
}catch(Exception e){
|
||||
FormMessage.Error("Resource Freeze", "Error parsing resource rewrite rules: "+e.Message, FormMessage.OK);
|
||||
return;
|
||||
}
|
||||
|
||||
BrowserCache.RefreshTimer();
|
||||
|
||||
CefSharpSettings.WcfEnabled = false;
|
||||
|
@@ -4,6 +4,7 @@ using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using TweetDuck.Configuration;
|
||||
using TweetDuck.Core.Other;
|
||||
|
||||
namespace TweetDuck{
|
||||
@@ -22,7 +23,11 @@ namespace TweetDuck{
|
||||
};
|
||||
}
|
||||
|
||||
public bool Log(string data){
|
||||
public bool LogVerbose(string data){
|
||||
return Arguments.HasFlag(Arguments.ArgLogging) && LogImportant(data);
|
||||
}
|
||||
|
||||
public bool LogImportant(string data){
|
||||
#if DEBUG
|
||||
Debug.WriteLine(data);
|
||||
#endif
|
||||
@@ -45,7 +50,7 @@ namespace TweetDuck{
|
||||
}
|
||||
|
||||
public void HandleException(string caption, string message, bool canIgnore, Exception e){
|
||||
bool loggedSuccessfully = Log(e.ToString());
|
||||
bool loggedSuccessfully = LogImportant(e.ToString());
|
||||
|
||||
string exceptionText = e is ExpandedLogException ? e.Message+"\n\nDetails with potentially sensitive information are in the Error Log." : e.Message;
|
||||
FormMessage form = new FormMessage(caption, message+"\nError: "+exceptionText, canIgnore ? MessageBoxIcon.Warning : MessageBoxIcon.Error);
|
||||
|
@@ -87,9 +87,9 @@ enabled(){
|
||||
// update UI
|
||||
|
||||
this.btnClearAllHTML = `
|
||||
<a class="clear-columns-btn-all-parent js-header-action link-clean cf app-nav-link padding-h--10" data-title="Clear columns (hold Shift to restore)" data-action="td-clearcolumns-doall">
|
||||
<a class="clear-columns-btn-all-parent js-header-action link-clean cf app-nav-link padding-h--16 padding-v--2" data-title="Clear columns (hold Shift to restore)" data-action="td-clearcolumns-doall">
|
||||
<div class="obj-left margin-l--2"><i class="icon icon-medium icon-clear-timeline"></i></div>
|
||||
<div class="clear-columns-btn-all nbfc padding-ts hide-condensed txt-size--16 app-nav-link-text">Clear columns</div>
|
||||
<div class="clear-columns-btn-all nbfc padding-ts hide-condensed txt-size--14 app-nav-link-text">Clear columns</div>
|
||||
</a>`;
|
||||
|
||||
this.btnClearOneHTML = `
|
||||
@@ -123,6 +123,7 @@ enabled(){
|
||||
this.css.insert(".js-app-add-column.is-hidden + .clear-columns-btn-all-parent { display: none; }");
|
||||
this.css.insert(".column-navigator-overflow .clear-columns-btn-all-parent { display: none !important; }");
|
||||
this.css.insert(".column-navigator-overflow { bottom: 224px !important; }");
|
||||
this.css.insert(".app-navigator .clear-columns-btn-all-parent { font-weight: 700; }");
|
||||
|
||||
this.css.insert(".column-header-links { min-width: 51px !important; }");
|
||||
this.css.insert(".column[data-td-icon='icon-message'] .column-header-links { min-width: 110px !important; }");
|
||||
|
@@ -800,10 +800,12 @@ html.dark .NotificationList .Notification-body{color:#14171A}
|
||||
html.dark .DrawerModal{color:#14171A}
|
||||
/* fixes */
|
||||
html.dark .app-search-fake{border-color:transparent}
|
||||
html.dark .spinner-small,html.dark .spinner-large{filter:grayscale(80%)brightness(93%)}
|
||||
html.dark .spinner-small,html.dark .spinner-large{filter:grayscale(85%)brightness(117%)}
|
||||
html.dark .tweet>.color-twitter-blue{color:#8bd!important}
|
||||
html.dark .hw-card-container>div{border-color:#292F33;background:transparent}
|
||||
html.dark .hw-card-container>div>div{border-color:#292F33}
|
||||
html.dark .modal-content,html.dark .lst-group{color:#292F33}
|
||||
html.dark .modal-content,html.dark .lst-group,html.dark #actions-modal{color:#292F33}
|
||||
html.dark #actions-modal .account-link{color:#38444d}
|
||||
html.dark .mdl-accent{background-color:transparent}
|
||||
html.dark .lst-launcher a span{color:#657786!important}
|
||||
html.dark .social-proof-names a{color:#3b94d9}
|
||||
|
@@ -62,6 +62,14 @@ enabled(){
|
||||
maybeDockedComposePanel.find(".cf.margin-t--12.margin-b--30").first().append(buttonHTML);
|
||||
}
|
||||
|
||||
this.getDrawerInput = () => {
|
||||
return $(".js-compose-text", me.composeDrawer);
|
||||
};
|
||||
|
||||
this.getDrawerScroller = () => {
|
||||
return $(".js-compose-scroller > .scroll-v", me.composeDrawer);
|
||||
};
|
||||
|
||||
// keyboard generation
|
||||
|
||||
this.currentKeyboard = null;
|
||||
@@ -79,12 +87,12 @@ enabled(){
|
||||
|
||||
this.currentKeywords = [];
|
||||
|
||||
this.composePanelScroller.trigger("scroll");
|
||||
this.getDrawerScroller().trigger("scroll");
|
||||
|
||||
$(".emoji-keyboard-popup-btn").removeClass("is-selected");
|
||||
|
||||
if (refocus){
|
||||
this.composeInput.focus();
|
||||
this.getDrawerInput().focus();
|
||||
|
||||
if (lastEmojiKeyword && lastEmojiPosition === 0){
|
||||
document.execCommand("insertText", false, lastEmojiKeyword);
|
||||
@@ -229,16 +237,16 @@ enabled(){
|
||||
this.currentSpanner.style.height = ($(this.currentKeyboard).height()-10)+"px";
|
||||
$(".emoji-keyboard-popup-btn").parent().after(this.currentSpanner);
|
||||
|
||||
this.composePanelScroller.trigger("scroll");
|
||||
this.getDrawerScroller().trigger("scroll");
|
||||
};
|
||||
|
||||
const getKeyboardTop = () => {
|
||||
let button = $(".emoji-keyboard-popup-btn");
|
||||
return button.offset().top+button.outerHeight()+me.composePanelScroller.scrollTop()+8;
|
||||
return button.offset().top + button.outerHeight() + me.getDrawerScroller().scrollTop() + 8;
|
||||
};
|
||||
|
||||
const insertEmoji = (src, alt) => {
|
||||
let input = this.composeInput;
|
||||
let input = this.getDrawerInput();
|
||||
|
||||
let val = input.val();
|
||||
let posStart = input[0].selectionStart;
|
||||
@@ -378,6 +386,15 @@ enabled(){
|
||||
hideKeyboard();
|
||||
};
|
||||
|
||||
this.drawerToggleEvent = function(e, data){
|
||||
if (data.activeDrawer === "compose"){
|
||||
setTimeout(function(){
|
||||
$(".emoji-keyboard-popup-btn", me.composeDrawer).on("click", me.emojiKeyboardButtonClickEvent);
|
||||
$(".js-docked-compose .js-compose-scroller > .scroll-v", me.composeDrawer).on("scroll", me.composerScrollEvent);
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
this.documentClickEvent = function(e){
|
||||
if (me.currentKeyboard && $(e.target).closest(".compose-text-container").length === 0){
|
||||
hideKeyboard();
|
||||
@@ -399,17 +416,14 @@ enabled(){
|
||||
}
|
||||
|
||||
ready(){
|
||||
this.composeDrawer = $("[data-drawer='compose']");
|
||||
this.composeInput = $(".js-compose-text", ".js-docked-compose");
|
||||
this.composeDrawer = $(".js-drawer[data-drawer='compose']");
|
||||
this.composeSelector = ".js-compose-text,.js-reply-tweetbox";
|
||||
|
||||
this.composePanelScroller = $(".js-compose-scroller", ".js-docked-compose").first().children().first();
|
||||
this.composePanelScroller.on("scroll", this.composerScrollEvent);
|
||||
|
||||
$(".emoji-keyboard-popup-btn").on("click", this.emojiKeyboardButtonClickEvent);
|
||||
$(document).on("click", this.documentClickEvent);
|
||||
$(document).on("keydown", this.documentKeyEvent);
|
||||
$(document).on("uiDrawerActive", this.drawerToggleEvent);
|
||||
$(document).on("uiComposeImageAdded", this.uploadFilesEvent);
|
||||
|
||||
this.composeDrawer.on("uiComposeTweetSending", this.composerSendingEvent);
|
||||
|
||||
$(document).on("keydown", this.composeSelector, this.composeInputKeyDownEvent);
|
||||
@@ -529,14 +543,13 @@ disabled(){
|
||||
$(this.currentSpanner).remove();
|
||||
}
|
||||
|
||||
this.composePanelScroller.off("scroll", this.composerScrollEvent);
|
||||
|
||||
$(".emoji-keyboard-popup-btn").off("click", this.emojiKeyboardButtonClickEvent);
|
||||
$(".emoji-keyboard-popup-btn").remove();
|
||||
|
||||
$(document).off("click", this.documentClickEvent);
|
||||
$(document).off("keydown", this.documentKeyEvent);
|
||||
$(document).off("uiDrawerActive", this.drawerToggleEvent);
|
||||
$(document).off("uiComposeImageAdded", this.uploadFilesEvent);
|
||||
|
||||
this.composeDrawer.off("uiComposeTweetSending", this.composerSendingEvent);
|
||||
|
||||
$(document).off("keydown", this.composeSelector, this.composeInputKeyDownEvent);
|
||||
|
@@ -383,7 +383,7 @@ enabled(){
|
||||
}
|
||||
|
||||
ready(){
|
||||
$(".manage-templates-btn").on("click", this.manageTemplatesButtonClickEvent);
|
||||
$(".js-drawer[data-drawer='compose']").on("click", ".manage-templates-btn", this.manageTemplatesButtonClickEvent);
|
||||
$(document).on("uiDrawerActive", this.drawerToggleEvent);
|
||||
}
|
||||
|
||||
@@ -391,6 +391,7 @@ disabled(){
|
||||
$(".manage-templates-btn").remove();
|
||||
$("#templates-modal-wrap").remove();
|
||||
|
||||
$(".js-drawer[data-drawer='compose']").off("click", ".manage-templates-btn", this.manageTemplatesButtonClickEvent);
|
||||
$(document).off("uiDrawerActive", this.drawerToggleEvent);
|
||||
|
||||
TD.mustaches["compose/docked_compose.mustache"] = this.prevComposeMustache;
|
||||
|
@@ -1039,14 +1039,20 @@
|
||||
// Block: Refocus the textbox after switching accounts.
|
||||
//
|
||||
onAppReady.push(function setupAccountSwitchRefocus(){
|
||||
const composeInput = $$(".js-compose-text", ".js-docked-compose");
|
||||
|
||||
const refocusInput = function(){
|
||||
composeInput.focus();
|
||||
$$(".js-compose-text", ".js-docked-compose").focus();
|
||||
};
|
||||
|
||||
$$(".js-account-list", ".js-docked-compose").delegate(".js-account-item", "click", function(e){
|
||||
const accountItemClickEvent = function(e){
|
||||
setTimeout(refocusInput, 0);
|
||||
};
|
||||
|
||||
$(document).on("uiDrawerActive", function(e, data){
|
||||
if (data.activeDrawer === "compose"){
|
||||
setTimeout(function(){
|
||||
$$(".js-account-list", ".js-docked-compose").delegate(".js-account-item", "click", accountItemClickEvent);
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1198,6 +1204,8 @@
|
||||
//
|
||||
execSafe(function setupVideoPlayer(){
|
||||
window.TDGF_playVideo = function(url, username){
|
||||
return if !url;
|
||||
|
||||
$('<div id="td-video-player-overlay" class="ovl" style="display:block"></div>').on("click contextmenu", function(){
|
||||
$TD.playVideo(null, null);
|
||||
}).appendTo(app);
|
||||
@@ -1503,6 +1511,8 @@
|
||||
//
|
||||
if (ensurePropertyExists(TD, "components", "ConversationDetailView", "prototype", "showChirp")){
|
||||
TD.components.ConversationDetailView.prototype.showChirp = appendToFunction(TD.components.ConversationDetailView.prototype.showChirp, function(){
|
||||
return if !$TDX.focusDmInput;
|
||||
|
||||
setTimeout(function(){
|
||||
$(".js-reply-tweetbox").first().focus();
|
||||
}, 100);
|
||||
|
@@ -7,19 +7,30 @@
|
||||
min-width: 515px;
|
||||
max-width: 835px;
|
||||
height: 328px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#td-introduction-modal .mdl-inner {
|
||||
padding-top: 0;
|
||||
#td-introduction-modal .mdl-header {
|
||||
color: #8899a6;
|
||||
}
|
||||
|
||||
#td-introduction-modal .mdl-header-title {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#td-introduction-modal .mdl-dismiss {
|
||||
color: #292f33;
|
||||
}
|
||||
|
||||
#td-introduction-modal .mdl-inner {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#td-introduction-modal .mdl-content {
|
||||
padding: 4px 16px 0;
|
||||
overflow-y: auto;
|
||||
border-color: #ccd6dd;
|
||||
background: #eaeaea;
|
||||
}
|
||||
|
||||
#td-introduction-modal p {
|
||||
|
@@ -1,38 +0,0 @@
|
||||
/*****************************/
|
||||
/* Fix min width and margins */
|
||||
/*****************************/
|
||||
|
||||
.page-canvas {
|
||||
width: auto !important;
|
||||
max-width: 888px;
|
||||
}
|
||||
|
||||
.signout-wrapper {
|
||||
width: auto !important;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
.signout {
|
||||
margin: 60px 0 54px !important;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
/*******************/
|
||||
/* General styling */
|
||||
/*******************/
|
||||
|
||||
.aside {
|
||||
/* hide elements around dialog */
|
||||
display: none;
|
||||
}
|
||||
|
||||
.buttons button, .buttons a {
|
||||
/* style buttons */
|
||||
display: inline-block;
|
||||
margin: 0 4px !important;
|
||||
border: 1px solid rgba(0, 0, 0, 0.3) !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
@@ -1,11 +1,3 @@
|
||||
/***********/
|
||||
/* General */
|
||||
/***********/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/***********************/
|
||||
/* Redesign scrollbars */
|
||||
/***********************/
|
||||
@@ -377,14 +369,25 @@ html[data-td-font='smallest'] .badge-verified:before {
|
||||
|
||||
html[data-td-font='smallest'] .tweet-detail-wrapper .badge-verified:before {
|
||||
/* fix cut off badge in detail view */
|
||||
width: 13px !important;
|
||||
width: 14px !important;
|
||||
height: 14px !important;
|
||||
background-position: -223px -97px !important;
|
||||
}
|
||||
|
||||
html[data-td-font='smallest'] .fullname-badged:before, html[data-td-font='small'] .fullname-badged:before {
|
||||
/* fix cut off badge in follow chirps */
|
||||
margin-top: -7px !important;
|
||||
/* fix cut off badge in follow chirps and detail view */
|
||||
margin-top: -1px !important;
|
||||
min-width: 14px !important;
|
||||
}
|
||||
|
||||
html[data-td-font='smallest'] .tweet-detail-wrapper .fullname-badged:before {
|
||||
/* fix misaligned badge in detail view */
|
||||
margin-top: -2px !important;
|
||||
}
|
||||
|
||||
html[data-td-font='small'] .tweet-detail-wrapper .fullname-badged:before {
|
||||
/* fix misaligned badge in detail view */
|
||||
margin-top: 0px !important;
|
||||
}
|
||||
|
||||
.keyboard-shortcut-list {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*********************/
|
||||
/* Center everything */
|
||||
/*********************/
|
||||
|
||||
|
||||
#doc {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -25,6 +25,17 @@
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
.ResponsiveLayout {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.Section {
|
||||
padding: 36px !important;
|
||||
}
|
||||
|
||||
/*******************/
|
||||
/* General styling */
|
||||
/*******************/
|
||||
@@ -39,7 +50,7 @@ body {
|
||||
box-shadow: 0 0 150px rgba(255, 255, 255, 0.3) !important;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
.topbar, .TopNav {
|
||||
/* hide top bar */
|
||||
display: none !important;
|
||||
}
|
||||
@@ -65,3 +76,42 @@ button[type='submit'] {
|
||||
margin-top: 15px !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/* Fix min width and margins on logout page */
|
||||
/********************************************/
|
||||
|
||||
html[logout] .page-canvas {
|
||||
width: auto !important;
|
||||
max-width: 888px;
|
||||
}
|
||||
|
||||
html[logout] .signout-wrapper {
|
||||
width: auto !important;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
html[logout] .signout {
|
||||
margin: 60px 0 54px !important;
|
||||
}
|
||||
|
||||
html[logout] .buttons {
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
/* General logout page styling */
|
||||
/*******************************/
|
||||
|
||||
html[logout] .aside {
|
||||
/* hide elements around dialog */
|
||||
display: none;
|
||||
}
|
||||
|
||||
html[logout] .buttons button, html[logout] .buttons a {
|
||||
/* style buttons */
|
||||
display: inline-block;
|
||||
margin: 0 4px !important;
|
||||
border: 1px solid rgba(0, 0, 0, 0.3) !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
@@ -8,15 +8,15 @@
|
||||
return;
|
||||
}
|
||||
|
||||
let style = document.createElement("style");
|
||||
let link = document.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = "https://abs.twimg.com/tduck/css";
|
||||
|
||||
style.innerText = `#import "styles/twitter.base.css"`;
|
||||
document.head.appendChild(link);
|
||||
|
||||
if (location.pathname === "/logout"){
|
||||
style.innerText += `#import "styles/twitter.logout.css"`;
|
||||
document.documentElement.setAttribute("logout", "");
|
||||
}
|
||||
|
||||
document.head.appendChild(style);
|
||||
};
|
||||
|
||||
setTimeout(injectCSS, 1);
|
||||
|
@@ -92,6 +92,7 @@
|
||||
<DependentUpon>FormBrowser.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Core\Handling\General\FileDialogHandler.cs" />
|
||||
<Compile Include="Core\Handling\KeyboardHandlerBase.cs" />
|
||||
<Compile Include="Core\Handling\KeyboardHandlerBrowser.cs" />
|
||||
<Compile Include="Core\Handling\KeyboardHandlerNotification.cs" />
|
||||
<Compile Include="Core\Handling\RequestHandlerBase.cs" />
|
||||
|
@@ -1,17 +1,29 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using CefSharp.BrowserSubprocess;
|
||||
|
||||
namespace TweetDuck.Browser{
|
||||
static class Program{
|
||||
internal const string Version = "1.4.1.0";
|
||||
internal const string Version = "1.4.2";
|
||||
|
||||
private static int Main(string[] args){
|
||||
SubProcess.EnableHighDPISupport();
|
||||
|
||||
const string typePrefix = "--type=";
|
||||
string type = Array.Find(args, arg => arg.StartsWith(typePrefix, StringComparison.OrdinalIgnoreCase)).Substring(typePrefix.Length);
|
||||
string FindArg(string key){
|
||||
return Array.Find(args, arg => arg.StartsWith(key, StringComparison.OrdinalIgnoreCase)).Substring(key.Length);
|
||||
}
|
||||
|
||||
if (type == "renderer"){
|
||||
const string typePrefix = "--type=";
|
||||
const string parentIdPrefix = "--host-process-id=";
|
||||
|
||||
if (!int.TryParse(FindArg(parentIdPrefix), out int parentId)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
Task.Factory.StartNew(() => KillWhenHung(parentId), TaskCreationOptions.LongRunning);
|
||||
|
||||
if (FindArg(typePrefix) == "renderer"){
|
||||
using(SubProcess subProcess = new SubProcess(args)){
|
||||
return subProcess.Run();
|
||||
}
|
||||
@@ -20,5 +32,18 @@ namespace TweetDuck.Browser{
|
||||
return SubProcess.ExecuteProcess();
|
||||
}
|
||||
}
|
||||
|
||||
private static async void KillWhenHung(int parentId){
|
||||
try{
|
||||
using(Process process = Process.GetProcessById(parentId)){
|
||||
process.WaitForExit();
|
||||
}
|
||||
}catch{
|
||||
// ded
|
||||
}
|
||||
|
||||
await Task.Delay(10000);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,14 @@ namespace TweetDuck.Video.Controls{
|
||||
Form form = control.FindForm();
|
||||
System.Diagnostics.Debug.Assert(form != null);
|
||||
|
||||
Text = tooltipFunc(args);
|
||||
string text = tooltipFunc(args);
|
||||
|
||||
if (text == null){
|
||||
Visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Text = text;
|
||||
|
||||
Point loc = form.PointToClient(control.Parent.PointToScreen(new Point(control.Location.X+(followCursor ? args.X : control.Width/2), 0)));
|
||||
loc.X = Math.Max(0, Math.Min(form.Width-Width, loc.X-Width/2));
|
||||
|
@@ -30,7 +30,7 @@ namespace TweetDuck.Video.Controls{
|
||||
brushBack.Color = Parent.BackColor;
|
||||
}
|
||||
|
||||
Rectangle rect = e.ClipRectangle;
|
||||
Rectangle rect = new Rectangle(0, 0, Width, Height);
|
||||
Point cursor = PointToClient(Cursor.Position);
|
||||
int width = rect.Width-1;
|
||||
int progress = (int)(width*((double)Value/Maximum));
|
||||
|
155
video/FormPlayer.Designer.cs
generated
155
video/FormPlayer.Designer.cs
generated
@@ -26,16 +26,18 @@
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.timerSync = new System.Windows.Forms.Timer(this.components);
|
||||
this.trackBarVolume = new System.Windows.Forms.TrackBar();
|
||||
this.tablePanel = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.tablePanelFull = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.progressSeek = new TweetDuck.Video.Controls.SeekBar();
|
||||
this.labelTime = new System.Windows.Forms.Label();
|
||||
this.timerData = new System.Windows.Forms.Timer(this.components);
|
||||
this.labelTooltip = new TweetDuck.Video.Controls.LabelTooltip();
|
||||
this.imageResize = new System.Windows.Forms.PictureBox();
|
||||
this.imageDownload = new System.Windows.Forms.PictureBox();
|
||||
this.imageClose = new System.Windows.Forms.PictureBox();
|
||||
this.timerData = new System.Windows.Forms.Timer(this.components);
|
||||
this.tablePanelCompactBottom = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.tablePanelCompactTop = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.labelTooltip = new TweetDuck.Video.Controls.LabelTooltip();
|
||||
((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).BeginInit();
|
||||
this.tablePanel.SuspendLayout();
|
||||
this.tablePanelFull.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.imageResize)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.imageDownload)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.imageClose)).BeginInit();
|
||||
@@ -64,30 +66,32 @@
|
||||
this.trackBarVolume.MouseDown += new System.Windows.Forms.MouseEventHandler(this.trackBarVolume_MouseDown);
|
||||
this.trackBarVolume.MouseUp += new System.Windows.Forms.MouseEventHandler(this.trackBarVolume_MouseUp);
|
||||
//
|
||||
// tablePanel
|
||||
// tablePanelFull
|
||||
//
|
||||
this.tablePanel.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.tablePanel.ColumnCount = 6;
|
||||
this.tablePanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 28F));
|
||||
this.tablePanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tablePanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 74F));
|
||||
this.tablePanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 130F));
|
||||
this.tablePanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 28F));
|
||||
this.tablePanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 28F));
|
||||
this.tablePanel.Controls.Add(this.trackBarVolume, 3, 0);
|
||||
this.tablePanel.Controls.Add(this.progressSeek, 1, 0);
|
||||
this.tablePanel.Controls.Add(this.labelTime, 2, 0);
|
||||
this.tablePanel.Controls.Add(this.imageResize, 5, 0);
|
||||
this.tablePanel.Controls.Add(this.imageDownload, 4, 0);
|
||||
this.tablePanel.Controls.Add(this.imageClose, 0, 0);
|
||||
this.tablePanel.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.tablePanel.Location = new System.Drawing.Point(0, 86);
|
||||
this.tablePanel.Name = "tablePanel";
|
||||
this.tablePanel.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.tablePanel.RowCount = 1;
|
||||
this.tablePanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tablePanel.Size = new System.Drawing.Size(400, 34);
|
||||
this.tablePanel.TabIndex = 1;
|
||||
this.tablePanelFull.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.tablePanelFull.ColumnCount = 6;
|
||||
this.tablePanelFull.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 28F));
|
||||
this.tablePanelFull.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tablePanelFull.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F));
|
||||
this.tablePanelFull.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 130F));
|
||||
this.tablePanelFull.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 28F));
|
||||
this.tablePanelFull.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 28F));
|
||||
this.tablePanelFull.Controls.Add(this.trackBarVolume, 3, 0);
|
||||
this.tablePanelFull.Controls.Add(this.progressSeek, 1, 0);
|
||||
this.tablePanelFull.Controls.Add(this.labelTime, 2, 0);
|
||||
this.tablePanelFull.Controls.Add(this.imageResize, 5, 0);
|
||||
this.tablePanelFull.Controls.Add(this.imageDownload, 4, 0);
|
||||
this.tablePanelFull.Controls.Add(this.imageClose, 0, 0);
|
||||
this.tablePanelFull.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.tablePanelFull.Enabled = false;
|
||||
this.tablePanelFull.Location = new System.Drawing.Point(0, 86);
|
||||
this.tablePanelFull.Name = "tablePanelFull";
|
||||
this.tablePanelFull.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.tablePanelFull.RowCount = 1;
|
||||
this.tablePanelFull.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tablePanelFull.Size = new System.Drawing.Size(400, 34);
|
||||
this.tablePanelFull.TabIndex = 0;
|
||||
this.tablePanelFull.Visible = false;
|
||||
//
|
||||
// progressSeek
|
||||
//
|
||||
@@ -98,7 +102,7 @@
|
||||
this.progressSeek.Margin = new System.Windows.Forms.Padding(9, 10, 8, 10);
|
||||
this.progressSeek.Maximum = 5000;
|
||||
this.progressSeek.Name = "progressSeek";
|
||||
this.progressSeek.Size = new System.Drawing.Size(91, 14);
|
||||
this.progressSeek.Size = new System.Drawing.Size(85, 14);
|
||||
this.progressSeek.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
|
||||
this.progressSeek.TabIndex = 0;
|
||||
this.progressSeek.MouseDown += new System.Windows.Forms.MouseEventHandler(this.progressSeek_MouseDown);
|
||||
@@ -106,32 +110,14 @@
|
||||
// labelTime
|
||||
//
|
||||
this.labelTime.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.labelTime.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular);
|
||||
this.labelTime.Location = new System.Drawing.Point(138, 3);
|
||||
this.labelTime.Font = new System.Drawing.Font("Segoe UI", 9F);
|
||||
this.labelTime.Location = new System.Drawing.Point(132, 3);
|
||||
this.labelTime.Margin = new System.Windows.Forms.Padding(0, 3, 0, 5);
|
||||
this.labelTime.Name = "labelTime";
|
||||
this.labelTime.Size = new System.Drawing.Size(74, 26);
|
||||
this.labelTime.Size = new System.Drawing.Size(80, 26);
|
||||
this.labelTime.TabIndex = 1;
|
||||
this.labelTime.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// timerData
|
||||
//
|
||||
this.timerData.Interval = 500;
|
||||
this.timerData.Tick += new System.EventHandler(this.timerData_Tick);
|
||||
//
|
||||
// labelTooltip
|
||||
//
|
||||
this.labelTooltip.AutoSize = true;
|
||||
this.labelTooltip.Font = new System.Drawing.Font("Segoe UI Semibold", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.labelTooltip.ForeColor = System.Drawing.Color.White;
|
||||
this.labelTooltip.Location = new System.Drawing.Point(0, 0);
|
||||
this.labelTooltip.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
|
||||
this.labelTooltip.Name = "labelTooltip";
|
||||
this.labelTooltip.Padding = new System.Windows.Forms.Padding(4, 2, 2, 2);
|
||||
this.labelTooltip.Size = new System.Drawing.Size(6, 19);
|
||||
this.labelTooltip.TabIndex = 2;
|
||||
this.labelTooltip.Visible = false;
|
||||
//
|
||||
// imageResize
|
||||
//
|
||||
this.imageResize.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
@@ -178,6 +164,66 @@
|
||||
this.imageClose.WaitOnLoad = true;
|
||||
this.imageClose.Click += new System.EventHandler(this.imageClose_Click);
|
||||
//
|
||||
// timerData
|
||||
//
|
||||
this.timerData.Interval = 500;
|
||||
this.timerData.Tick += new System.EventHandler(this.timerData_Tick);
|
||||
//
|
||||
// tablePanelCompactBottom
|
||||
//
|
||||
this.tablePanelCompactBottom.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.tablePanelCompactBottom.ColumnCount = 5;
|
||||
this.tablePanelCompactBottom.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 28F));
|
||||
this.tablePanelCompactBottom.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tablePanelCompactBottom.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 130F));
|
||||
this.tablePanelCompactBottom.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 28F));
|
||||
this.tablePanelCompactBottom.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 28F));
|
||||
this.tablePanelCompactBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.tablePanelCompactBottom.Enabled = false;
|
||||
this.tablePanelCompactBottom.Location = new System.Drawing.Point(0, 52);
|
||||
this.tablePanelCompactBottom.Margin = new System.Windows.Forms.Padding(3, 0, 3, 3);
|
||||
this.tablePanelCompactBottom.Name = "tablePanelCompactBottom";
|
||||
this.tablePanelCompactBottom.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.tablePanelCompactBottom.RowCount = 1;
|
||||
this.tablePanelCompactBottom.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tablePanelCompactBottom.Size = new System.Drawing.Size(400, 34);
|
||||
this.tablePanelCompactBottom.TabIndex = 1;
|
||||
//
|
||||
// tablePanelCompactTop
|
||||
//
|
||||
this.tablePanelCompactTop.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.tablePanelCompactTop.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.tablePanelCompactTop.ColumnCount = 2;
|
||||
this.tablePanelCompactTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tablePanelCompactTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F));
|
||||
this.tablePanelCompactTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tablePanelCompactTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tablePanelCompactTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tablePanelCompactTop.Enabled = false;
|
||||
this.tablePanelCompactTop.Location = new System.Drawing.Point(0, 60);
|
||||
this.tablePanelCompactTop.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tablePanelCompactTop.Name = "tablePanelCompactTop";
|
||||
this.tablePanelCompactTop.Padding = new System.Windows.Forms.Padding(2, 0, 4, 0);
|
||||
this.tablePanelCompactTop.RowCount = 1;
|
||||
this.tablePanelCompactTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tablePanelCompactTop.Size = new System.Drawing.Size(400, 34);
|
||||
this.tablePanelCompactTop.TabIndex = 2;
|
||||
this.tablePanelCompactTop.Visible = false;
|
||||
//
|
||||
// labelTooltip
|
||||
//
|
||||
this.labelTooltip.AutoSize = true;
|
||||
this.labelTooltip.Font = new System.Drawing.Font("Segoe UI Semibold", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.labelTooltip.ForeColor = System.Drawing.Color.White;
|
||||
this.labelTooltip.Location = new System.Drawing.Point(0, 0);
|
||||
this.labelTooltip.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
|
||||
this.labelTooltip.Name = "labelTooltip";
|
||||
this.labelTooltip.Padding = new System.Windows.Forms.Padding(4, 2, 2, 2);
|
||||
this.labelTooltip.Size = new System.Drawing.Size(6, 19);
|
||||
this.labelTooltip.TabIndex = 3;
|
||||
this.labelTooltip.Visible = false;
|
||||
//
|
||||
// FormPlayer
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
@@ -186,12 +232,13 @@
|
||||
this.ClientSize = new System.Drawing.Size(400, 120);
|
||||
this.ControlBox = false;
|
||||
this.Controls.Add(this.labelTooltip);
|
||||
this.Controls.Add(this.tablePanel);
|
||||
this.Controls.Add(this.tablePanelCompactBottom);
|
||||
this.Controls.Add(this.tablePanelFull);
|
||||
this.Controls.Add(this.tablePanelCompactTop);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
||||
this.Location = new System.Drawing.Point(-32000, -32000);
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.MinimumSize = new System.Drawing.Size(400, 120);
|
||||
this.Name = "FormPlayer";
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
@@ -199,7 +246,7 @@
|
||||
this.Text = "TweetDuck Video";
|
||||
this.Load += new System.EventHandler(this.FormPlayer_Load);
|
||||
((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).EndInit();
|
||||
this.tablePanel.ResumeLayout(false);
|
||||
this.tablePanelFull.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.imageResize)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.imageDownload)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.imageClose)).EndInit();
|
||||
@@ -212,7 +259,7 @@
|
||||
|
||||
private System.Windows.Forms.Timer timerSync;
|
||||
private System.Windows.Forms.TrackBar trackBarVolume;
|
||||
private System.Windows.Forms.TableLayoutPanel tablePanel;
|
||||
private System.Windows.Forms.TableLayoutPanel tablePanelFull;
|
||||
private Controls.SeekBar progressSeek;
|
||||
private System.Windows.Forms.Label labelTime;
|
||||
private System.Windows.Forms.Timer timerData;
|
||||
@@ -220,6 +267,8 @@
|
||||
private System.Windows.Forms.PictureBox imageResize;
|
||||
private System.Windows.Forms.PictureBox imageDownload;
|
||||
private System.Windows.Forms.PictureBox imageClose;
|
||||
private System.Windows.Forms.TableLayoutPanel tablePanelCompactBottom;
|
||||
private System.Windows.Forms.TableLayoutPanel tablePanelCompactTop;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -10,9 +10,17 @@ using WMPLib;
|
||||
|
||||
namespace TweetDuck.Video{
|
||||
sealed partial class FormPlayer : Form{
|
||||
private bool IsCursorOverVideo{
|
||||
get{
|
||||
Point cursor = PointToClient(Cursor.Position);
|
||||
return cursor.Y < (tablePanelFull.Enabled ? tablePanelFull.Location.Y : tablePanelCompactTop.Location.Y);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool ShowWithoutActivation => true;
|
||||
|
||||
private readonly IntPtr ownerHandle;
|
||||
private readonly float ownerDpi;
|
||||
private readonly string videoUrl;
|
||||
private readonly DuplexPipe pipe;
|
||||
|
||||
@@ -23,13 +31,20 @@ namespace TweetDuck.Video{
|
||||
|
||||
private WindowsMediaPlayer Player => player.Ocx;
|
||||
|
||||
public FormPlayer(IntPtr handle, int volume, string url, string token){
|
||||
public FormPlayer(IntPtr handle, int dpi, int volume, string url, string token){
|
||||
InitializeComponent();
|
||||
|
||||
this.ownerHandle = handle;
|
||||
this.ownerDpi = dpi / 100F;
|
||||
this.videoUrl = url;
|
||||
this.pipe = DuplexPipe.CreateClient(token);
|
||||
this.pipe.DataIn += pipe_DataIn;
|
||||
|
||||
if (NativeMethods.GetWindowRect(ownerHandle, out NativeMethods.RECT rect)){
|
||||
ClientSize = new Size(0, 0);
|
||||
Location = new Point((rect.Left+rect.Right)/2, (rect.Top+rect.Bottom)/2);
|
||||
Opacity = 0;
|
||||
}
|
||||
|
||||
player = new ControlWMP{
|
||||
Dock = DockStyle.Fill
|
||||
@@ -51,6 +66,10 @@ namespace TweetDuck.Video{
|
||||
trackBarVolume.Value = volume; // changes player volume too if non-default
|
||||
|
||||
labelTooltip.AttachTooltip(progressSeek, true, args => {
|
||||
if (args.X < 0 || args.Y < 0 || args.X >= progressSeek.Width || args.Y >= progressSeek.Height){
|
||||
return null;
|
||||
}
|
||||
|
||||
IWMPMedia media = Player.currentMedia;
|
||||
int progress = (int)(media.duration*progressSeek.GetProgress(args.X));
|
||||
|
||||
@@ -68,6 +87,59 @@ namespace TweetDuck.Video{
|
||||
Application.AddMessageFilter(new MessageFilter(this));
|
||||
}
|
||||
|
||||
// Layout
|
||||
|
||||
private int DpiScaled(int value){
|
||||
return (int)Math.Round(value*ownerDpi);
|
||||
}
|
||||
|
||||
private void RefreshControlPanel(){
|
||||
bool useCompactLayout = ClientSize.Width < DpiScaled(480);
|
||||
bool needsUpdate = !timerSync.Enabled || (useCompactLayout ? tablePanelFull.Enabled : tablePanelCompactBottom.Enabled);
|
||||
|
||||
if (needsUpdate){
|
||||
void Disable(TableLayoutPanel panel){
|
||||
panel.Controls.Clear();
|
||||
panel.Visible = false;
|
||||
panel.Enabled = false;
|
||||
}
|
||||
|
||||
tablePanelFull.SuspendLayout();
|
||||
tablePanelCompactBottom.SuspendLayout();
|
||||
tablePanelCompactTop.SuspendLayout();
|
||||
|
||||
if (useCompactLayout){
|
||||
Disable(tablePanelFull);
|
||||
|
||||
tablePanelCompactBottom.Enabled = true;
|
||||
tablePanelCompactBottom.Controls.Add(imageClose, 0, 0);
|
||||
tablePanelCompactBottom.Controls.Add(trackBarVolume, 2, 0);
|
||||
tablePanelCompactBottom.Controls.Add(imageDownload, 3, 0);
|
||||
tablePanelCompactBottom.Controls.Add(imageResize, 4, 0);
|
||||
|
||||
tablePanelCompactTop.Enabled = true;
|
||||
tablePanelCompactTop.Controls.Add(progressSeek, 0, 0);
|
||||
tablePanelCompactTop.Controls.Add(labelTime, 1, 0);
|
||||
}
|
||||
else{
|
||||
Disable(tablePanelCompactBottom);
|
||||
Disable(tablePanelCompactTop);
|
||||
|
||||
tablePanelFull.Enabled = true;
|
||||
tablePanelFull.Controls.Add(imageClose, 0, 0);
|
||||
tablePanelFull.Controls.Add(progressSeek, 1, 0);
|
||||
tablePanelFull.Controls.Add(labelTime, 2, 0);
|
||||
tablePanelFull.Controls.Add(trackBarVolume, 3, 0);
|
||||
tablePanelFull.Controls.Add(imageDownload, 4, 0);
|
||||
tablePanelFull.Controls.Add(imageResize, 5, 0);
|
||||
}
|
||||
|
||||
tablePanelFull.ResumeLayout();
|
||||
tablePanelCompactBottom.ResumeLayout();
|
||||
tablePanelCompactTop.ResumeLayout();
|
||||
}
|
||||
}
|
||||
|
||||
// Events
|
||||
|
||||
private void FormPlayer_Load(object sender, EventArgs e){
|
||||
@@ -97,9 +169,14 @@ namespace TweetDuck.Video{
|
||||
else if (state == WMPPlayState.wmppsPlaying){
|
||||
Player.PlayStateChange -= player_PlayStateChange;
|
||||
|
||||
timerSync.Start();
|
||||
NativeMethods.SetWindowOwner(Handle, ownerHandle);
|
||||
Cursor.Current = Cursors.Default;
|
||||
|
||||
SuspendLayout();
|
||||
timerSync_Tick(timerSync, EventArgs.Empty);
|
||||
timerSync.Start();
|
||||
Opacity = 1;
|
||||
ResumeLayout(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,20 +192,38 @@ namespace TweetDuck.Video{
|
||||
[HandleProcessCorruptedStateExceptions]
|
||||
private void timerSync_Tick(object sender, EventArgs e){
|
||||
if (NativeMethods.GetWindowRect(ownerHandle, out NativeMethods.RECT rect)){
|
||||
int width = rect.Right-rect.Left+1;
|
||||
int height = rect.Bottom-rect.Top+1;
|
||||
|
||||
IWMPMedia media = Player.currentMedia;
|
||||
IWMPControls controls = Player.controls;
|
||||
|
||||
int ownerLeft = rect.Left;
|
||||
int ownerTop = rect.Top;
|
||||
int ownerWidth = rect.Right-rect.Left+1;
|
||||
int ownerHeight = rect.Bottom-rect.Top+1;
|
||||
|
||||
// roughly matches MinimumSize for client bounds, adjusted a bit for weirdness with higher DPI
|
||||
int minWidth = DpiScaled(356);
|
||||
int minHeight = DpiScaled(386);
|
||||
|
||||
if (NativeMethods.GetClientRect(ownerHandle, out NativeMethods.RECT clientSize)){
|
||||
minWidth = Math.Min(minWidth, clientSize.Right);
|
||||
minHeight = Math.Min(minHeight, clientSize.Bottom);
|
||||
}
|
||||
|
||||
int maxWidth = Math.Min(DpiScaled(media.imageSourceWidth), ownerWidth*3/4);
|
||||
int maxHeight = Math.Min(DpiScaled(media.imageSourceHeight), ownerHeight*3/4);
|
||||
|
||||
bool isCursorInside = ClientRectangle.Contains(PointToClient(Cursor.Position));
|
||||
|
||||
ClientSize = new Size(Math.Max(MinimumSize.Width, Math.Min(media.imageSourceWidth, width*3/4)), Math.Max(MinimumSize.Height, Math.Min(media.imageSourceHeight, height*3/4)));
|
||||
Location = new Point(rect.Left+(width-ClientSize.Width)/2, rect.Top+(height-ClientSize.Height+SystemInformation.CaptionHeight)/2);
|
||||
|
||||
tablePanel.Visible = isCursorInside || isDragging;
|
||||
|
||||
if (tablePanel.Visible){
|
||||
|
||||
Size newSize = new Size(Math.Max(minWidth+2, maxWidth), Math.Max(minHeight+2, maxHeight));
|
||||
Point newLocation = new Point(ownerLeft+(ownerWidth-newSize.Width)/2, ownerTop+(ownerHeight-newSize.Height+SystemInformation.CaptionHeight)/2);
|
||||
|
||||
if (ClientSize != newSize || Location != newLocation){
|
||||
ClientSize = newSize;
|
||||
Location = newLocation;
|
||||
RefreshControlPanel();
|
||||
}
|
||||
|
||||
if (isCursorInside || isDragging){
|
||||
labelTime.Text = $"{controls.currentPositionString} / {media.durationString}";
|
||||
|
||||
int value = (int)Math.Round(progressSeek.Maximum*controls.currentPosition/media.duration);
|
||||
@@ -142,8 +237,21 @@ namespace TweetDuck.Video{
|
||||
progressSeek.Value = value+1;
|
||||
progressSeek.Value = value;
|
||||
}
|
||||
|
||||
if (tablePanelFull.Enabled){
|
||||
tablePanelFull.Visible = true;
|
||||
}
|
||||
else{
|
||||
tablePanelCompactBottom.Visible = true;
|
||||
tablePanelCompactTop.Visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
else{
|
||||
tablePanelFull.Visible = false;
|
||||
tablePanelCompactBottom.Visible = false;
|
||||
tablePanelCompactTop.Visible = false;
|
||||
}
|
||||
|
||||
if (controls.currentPosition > media.duration){ // pausing near the end of the video causes WMP to play beyond the end of the video wtf
|
||||
try{
|
||||
controls.stop();
|
||||
@@ -157,6 +265,10 @@ namespace TweetDuck.Video{
|
||||
|
||||
if (isCursorInside && !wasCursorInside){
|
||||
wasCursorInside = true;
|
||||
|
||||
if (IsCursorOverVideo){
|
||||
Cursor.Current = Cursors.Default;
|
||||
}
|
||||
}
|
||||
else if (!isCursorInside && wasCursorInside){
|
||||
wasCursorInside = false;
|
||||
@@ -273,26 +385,19 @@ namespace TweetDuck.Video{
|
||||
internal sealed class MessageFilter : IMessageFilter{
|
||||
private readonly FormPlayer form;
|
||||
|
||||
private bool IsCursorOverVideo{
|
||||
get{
|
||||
Point cursor = form.PointToClient(Cursor.Position);
|
||||
return cursor.Y < form.tablePanel.Location.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public MessageFilter(FormPlayer form){
|
||||
this.form = form;
|
||||
}
|
||||
|
||||
bool IMessageFilter.PreFilterMessage(ref Message m){
|
||||
if (m.Msg == 0x0201){ // WM_LBUTTONDOWN
|
||||
if (IsCursorOverVideo){
|
||||
if (form.IsCursorOverVideo){
|
||||
form.TogglePause();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (m.Msg == 0x0203){ // WM_LBUTTONDBLCLK
|
||||
if (IsCursorOverVideo){
|
||||
if (form.IsCursorOverVideo){
|
||||
form.TogglePause();
|
||||
form.Player.fullScreen = !form.Player.fullScreen;
|
||||
return true;
|
||||
|
@@ -9,6 +9,10 @@ namespace TweetDuck.Video{
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
|
||||
|
||||
|
@@ -5,7 +5,7 @@ using System.Windows.Forms;
|
||||
|
||||
namespace TweetDuck.Video{
|
||||
static class Program{
|
||||
internal const string Version = "1.3";
|
||||
internal const string Version = "1.4.2";
|
||||
|
||||
// referenced in VideoPlayer
|
||||
// set by task manager -- public const int CODE_PROCESS_KILLED = 1;
|
||||
@@ -25,21 +25,23 @@ namespace TweetDuck.Video{
|
||||
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
|
||||
|
||||
IntPtr ownerHandle;
|
||||
int ownerDpi;
|
||||
int defaultVolume;
|
||||
string videoUrl;
|
||||
string pipeToken;
|
||||
|
||||
try{
|
||||
ownerHandle = new IntPtr(int.Parse(args[0], NumberStyles.Integer));
|
||||
defaultVolume = int.Parse(args[1], NumberStyles.Integer);
|
||||
videoUrl = new Uri(args[2], UriKind.Absolute).AbsoluteUri;
|
||||
pipeToken = args[3];
|
||||
ownerDpi = int.Parse(args[1], NumberStyles.Integer);
|
||||
defaultVolume = int.Parse(args[2], NumberStyles.Integer);
|
||||
videoUrl = new Uri(args[3], UriKind.Absolute).AbsoluteUri;
|
||||
pipeToken = args[4];
|
||||
}catch{
|
||||
return CODE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
try{
|
||||
Application.Run(new FormPlayer(ownerHandle, defaultVolume, videoUrl, pipeToken));
|
||||
Application.Run(new FormPlayer(ownerHandle, ownerDpi, defaultVolume, videoUrl, pipeToken));
|
||||
}catch(Exception e){
|
||||
Console.Out.WriteLine(e);
|
||||
return CODE_LAUNCH_FAIL;
|
||||
|
Reference in New Issue
Block a user