mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-09-14 10:32:10 +02:00
Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
a391d8ee83 | |||
48c38f6e1d | |||
37c5fba162 | |||
23e99b1d44 | |||
8432240a47 | |||
a4bab743d6 | |||
60766789ab | |||
ca014f881c | |||
886eabe26c | |||
65b7167b5f | |||
abbdde851e | |||
54ac54aba6 | |||
184340f400 | |||
93dd6813e8 | |||
b689b08711 | |||
1479a097d6 | |||
e4967ea46d | |||
3f28f18fb4 |
@@ -6,7 +6,7 @@ using TweetDuck.Data.Serialization;
|
|||||||
namespace TweetDuck.Configuration{
|
namespace TweetDuck.Configuration{
|
||||||
sealed class SystemConfig{
|
sealed class SystemConfig{
|
||||||
private static readonly FileSerializer<SystemConfig> Serializer = new FileSerializer<SystemConfig>{
|
private static readonly FileSerializer<SystemConfig> Serializer = new FileSerializer<SystemConfig>{
|
||||||
OnReadUnknownProperty = (obj, property, value) => false
|
// HandleUnknownProperties = (obj, data) => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly bool IsHardwareAccelerationSupported = File.Exists(Path.Combine(Program.ProgramPath, "libEGL.dll")) &&
|
public static readonly bool IsHardwareAccelerationSupported = File.Exists(Path.Combine(Program.ProgramPath, "libEGL.dll")) &&
|
||||||
@@ -16,6 +16,9 @@ namespace TweetDuck.Configuration{
|
|||||||
|
|
||||||
private bool _hardwareAcceleration = true;
|
private bool _hardwareAcceleration = true;
|
||||||
|
|
||||||
|
public bool EnableBrowserGCReload { get; set; } = true;
|
||||||
|
public int BrowserMemoryThreshold { get; set; } = 400;
|
||||||
|
|
||||||
// SPECIAL PROPERTIES
|
// SPECIAL PROPERTIES
|
||||||
|
|
||||||
public bool HardwareAcceleration{
|
public bool HardwareAcceleration{
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using TweetDuck.Core;
|
using TweetDuck.Core;
|
||||||
@@ -10,9 +11,26 @@ using TweetDuck.Data.Serialization;
|
|||||||
|
|
||||||
namespace TweetDuck.Configuration{
|
namespace TweetDuck.Configuration{
|
||||||
sealed class UserConfig{
|
sealed class UserConfig{
|
||||||
private static readonly FileSerializer<UserConfig> Serializer = new FileSerializer<UserConfig>{
|
private static readonly FileSerializer<UserConfig> Serializer = new FileSerializer<UserConfig>{ HandleUnknownProperties = HandleUnknownProperties };
|
||||||
OnReadUnknownProperty = (obj, property, value) => false
|
|
||||||
};
|
private static void HandleUnknownProperties(UserConfig obj, Dictionary<string, string> data){
|
||||||
|
if (data.TryGetValue("EnableBrowserGCReload", out string propGCReload) && data.TryGetValue("BrowserMemoryThreshold", out string propMemThreshold)){
|
||||||
|
if (bool.TryParse(propGCReload, out bool isGCReloadEnabled) && isGCReloadEnabled && int.TryParse(propMemThreshold, out int memThreshold)){
|
||||||
|
// SystemConfig initialization was moved before UserConfig to allow for this
|
||||||
|
// TODO remove the migration soon
|
||||||
|
Program.SystemConfig.EnableBrowserGCReload = true;
|
||||||
|
Program.SystemConfig.BrowserMemoryThreshold = memThreshold;
|
||||||
|
Program.SystemConfig.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Remove("EnableBrowserGCReload");
|
||||||
|
data.Remove("BrowserMemoryThreshold");
|
||||||
|
|
||||||
|
if (data.Count == 0){
|
||||||
|
obj.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static UserConfig(){
|
static UserConfig(){
|
||||||
Serializer.RegisterTypeConverter(typeof(WindowState), WindowState.Converter);
|
Serializer.RegisterTypeConverter(typeof(WindowState), WindowState.Converter);
|
||||||
@@ -77,9 +95,6 @@ namespace TweetDuck.Configuration{
|
|||||||
public string CustomBrowserCSS { get; set; } = null;
|
public string CustomBrowserCSS { get; set; } = null;
|
||||||
public string CustomNotificationCSS { get; set; } = null;
|
public string CustomNotificationCSS { get; set; } = null;
|
||||||
|
|
||||||
public bool EnableBrowserGCReload { get; set; } = false;
|
|
||||||
public int BrowserMemoryThreshold { get; set; } = 350;
|
|
||||||
|
|
||||||
// SPECIAL PROPERTIES
|
// SPECIAL PROPERTIES
|
||||||
|
|
||||||
public bool IsCustomNotificationPositionSet => CustomNotificationPosition != ControlExtensions.InvisibleLocation;
|
public bool IsCustomNotificationPositionSet => CustomNotificationPosition != ControlExtensions.InvisibleLocation;
|
||||||
|
@@ -1,8 +1,12 @@
|
|||||||
using System.Windows.Forms;
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using CefSharp;
|
||||||
using TweetDuck.Core.Controls;
|
using TweetDuck.Core.Controls;
|
||||||
using TweetDuck.Core.Notification;
|
using TweetDuck.Core.Notification;
|
||||||
using TweetDuck.Core.Other;
|
using TweetDuck.Core.Other;
|
||||||
using TweetDuck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
|
using TweetDuck.Resources;
|
||||||
|
|
||||||
namespace TweetDuck.Core.Bridge{
|
namespace TweetDuck.Core.Bridge{
|
||||||
sealed class TweetDeckBridge{
|
sealed class TweetDeckBridge{
|
||||||
@@ -10,13 +14,28 @@ namespace TweetDuck.Core.Bridge{
|
|||||||
public static string LastRightClickedImage = string.Empty;
|
public static string LastRightClickedImage = string.Empty;
|
||||||
public static string LastHighlightedTweet = string.Empty;
|
public static string LastHighlightedTweet = string.Empty;
|
||||||
public static string LastHighlightedQuotedTweet = string.Empty;
|
public static string LastHighlightedQuotedTweet = string.Empty;
|
||||||
|
public static string LastHighlightedTweetAuthor = string.Empty;
|
||||||
public static string[] LastHighlightedTweetImages = StringUtils.EmptyArray;
|
public static string[] LastHighlightedTweetImages = StringUtils.EmptyArray;
|
||||||
|
public static Dictionary<string, string> SessionData = new Dictionary<string, string>(2);
|
||||||
|
|
||||||
public static void ResetStaticProperties(){
|
public static void ResetStaticProperties(){
|
||||||
LastRightClickedLink = LastRightClickedImage = LastHighlightedTweet = LastHighlightedQuotedTweet = string.Empty;
|
LastRightClickedLink = LastRightClickedImage = LastHighlightedTweet = LastHighlightedQuotedTweet = LastHighlightedTweetAuthor = string.Empty;
|
||||||
LastHighlightedTweetImages = StringUtils.EmptyArray;
|
LastHighlightedTweetImages = StringUtils.EmptyArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void RestoreSessionData(IFrame frame){
|
||||||
|
if (SessionData.Count > 0){
|
||||||
|
StringBuilder build = new StringBuilder().Append("window.TD_SESSION={");
|
||||||
|
|
||||||
|
foreach(KeyValuePair<string, string> kvp in SessionData){
|
||||||
|
build.Append(kvp.Key).Append(":'").Append(kvp.Value.Replace("'", "\\'")).Append("',");
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptLoader.ExecuteScript(frame, build.Append("}").ToString(), "gen:session");
|
||||||
|
SessionData.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly FormBrowser form;
|
private readonly FormBrowser form;
|
||||||
private readonly FormNotificationMain notification;
|
private readonly FormNotificationMain notification;
|
||||||
|
|
||||||
@@ -45,10 +64,11 @@ namespace TweetDuck.Core.Bridge{
|
|||||||
form.InvokeAsyncSafe(() => LastRightClickedImage = link);
|
form.InvokeAsyncSafe(() => LastRightClickedImage = link);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetLastHighlightedTweet(string link, string quotedLink, string imageList){
|
public void SetLastHighlightedTweet(string link, string quotedLink, string author, string imageList){
|
||||||
form.InvokeAsyncSafe(() => {
|
form.InvokeAsyncSafe(() => {
|
||||||
LastHighlightedTweet = link;
|
LastHighlightedTweet = link;
|
||||||
LastHighlightedQuotedTweet = quotedLink;
|
LastHighlightedQuotedTweet = quotedLink;
|
||||||
|
LastHighlightedTweetAuthor = author;
|
||||||
LastHighlightedTweetImages = imageList.Split(';');
|
LastHighlightedTweetImages = imageList.Split(';');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -80,6 +100,12 @@ namespace TweetDuck.Core.Bridge{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetSessionData(string key, string value){
|
||||||
|
form.InvokeSafe(() => { // do not use InvokeAsyncSafe, return only after invocation
|
||||||
|
SessionData.Add(key, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void LoadNextNotification(){
|
public void LoadNextNotification(){
|
||||||
notification.InvokeAsyncSafe(notification.FinishCurrentNotification);
|
notification.InvokeAsyncSafe(notification.FinishCurrentNotification);
|
||||||
}
|
}
|
||||||
|
@@ -204,6 +204,7 @@ namespace TweetDuck.Core{
|
|||||||
e.Frame.ExecuteJavaScriptAsync(TwitterUtils.BackgroundColorFix);
|
e.Frame.ExecuteJavaScriptAsync(TwitterUtils.BackgroundColorFix);
|
||||||
|
|
||||||
UpdateProperties(PropertyBridge.Environment.Browser);
|
UpdateProperties(PropertyBridge.Environment.Browser);
|
||||||
|
TweetDeckBridge.RestoreSessionData(e.Frame);
|
||||||
ScriptLoader.ExecuteFile(e.Frame, "code.js");
|
ScriptLoader.ExecuteFile(e.Frame, "code.js");
|
||||||
ReinjectCustomCSS(Config.CustomBrowserCSS);
|
ReinjectCustomCSS(Config.CustomBrowserCSS);
|
||||||
|
|
||||||
@@ -215,8 +216,8 @@ namespace TweetDuck.Core{
|
|||||||
|
|
||||||
TweetDeckBridge.ResetStaticProperties();
|
TweetDeckBridge.ResetStaticProperties();
|
||||||
|
|
||||||
if (Config.EnableBrowserGCReload){
|
if (Program.SystemConfig.EnableBrowserGCReload){
|
||||||
memoryUsageTracker.Start(this, e.Browser, Config.BrowserMemoryThreshold);
|
memoryUsageTracker.Start(this, e.Browser, Program.SystemConfig.BrowserMemoryThreshold);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -327,7 +328,7 @@ namespace TweetDuck.Core{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void plugins_Reloaded(object sender, PluginErrorEventArgs e){
|
private void plugins_Reloaded(object sender, PluginErrorEventArgs e){
|
||||||
browser.GetBrowser().Reload();
|
ReloadToTweetDeck();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void plugins_PluginChangedState(object sender, PluginChangedStateEventArgs e){
|
private void plugins_PluginChangedState(object sender, PluginChangedStateEventArgs e){
|
||||||
@@ -428,7 +429,7 @@ namespace TweetDuck.Core{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void ReloadToTweetDeck(){
|
public void ReloadToTweetDeck(){
|
||||||
browser.ExecuteScriptAsync($"gc&&gc();window.location.href='{TwitterUtils.TweetDeckURL}'");
|
browser.ExecuteScriptAsync($"if(window.TDGF_reload)window.TDGF_reload();else window.location.href='{TwitterUtils.TweetDeckURL}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
// callback handlers
|
// callback handlers
|
||||||
@@ -457,8 +458,8 @@ namespace TweetDuck.Core{
|
|||||||
trayIcon.HasNotifications = false;
|
trayIcon.HasNotifications = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.EnableBrowserGCReload){
|
if (Program.SystemConfig.EnableBrowserGCReload){
|
||||||
memoryUsageTracker.Start(this, browser.GetBrowser(), Config.BrowserMemoryThreshold);
|
memoryUsageTracker.Start(this, browser.GetBrowser(), Program.SystemConfig.BrowserMemoryThreshold);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
memoryUsageTracker.Stop();
|
memoryUsageTracker.Stop();
|
||||||
|
@@ -32,6 +32,7 @@ namespace TweetDuck.Core.Handling{
|
|||||||
|
|
||||||
private readonly Form form;
|
private readonly Form form;
|
||||||
|
|
||||||
|
private string lastHighlightedTweetAuthor;
|
||||||
private string[] lastHighlightedTweetImageList;
|
private string[] lastHighlightedTweetImageList;
|
||||||
|
|
||||||
protected ContextMenuBase(Form form){
|
protected ContextMenuBase(Form form){
|
||||||
@@ -40,9 +41,11 @@ namespace TweetDuck.Core.Handling{
|
|||||||
|
|
||||||
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
||||||
bool hasTweetImage = !string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedImage);
|
bool hasTweetImage = !string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedImage);
|
||||||
|
lastHighlightedTweetAuthor = TweetDeckBridge.LastHighlightedTweetAuthor;
|
||||||
lastHighlightedTweetImageList = TweetDeckBridge.LastHighlightedTweetImages;
|
lastHighlightedTweetImageList = TweetDeckBridge.LastHighlightedTweetImages;
|
||||||
|
|
||||||
if (!TwitterUtils.IsTweetDeckWebsite(frame) || browser.IsLoading){
|
if (!TwitterUtils.IsTweetDeckWebsite(frame) || browser.IsLoading){
|
||||||
|
lastHighlightedTweetAuthor = string.Empty;
|
||||||
lastHighlightedTweetImageList = StringUtils.EmptyArray;
|
lastHighlightedTweetImageList = StringUtils.EmptyArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,11 +91,11 @@ namespace TweetDuck.Core.Handling{
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuSaveImage:
|
case MenuSaveImage:
|
||||||
TwitterUtils.DownloadImage(GetImage(parameters), ImageQuality);
|
TwitterUtils.DownloadImage(GetImage(parameters), lastHighlightedTweetAuthor, ImageQuality);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuSaveAllImages:
|
case MenuSaveAllImages:
|
||||||
TwitterUtils.DownloadImages(lastHighlightedTweetImageList, ImageQuality);
|
TwitterUtils.DownloadImages(lastHighlightedTweetImageList, lastHighlightedTweetAuthor, ImageQuality);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuCopyImageUrl:
|
case MenuCopyImageUrl:
|
||||||
|
22
Core/Other/Settings/TabSettingsAdvanced.Designer.cs
generated
22
Core/Other/Settings/TabSettingsAdvanced.Designer.cs
generated
@@ -68,7 +68,7 @@
|
|||||||
this.checkHardwareAcceleration.Size = new System.Drawing.Size(134, 17);
|
this.checkHardwareAcceleration.Size = new System.Drawing.Size(134, 17);
|
||||||
this.checkHardwareAcceleration.TabIndex = 0;
|
this.checkHardwareAcceleration.TabIndex = 0;
|
||||||
this.checkHardwareAcceleration.Text = "Hardware Acceleration";
|
this.checkHardwareAcceleration.Text = "Hardware Acceleration";
|
||||||
this.toolTip.SetToolTip(this.checkHardwareAcceleration, "Uses your graphics card to improve performance.\r\nDisable if you experience issues with rendering.");
|
this.toolTip.SetToolTip(this.checkHardwareAcceleration, "Uses graphics card to improve performance. Disable if you experience\r\nvisual glitches. This option will not be exported in a profile.");
|
||||||
this.checkHardwareAcceleration.UseVisualStyleBackColor = true;
|
this.checkHardwareAcceleration.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// btnEditCefArgs
|
// btnEditCefArgs
|
||||||
@@ -142,26 +142,14 @@
|
|||||||
0,
|
0,
|
||||||
0});
|
0});
|
||||||
this.numMemoryThreshold.Location = new System.Drawing.Point(202, 82);
|
this.numMemoryThreshold.Location = new System.Drawing.Point(202, 82);
|
||||||
this.numMemoryThreshold.Maximum = new decimal(new int[] {
|
this.numMemoryThreshold.Maximum = 2000;
|
||||||
3000,
|
this.numMemoryThreshold.Minimum = 200;
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0});
|
|
||||||
this.numMemoryThreshold.Minimum = new decimal(new int[] {
|
|
||||||
200,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0});
|
|
||||||
this.numMemoryThreshold.Name = "numMemoryThreshold";
|
this.numMemoryThreshold.Name = "numMemoryThreshold";
|
||||||
this.numMemoryThreshold.Size = new System.Drawing.Size(97, 20);
|
this.numMemoryThreshold.Size = new System.Drawing.Size(97, 20);
|
||||||
this.numMemoryThreshold.TabIndex = 4;
|
this.numMemoryThreshold.TabIndex = 4;
|
||||||
this.numMemoryThreshold.TextSuffix = " MB";
|
this.numMemoryThreshold.TextSuffix = " MB";
|
||||||
this.toolTip.SetToolTip(this.numMemoryThreshold, "Minimum amount of memory usage by the browser process to trigger the cleanup.\r\nThis is not a limit, the usage is allowed to exceed this value.");
|
this.toolTip.SetToolTip(this.numMemoryThreshold, "Minimum amount of memory usage by the browser process to trigger the cleanup.\r\nThis is not a limit, the usage is allowed to exceed this value.");
|
||||||
this.numMemoryThreshold.Value = new decimal(new int[] {
|
this.numMemoryThreshold.Value = 400;
|
||||||
350,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0});
|
|
||||||
//
|
//
|
||||||
// checkBrowserGCReload
|
// checkBrowserGCReload
|
||||||
//
|
//
|
||||||
@@ -172,7 +160,7 @@
|
|||||||
this.checkBrowserGCReload.Size = new System.Drawing.Size(190, 17);
|
this.checkBrowserGCReload.Size = new System.Drawing.Size(190, 17);
|
||||||
this.checkBrowserGCReload.TabIndex = 3;
|
this.checkBrowserGCReload.TabIndex = 3;
|
||||||
this.checkBrowserGCReload.Text = "Enable Browser Memory Threshold";
|
this.checkBrowserGCReload.Text = "Enable Browser Memory Threshold";
|
||||||
this.toolTip.SetToolTip(this.checkBrowserGCReload, "Automatically reloads TweetDeck to save memory. This option only works\r\nif the browser is in a \'default state\', i.e. all modals and drawers are closed,\r\nand all columns are scrolled to top. Some notifications may be lost.");
|
this.toolTip.SetToolTip(this.checkBrowserGCReload, "Automatically reloads TweetDeck to save memory. This option only works if\r\nthe browser is in a \'default state\', i.e. all modals and drawers are closed, and\r\nall columns are scrolled to top. This option will not be exported in a profile.");
|
||||||
this.checkBrowserGCReload.UseVisualStyleBackColor = true;
|
this.checkBrowserGCReload.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// labelApp
|
// labelApp
|
||||||
|
@@ -8,6 +8,8 @@ using TweetDuck.Core.Utils;
|
|||||||
|
|
||||||
namespace TweetDuck.Core.Other.Settings{
|
namespace TweetDuck.Core.Other.Settings{
|
||||||
partial class TabSettingsAdvanced : BaseTabSettings{
|
partial class TabSettingsAdvanced : BaseTabSettings{
|
||||||
|
private static SystemConfig SysConfig => Program.SystemConfig;
|
||||||
|
|
||||||
private readonly Action<string> reinjectBrowserCSS;
|
private readonly Action<string> reinjectBrowserCSS;
|
||||||
|
|
||||||
public TabSettingsAdvanced(Action<string> reinjectBrowserCSS){
|
public TabSettingsAdvanced(Action<string> reinjectBrowserCSS){
|
||||||
@@ -16,16 +18,16 @@ namespace TweetDuck.Core.Other.Settings{
|
|||||||
this.reinjectBrowserCSS = reinjectBrowserCSS;
|
this.reinjectBrowserCSS = reinjectBrowserCSS;
|
||||||
|
|
||||||
if (SystemConfig.IsHardwareAccelerationSupported){
|
if (SystemConfig.IsHardwareAccelerationSupported){
|
||||||
checkHardwareAcceleration.Checked = Program.SystemConfig.HardwareAcceleration;
|
checkHardwareAcceleration.Checked = SysConfig.HardwareAcceleration;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
checkHardwareAcceleration.Enabled = false;
|
checkHardwareAcceleration.Enabled = false;
|
||||||
checkHardwareAcceleration.Checked = false;
|
checkHardwareAcceleration.Checked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkBrowserGCReload.Checked = Config.EnableBrowserGCReload;
|
checkBrowserGCReload.Checked = SysConfig.EnableBrowserGCReload;
|
||||||
numMemoryThreshold.Enabled = checkBrowserGCReload.Checked;
|
numMemoryThreshold.Enabled = checkBrowserGCReload.Checked;
|
||||||
numMemoryThreshold.SetValueSafe(Config.BrowserMemoryThreshold);
|
numMemoryThreshold.SetValueSafe(SysConfig.BrowserMemoryThreshold);
|
||||||
|
|
||||||
BrowserCache.CalculateCacheSize(bytes => this.InvokeSafe(() => {
|
BrowserCache.CalculateCacheSize(bytes => this.InvokeSafe(() => {
|
||||||
if (bytes == -1L){
|
if (bytes == -1L){
|
||||||
@@ -53,6 +55,10 @@ namespace TweetDuck.Core.Other.Settings{
|
|||||||
btnRestartArgs.Click += btnRestartArgs_Click;
|
btnRestartArgs.Click += btnRestartArgs_Click;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnClosing(){
|
||||||
|
SysConfig.Save();
|
||||||
|
}
|
||||||
|
|
||||||
private void btnClearCache_Click(object sender, EventArgs e){
|
private void btnClearCache_Click(object sender, EventArgs e){
|
||||||
btnClearCache.Enabled = false;
|
btnClearCache.Enabled = false;
|
||||||
BrowserCache.SetClearOnExit();
|
BrowserCache.SetClearOnExit();
|
||||||
@@ -60,18 +66,17 @@ namespace TweetDuck.Core.Other.Settings{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkHardwareAcceleration_CheckedChanged(object sender, EventArgs e){
|
private void checkHardwareAcceleration_CheckedChanged(object sender, EventArgs e){
|
||||||
Program.SystemConfig.HardwareAcceleration = checkHardwareAcceleration.Checked;
|
SysConfig.HardwareAcceleration = checkHardwareAcceleration.Checked;
|
||||||
Program.SystemConfig.Save();
|
PromptRestart(); // calls OnClosing
|
||||||
PromptRestart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBrowserGCReload_CheckedChanged(object sender, EventArgs e){
|
private void checkBrowserGCReload_CheckedChanged(object sender, EventArgs e){
|
||||||
Config.EnableBrowserGCReload = checkBrowserGCReload.Checked;
|
SysConfig.EnableBrowserGCReload = checkBrowserGCReload.Checked;
|
||||||
numMemoryThreshold.Enabled = checkBrowserGCReload.Checked;
|
numMemoryThreshold.Enabled = checkBrowserGCReload.Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void numMemoryThreshold_ValueChanged(object sender, EventArgs e){
|
private void numMemoryThreshold_ValueChanged(object sender, EventArgs e){
|
||||||
Config.BrowserMemoryThreshold = (int)numMemoryThreshold.Value;
|
SysConfig.BrowserMemoryThreshold = (int)numMemoryThreshold.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnEditCefArgs_Click(object sender, EventArgs e){
|
private void btnEditCefArgs_Click(object sender, EventArgs e){
|
||||||
|
@@ -34,7 +34,7 @@ namespace TweetDuck.Core.Other.Settings{
|
|||||||
|
|
||||||
private void tbCustomSound_TextChanged(object sender, EventArgs e){
|
private void tbCustomSound_TextChanged(object sender, EventArgs e){
|
||||||
bool isEmpty = string.IsNullOrEmpty(tbCustomSound.Text);
|
bool isEmpty = string.IsNullOrEmpty(tbCustomSound.Text);
|
||||||
tbCustomSound.ForeColor = isEmpty || File.Exists(tbCustomSound.Text) ? SystemColors.WindowText : Color.Maroon;
|
tbCustomSound.ForeColor = isEmpty || File.Exists(tbCustomSound.Text) ? SystemColors.WindowText : Color.Red;
|
||||||
btnPlaySound.Enabled = !isEmpty;
|
btnPlaySound.Enabled = !isEmpty;
|
||||||
btnResetSound.Enabled = !isEmpty;
|
btnResetSound.Enabled = !isEmpty;
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
using CefSharp;
|
using CefSharp;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDuck.Core.Other;
|
using TweetDuck.Core.Other;
|
||||||
@@ -52,23 +53,32 @@ namespace TweetDuck.Core.Utils{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DownloadImage(string url, ImageQuality quality){
|
public static void DownloadImage(string url, string username, ImageQuality quality){
|
||||||
DownloadImages(new string[]{ url }, quality);
|
DownloadImages(new string[]{ url }, username, quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DownloadImages(string[] urls, ImageQuality quality){
|
public static void DownloadImages(string[] urls, string username, ImageQuality quality){
|
||||||
if (urls.Length == 0){
|
if (urls.Length == 0){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string file = BrowserUtils.GetFileNameFromUrl(ExtractImageBaseLink(urls[0]));
|
string firstImageLink = GetImageLink(urls[0], quality);
|
||||||
|
int qualityIndex = firstImageLink.LastIndexOf(':');
|
||||||
|
|
||||||
|
string file = BrowserUtils.GetFileNameFromUrl(ExtractImageBaseLink(firstImageLink));
|
||||||
string ext = Path.GetExtension(file); // includes dot
|
string ext = Path.GetExtension(file); // includes dot
|
||||||
|
|
||||||
|
string[] fileNameParts = {
|
||||||
|
username,
|
||||||
|
Path.ChangeExtension(file, null),
|
||||||
|
qualityIndex == -1 ? string.Empty : firstImageLink.Substring(qualityIndex+1)
|
||||||
|
};
|
||||||
|
|
||||||
using(SaveFileDialog dialog = new SaveFileDialog{
|
using(SaveFileDialog dialog = new SaveFileDialog{
|
||||||
AutoUpgradeEnabled = true,
|
AutoUpgradeEnabled = true,
|
||||||
OverwritePrompt = urls.Length == 1,
|
OverwritePrompt = urls.Length == 1,
|
||||||
Title = "Save image",
|
Title = "Save image",
|
||||||
FileName = file,
|
FileName = $"{string.Join(" ", fileNameParts.Where(part => part.Length > 0))}{ext}",
|
||||||
Filter = (urls.Length == 1 ? "Image" : "Images")+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
|
Filter = (urls.Length == 1 ? "Image" : "Images")+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
|
||||||
}){
|
}){
|
||||||
if (dialog.ShowDialog() == DialogResult.OK){
|
if (dialog.ShowDialog() == DialogResult.OK){
|
||||||
@@ -77,14 +87,14 @@ namespace TweetDuck.Core.Utils{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (urls.Length == 1){
|
if (urls.Length == 1){
|
||||||
BrowserUtils.DownloadFileAsync(GetImageLink(urls[0], quality), dialog.FileName, null, OnFailure);
|
BrowserUtils.DownloadFileAsync(firstImageLink, dialog.FileName, null, OnFailure);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
string pathBase = Path.ChangeExtension(dialog.FileName, null);
|
string pathBase = Path.ChangeExtension(dialog.FileName, null);
|
||||||
string pathExt = Path.GetExtension(dialog.FileName);
|
string pathExt = Path.GetExtension(dialog.FileName);
|
||||||
|
|
||||||
for(int index = 0; index < urls.Length; index++){
|
for(int index = 0; index < urls.Length; index++){
|
||||||
BrowserUtils.DownloadFileAsync(GetImageLink(urls[index], quality), pathBase+(index+1)+pathExt, null, OnFailure);
|
BrowserUtils.DownloadFileAsync(GetImageLink(urls[index], quality), $"{pathBase} {index+1}{pathExt}", null, OnFailure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,8 +12,8 @@ namespace TweetDuck.Data.Serialization{
|
|||||||
|
|
||||||
private static readonly ITypeConverter BasicSerializerObj = new BasicTypeConverter();
|
private static readonly ITypeConverter BasicSerializerObj = new BasicTypeConverter();
|
||||||
|
|
||||||
public delegate bool OnReadUnknownPropertyHandler(T obj, string property, string value);
|
public delegate void HandleUnknownPropertiesHandler(T obj, Dictionary<string, string> data);
|
||||||
public OnReadUnknownPropertyHandler OnReadUnknownProperty { get; set; }
|
public HandleUnknownPropertiesHandler HandleUnknownProperties { get; set; }
|
||||||
|
|
||||||
private readonly Dictionary<string, PropertyInfo> props;
|
private readonly Dictionary<string, PropertyInfo> props;
|
||||||
private readonly Dictionary<Type, ITypeConverter> converters;
|
private readonly Dictionary<Type, ITypeConverter> converters;
|
||||||
@@ -51,6 +51,8 @@ namespace TweetDuck.Data.Serialization{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Read(string file, T obj){
|
public void Read(string file, T obj){
|
||||||
|
Dictionary<string, string> unknownProperties = new Dictionary<string, string>(4);
|
||||||
|
|
||||||
using(StreamReader reader = new StreamReader(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))){
|
using(StreamReader reader = new StreamReader(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))){
|
||||||
if (reader.Peek() <= 1){
|
if (reader.Peek() <= 1){
|
||||||
throw new FormatException("Input appears to be a binary file.");
|
throw new FormatException("Input appears to be a binary file.");
|
||||||
@@ -78,11 +80,19 @@ namespace TweetDuck.Data.Serialization{
|
|||||||
throw new SerializationException($"Invalid file format, cannot convert value: {value} (property: {property})");
|
throw new SerializationException($"Invalid file format, cannot convert value: {value} (property: {property})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!(OnReadUnknownProperty?.Invoke(obj, property, value) ?? false)){
|
else{
|
||||||
throw new SerializationException($"Invalid file format, unknown property: {property}+");
|
unknownProperties[property] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unknownProperties.Count > 0){
|
||||||
|
HandleUnknownProperties?.Invoke(obj, unknownProperties);
|
||||||
|
|
||||||
|
if (unknownProperties.Count > 0){
|
||||||
|
throw new SerializationException($"Invalid file format, unknown properties: {string.Join(", ", unknownProperties.Keys)}+");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BasicTypeConverter : ITypeConverter{
|
private class BasicTypeConverter : ITypeConverter{
|
||||||
|
@@ -22,8 +22,8 @@ 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.8.4";
|
public const string VersionTag = "1.8.4.1";
|
||||||
public const string VersionFull = "1.8.4";
|
public const string VersionFull = "1.8.4.1";
|
||||||
|
|
||||||
public static readonly Version Version = new Version(VersionTag);
|
public static readonly Version Version = new Version(VersionTag);
|
||||||
public static readonly bool IsPortable = File.Exists("makeportable");
|
public static readonly bool IsPortable = File.Exists("makeportable");
|
||||||
@@ -115,8 +115,8 @@ namespace TweetDuck{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReloadConfig();
|
|
||||||
SystemConfig = SystemConfig.Load(SystemConfigFilePath);
|
SystemConfig = SystemConfig.Load(SystemConfigFilePath);
|
||||||
|
ReloadConfig();
|
||||||
|
|
||||||
if (Arguments.HasFlag(Arguments.ArgImportCookies)){
|
if (Arguments.HasFlag(Arguments.ArgImportCookies)){
|
||||||
ExportManager.ImportCookies();
|
ExportManager.ImportCookies();
|
||||||
|
@@ -459,7 +459,8 @@ enabled(){
|
|||||||
.icon-list-filled:before{content:"\\f014";font-family:tweetdeckold}
|
.icon-list-filled:before{content:"\\f014";font-family:tweetdeckold}
|
||||||
.icon-user-filled:before{content:"\\f035";font-family:tweetdeckold}
|
.icon-user-filled:before{content:"\\f035";font-family:tweetdeckold}
|
||||||
|
|
||||||
.column-type-icon { bottom: 26px !important }
|
.drawer .btn .icon, .app-header .btn .icon { line-height: 1em !important }
|
||||||
|
.column-header .column-type-icon { bottom: 26px !important }
|
||||||
.is-options-open .column-type-icon { bottom: 25px !important }
|
.is-options-open .column-type-icon { bottom: 25px !important }
|
||||||
.tweet-footer { margin-top: 6px !important }`;
|
.tweet-footer { margin-top: 6px !important }`;
|
||||||
|
|
||||||
|
@@ -108,7 +108,7 @@
|
|||||||
recentTweetTimer = window.setTimeout(() => {
|
recentTweetTimer = window.setTimeout(() => {
|
||||||
recentTweetTimer = null;
|
recentTweetTimer = null;
|
||||||
recentTweets.clear();
|
recentTweets.clear();
|
||||||
}, 10000);
|
}, 20000);
|
||||||
};
|
};
|
||||||
|
|
||||||
let checkRecentTweet = id => {
|
let checkRecentTweet = id => {
|
||||||
@@ -391,12 +391,12 @@
|
|||||||
return !!highlightedColumnObj;
|
return !!highlightedColumnObj;
|
||||||
};
|
};
|
||||||
|
|
||||||
var updateHighlightedTweet = function(ele, obj, link, embeddedLink, imageList){
|
var updateHighlightedTweet = function(ele, obj, link, embeddedLink, author, imageList){
|
||||||
highlightedTweetEle = ele;
|
highlightedTweetEle = ele;
|
||||||
highlightedTweetObj = obj;
|
highlightedTweetObj = obj;
|
||||||
|
|
||||||
if (lastTweet !== link){
|
if (lastTweet !== link){
|
||||||
$TD.setLastHighlightedTweet(link, embeddedLink, imageList);
|
$TD.setLastHighlightedTweet(link, embeddedLink, author, imageList);
|
||||||
lastTweet = link;
|
lastTweet = link;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -426,18 +426,19 @@
|
|||||||
if (tweet.chirpType === TD.services.ChirpBase.TWEET){
|
if (tweet.chirpType === TD.services.ChirpBase.TWEET){
|
||||||
let link = tweet.getChirpURL();
|
let link = tweet.getChirpURL();
|
||||||
let embedded = tweet.quotedTweet ? tweet.quotedTweet.getChirpURL() : "";
|
let embedded = tweet.quotedTweet ? tweet.quotedTweet.getChirpURL() : "";
|
||||||
|
let username = tweet.getMainUser().screenName;
|
||||||
let images = tweet.hasImage() ? tweet.getMedia().filter(item => !item.isAnimatedGif).map(item => item.entity.media_url_https+":small").join(";") : "";
|
let images = tweet.hasImage() ? tweet.getMedia().filter(item => !item.isAnimatedGif).map(item => item.entity.media_url_https+":small").join(";") : "";
|
||||||
// TODO maybe handle embedded images too?
|
// TODO maybe handle embedded images too?
|
||||||
|
|
||||||
updateHighlightedTweet(me, tweet, link || "", embedded || "", images);
|
updateHighlightedTweet(me, tweet, link || "", embedded || "", username, images);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
updateHighlightedTweet(me, tweet, "", "", "");
|
updateHighlightedTweet(me, tweet, "", "", "", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (e.type === "mouseleave"){
|
else if (e.type === "mouseleave"){
|
||||||
updateHighlightedTweet(null, null, "", "", "");
|
updateHighlightedTweet(null, null, "", "", "", "");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
@@ -521,7 +522,12 @@
|
|||||||
app.delegate(".js-compose-text,.js-reply-tweetbox", "paste", function(e){
|
app.delegate(".js-compose-text,.js-reply-tweetbox", "paste", function(e){
|
||||||
for(let item of e.originalEvent.clipboardData.items){
|
for(let item of e.originalEvent.clipboardData.items){
|
||||||
if (item.type.startsWith("image/")){
|
if (item.type.startsWith("image/")){
|
||||||
$(this).closest(".rpl").find(".js-reply-popout").click(); // popout direct messages
|
if (!$(this).closest(".rpl").find(".js-reply-popout").click().length){ // popout direct messages
|
||||||
|
if ($(".js-add-image-button").is(".is-disabled")){ // tweetdeck does not check upload count properly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uploader.addFilesToUpload([ item.getAsFile() ]);
|
uploader.addFilesToUpload([ item.getAsFile() ]);
|
||||||
|
|
||||||
$(".js-compose-text", ".js-docked-compose").focus();
|
$(".js-compose-text", ".js-docked-compose").focus();
|
||||||
@@ -705,10 +711,13 @@
|
|||||||
addRule(".column-nav-link .attribution { position: absolute; }"); // fix cut off account names
|
addRule(".column-nav-link .attribution { position: absolute; }"); // fix cut off account names
|
||||||
addRule(".txt-base-smallest .sprite-verified-mini { width: 13px !important; height: 13px !important; background-position: -223px -99px !important; }"); // fix cut off badge icon when zoomed in
|
addRule(".txt-base-smallest .sprite-verified-mini { width: 13px !important; height: 13px !important; background-position: -223px -99px !important; }"); // fix cut off badge icon when zoomed in
|
||||||
|
|
||||||
addRule(".btn, .mdl, .mdl-content, .app-search-fake, .app-search-input, .popover, .lst-modal, .media-item { border-radius: 1px !important; }"); // square-ify buttons, inputs, dialogs, menus, and media previews
|
addRule(".btn, .mdl, .mdl-content, .app-search-fake, .app-search-input, .popover, .lst-modal, .media-item { border-radius: 1px !important; }"); // square-ify buttons, inputs, dialogs, menus, media previews
|
||||||
addRule(".dropdown-menu, .list-item-last { border-radius: 0 !important; }"); // square-ify dropdowns
|
addRule(".dropdown-menu, .list-item-last, .quoted-tweet { border-radius: 0 !important; }"); // square-ify dropdowns, quoted tweets, and account selectors
|
||||||
addRule(".prf-header { border-radius: 0; }"); // fix user account header border
|
addRule(".prf-header { border-radius: 0; }"); // fix user account header border
|
||||||
|
|
||||||
|
addRule(".accs li, .accs img { border-radius: 0 !important; }"); // square-ify retweet account selector
|
||||||
|
addRule(".accs-header { padding-left: 0 !important; }"); // fix retweet account selector heading
|
||||||
|
|
||||||
addRule(".scroll-styled-v::-webkit-scrollbar-thumb, .scroll-styled-h::-webkit-scrollbar-thumb, .antiscroll-scrollbar { border-radius: 0; }"); // square-ify scroll bars
|
addRule(".scroll-styled-v::-webkit-scrollbar-thumb, .scroll-styled-h::-webkit-scrollbar-thumb, .antiscroll-scrollbar { border-radius: 0; }"); // square-ify scroll bars
|
||||||
addRule(".antiscroll-scrollbar-vertical { margin-top: 0; }"); // square-ify scroll bars
|
addRule(".antiscroll-scrollbar-vertical { margin-top: 0; }"); // square-ify scroll bars
|
||||||
addRule(".antiscroll-scrollbar-horizontal { margin-left: 0; }"); // square-ify scroll bars
|
addRule(".antiscroll-scrollbar-horizontal { margin-left: 0; }"); // square-ify scroll bars
|
||||||
@@ -733,6 +742,9 @@
|
|||||||
addRule(".activity-header { align-items: center !important; margin-bottom: 4px; }"); // tweak alignment of avatar and text in notifications
|
addRule(".activity-header { align-items: center !important; margin-bottom: 4px; }"); // tweak alignment of avatar and text in notifications
|
||||||
addRule(".activity-header .tweet-timestamp { line-height: unset; }"); // fix timestamp position in notifications
|
addRule(".activity-header .tweet-timestamp { line-height: unset; }"); // fix timestamp position in notifications
|
||||||
|
|
||||||
|
addRule("html[data-td-theme='light'] .stream-item:not(:hover) .js-user-actions-menu { color: #000; border-color: #000; opacity: 0.25; }"); // make follow notification button nicer
|
||||||
|
addRule("html[data-td-theme='dark'] .stream-item:not(:hover) .js-user-actions-menu { color: #fff; border-color: #fff; opacity: 0.25; }"); // make follow notification button nicer
|
||||||
|
|
||||||
addRule(".app-columns-container::-webkit-scrollbar-track { border-left: 0; }"); // remove weird border in the column container scrollbar
|
addRule(".app-columns-container::-webkit-scrollbar-track { border-left: 0; }"); // remove weird border in the column container scrollbar
|
||||||
addRule(".app-columns-container { bottom: 0 !important; }"); // move column container scrollbar to bottom to fit updated style
|
addRule(".app-columns-container { bottom: 0 !important; }"); // move column container scrollbar to bottom to fit updated style
|
||||||
|
|
||||||
@@ -848,8 +860,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Block: Memory cleanup check and execution.
|
// Block: Custom reload function with memory cleanup.
|
||||||
//
|
//
|
||||||
|
window.TDGF_reload = function(){
|
||||||
|
let session = TD.storage.feedController.getAll()
|
||||||
|
.filter(feed => !!feed.getTopSortIndex())
|
||||||
|
.reduce((obj, feed) => (obj[feed.privateState.key] = feed.getTopSortIndex(), obj), {});
|
||||||
|
|
||||||
|
$TD.setSessionData("gc", JSON.stringify(session)).then(() => {
|
||||||
|
window.gc && window.gc();
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
window.TDGF_tryRunCleanup = function(){
|
window.TDGF_tryRunCleanup = function(){
|
||||||
// all textareas are empty
|
// all textareas are empty
|
||||||
if ($("textarea").is(function(){
|
if ($("textarea").is(function(){
|
||||||
@@ -876,11 +899,62 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
window.gc && window.gc();
|
window.TDGF_reload();
|
||||||
window.location.reload();
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (window.TD_SESSION && window.TD_SESSION.gc){
|
||||||
|
var state;
|
||||||
|
|
||||||
|
try{
|
||||||
|
state = JSON.parse(window.TD_SESSION.gc);
|
||||||
|
}catch(err){
|
||||||
|
$TD.crashDebug("Invalid session gc data: "+window.TD_SESSION.gc);
|
||||||
|
state = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var showMissedNotifications = function(){
|
||||||
|
let tweets = [];
|
||||||
|
let columns = {};
|
||||||
|
|
||||||
|
let tmp = new TD.services.ChirpBase;
|
||||||
|
|
||||||
|
for(let column of Object.values(TD.controller.columnManager.getAll())){
|
||||||
|
for(let feed of column.getFeeds()){
|
||||||
|
if (feed.privateState.key in state){
|
||||||
|
tmp.sortIndex = state[feed.privateState.key];
|
||||||
|
|
||||||
|
for(let tweet of [].concat.apply([], column.updateArray.map(function(chirp){
|
||||||
|
return chirp.getUnreadChirps(tmp);
|
||||||
|
}))){
|
||||||
|
tweets.push(tweet);
|
||||||
|
columns[tweet.id] = column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tweets.sort(TD.util.chirpReverseColumnSort);
|
||||||
|
|
||||||
|
for(let tweet of tweets){
|
||||||
|
onNewTweet(columns[tweet.id], tweet);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).one("dataColumnsLoaded", function(){
|
||||||
|
let columns = Object.values(TD.controller.columnManager.getAll());
|
||||||
|
let remaining = columns.length;
|
||||||
|
|
||||||
|
for(let column of columns){
|
||||||
|
column.ui.getChirpContainer().one("dataColumnFeedUpdated", () => {
|
||||||
|
if (--remaining === 0){
|
||||||
|
setTimeout(showMissedNotifications, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Block: Disable TweetDeck metrics.
|
// Block: Disable TweetDeck metrics.
|
||||||
//
|
//
|
||||||
@@ -905,6 +979,8 @@
|
|||||||
onAppReady.forEach(func => func());
|
onAppReady.forEach(func => func());
|
||||||
onAppReady = null;
|
onAppReady = null;
|
||||||
|
|
||||||
|
delete window.TD_SESSION;
|
||||||
|
|
||||||
if (window.TD_PLUGINS){
|
if (window.TD_PLUGINS){
|
||||||
window.TD_PLUGINS.onReady();
|
window.TD_PLUGINS.onReady();
|
||||||
}
|
}
|
||||||
|
@@ -98,7 +98,7 @@
|
|||||||
//
|
//
|
||||||
window.TDPF_requestReload = function(){
|
window.TDPF_requestReload = function(){
|
||||||
if (!isReloading){
|
if (!isReloading){
|
||||||
window.setTimeout(() => location.reload(), 1);
|
window.setTimeout(window.TDGF_reload, 1);
|
||||||
isReloading = true;
|
isReloading = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -131,11 +131,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#tweetduck-changelog p {
|
#tweetduck-changelog p {
|
||||||
margin: 0 0 2px 30px;
|
margin: 8px 8px 0 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-changelog p.li {
|
||||||
|
margin: 0 8px 2px 30px;
|
||||||
display: list-item;
|
display: list-item;
|
||||||
}
|
}
|
||||||
|
|
||||||
#tweetduck-changelog p.l2 {
|
#tweetduck-changelog .l2 {
|
||||||
margin-left: 50px;
|
margin-left: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,13 +272,15 @@
|
|||||||
return md.replace(/&/g, "&")
|
return md.replace(/&/g, "&")
|
||||||
.replace(/</g, "<")
|
.replace(/</g, "<")
|
||||||
.replace(/>/g, ">")
|
.replace(/>/g, ">")
|
||||||
|
.replace(/^##? (.*?)$/gm, "<h2>$1</h2>")
|
||||||
.replace(/^### (.*?)$/gm, "<h3>$1</h3>")
|
.replace(/^### (.*?)$/gm, "<h3>$1</h3>")
|
||||||
.replace(/^- (.*?)$/gm, "<p>$1</p>")
|
.replace(/^- (.*?)$/gm, "<p class='li'>$1</p>")
|
||||||
.replace(/^ - (.*?)$/gm, "<p class='l2'>$1</p>")
|
.replace(/^ - (.*?)$/gm, "<p class='li l2'>$1</p>")
|
||||||
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
|
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
|
||||||
.replace(/\*(.*?)\*/g, "<em>$1</em>")
|
.replace(/\*(.*?)\*/g, "<em>$1</em>")
|
||||||
.replace(/`(.*?)`/g, "<code>$1</code>")
|
.replace(/`(.*?)`/g, "<code>$1</code>")
|
||||||
.replace(/\[(.*?)\]\((.*?)\)/g, "<a href='$2'>$1</a>")
|
.replace(/\[(.*?)\]\((.*?)\)/g, "<a href='$2'>$1</a>")
|
||||||
|
.replace(/^([a-z0-9].*?)$/gmi, "<p>$1</p>")
|
||||||
.replace(/\n\r?\n/g, "<br>");
|
.replace(/\n\r?\n/g, "<br>");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user