mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-09-14 19:32:10 +02:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
651d9be57c | |||
eeb32db6fb | |||
daa0780644 | |||
8502f9105f | |||
16ced3d827 |
@@ -4,19 +4,19 @@ using CefSharp;
|
|||||||
|
|
||||||
namespace TweetDuck.Browser.Data{
|
namespace TweetDuck.Browser.Data{
|
||||||
sealed class ResourceHandlers{
|
sealed class ResourceHandlers{
|
||||||
private readonly ConcurrentDictionary<string, IResourceHandler> handlers = new ConcurrentDictionary<string, IResourceHandler>(StringComparer.OrdinalIgnoreCase);
|
private readonly ConcurrentDictionary<string, Func<IResourceHandler>> handlers = new ConcurrentDictionary<string, Func<IResourceHandler>>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public bool HasHandler(IRequest request){
|
public bool HasHandler(IRequest request){
|
||||||
return handlers.ContainsKey(request.Url);
|
return handlers.ContainsKey(request.Url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IResourceHandler GetHandler(IRequest request){
|
public IResourceHandler GetHandler(IRequest request){
|
||||||
return handlers.TryGetValue(request.Url, out var handler) ? handler : null;
|
return handlers.TryGetValue(request.Url, out var factory) ? factory() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Register(string url, IResourceHandler handler){
|
public bool Register(string url, Func<IResourceHandler> factory){
|
||||||
if (Uri.TryCreate(url, UriKind.Absolute, out Uri uri)){
|
if (Uri.TryCreate(url, UriKind.Absolute, out Uri uri)){
|
||||||
handlers.AddOrUpdate(uri.AbsoluteUri, handler, (key, prev) => handler);
|
handlers.AddOrUpdate(uri.AbsoluteUri, factory, (key, prev) => factory);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,15 +24,27 @@ namespace TweetDuck.Browser.Data{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public bool Register(ResourceLink link){
|
public bool Register(ResourceLink link){
|
||||||
return Register(link.Url, link.Handler);
|
return Register(link.Url, link.Factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Unregister(string url){
|
public bool Unregister(string url){
|
||||||
return handlers.TryRemove(url, out IResourceHandler _);
|
return handlers.TryRemove(url, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Unregister(ResourceLink link){
|
public bool Unregister(ResourceLink link){
|
||||||
return Unregister(link.Url);
|
return Unregister(link.Url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Func<IResourceHandler> ForString(string str){
|
||||||
|
return () => ResourceHandler.FromString(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Func<IResourceHandler> ForString(string str, string mimeType){
|
||||||
|
return () => ResourceHandler.FromString(str, mimeType: mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Func<IResourceHandler> ForBytes(byte[] bytes, string mimeType){
|
||||||
|
return () => ResourceHandler.FromByteArray(bytes, mimeType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
using CefSharp;
|
using System;
|
||||||
|
using CefSharp;
|
||||||
|
|
||||||
namespace TweetDuck.Browser.Data{
|
namespace TweetDuck.Browser.Data{
|
||||||
sealed class ResourceLink{
|
sealed class ResourceLink{
|
||||||
public string Url { get; }
|
public string Url { get; }
|
||||||
public IResourceHandler Handler { get; }
|
public Func<IResourceHandler> Factory { get; }
|
||||||
|
|
||||||
public ResourceLink(string url, IResourceHandler handler){
|
public ResourceLink(string url, Func<IResourceHandler> factory){
|
||||||
this.Url = url;
|
this.Url = url;
|
||||||
this.Handler = handler;
|
this.Factory = factory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using CefSharp;
|
|
||||||
using CefSharp.WinForms;
|
using CefSharp.WinForms;
|
||||||
using TweetDuck.Browser.Data;
|
using TweetDuck.Browser.Data;
|
||||||
using TweetDuck.Browser.Handling;
|
using TweetDuck.Browser.Handling;
|
||||||
@@ -14,7 +13,7 @@ using TweetLib.Core.Features.Twitter;
|
|||||||
|
|
||||||
namespace TweetDuck.Browser.Notification{
|
namespace TweetDuck.Browser.Notification{
|
||||||
abstract partial class FormNotificationBase : Form, AnalyticsFile.IProvider{
|
abstract partial class FormNotificationBase : Form, AnalyticsFile.IProvider{
|
||||||
public static readonly ResourceLink AppLogo = new ResourceLink("https://ton.twimg.com/tduck/avatar", ResourceHandler.FromByteArray(Properties.Resources.avatar, "image/png"));
|
public static readonly ResourceLink AppLogo = new ResourceLink("https://ton.twimg.com/tduck/avatar", ResourceHandlers.ForBytes(Properties.Resources.avatar, "image/png"));
|
||||||
|
|
||||||
protected const string BlankURL = TwitterUrls.TweetDeck + "/?blank";
|
protected const string BlankURL = TwitterUrls.TweetDeck + "/?blank";
|
||||||
|
|
||||||
@@ -135,8 +134,8 @@ namespace TweetDuck.Browser.Notification{
|
|||||||
var resourceRequestHandler = new ResourceRequestHandlerBase();
|
var resourceRequestHandler = new ResourceRequestHandlerBase();
|
||||||
var resourceHandlers = resourceRequestHandler.ResourceHandlers;
|
var resourceHandlers = resourceRequestHandler.ResourceHandlers;
|
||||||
|
|
||||||
resourceHandlers.Register(BlankURL, ResourceHandler.FromString(string.Empty));
|
resourceHandlers.Register(BlankURL, ResourceHandlers.ForString(string.Empty));
|
||||||
resourceHandlers.Register(TwitterUrls.TweetDeck, this.resourceHandler);
|
resourceHandlers.Register(TwitterUrls.TweetDeck, () => this.resourceHandler);
|
||||||
resourceHandlers.Register(AppLogo);
|
resourceHandlers.Register(AppLogo);
|
||||||
|
|
||||||
this.browser = new ChromiumWebBrowser(BlankURL){
|
this.browser = new ChromiumWebBrowser(BlankURL){
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
using System.Drawing;
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using CefSharp;
|
using CefSharp;
|
||||||
|
using TweetDuck.Browser.Data;
|
||||||
using TweetDuck.Controls;
|
using TweetDuck.Controls;
|
||||||
using TweetDuck.Dialogs;
|
using TweetDuck.Dialogs;
|
||||||
using TweetDuck.Dialogs.Settings;
|
using TweetDuck.Dialogs.Settings;
|
||||||
@@ -11,7 +13,7 @@ namespace TweetDuck.Browser.Notification{
|
|||||||
static class SoundNotification{
|
static class SoundNotification{
|
||||||
public const string SupportedFormats = "*.wav;*.ogg;*.mp3;*.flac;*.opus;*.weba;*.webm";
|
public const string SupportedFormats = "*.wav;*.ogg;*.mp3;*.flac;*.opus;*.weba;*.webm";
|
||||||
|
|
||||||
public static IResourceHandler CreateFileHandler(string path){
|
public static Func<IResourceHandler> CreateFileHandler(string path){
|
||||||
string mimeType = Path.GetExtension(path) switch{
|
string mimeType = Path.GetExtension(path) switch{
|
||||||
".weba" => "audio/webm",
|
".weba" => "audio/webm",
|
||||||
".webm" => "audio/webm",
|
".webm" => "audio/webm",
|
||||||
@@ -24,7 +26,7 @@ namespace TweetDuck.Browser.Notification{
|
|||||||
};
|
};
|
||||||
|
|
||||||
try{
|
try{
|
||||||
return ResourceHandler.FromFilePath(path, mimeType);
|
return ResourceHandlers.ForBytes(File.ReadAllBytes(path), mimeType);
|
||||||
}catch{
|
}catch{
|
||||||
FormBrowser browser = FormManager.TryFind<FormBrowser>();
|
FormBrowser browser = FormManager.TryFind<FormBrowser>();
|
||||||
|
|
||||||
|
@@ -137,7 +137,7 @@ namespace TweetDuck.Browser{
|
|||||||
|
|
||||||
if (TwitterUrls.IsTwitter(url)){
|
if (TwitterUrls.IsTwitter(url)){
|
||||||
string css = Program.Resources.Load("styles/twitter.css");
|
string css = Program.Resources.Load("styles/twitter.css");
|
||||||
resourceHandlers.Register(TwitterStyleUrl, ResourceHandler.FromString(css, mimeType: "text/css"));
|
resourceHandlers.Register(TwitterStyleUrl, ResourceHandlers.ForString(css, "text/css"));
|
||||||
|
|
||||||
CefScriptExecutor.RunFile(frame, "twitter.js");
|
CefScriptExecutor.RunFile(frame, "twitter.js");
|
||||||
}
|
}
|
||||||
@@ -192,7 +192,7 @@ namespace TweetDuck.Browser{
|
|||||||
string errorName = Enum.GetName(typeof(CefErrorCode), e.ErrorCode);
|
string errorName = Enum.GetName(typeof(CefErrorCode), e.ErrorCode);
|
||||||
string errorTitle = StringUtils.ConvertPascalCaseToScreamingSnakeCase(errorName ?? string.Empty);
|
string errorTitle = StringUtils.ConvertPascalCaseToScreamingSnakeCase(errorName ?? string.Empty);
|
||||||
|
|
||||||
resourceHandlers.Register(ErrorUrl, ResourceHandler.FromString(errorPage.Replace("{err}", errorTitle)));
|
resourceHandlers.Register(ErrorUrl, ResourceHandlers.ForString(errorPage.Replace("{err}", errorTitle)));
|
||||||
browser.Load(ErrorUrl);
|
browser.Load(ErrorUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ namespace TweetDuck.Dialogs{
|
|||||||
private const string GuideUrl = "https://tweetduck.chylex.com/guide/v2/";
|
private const string GuideUrl = "https://tweetduck.chylex.com/guide/v2/";
|
||||||
private const string GuidePathRegex = @"^guide(?:/v\d+)?(?:/(#.*))?";
|
private const string GuidePathRegex = @"^guide(?:/v\d+)?(?:/(#.*))?";
|
||||||
|
|
||||||
private static readonly ResourceLink DummyPage = new ResourceLink("http://td/dummy", ResourceHandler.FromString(""));
|
private static readonly ResourceLink DummyPage = new ResourceLink("http://td/dummy", ResourceHandlers.ForString(string.Empty));
|
||||||
|
|
||||||
public static bool CheckGuideUrl(string url, out string hash){
|
public static bool CheckGuideUrl(string url, out string hash){
|
||||||
if (!url.Contains("//tweetduck.chylex.com/guide")){
|
if (!url.Contains("//tweetduck.chylex.com/guide")){
|
||||||
|
@@ -72,6 +72,14 @@ namespace TweetDuck.Dialogs.Settings{
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (dialog.ShowDialog() == DialogResult.OK){
|
if (dialog.ShowDialog() == DialogResult.OK){
|
||||||
|
try{
|
||||||
|
if (new FileInfo(dialog.FileName).Length > (1024 * 1024) && !FormMessage.Warning("Sound Notification", "The sound file is larger than 1 MB, this will cause increased memory usage. Use this file anyway?", FormMessage.Yes, FormMessage.No)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}catch{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
tbCustomSound.Text = dialog.FileName;
|
tbCustomSound.Text = dialog.FileName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -95,8 +95,9 @@
|
|||||||
html.find(".js-media").remove();
|
html.find(".js-media").remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
html.find("a[data-full-url]").each(function(){ // bypass t.co on all links
|
html.find("a[data-full-url]").each(function(){ // bypass t.co on all links and fix tooltips
|
||||||
this.href = this.getAttribute("data-full-url");
|
this.href = this.getAttribute("data-full-url");
|
||||||
|
this.removeAttribute("title");
|
||||||
});
|
});
|
||||||
|
|
||||||
html.find("a[href='#']").each(function(){ // remove <a> tags around links that don't lead anywhere (such as account names the tweet replied to)
|
html.find("a[href='#']").each(function(){ // remove <a> tags around links that don't lead anywhere (such as account names the tweet replied to)
|
||||||
@@ -303,6 +304,8 @@ execSafe(function setupLinkExpansionOrTooltip(){
|
|||||||
}, 200);
|
}, 200);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
me.removeAttr("title");
|
||||||
|
|
||||||
tooltipTimer = window.setTimeout(function(){
|
tooltipTimer = window.setTimeout(function(){
|
||||||
$TD.displayTooltip(me.attr("data-full-url"));
|
$TD.displayTooltip(me.attr("data-full-url"));
|
||||||
tooltipDisplayed = true;
|
tooltipDisplayed = true;
|
||||||
|
@@ -19,7 +19,7 @@ namespace TweetDuck.Utils{
|
|||||||
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;margin:0}';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", ResourceHandlers.ForBytes(Properties.Resources.spinner, "image/apng"));
|
||||||
|
|
||||||
public static readonly string[] DictionaryWords = {
|
public static readonly string[] DictionaryWords = {
|
||||||
"tweetdeck", "TweetDeck", "tweetduck", "TweetDuck", "TD"
|
"tweetdeck", "TweetDeck", "tweetduck", "TweetDuck", "TD"
|
||||||
|
@@ -6,6 +6,6 @@ using Version = TweetDuck.Version;
|
|||||||
|
|
||||||
namespace TweetDuck{
|
namespace TweetDuck{
|
||||||
internal static class Version{
|
internal static class Version{
|
||||||
public const string Tag = "1.19";
|
public const string Tag = "1.19.0.2";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user