1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-09-14 19:32:10 +02:00

Compare commits

..

29 Commits

Author SHA1 Message Date
2be46464d6 Release 1.17.2 2018-11-23 06:19:43 +01:00
8d536a6734 Fix video player seek bar resizing when clipped & adjust min window size 2018-11-23 04:13:39 +01:00
250d502238 Add a compact layout for video player controls if the window is small
Closes #245
2018-11-23 03:03:58 +01:00
e8de7266d0 Fix cursor staying on 'resize' when moved over minimum size video player 2018-11-23 01:31:01 +01:00
9414f372d7 Fix video player size with a small window on high DPI 2018-11-23 00:45:02 +01:00
b0f9de67cf Release 1.7.1 2018-11-21 04:41:18 +01:00
9b082e114e Redirect plain twitter.com requests to TD to fix 2FA bug 2018-11-20 20:58:04 +01:00
816a5334ac Make the fix to visible scrollbar when loading TweetDeck more reliable 2018-11-20 20:56:52 +01:00
15a4e10da9 Hide the Manage Options dialog when cancelling profile import from login page 2018-11-20 20:44:44 +01:00
01b9302b0c Fix colors in introduction dialog 2018-11-20 20:13:18 +01:00
442126a11a Rewrite login/logout page CSS handling to fix broken 2FA styles
Closes #218
2018-11-20 20:07:42 +01:00
a9c140c0fc Fix video player seek bar tooltip not disappearing when cursor moves outside 2018-11-20 18:30:06 +01:00
97ad7a3e68 Fix video player bug where playback freezes for ~3s on non-primary screen 2018-11-20 18:04:34 +01:00
7d737eefb6 Fix video player's minimum size 2018-11-20 17:33:09 +01:00
4ac05b38d3 Fix column loading spinner color when using black theme 2018-11-20 15:25:26 +01:00
651bbbb672 Fix crash when showing a browser error message
Closes #244
2018-11-20 14:55:40 +01:00
52da4d8687 Release 1.17 2018-11-16 22:06:47 +01:00
36063ae76a Fix Visual Studio being stupid 2018-11-15 10:16:27 +01:00
2fcec2d2cd Update CefSharp to 67 (release) 2018-11-14 22:53:55 +01:00
762a7fdfb7 Disable compression on vendor.js as the x-ton-expected-size header isn't sometimes sent
Closes #241
2018-11-14 19:22:49 +01:00
cd7aeaeed2 Create and use a custom resource handler factory 2018-11-14 18:47:19 +01:00
6f414d312c Clear cache after each update 2018-11-10 06:20:22 +01:00
1b5304efb7 Release 1.16.3 2018-11-07 11:55:37 +01:00
d59375308f Work around clear-columns plugin reappearing after being disabled
Closes #240
2018-11-07 11:16:44 +01:00
8c9509a906 Fix broken colors of plugin elements with dark theme 2018-11-07 10:27:08 +01:00
fb86d8f3a8 Fix broken black theme colors 2018-11-07 10:18:24 +01:00
50e909cb3d Move debug TweetDeck resource freezing and update it to support CSS 2018-11-07 05:45:20 +01:00
2f54edf7e7 Fix missing <body> margin reset 2018-11-07 00:26:43 +01:00
c251603e1e Fix broken Arial font override 2018-11-07 00:26:22 +01:00
44 changed files with 610 additions and 254 deletions

View File

@@ -494,7 +494,7 @@ namespace TweetDuck.Core{
FormManager.TryFind<FormSettings>()?.Close(); FormManager.TryFind<FormSettings>()?.Close();
using(DialogSettingsManage dialog = new DialogSettingsManage(plugins, true)){ 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(); BrowserProcessHandler.UpdatePrefs();
FormManager.TryFind<FormPlugins>()?.Close(); FormManager.TryFind<FormPlugins>()?.Close();
plugins.Reload(); // also reloads the browser plugins.Reload(); // also reloads the browser

View File

@@ -1,9 +1,18 @@
using System.Collections.Specialized; // Uncomment to force TweetDeck to load a predefined version of the vendor/bundle scripts and stylesheets
// #define FREEZE_TWEETDECK_RESOURCES
using System.Collections.Specialized;
using CefSharp; using CefSharp;
using CefSharp.Handler; using CefSharp.Handler;
using TweetDuck.Core.Handling.General; using TweetDuck.Core.Handling.General;
using TweetDuck.Core.Utils; using TweetDuck.Core.Utils;
#if FREEZE_TWEETDECK_RESOURCES
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions;
#endif
namespace TweetDuck.Core.Handling{ namespace TweetDuck.Core.Handling{
class RequestHandlerBase : DefaultRequestHandler{ class RequestHandlerBase : DefaultRequestHandler{
private readonly bool autoReload; private readonly bool autoReload;
@@ -31,5 +40,36 @@ namespace TweetDuck.Core.Handling{
browser.Reload(); 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){
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}");
}
else{
Debug.WriteLine($"Rewriting {url} hash to {hash}");
request.Url = TweetDeckResourceUrl.Replace(url, $"/dist/$1.{hash}.$3");
return true;
}
}
}
return base.OnResourceResponse(browserControl, browser, frame, request, response);
}
#endif
} }
} }

View File

@@ -1,26 +1,35 @@
// Uncomment to force TweetDeck to load a predefined version of the vendor/bundle scripts using System.Collections.Specialized;
// #define FREEZE_TWEETDECK_SCRIPTS
using System.Collections.Specialized;
using CefSharp; using CefSharp;
using TweetDuck.Core.Handling.Filters; using TweetDuck.Core.Handling.Filters;
using TweetDuck.Core.Utils; using TweetDuck.Core.Utils;
#if FREEZE_TWEETDECK_SCRIPTS
using System.Collections.Generic;
using System.Text.RegularExpressions;
#endif
namespace TweetDuck.Core.Handling{ namespace TweetDuck.Core.Handling{
sealed class RequestHandlerBrowser : RequestHandlerBase{ sealed class RequestHandlerBrowser : RequestHandlerBase{
private const string UrlVendorResource = "/dist/vendor";
private const string UrlLoadingSpinner = "/backgrounds/spinner_blue";
public string BlockNextUserNavUrl { get; set; } public string BlockNextUserNavUrl { get; set; }
public RequestHandlerBrowser() : base(true){} public RequestHandlerBrowser() : base(true){}
public override CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback){ public override CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback){
if (request.ResourceType == ResourceType.Script && request.Url.Contains("analytics.")){ if (request.ResourceType == ResourceType.MainFrame){
callback.Dispose(); if (request.Url.EndsWith("//twitter.com/")){
return CefReturnValue.Cancel; 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.")){
callback.Dispose();
return CefReturnValue.Cancel;
}
else if (url.Contains(UrlVendorResource)){
NameValueCollection headers = request.Headers;
headers["Accept-Encoding"] = "identity";
request.Headers = headers;
}
} }
return base.OnBeforeResourceLoad(browserControl, browser, frame, request, callback); return base.OnBeforeResourceLoad(browserControl, browser, frame, request, callback);
@@ -36,58 +45,18 @@ namespace TweetDuck.Core.Handling{
return base.OnBeforeBrowse(browserControl, browser, frame, request, userGesture, isRedirect); return base.OnBeforeBrowse(browserControl, browser, frame, request, userGesture, isRedirect);
} }
#if FREEZE_TWEETDECK_SCRIPTS
private static readonly Regex TweetDeckScriptUrl = new Regex(@"/dist/(.*?)\.(.*?)\.js$", RegexOptions.Compiled);
private static readonly SortedList<string, string> TweetDeckHashes = new SortedList<string, string>(2){
{ "vendor", "942c0a20e8" },
{ "bundle", "1bd75b5854" }
};
#endif
public override bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response){ public override bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response){
if (request.ResourceType == ResourceType.Image && request.Url.Contains("/backgrounds/spinner_blue")){ if (request.ResourceType == ResourceType.Image && request.Url.Contains(UrlLoadingSpinner)){
request.Url = TwitterUtils.LoadingSpinner.Url; request.Url = TwitterUtils.LoadingSpinner.Url;
return true; return true;
} }
#if FREEZE_TWEETDECK_SCRIPTS
else if (request.ResourceType == ResourceType.Script){
Match match = TweetDeckScriptUrl.Match(request.Url);
if (match.Success && TweetDeckHashes.TryGetValue(match.Groups[1].Value, out string hash)){
if (match.Groups[2].Value == hash){
System.Diagnostics.Debug.WriteLine($"accepting {request.Url}");
}
else{
System.Diagnostics.Debug.WriteLine($"rewriting {request.Url} to {hash}");
request.Url = TweetDeckScriptUrl.Replace(request.Url, "/dist/$1."+hash+".js");
return true;
}
}
}
#endif
return base.OnResourceResponse(browserControl, browser, frame, request, response); return base.OnResourceResponse(browserControl, browser, frame, request, response);
} }
public override IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response){ public override IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response){
if (request.ResourceType == ResourceType.Script && request.Url.Contains("/dist/vendor")){ if (request.ResourceType == ResourceType.Script && request.Url.Contains(UrlVendorResource) && int.TryParse(response.ResponseHeaders["Content-Length"], out int totalBytes)){
NameValueCollection headers = response.ResponseHeaders; return new ResponseFilterVendor(totalBytes);
if (int.TryParse(headers["x-ton-expected-size"], out int totalBytes)){
return new ResponseFilterVendor(totalBytes);
}
#if DEBUG
else{
System.Diagnostics.Debug.WriteLine($"Missing uncompressed size header in {request.Url}");
foreach(string key in headers){
System.Diagnostics.Debug.WriteLine($" {key}: {headers[key]}");
}
System.Diagnostics.Debugger.Break();
}
#endif
} }
return base.GetResourceResponseFilter(browserControl, browser, frame, request, response); return base.GetResourceResponseFilter(browserControl, browser, frame, request, response);

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Concurrent;
using CefSharp;
using TweetDuck.Data;
namespace TweetDuck.Core.Handling{
sealed class ResourceHandlerFactory : IResourceHandlerFactory{
public bool HasHandlers => !handlers.IsEmpty;
private readonly ConcurrentDictionary<string, IResourceHandler> handlers = new ConcurrentDictionary<string, IResourceHandler>(StringComparer.OrdinalIgnoreCase);
public IResourceHandler GetResourceHandler(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request){
try{
return handlers.TryGetValue(request.Url, out IResourceHandler handler) ? handler : null;
}finally{
request.Dispose();
}
}
// registration
public bool RegisterHandler(string url, IResourceHandler handler){
if (Uri.TryCreate(url, UriKind.Absolute, out Uri uri)){
handlers.AddOrUpdate(uri.AbsoluteUri, handler, (key, prev) => handler);
return true;
}
return false;
}
public bool RegisterHandler(ResourceLink link){
return RegisterHandler(link.Url, link.Handler);
}
public bool UnregisterHandler(string url){
return handlers.TryRemove(url, out IResourceHandler _);
}
public bool UnregisterHandler(ResourceLink link){
return UnregisterHandler(link.Url);
}
}
}

View File

@@ -54,6 +54,14 @@ namespace TweetDuck.Core.Management{
RefreshTimer(); RefreshTimer();
} }
public static void TryClearNow(){
try{
Directory.Delete(CacheFolder, true);
}catch{
// welp, too bad
}
}
public static void Exit(){ public static void Exit(){
if (AutoClearTimer != null){ if (AutoClearTimer != null){
AutoClearTimer.Dispose(); AutoClearTimer.Dispose();
@@ -61,11 +69,7 @@ namespace TweetDuck.Core.Management{
} }
if (ClearOnExit){ if (ClearOnExit){
try{ TryClearNow();
Directory.Delete(CacheFolder, true);
}catch{
// welp, too bad
}
} }
} }
} }

View File

@@ -40,7 +40,7 @@ namespace TweetDuck.Core.Management{
if ((process = Process.Start(new ProcessStartInfo{ if ((process = Process.Start(new ProcessStartInfo{
FileName = Path.Combine(Program.ProgramPath, "TweetDuck.Video.exe"), 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, UseShellExecute = false,
RedirectStandardOutput = true RedirectStandardOutput = true
})) != null){ })) != null){

View File

@@ -121,18 +121,20 @@ namespace TweetDuck.Core.Notification{
this.owner = owner; this.owner = owner;
this.owner.FormClosed += owner_FormClosed; this.owner.FormClosed += owner_FormClosed;
ResourceHandlerFactory resourceHandlerFactory = new ResourceHandlerFactory();
resourceHandlerFactory.RegisterHandler(TwitterUtils.TweetDeckURL, this.resourceHandler);
resourceHandlerFactory.RegisterHandler(TweetNotification.AppLogo);
this.browser = new ChromiumWebBrowser("about:blank"){ this.browser = new ChromiumWebBrowser("about:blank"){
MenuHandler = new ContextMenuNotification(this, enableContextMenu), MenuHandler = new ContextMenuNotification(this, enableContextMenu),
JsDialogHandler = new JavaScriptDialogHandler(), JsDialogHandler = new JavaScriptDialogHandler(),
LifeSpanHandler = new LifeSpanHandler(), LifeSpanHandler = new LifeSpanHandler(),
RequestHandler = new RequestHandlerBase(false) RequestHandler = new RequestHandlerBase(false),
ResourceHandlerFactory = resourceHandlerFactory
}; };
this.browser.Dock = DockStyle.None; this.browser.Dock = DockStyle.None;
this.browser.ClientSize = ClientSize; this.browser.ClientSize = ClientSize;
this.browser.SetupResourceHandler(TwitterUtils.TweetDeckURL, this.resourceHandler);
this.browser.SetupResourceHandler(TweetNotification.AppLogo);
this.browser.SetupZoomEvents(); this.browser.SetupZoomEvents();
Controls.Add(browser); Controls.Add(browser);

View File

@@ -59,7 +59,7 @@ namespace TweetDuck.Core.Notification{
build.Append("<style type='text/css'>").Append(customCSS).Append("</style>"); build.Append("<style type='text/css'>").Append(customCSS).Append("</style>");
} }
build.Append("</head><body class='scroll-styled-v system-font-stack"); build.Append("</head><body class='scroll-styled-v");
if (!string.IsNullOrEmpty(bodyClasses)){ if (!string.IsNullOrEmpty(bodyClasses)){
build.Append(' ').Append(bodyClasses); build.Append(' ').Append(bodyClasses);

View File

@@ -63,12 +63,16 @@ namespace TweetDuck.Core.Other{
Text = Program.BrandName+" Guide"; Text = Program.BrandName+" Guide";
Size = new Size(owner.Size.Width*3/4, owner.Size.Height*3/4); Size = new Size(owner.Size.Width*3/4, owner.Size.Height*3/4);
VisibleChanged += (sender, args) => this.MoveToCenter(owner); VisibleChanged += (sender, args) => this.MoveToCenter(owner);
ResourceHandlerFactory resourceHandlerFactory = new ResourceHandlerFactory();
resourceHandlerFactory.RegisterHandler(DummyPage);
this.browser = new ChromiumWebBrowser(url){ this.browser = new ChromiumWebBrowser(url){
MenuHandler = new ContextMenuGuide(owner), MenuHandler = new ContextMenuGuide(owner),
JsDialogHandler = new JavaScriptDialogHandler(), JsDialogHandler = new JavaScriptDialogHandler(),
LifeSpanHandler = new LifeSpanHandler(), LifeSpanHandler = new LifeSpanHandler(),
RequestHandler = new RequestHandlerBase(true) RequestHandler = new RequestHandlerBase(true),
ResourceHandlerFactory = resourceHandlerFactory
}; };
browser.LoadingStateChanged += browser_LoadingStateChanged; browser.LoadingStateChanged += browser_LoadingStateChanged;
@@ -77,8 +81,6 @@ namespace TweetDuck.Core.Other{
browser.BrowserSettings.BackgroundColor = (uint)BackColor.ToArgb(); browser.BrowserSettings.BackgroundColor = (uint)BackColor.ToArgb();
browser.Dock = DockStyle.None; browser.Dock = DockStyle.None;
browser.Location = ControlExtensions.InvisibleLocation; browser.Location = ControlExtensions.InvisibleLocation;
browser.SetupResourceHandler(DummyPage);
browser.SetupZoomEvents(); browser.SetupZoomEvents();
Controls.Add(browser); Controls.Add(browser);

View File

@@ -33,6 +33,7 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
private readonly PluginManager plugins; private readonly PluginManager plugins;
private readonly Dictionary<CheckBox, ProfileManager.Items> checkBoxMap = new Dictionary<CheckBox, ProfileManager.Items>(4); private readonly Dictionary<CheckBox, ProfileManager.Items> checkBoxMap = new Dictionary<CheckBox, ProfileManager.Items>(4);
private readonly bool openImportImmediately;
private State currentState; private State currentState;
private ProfileManager importManager; private ProfileManager importManager;
@@ -51,6 +52,8 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
this.checkBoxMap[cbSession] = ProfileManager.Items.Session; this.checkBoxMap[cbSession] = ProfileManager.Items.Session;
this.checkBoxMap[cbPluginData] = ProfileManager.Items.PluginData; this.checkBoxMap[cbPluginData] = ProfileManager.Items.PluginData;
this.openImportImmediately = openImportImmediately;
if (openImportImmediately){ if (openImportImmediately){
radioImport.Checked = true; radioImport.Checked = true;
btnContinue_Click(null, EventArgs.Empty); btnContinue_Click(null, EventArgs.Empty);
@@ -88,6 +91,10 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
Filter = "TweetDuck Profile (*.tdsettings)|*.tdsettings" Filter = "TweetDuck Profile (*.tdsettings)|*.tdsettings"
}){ }){
if (dialog.ShowDialog() != DialogResult.OK){ if (dialog.ShowDialog() != DialogResult.OK){
if (openImportImmediately){
Close();
}
return; return;
} }

View File

@@ -19,6 +19,9 @@ namespace TweetDuck.Core{
sealed class TweetDeckBrowser : IDisposable{ sealed class TweetDeckBrowser : IDisposable{
private static UserConfig Config => Program.Config.User; 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 Ready { get; private set; }
public bool Enabled{ public bool Enabled{
@@ -39,10 +42,14 @@ namespace TweetDuck.Core{
} }
private readonly ChromiumWebBrowser browser; private readonly ChromiumWebBrowser browser;
private readonly ResourceHandlerFactory resourceHandlerFactory = new ResourceHandlerFactory();
private string prevSoundNotificationPath = null; private string prevSoundNotificationPath = null;
public TweetDeckBrowser(FormBrowser owner, PluginManager plugins, TweetDeckBridge tdBridge, UpdateBridge updateBridge){ public TweetDeckBrowser(FormBrowser owner, PluginManager plugins, TweetDeckBridge tdBridge, UpdateBridge updateBridge){
resourceHandlerFactory.RegisterHandler(TweetNotification.AppLogo);
resourceHandlerFactory.RegisterHandler(TwitterUtils.LoadingSpinner);
RequestHandlerBrowser requestHandler = new RequestHandlerBrowser(); RequestHandlerBrowser requestHandler = new RequestHandlerBrowser();
this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){ this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){
@@ -52,7 +59,8 @@ namespace TweetDuck.Core{
JsDialogHandler = new JavaScriptDialogHandler(), JsDialogHandler = new JavaScriptDialogHandler(),
KeyboardHandler = new KeyboardHandlerBrowser(owner), KeyboardHandler = new KeyboardHandlerBrowser(owner),
LifeSpanHandler = new LifeSpanHandler(), LifeSpanHandler = new LifeSpanHandler(),
RequestHandler = requestHandler RequestHandler = requestHandler,
ResourceHandlerFactory = resourceHandlerFactory
}; };
this.browser.LoadingStateChanged += browser_LoadingStateChanged; this.browser.LoadingStateChanged += browser_LoadingStateChanged;
@@ -66,11 +74,8 @@ namespace TweetDuck.Core{
this.browser.BrowserSettings.BackgroundColor = (uint)TwitterUtils.BackgroundColor.ToArgb(); this.browser.BrowserSettings.BackgroundColor = (uint)TwitterUtils.BackgroundColor.ToArgb();
this.browser.Dock = DockStyle.None; this.browser.Dock = DockStyle.None;
this.browser.Location = ControlExtensions.InvisibleLocation; this.browser.Location = ControlExtensions.InvisibleLocation;
this.browser.SetupResourceHandler(TweetNotification.AppLogo);
this.browser.SetupResourceHandler(TwitterUtils.LoadingSpinner);
this.browser.SetupZoomEvents(); this.browser.SetupZoomEvents();
owner.Controls.Add(browser); owner.Controls.Add(browser);
plugins.Register(browser, PluginEnvironment.Browser, owner, true); plugins.Register(browser, PluginEnvironment.Browser, owner, true);
@@ -117,10 +122,15 @@ namespace TweetDuck.Core{
if (frame.IsMain){ if (frame.IsMain){
if (TwitterUtils.IsTwitterWebsite(frame)){ 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); ScriptLoader.ExecuteFile(frame, "twitter.js", browser);
} }
frame.ExecuteJavaScriptAsync(TwitterUtils.BackgroundColorOverride); if (!TwitterUtils.IsTwitterLogin2FactorWebsite(frame)){
frame.ExecuteJavaScriptAsync(TwitterUtils.BackgroundColorOverride);
}
} }
} }
@@ -149,6 +159,10 @@ namespace TweetDuck.Core{
ScriptLoader.ExecuteFile(frame, "update.js", browser); ScriptLoader.ExecuteFile(frame, "update.js", browser);
} }
if (frame.Url == ErrorUrl){
resourceHandlerFactory.UnregisterHandler(ErrorUrl);
}
} }
private void browser_LoadError(object sender, LoadErrorEventArgs e){ private void browser_LoadError(object sender, LoadErrorEventArgs e){
@@ -160,7 +174,8 @@ namespace TweetDuck.Core{
string errorPage = ScriptLoader.LoadResourceSilent("pages/error.html"); string errorPage = ScriptLoader.LoadResourceSilent("pages/error.html");
if (errorPage != null){ 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);
} }
} }
} }
@@ -174,10 +189,16 @@ namespace TweetDuck.Core{
bool hasCustomSound = Config.IsCustomSoundNotificationSet; bool hasCustomSound = Config.IsCustomSoundNotificationSet;
string newNotificationPath = Config.NotificationSoundPath; string newNotificationPath = Config.NotificationSoundPath;
if (prevSoundNotificationPath != newNotificationPath){ if (prevSoundNotificationPath != newNotificationPath){
browser.SetupResourceHandler(soundUrl, hasCustomSound ? SoundNotification.CreateFileHandler(newNotificationPath) : null);
prevSoundNotificationPath = newNotificationPath; prevSoundNotificationPath = newNotificationPath;
if (hasCustomSound){
resourceHandlerFactory.RegisterHandler(soundUrl, SoundNotification.CreateFileHandler(newNotificationPath));
}
else{
resourceHandlerFactory.UnregisterHandler(soundUrl);
}
} }
browser.ExecuteScriptAsync("TDGF_setSoundNotificationData", hasCustomSound, Config.NotificationSoundVolume); browser.ExecuteScriptAsync("TDGF_setSoundNotificationData", hasCustomSound, Config.NotificationSoundVolume);

View File

@@ -8,7 +8,6 @@ using System.Windows.Forms;
using CefSharp.WinForms; using CefSharp.WinForms;
using TweetDuck.Configuration; using TweetDuck.Configuration;
using TweetDuck.Core.Other; using TweetDuck.Core.Other;
using TweetDuck.Data;
namespace TweetDuck.Core.Utils{ namespace TweetDuck.Core.Utils{
static class BrowserUtils{ static class BrowserUtils{
@@ -60,21 +59,6 @@ namespace TweetDuck.Core.Utils{
return (ChromiumWebBrowser)browserControl; return (ChromiumWebBrowser)browserControl;
} }
public static void SetupResourceHandler(this ChromiumWebBrowser browser, string url, IResourceHandler handler){
DefaultResourceHandlerFactory factory = (DefaultResourceHandlerFactory)browser.ResourceHandlerFactory;
if (handler == null){
factory.UnregisterHandler(url);
}
else{
factory.RegisterHandler(url, handler);
}
}
public static void SetupResourceHandler(this ChromiumWebBrowser browser, ResourceLink resource){
browser.SetupResourceHandler(resource.Url, resource.Handler);
}
public static void SetupZoomEvents(this ChromiumWebBrowser browser){ public static void SetupZoomEvents(this ChromiumWebBrowser browser){
void UpdateZoomLevel(object sender, EventArgs args){ void UpdateZoomLevel(object sender, EventArgs args){
SetZoomLevel(browser.GetBrowser(), Config.ZoomLevel); SetZoomLevel(browser.GetBrowser(), Config.ZoomLevel);

View File

@@ -16,7 +16,7 @@ namespace TweetDuck.Core.Utils{
public const string TweetDeckURL = "https://tweetdeck.twitter.com"; public const string TweetDeckURL = "https://tweetdeck.twitter.com";
public static readonly Color BackgroundColor = Color.FromArgb(28, 99, 153); 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")); 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/"); 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){ private static string ExtractMediaBaseLink(string url){
int slash = url.LastIndexOf('/'); int slash = url.LastIndexOf('/');
return slash == -1 ? url : StringUtils.ExtractBefore(url, ':', slash); return slash == -1 ? url : StringUtils.ExtractBefore(url, ':', slash);

View File

@@ -20,7 +20,7 @@ namespace TweetDuck{
public const string BrandName = "TweetDuck"; public const string BrandName = "TweetDuck";
public const string Website = "https://tweetduck.chylex.com"; public const string Website = "https://tweetduck.chylex.com";
public const string VersionTag = "1.16.2"; public const string VersionTag = "1.17.2";
public static readonly string ProgramPath = AppDomain.CurrentDomain.BaseDirectory; public static readonly string ProgramPath = AppDomain.CurrentDomain.BaseDirectory;
public static readonly bool IsPortable = File.Exists(Path.Combine(ProgramPath, "makeportable")); public static readonly bool IsPortable = File.Exists(Path.Combine(ProgramPath, "makeportable"));
@@ -126,6 +126,7 @@ namespace TweetDuck{
if (Arguments.HasFlag(Arguments.ArgUpdated)){ if (Arguments.HasFlag(Arguments.ArgUpdated)){
WindowsUtils.TryDeleteFolderWhenAble(InstallerPath, 8000); WindowsUtils.TryDeleteFolderWhenAble(InstallerPath, 8000);
BrowserCache.TryClearNow();
} }
BrowserCache.RefreshTimer(); BrowserCache.RefreshTimer();

View File

@@ -45,7 +45,7 @@ If you decide to publicly release a custom version, please make it clear that it
- `Resources/Plugins/emoji-keyboard/emoji-ordering.txt` line endings must be LF (line feed); any CR (carriage return) in the file will cause a failed build, and you will need to ensure correct line endings in your text editor - `Resources/Plugins/emoji-keyboard/emoji-ordering.txt` line endings must be LF (line feed); any CR (carriage return) in the file will cause a failed build, and you will need to ensure correct line endings in your text editor
#### Error: The "EmbedAllSources" parameter is not supported by the "Csc" task #### Error: The "EmbedAllSources" parameter is not supported by the "Csc" task
1. Open `C:\Program Files (x86)\Visual Studio\2017\<edition>\MSBuild\15.0\Bin\Microsoft.CSharp.CurrentVersion.targets` in a text editor 1. Open `C:\Program Files (x86)\Visual Studio\2017\<edition>\MSBuild\15.0\Bin\Roslyn\Microsoft.CSharp.Core.targets` in a text editor
2. Remove line that says `EmbedAllSources="$(EmbedAllSources)"` 2. Remove line that says `EmbedAllSources="$(EmbedAllSources)"`
3. Hope the next Visual Studio update fixes it... 3. Hope the next Visual Studio update fixes it...

View File

@@ -94,7 +94,7 @@ enabled(){
this.btnClearOneHTML = ` this.btnClearOneHTML = `
<a class="js-action-header-button column-header-link" href="#" data-action="td-clearcolumns-dosingle"> <a class="js-action-header-button column-header-link" href="#" data-action="td-clearcolumns-dosingle">
<i class="icon icon-clear-timeline js-show-tip" data-placement="bottom" data-original-title="Clear column (hold Shift to restore)" data-action="td-clearcolumns-dosingle"></i> <i class="icon icon-clear-timeline js-show-tip" data-placement="bottom" data-original-title="Clear column (hold Shift to restore)" data-action="td-clearcolumns-dosingle"></i>
</a>`; </a>`;
this.prevNavMenuMustache = TD.mustaches["menus/column_nav_menu.mustache"]; this.prevNavMenuMustache = TD.mustaches["menus/column_nav_menu.mustache"];
@@ -110,6 +110,14 @@ enabled(){
// styles // styles
if (!document.getElementById("td-clearcolumns-workaround")){
// TD started caching mustaches so disabling the plugin doesn't update the column headers properly...
let workaround = document.createElement("style");
workaround.id = "td-clearcolumns-workaround";
workaround.innerText = "#tduck a[data-action='td-clearcolumns-dosingle'] { display: none }";
document.head.appendChild(workaround);
}
this.css = window.TDPF_createCustomStyle(this); this.css = window.TDPF_createCustomStyle(this);
this.css.insert(".js-app-add-column.is-hidden + .clear-columns-btn-all-parent { display: none; }"); this.css.insert(".js-app-add-column.is-hidden + .clear-columns-btn-all-parent { display: none; }");
@@ -120,8 +128,9 @@ enabled(){
this.css.insert(".column[data-td-icon='icon-message'] .column-header-links { min-width: 110px !important; }"); this.css.insert(".column[data-td-icon='icon-message'] .column-header-links { min-width: 110px !important; }");
this.css.insert(".btn-options-tray[data-action='clear'] { display: none !important; }"); this.css.insert(".btn-options-tray[data-action='clear'] { display: none !important; }");
this.css.insert(".column[data-td-icon='icon-schedule'] a[data-action='td-clearcolumns-dosingle'] { display: none; }"); this.css.insert("#tduck a[data-action='td-clearcolumns-dosingle'] { display: inline-block; }");
this.css.insert(".column[data-td-icon='icon-custom-timeline'] a[data-action='td-clearcolumns-dosingle'] { display: none; }"); this.css.insert("#tduck .column[data-td-icon='icon-schedule'] a[data-action='td-clearcolumns-dosingle'] { display: none; }");
this.css.insert("#tduck .column[data-td-icon='icon-custom-timeline'] a[data-action='td-clearcolumns-dosingle'] { display: none; }");
} }
ready(){ ready(){

View File

@@ -432,7 +432,8 @@ enabled(){
} }
if (this.config.forceArialFont){ if (this.config.forceArialFont){
this.css.insert("#tduck .system-font-stack { font-family: Arial, sans-serif; font-weight: 400 }"); this.css.insert("#tduck { font-family: Arial, sans-serif; font-weight: 400 }");
this.css.insert("#tduck input, #tduck label, #tduck select, #tduck textarea { font-family: Arial }")
} }
if (this.config.increaseQuoteTextSize){ if (this.config.increaseQuoteTextSize){
@@ -603,7 +604,7 @@ html[data-td-font] { font-size: ${this.config.fontSize} !important }
.avatar { border-radius: ${this.config.avatarRadius}% !important } .avatar { border-radius: ${this.config.avatarRadius}% !important }
${this.config.forceArialFont ? ` ${this.config.forceArialFont ? `
#tduck .system-font-stack { font-family: Arial, sans-serif; font-weight: 400 } #tduck { font-family: Arial, sans-serif; font-weight: 400 }
` : ``} ` : ``}
${this.config.increaseQuoteTextSize ? ` ${this.config.increaseQuoteTextSize ? `

View File

@@ -173,12 +173,23 @@
#edit-design-panel { #edit-design-panel {
width: 693px; width: 693px;
height: 380px; height: 380px;
background-color: #FFF;
box-shadow: 0 0 10px rgba(17, 17, 17, 0.5);
}
#edit-design-panel .mdl-header {
color: #8899A6;
} }
#edit-design-panel .mdl-inner { #edit-design-panel .mdl-inner {
padding-top: 0; padding-top: 0;
} }
#edit-design-panel .mdl-content {
border: 1px solid #CCD6DD;
background: #EAEAEA;
}
#edit-design-panel-inner-cols { #edit-design-panel-inner-cols {
padding: 0 6px; padding: 0 6px;
} }

View File

@@ -117,7 +117,7 @@ html.dark .account-settings-bt{border-top:1px solid #e1e8ed}
html.dark .account-settings-bb{border-bottom:1px solid #e1e8ed} html.dark .account-settings-bb{border-bottom:1px solid #e1e8ed}
html.dark .account-stats a{color:#66757f} html.dark .account-stats a{color:#66757f}
html.dark .account-stats a:hover{color:#2b7bb9} html.dark .account-stats a:hover{color:#2b7bb9}
html.dark .column{background-color:#222426} html.dark .column-panel{background-color:#222426}
html.dark .column.is-focused{box-shadow:0 0 0 6px #7aa2c0} html.dark .column.is-focused{box-shadow:0 0 0 6px #7aa2c0}
html.dark .column-background-fill{background-color:#F5F8FA} html.dark .column-background-fill{background-color:#F5F8FA}
html.dark .more-tweets-glow{background-color:#55acee;background:radial-gradient(ellipse farthest-corner at 50% 100%,#55acee 0%,#55acee 25%,rgba(255,255,255,0) 75%)} html.dark .more-tweets-glow{background-color:#55acee;background:radial-gradient(ellipse farthest-corner at 50% 100%,#55acee 0%,#55acee 25%,rgba(255,255,255,0) 75%)}
@@ -135,7 +135,6 @@ html.dark .column-header{background-color:#292F33}
html.dark .is-inverted-dark .column-header{border-bottom:1px solid #ddd} html.dark .is-inverted-dark .column-header{border-bottom:1px solid #ddd}
html.dark .is-inverted-dark .column-title-edit-box{color:#111;background-color:#fff;border-color:#e1e8ed} html.dark .is-inverted-dark .column-title-edit-box{color:#111;background-color:#fff;border-color:#e1e8ed}
html.dark .column-header{border-bottom:1px solid #222426} html.dark .column-header{border-bottom:1px solid #222426}
html.dark .column-header-temp{border-bottom:1px solid #ddd}
html.dark .column-title-edit-box{color:#e1e8ed;background-color:#14171A;border-color:#111} html.dark .column-title-edit-box{color:#e1e8ed;background-color:#14171A;border-color:#111}
html.dark .column-number{color:#66757f} html.dark .column-number{color:#66757f}
html.dark .is-new .column-type-icon{color:#55acee} html.dark .is-new .column-type-icon{color:#55acee}
@@ -428,8 +427,7 @@ html.dark .list-account .username{color:#8899a6}
html.dark .list-listmember .username{color:#8899a6} html.dark .list-listmember .username{color:#8899a6}
html.dark .list-listmember .bio{color:#657786} html.dark .list-listmember .bio{color:#657786}
html.dark .divider-bar{background-color:#ddd} html.dark .divider-bar{background-color:#ddd}
html.dark select{background-color:#fff} html.dark input,html.dark textarea,html.dark select{color:#111;border:1px solid #e1e8ed;background-color:#fff}
html.dark input,html.dark textarea,html.dark select{color:#111;border:1px solid #e1e8ed}
html.dark input:disabled{background-color:#eaeaea;border-color:#e1e8ed} html.dark input:disabled{background-color:#eaeaea;border-color:#e1e8ed}
html.dark select:disabled{background-color:#f5f8fa} html.dark select:disabled{background-color:#f5f8fa}
html.dark input:focus,html.dark select:focus,html.dark textarea:focus,html.dark .focus{border-color:rgba(80,165,230,0.8);box-shadow:inset 0 1px 3px rgba(17,17,17,0.1),0 0 8px rgba(80,165,230,0.6)} html.dark input:focus,html.dark select:focus,html.dark textarea:focus,html.dark .focus{border-color:rgba(80,165,230,0.8);box-shadow:inset 0 1px 3px rgba(17,17,17,0.1),0 0 8px rgba(80,165,230,0.6)}
@@ -802,7 +800,10 @@ html.dark .NotificationList .Notification-body{color:#14171A}
html.dark .DrawerModal{color:#14171A} html.dark .DrawerModal{color:#14171A}
/* fixes */ /* fixes */
html.dark .app-search-fake{border-color:transparent} 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 .tweet>.color-twitter-blue{color:#8bd!important}
html.dark .hw-card-container>div{border-color:#292F33;background:transparent} html.dark .hw-card-container>div{border-color:#292F33;background:transparent}
html.dark .hw-card-container>div>div{border-color:#292F33} html.dark .hw-card-container>div>div{border-color:#292F33}
html.dark .modal-content,html.dark .lst-group{color:#292F33}
html.dark .lst-launcher a span{color:#657786!important}
html.dark .social-proof-names a{color:#3b94d9}

View File

@@ -171,14 +171,14 @@
} }
.template-editor-form input, .template-editor-form textarea { .template-editor-form input, .template-editor-form textarea {
color: #111; color: #111 !important;
background-color: #fff; background-color: #fff !important;
border: none; border: none;
border-radius: 0; border-radius: 0;
} }
.template-editor-form input:focus, .template-editor-form textarea:focus { .template-editor-form input:focus, .template-editor-form textarea:focus {
box-shadow: inset 0 1px 3px rgba(17, 17, 17, 0.1), 0 0 8px rgba(80, 165, 230, 0.6); box-shadow: inset 0 1px 3px rgba(17, 17, 17, 0.1), 0 0 8px rgba(80, 165, 230, 0.6) !important;
} }
.template-editor-form textarea { .template-editor-form textarea {

View File

@@ -414,7 +414,7 @@
let fontSizeName = TD.settings.getFontSize(); let fontSizeName = TD.settings.getFontSize();
let themeName = TD.settings.getTheme(); let themeName = TD.settings.getTheme();
let columnBackground = getClassStyleProperty("column", "background-color"); let columnBackground = getClassStyleProperty("column-panel", "background-color");
let tags = [ let tags = [
"<html "+Array.prototype.map.call(document.documentElement.attributes, ele => `${ele.name}="${ele.value}"`).join(" ")+"><head>" "<html "+Array.prototype.map.call(document.documentElement.attributes, ele => `${ele.name}="${ele.value}"`).join(" ")+"><head>"

View File

@@ -7,19 +7,30 @@
min-width: 515px; min-width: 515px;
max-width: 835px; max-width: 835px;
height: 328px; height: 328px;
background-color: #fff;
} }
#td-introduction-modal .mdl-inner { #td-introduction-modal .mdl-header {
padding-top: 0; color: #8899a6;
} }
#td-introduction-modal .mdl-header-title { #td-introduction-modal .mdl-header-title {
cursor: default; cursor: default;
} }
#td-introduction-modal .mdl-dismiss {
color: #292f33;
}
#td-introduction-modal .mdl-inner {
padding-top: 0;
}
#td-introduction-modal .mdl-content { #td-introduction-modal .mdl-content {
padding: 4px 16px 0; padding: 4px 16px 0;
overflow-y: auto; overflow-y: auto;
border-color: #ccd6dd;
background: #eaeaea;
} }
#td-introduction-modal p { #td-introduction-modal p {

View File

@@ -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;
}

View File

@@ -50,7 +50,7 @@ button, .btn, .mdl, .mdl-content, .modal-content, .popover, .lst-modal, .tooltip
border-radius: 1px !important; border-radius: 1px !important;
} }
.tweet-button, .app-search-fake, .app-search-input, .compose-text-container, .compose-reply-tweet, .compose-message-recipient-input-container, .compose-message-recipient, .compose-media-bar-holder, .compose-media-bar-thumb, .media-grid-container, .js-add-image-description, .js-quote-tweet-holder, .detail-view-inline-text { .tweet-button, .app-search-fake, .app-search-input, .compose-text-container, .compose-reply-tweet, .compose-message-recipient-input-container, .compose-message-recipient, .compose-media-bar-holder, .compose-media-bar-thumb, .media-grid-container, .js-add-image-description, .js-quote-tweet-holder, .detail-view-inline-text, .mdl-column-rhs {
border-radius: 0 !important; border-radius: 0 !important;
} }

View File

@@ -6,6 +6,7 @@ html, body {
height: auto !important; height: auto !important;
overflow-x: hidden !important; overflow-x: hidden !important;
overflow-y: auto !important; overflow-y: auto !important;
margin: 0;
} }
body::before { body::before {

View File

@@ -1,7 +1,7 @@
/*********************/ /*********************/
/* Center everything */ /* Center everything */
/*********************/ /*********************/
#doc { #doc {
width: 100%; width: 100%;
height: 100%; height: 100%;
@@ -25,6 +25,17 @@
margin: 0 auto !important; margin: 0 auto !important;
} }
.ResponsiveLayout {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.Section {
padding: 36px !important;
}
/*******************/ /*******************/
/* General styling */ /* General styling */
/*******************/ /*******************/
@@ -39,7 +50,7 @@ body {
box-shadow: 0 0 150px rgba(255, 255, 255, 0.3) !important; box-shadow: 0 0 150px rgba(255, 255, 255, 0.3) !important;
} }
.topbar { .topbar, .TopNav {
/* hide top bar */ /* hide top bar */
display: none !important; display: none !important;
} }
@@ -65,3 +76,42 @@ button[type='submit'] {
margin-top: 15px !important; margin-top: 15px !important;
font-weight: bold !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;
}

View File

@@ -8,15 +8,15 @@
return; 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"){ if (location.pathname === "/logout"){
style.innerText += `#import "styles/twitter.logout.css"`; document.documentElement.setAttribute("logout", "");
} }
document.head.appendChild(style);
}; };
setTimeout(injectCSS, 1); setTimeout(injectCSS, 1);

View File

@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\CefSharp.WinForms.67.0.0-pre01\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.67.0.0-pre01\build\CefSharp.WinForms.props')" /> <Import Project="packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props" Condition="Exists('packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props')" />
<Import Project="packages\CefSharp.Common.67.0.0-pre01\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.67.0.0-pre01\build\CefSharp.Common.props')" /> <Import Project="packages\CefSharp.WinForms.67.0.0\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.67.0.0\build\CefSharp.WinForms.props')" />
<Import Project="packages\CefSharp.Common.67.0.0\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.67.0.0\build\CefSharp.Common.props')" />
<Import Project="packages\cef.redist.x86.3.3396.1786\build\cef.redist.x86.props" Condition="Exists('packages\cef.redist.x86.3.3396.1786\build\cef.redist.x86.props')" /> <Import Project="packages\cef.redist.x86.3.3396.1786\build\cef.redist.x86.props" Condition="Exists('packages\cef.redist.x86.3.3396.1786\build\cef.redist.x86.props')" />
<Import Project="packages\cef.redist.x64.3.3396.1786\build\cef.redist.x64.props" Condition="Exists('packages\cef.redist.x64.3.3396.1786\build\cef.redist.x64.props')" /> <Import Project="packages\cef.redist.x64.3.3396.1786\build\cef.redist.x64.props" Condition="Exists('packages\cef.redist.x64.3.3396.1786\build\cef.redist.x64.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
@@ -95,6 +96,7 @@
<Compile Include="Core\Handling\KeyboardHandlerNotification.cs" /> <Compile Include="Core\Handling\KeyboardHandlerNotification.cs" />
<Compile Include="Core\Handling\RequestHandlerBase.cs" /> <Compile Include="Core\Handling\RequestHandlerBase.cs" />
<Compile Include="Core\Handling\RequestHandlerBrowser.cs" /> <Compile Include="Core\Handling\RequestHandlerBrowser.cs" />
<Compile Include="Core\Handling\ResourceHandlerFactory.cs" />
<Compile Include="Core\Handling\ResourceHandlerNotification.cs" /> <Compile Include="Core\Handling\ResourceHandlerNotification.cs" />
<Compile Include="Core\Management\ContextInfo.cs" /> <Compile Include="Core\Management\ContextInfo.cs" />
<Compile Include="Core\Notification\Example\FormNotificationExample.cs"> <Compile Include="Core\Notification\Example\FormNotificationExample.cs">
@@ -424,11 +426,12 @@ IF EXIST "$(ProjectDir)bld\post_build.exe" (
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('packages\cef.redist.x64.3.3396.1786\build\cef.redist.x64.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.3396.1786\build\cef.redist.x64.props'))" /> <Error Condition="!Exists('packages\cef.redist.x64.3.3396.1786\build\cef.redist.x64.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.3396.1786\build\cef.redist.x64.props'))" />
<Error Condition="!Exists('packages\cef.redist.x86.3.3396.1786\build\cef.redist.x86.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.3396.1786\build\cef.redist.x86.props'))" /> <Error Condition="!Exists('packages\cef.redist.x86.3.3396.1786\build\cef.redist.x86.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.3396.1786\build\cef.redist.x86.props'))" />
<Error Condition="!Exists('packages\CefSharp.Common.67.0.0-pre01\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.67.0.0-pre01\build\CefSharp.Common.props'))" /> <Error Condition="!Exists('packages\CefSharp.Common.67.0.0\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.67.0.0\build\CefSharp.Common.props'))" />
<Error Condition="!Exists('packages\CefSharp.Common.67.0.0-pre01\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.67.0.0-pre01\build\CefSharp.Common.targets'))" /> <Error Condition="!Exists('packages\CefSharp.Common.67.0.0\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.67.0.0\build\CefSharp.Common.targets'))" />
<Error Condition="!Exists('packages\CefSharp.WinForms.67.0.0-pre01\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.67.0.0-pre01\build\CefSharp.WinForms.props'))" /> <Error Condition="!Exists('packages\CefSharp.WinForms.67.0.0\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.67.0.0\build\CefSharp.WinForms.props'))" />
<Error Condition="!Exists('packages\CefSharp.WinForms.67.0.0-pre01\build\CefSharp.WinForms.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.67.0.0-pre01\build\CefSharp.WinForms.targets'))" /> <Error Condition="!Exists('packages\CefSharp.WinForms.67.0.0\build\CefSharp.WinForms.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.67.0.0\build\CefSharp.WinForms.targets'))" />
<Error Condition="!Exists('packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props'))" />
</Target> </Target>
<Import Project="packages\CefSharp.Common.67.0.0-pre01\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.67.0.0-pre01\build\CefSharp.Common.targets')" /> <Import Project="packages\CefSharp.Common.67.0.0\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.67.0.0\build\CefSharp.Common.targets')" />
<Import Project="packages\CefSharp.WinForms.67.0.0-pre01\build\CefSharp.WinForms.targets" Condition="Exists('packages\CefSharp.WinForms.67.0.0-pre01\build\CefSharp.WinForms.targets')" /> <Import Project="packages\CefSharp.WinForms.67.0.0\build\CefSharp.WinForms.targets" Condition="Exists('packages\CefSharp.WinForms.67.0.0\build\CefSharp.WinForms.targets')" />
</Project> </Project>

View File

@@ -220,14 +220,14 @@ begin
end; end;
{ Return whether the version of the installed libcef.dll library matches internal one. } { Return whether the version of the installed libcef.dll library matches internal one. }
{ TODO: Remove workaround that forces full installation for 1.15 and older eventually. } { TODO: Remove workaround that forces full installation for 1.16 and older eventually. }
function TDIsMatchingCEFVersion: Boolean; function TDIsMatchingCEFVersion: Boolean;
var CEFVersion: String; var CEFVersion: String;
var TDVersionMS: Cardinal; var TDVersionMS: Cardinal;
var TDVersionLS: Cardinal; var TDVersionLS: Cardinal;
begin begin
if (GetVersionNumbers(UpdatePath+'TweetDuck.exe', TDVersionMS, TDVersionLS)) and ((TDVersionMS and $FFFF) < 16) then if (GetVersionNumbers(UpdatePath+'TweetDuck.exe', TDVersionMS, TDVersionLS)) and ((TDVersionMS and $FFFF) < 17) then
begin begin
Result := False Result := False
Exit Exit

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -11,6 +12,8 @@
<AssemblyName>TweetLib.Communication</AssemblyName> <AssemblyName>TweetLib.Communication</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@@ -40,5 +43,14 @@
<Compile Include="DuplexPipe.cs" /> <Compile Include="DuplexPipe.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props'))" />
</Target>
</Project> </Project>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Net.Compilers" version="2.9.0" targetFramework="net452" developmentDependency="true" />
</packages>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
@@ -17,6 +18,8 @@
<IsCodedUITest>False</IsCodedUITest> <IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType> <TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
@@ -55,6 +58,9 @@
<Name>TweetDuck</Name> <Name>TweetDuck</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Choose> <Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'"> <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup> <ItemGroup>
@@ -75,6 +81,12 @@
</Choose> </Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Net.Compilers" version="2.9.0" targetFramework="net452" developmentDependency="true" />
</packages>

View File

@@ -2,6 +2,7 @@
<packages> <packages>
<package id="cef.redist.x64" version="3.3396.1786" targetFramework="net452" /> <package id="cef.redist.x64" version="3.3396.1786" targetFramework="net452" />
<package id="cef.redist.x86" version="3.3396.1786" targetFramework="net452" /> <package id="cef.redist.x86" version="3.3396.1786" targetFramework="net452" />
<package id="CefSharp.Common" version="67.0.0-pre01" targetFramework="net452" /> <package id="CefSharp.Common" version="67.0.0" targetFramework="net452" />
<package id="CefSharp.WinForms" version="67.0.0-pre01" targetFramework="net452" /> <package id="CefSharp.WinForms" version="67.0.0" targetFramework="net452" />
<package id="Microsoft.Net.Compilers" version="2.9.0" targetFramework="net452" developmentDependency="true" />
</packages> </packages>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -11,6 +12,8 @@
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
@@ -28,7 +31,7 @@
<ItemGroup> <ItemGroup>
<Reference Include="CefSharp.BrowserSubprocess.Core, Version=67.0.0.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138, processorArchitecture=x86"> <Reference Include="CefSharp.BrowserSubprocess.Core, Version=67.0.0.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CefSharp.Common.67.0.0-pre01\CefSharp\x86\CefSharp.BrowserSubprocess.Core.dll</HintPath> <HintPath>..\packages\CefSharp.Common.67.0.0\CefSharp\x86\CefSharp.BrowserSubprocess.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
</ItemGroup> </ItemGroup>
@@ -36,9 +39,18 @@
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
<PostBuildEvent>call "$(DevEnvDir)..\..\VC\Auxiliary\Build\vcvars32.bat" <PostBuildEvent>call "$(DevEnvDir)..\..\VC\Auxiliary\Build\vcvars32.bat"
editbin /largeaddressaware /TSAWARE "$(TargetPath)"</PostBuildEvent> editbin /largeaddressaware /TSAWARE "$(TargetPath)"</PostBuildEvent>
</PropertyGroup> </PropertyGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props'))" />
</Target>
</Project> </Project>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Net.Compilers" version="2.9.0" targetFramework="net452" developmentDependency="true" />
</packages>

View File

@@ -19,7 +19,14 @@ namespace TweetDuck.Video.Controls{
Form form = control.FindForm(); Form form = control.FindForm();
System.Diagnostics.Debug.Assert(form != null); 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))); 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)); loc.X = Math.Max(0, Math.Min(form.Width-Width, loc.X-Width/2));

View File

@@ -30,7 +30,7 @@ namespace TweetDuck.Video.Controls{
brushBack.Color = Parent.BackColor; brushBack.Color = Parent.BackColor;
} }
Rectangle rect = e.ClipRectangle; Rectangle rect = new Rectangle(0, 0, Width, Height);
Point cursor = PointToClient(Cursor.Position); Point cursor = PointToClient(Cursor.Position);
int width = rect.Width-1; int width = rect.Width-1;
int progress = (int)(width*((double)Value/Maximum)); int progress = (int)(width*((double)Value/Maximum));

View File

@@ -26,16 +26,18 @@
this.components = new System.ComponentModel.Container(); this.components = new System.ComponentModel.Container();
this.timerSync = new System.Windows.Forms.Timer(this.components); this.timerSync = new System.Windows.Forms.Timer(this.components);
this.trackBarVolume = new System.Windows.Forms.TrackBar(); 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.progressSeek = new TweetDuck.Video.Controls.SeekBar();
this.labelTime = new System.Windows.Forms.Label(); 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.imageResize = new System.Windows.Forms.PictureBox();
this.imageDownload = new System.Windows.Forms.PictureBox(); this.imageDownload = new System.Windows.Forms.PictureBox();
this.imageClose = 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(); ((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).BeginInit();
this.tablePanel.SuspendLayout(); this.tablePanelFull.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.imageResize)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.imageResize)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.imageDownload)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.imageDownload)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.imageClose)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.imageClose)).BeginInit();
@@ -64,30 +66,31 @@
this.trackBarVolume.MouseDown += new System.Windows.Forms.MouseEventHandler(this.trackBarVolume_MouseDown); this.trackBarVolume.MouseDown += new System.Windows.Forms.MouseEventHandler(this.trackBarVolume_MouseDown);
this.trackBarVolume.MouseUp += new System.Windows.Forms.MouseEventHandler(this.trackBarVolume_MouseUp); this.trackBarVolume.MouseUp += new System.Windows.Forms.MouseEventHandler(this.trackBarVolume_MouseUp);
// //
// tablePanel // tablePanelFull
// //
this.tablePanel.BackColor = System.Drawing.SystemColors.Control; this.tablePanelFull.BackColor = System.Drawing.SystemColors.Control;
this.tablePanel.ColumnCount = 6; this.tablePanelFull.ColumnCount = 6;
this.tablePanel.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.tablePanel.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.Percent, 100F));
this.tablePanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 74F)); this.tablePanelFull.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F));
this.tablePanel.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, 130F));
this.tablePanel.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.tablePanel.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.tablePanel.Controls.Add(this.trackBarVolume, 3, 0); this.tablePanelFull.Controls.Add(this.trackBarVolume, 3, 0);
this.tablePanel.Controls.Add(this.progressSeek, 1, 0); this.tablePanelFull.Controls.Add(this.progressSeek, 1, 0);
this.tablePanel.Controls.Add(this.labelTime, 2, 0); this.tablePanelFull.Controls.Add(this.labelTime, 2, 0);
this.tablePanel.Controls.Add(this.imageResize, 5, 0); this.tablePanelFull.Controls.Add(this.imageResize, 5, 0);
this.tablePanel.Controls.Add(this.imageDownload, 4, 0); this.tablePanelFull.Controls.Add(this.imageDownload, 4, 0);
this.tablePanel.Controls.Add(this.imageClose, 0, 0); this.tablePanelFull.Controls.Add(this.imageClose, 0, 0);
this.tablePanel.Dock = System.Windows.Forms.DockStyle.Bottom; this.tablePanelFull.Dock = System.Windows.Forms.DockStyle.Bottom;
this.tablePanel.Location = new System.Drawing.Point(0, 86); this.tablePanelFull.Location = new System.Drawing.Point(0, 86);
this.tablePanel.Name = "tablePanel"; this.tablePanelFull.Name = "tablePanelFull";
this.tablePanel.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0); this.tablePanelFull.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.tablePanel.RowCount = 1; this.tablePanelFull.RowCount = 1;
this.tablePanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tablePanelFull.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tablePanel.Size = new System.Drawing.Size(400, 34); this.tablePanelFull.Size = new System.Drawing.Size(400, 34);
this.tablePanel.TabIndex = 1; this.tablePanelFull.TabIndex = 0;
this.tablePanelFull.Visible = false;
// //
// progressSeek // progressSeek
// //
@@ -98,7 +101,7 @@
this.progressSeek.Margin = new System.Windows.Forms.Padding(9, 10, 8, 10); this.progressSeek.Margin = new System.Windows.Forms.Padding(9, 10, 8, 10);
this.progressSeek.Maximum = 5000; this.progressSeek.Maximum = 5000;
this.progressSeek.Name = "progressSeek"; 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.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
this.progressSeek.TabIndex = 0; this.progressSeek.TabIndex = 0;
this.progressSeek.MouseDown += new System.Windows.Forms.MouseEventHandler(this.progressSeek_MouseDown); this.progressSeek.MouseDown += new System.Windows.Forms.MouseEventHandler(this.progressSeek_MouseDown);
@@ -106,32 +109,14 @@
// labelTime // labelTime
// //
this.labelTime.Dock = System.Windows.Forms.DockStyle.Fill; this.labelTime.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelTime.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular); this.labelTime.Font = new System.Drawing.Font("Segoe UI", 9F);
this.labelTime.Location = new System.Drawing.Point(138, 3); this.labelTime.Location = new System.Drawing.Point(132, 3);
this.labelTime.Margin = new System.Windows.Forms.Padding(0, 3, 0, 5); this.labelTime.Margin = new System.Windows.Forms.Padding(0, 3, 0, 5);
this.labelTime.Name = "labelTime"; 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.TabIndex = 1;
this.labelTime.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 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 // imageResize
// //
this.imageResize.Cursor = System.Windows.Forms.Cursors.Hand; this.imageResize.Cursor = System.Windows.Forms.Cursors.Hand;
@@ -178,6 +163,66 @@
this.imageClose.WaitOnLoad = true; this.imageClose.WaitOnLoad = true;
this.imageClose.Click += new System.EventHandler(this.imageClose_Click); 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 // FormPlayer
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -186,12 +231,13 @@
this.ClientSize = new System.Drawing.Size(400, 120); this.ClientSize = new System.Drawing.Size(400, 120);
this.ControlBox = false; this.ControlBox = false;
this.Controls.Add(this.labelTooltip); 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.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Location = new System.Drawing.Point(-32000, -32000); this.Location = new System.Drawing.Point(-32000, -32000);
this.MaximizeBox = false; this.MaximizeBox = false;
this.MinimizeBox = false; this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(400, 120);
this.Name = "FormPlayer"; this.Name = "FormPlayer";
this.ShowIcon = false; this.ShowIcon = false;
this.ShowInTaskbar = false; this.ShowInTaskbar = false;
@@ -199,7 +245,7 @@
this.Text = "TweetDuck Video"; this.Text = "TweetDuck Video";
this.Load += new System.EventHandler(this.FormPlayer_Load); this.Load += new System.EventHandler(this.FormPlayer_Load);
((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).EndInit();
this.tablePanel.ResumeLayout(false); this.tablePanelFull.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.imageResize)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.imageResize)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.imageDownload)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.imageDownload)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.imageClose)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.imageClose)).EndInit();
@@ -212,7 +258,7 @@
private System.Windows.Forms.Timer timerSync; private System.Windows.Forms.Timer timerSync;
private System.Windows.Forms.TrackBar trackBarVolume; private System.Windows.Forms.TrackBar trackBarVolume;
private System.Windows.Forms.TableLayoutPanel tablePanel; private System.Windows.Forms.TableLayoutPanel tablePanelFull;
private Controls.SeekBar progressSeek; private Controls.SeekBar progressSeek;
private System.Windows.Forms.Label labelTime; private System.Windows.Forms.Label labelTime;
private System.Windows.Forms.Timer timerData; private System.Windows.Forms.Timer timerData;
@@ -220,6 +266,8 @@
private System.Windows.Forms.PictureBox imageResize; private System.Windows.Forms.PictureBox imageResize;
private System.Windows.Forms.PictureBox imageDownload; private System.Windows.Forms.PictureBox imageDownload;
private System.Windows.Forms.PictureBox imageClose; private System.Windows.Forms.PictureBox imageClose;
private System.Windows.Forms.TableLayoutPanel tablePanelCompactBottom;
private System.Windows.Forms.TableLayoutPanel tablePanelCompactTop;
} }
} }

View File

@@ -10,9 +10,17 @@ using WMPLib;
namespace TweetDuck.Video{ namespace TweetDuck.Video{
sealed partial class FormPlayer : Form{ 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; protected override bool ShowWithoutActivation => true;
private readonly IntPtr ownerHandle; private readonly IntPtr ownerHandle;
private readonly float ownerDpi;
private readonly string videoUrl; private readonly string videoUrl;
private readonly DuplexPipe pipe; private readonly DuplexPipe pipe;
@@ -23,13 +31,20 @@ namespace TweetDuck.Video{
private WindowsMediaPlayer Player => player.Ocx; 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(); InitializeComponent();
this.ownerHandle = handle; this.ownerHandle = handle;
this.ownerDpi = dpi / 100F;
this.videoUrl = url; this.videoUrl = url;
this.pipe = DuplexPipe.CreateClient(token); this.pipe = DuplexPipe.CreateClient(token);
this.pipe.DataIn += pipe_DataIn; 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{ player = new ControlWMP{
Dock = DockStyle.Fill Dock = DockStyle.Fill
@@ -51,6 +66,10 @@ namespace TweetDuck.Video{
trackBarVolume.Value = volume; // changes player volume too if non-default trackBarVolume.Value = volume; // changes player volume too if non-default
labelTooltip.AttachTooltip(progressSeek, true, args => { 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; IWMPMedia media = Player.currentMedia;
int progress = (int)(media.duration*progressSeek.GetProgress(args.X)); int progress = (int)(media.duration*progressSeek.GetProgress(args.X));
@@ -68,6 +87,59 @@ namespace TweetDuck.Video{
Application.AddMessageFilter(new MessageFilter(this)); 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 = 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 // Events
private void FormPlayer_Load(object sender, EventArgs e){ private void FormPlayer_Load(object sender, EventArgs e){
@@ -100,6 +172,11 @@ namespace TweetDuck.Video{
timerSync.Start(); timerSync.Start();
NativeMethods.SetWindowOwner(Handle, ownerHandle); NativeMethods.SetWindowOwner(Handle, ownerHandle);
Cursor.Current = Cursors.Default; Cursor.Current = Cursors.Default;
SuspendLayout();
timerSync_Tick(timerSync, EventArgs.Empty);
Opacity = 1;
ResumeLayout(true);
} }
} }
@@ -115,20 +192,39 @@ namespace TweetDuck.Video{
[HandleProcessCorruptedStateExceptions] [HandleProcessCorruptedStateExceptions]
private void timerSync_Tick(object sender, EventArgs e){ private void timerSync_Tick(object sender, EventArgs e){
if (NativeMethods.GetWindowRect(ownerHandle, out NativeMethods.RECT rect)){ 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; IWMPMedia media = Player.currentMedia;
IWMPControls controls = Player.controls; 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)); bool isCursorInside = ClientRectangle.Contains(PointToClient(Cursor.Position));
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;
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))); RefreshControlPanel();
Location = new Point(rect.Left+(width-ClientSize.Width)/2, rect.Top+(height-ClientSize.Height+SystemInformation.CaptionHeight)/2); }
tablePanel.Visible = isCursorInside || isDragging; if (isCursorInside || isDragging){
if (tablePanel.Visible){
labelTime.Text = $"{controls.currentPositionString} / {media.durationString}"; labelTime.Text = $"{controls.currentPositionString} / {media.durationString}";
int value = (int)Math.Round(progressSeek.Maximum*controls.currentPosition/media.duration); int value = (int)Math.Round(progressSeek.Maximum*controls.currentPosition/media.duration);
@@ -142,8 +238,21 @@ namespace TweetDuck.Video{
progressSeek.Value = value+1; progressSeek.Value = value+1;
progressSeek.Value = value; 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 if (controls.currentPosition > media.duration){ // pausing near the end of the video causes WMP to play beyond the end of the video wtf
try{ try{
controls.stop(); controls.stop();
@@ -157,6 +266,10 @@ namespace TweetDuck.Video{
if (isCursorInside && !wasCursorInside){ if (isCursorInside && !wasCursorInside){
wasCursorInside = true; wasCursorInside = true;
if (IsCursorOverVideo){
Cursor.Current = Cursors.Default;
}
} }
else if (!isCursorInside && wasCursorInside){ else if (!isCursorInside && wasCursorInside){
wasCursorInside = false; wasCursorInside = false;
@@ -273,26 +386,19 @@ namespace TweetDuck.Video{
internal sealed class MessageFilter : IMessageFilter{ internal sealed class MessageFilter : IMessageFilter{
private readonly FormPlayer form; 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){ public MessageFilter(FormPlayer form){
this.form = form; this.form = form;
} }
bool IMessageFilter.PreFilterMessage(ref Message m){ bool IMessageFilter.PreFilterMessage(ref Message m){
if (m.Msg == 0x0201){ // WM_LBUTTONDOWN if (m.Msg == 0x0201){ // WM_LBUTTONDOWN
if (IsCursorOverVideo){ if (form.IsCursorOverVideo){
form.TogglePause(); form.TogglePause();
return true; return true;
} }
} }
else if (m.Msg == 0x0203){ // WM_LBUTTONDBLCLK else if (m.Msg == 0x0203){ // WM_LBUTTONDBLCLK
if (IsCursorOverVideo){ if (form.IsCursorOverVideo){
form.TogglePause(); form.TogglePause();
form.Player.fullScreen = !form.Player.fullScreen; form.Player.fullScreen = !form.Player.fullScreen;
return true; return true;

View File

@@ -9,6 +9,10 @@ namespace TweetDuck.Video{
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); 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")] [DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong); private static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

View File

@@ -5,7 +5,7 @@ using System.Windows.Forms;
namespace TweetDuck.Video{ namespace TweetDuck.Video{
static class Program{ static class Program{
internal const string Version = "1.3"; internal const string Version = "1.4.1";
// referenced in VideoPlayer // referenced in VideoPlayer
// set by task manager -- public const int CODE_PROCESS_KILLED = 1; // set by task manager -- public const int CODE_PROCESS_KILLED = 1;
@@ -25,21 +25,23 @@ namespace TweetDuck.Video{
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
IntPtr ownerHandle; IntPtr ownerHandle;
int ownerDpi;
int defaultVolume; int defaultVolume;
string videoUrl; string videoUrl;
string pipeToken; string pipeToken;
try{ try{
ownerHandle = new IntPtr(int.Parse(args[0], NumberStyles.Integer)); ownerHandle = new IntPtr(int.Parse(args[0], NumberStyles.Integer));
defaultVolume = int.Parse(args[1], NumberStyles.Integer); ownerDpi = int.Parse(args[1], NumberStyles.Integer);
videoUrl = new Uri(args[2], UriKind.Absolute).AbsoluteUri; defaultVolume = int.Parse(args[2], NumberStyles.Integer);
pipeToken = args[3]; videoUrl = new Uri(args[3], UriKind.Absolute).AbsoluteUri;
pipeToken = args[4];
}catch{ }catch{
return CODE_INVALID_ARGS; return CODE_INVALID_ARGS;
} }
try{ try{
Application.Run(new FormPlayer(ownerHandle, defaultVolume, videoUrl, pipeToken)); Application.Run(new FormPlayer(ownerHandle, ownerDpi, defaultVolume, videoUrl, pipeToken));
}catch(Exception e){ }catch(Exception e){
Console.Out.WriteLine(e); Console.Out.WriteLine(e);
return CODE_LAUNCH_FAIL; return CODE_LAUNCH_FAIL;

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -12,6 +13,8 @@
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<ResolveComReferenceSilent>True</ResolveComReferenceSilent> <ResolveComReferenceSilent>True</ResolveComReferenceSilent>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@@ -82,6 +85,7 @@
</COMReference> </COMReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" />
<None Include="Resources\btnResize.png" /> <None Include="Resources\btnResize.png" />
<None Include="Resources\btnDownload.png" /> <None Include="Resources\btnDownload.png" />
<None Include="Resources\btnClose.png" /> <None Include="Resources\btnClose.png" />
@@ -100,4 +104,10 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.2.9.0\build\Microsoft.Net.Compilers.props'))" />
</Target>
</Project> </Project>

4
video/packages.config Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Net.Compilers" version="2.9.0" targetFramework="net452" developmentDependency="true" />
</packages>