Compare commits
95 Commits
Author | SHA1 | Date | |
---|---|---|---|
90414ae579 | |||
41c8caa2a4 | |||
15305ecabe | |||
50090effd4 | |||
6dffdcd1ed | |||
db9daf2714 | |||
502ac4ebc1 | |||
3f44f3bab4 | |||
746eba185b | |||
82dec92510 | |||
2edc93df47 | |||
c5a6738199 | |||
dfd578165b | |||
285d400f69 | |||
47a3444ace | |||
0ec227da52 | |||
f9cf582306 | |||
b0883229bf | |||
31b5d9a4c0 | |||
6841a78556 | |||
9d2089a8ce | |||
6d6bb79199 | |||
937c8e22c4 | |||
34c8d44dfe | |||
2dbf778e56 | |||
873fe2b393 | |||
0c53bc6f32 | |||
fa407e150b | |||
4e52102c5c | |||
0355a5c646 | |||
377d9c3554 | |||
20b1b3c895 | |||
41bbe7c51b | |||
27fa6aefd3 | |||
a63c3232da | |||
146908a115 | |||
48b0f35fee | |||
6c435ebe26 | |||
b8d0b721a2 | |||
a6d5957f46 | |||
9e5f676e23 | |||
414f3a1f9d | |||
fedf9c60ee | |||
b6385d9622 | |||
76d25a712d | |||
2c6d935273 | |||
830d98a101 | |||
d7378bd75a | |||
0f41cb9dbc | |||
77bc922d93 | |||
c91b635132 | |||
e5521de34a | |||
7c0f8d0f24 | |||
f60d5f650f | |||
ca67f2fe0a | |||
16cce8be1d | |||
770619d948 | |||
cfedb7d6b1 | |||
738557b3a2 | |||
38b01deec1 | |||
1a31e69ec9 | |||
e065983c95 | |||
30a169171a | |||
8d1900362e | |||
e154189de1 | |||
b0f147de24 | |||
979b3548db | |||
05d6c578b3 | |||
a117559063 | |||
f87c649b09 | |||
6504dc9184 | |||
25a8ddffd4 | |||
fa0f9b89cf | |||
4d00a67891 | |||
bd2c43e1f4 | |||
c7279eaa34 | |||
fd523e552c | |||
cb877b8b23 | |||
ed1bee8b89 | |||
a8e1492056 | |||
5587216c01 | |||
86569261ad | |||
4a9049c7aa | |||
75d60a8182 | |||
14d4dc2ed9 | |||
fd0e1740a5 | |||
70ca890bef | |||
b9318dfd8e | |||
995642a719 | |||
d14de4ac9e | |||
b7f325a241 | |||
27c55718c2 | |||
421ff0654b | |||
ed947458f9 | |||
9cdb20ba84 |
@@ -1,28 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using TweetDuck.Data.Serialization;
|
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>();
|
||||||
|
|
||||||
public static readonly bool IsHardwareAccelerationSupported = File.Exists(Path.Combine(Program.ProgramPath, "libEGL.dll")) &&
|
|
||||||
File.Exists(Path.Combine(Program.ProgramPath, "libGLESv2.dll"));
|
|
||||||
|
|
||||||
// CONFIGURATION DATA
|
// CONFIGURATION DATA
|
||||||
|
|
||||||
private bool _hardwareAcceleration = true;
|
public bool HardwareAcceleration { get; set; } = true;
|
||||||
|
|
||||||
public bool ClearCacheAutomatically { get; set; } = true;
|
public bool ClearCacheAutomatically { get; set; } = true;
|
||||||
public int ClearCacheThreshold { get; set; } = 250;
|
public int ClearCacheThreshold { get; set; } = 250;
|
||||||
|
|
||||||
// SPECIAL PROPERTIES
|
|
||||||
|
|
||||||
public bool HardwareAcceleration{
|
|
||||||
get => _hardwareAcceleration && IsHardwareAccelerationSupported;
|
|
||||||
set => _hardwareAcceleration = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// END OF CONFIG
|
// END OF CONFIG
|
||||||
|
|
||||||
private readonly string file;
|
private readonly string file;
|
||||||
|
@@ -51,6 +51,10 @@ namespace TweetDuck.Core.Bridge{
|
|||||||
form.InvokeAsyncSafe(form.OpenContextMenu);
|
form.InvokeAsyncSafe(form.OpenContextMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OpenProfileImport(){
|
||||||
|
form.InvokeAsyncSafe(form.OpenProfileImport);
|
||||||
|
}
|
||||||
|
|
||||||
public void OnIntroductionClosed(bool showGuide, bool allowDataCollection){
|
public void OnIntroductionClosed(bool showGuide, bool allowDataCollection){
|
||||||
form.InvokeAsyncSafe(() => {
|
form.InvokeAsyncSafe(() => {
|
||||||
form.OnIntroductionClosed(showGuide, allowDataCollection);
|
form.OnIntroductionClosed(showGuide, allowDataCollection);
|
||||||
@@ -64,6 +68,10 @@ namespace TweetDuck.Core.Bridge{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetRightClickedLink(string type, string url){
|
||||||
|
ContextInfo.SetLink(type, url);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetRightClickedChirp(string tweetUrl, string quoteUrl, string chirpAuthors, string chirpImages){
|
public void SetRightClickedChirp(string tweetUrl, string quoteUrl, string chirpAuthors, string chirpImages){
|
||||||
ContextInfo.SetChirp(tweetUrl, quoteUrl, chirpAuthors, chirpImages);
|
ContextInfo.SetChirp(tweetUrl, quoteUrl, chirpAuthors, chirpImages);
|
||||||
}
|
}
|
||||||
@@ -99,10 +107,6 @@ namespace TweetDuck.Core.Bridge{
|
|||||||
|
|
||||||
// Global
|
// Global
|
||||||
|
|
||||||
public void SetLastRightClickInfo(string type, string url){
|
|
||||||
ContextInfo.SetLink(type, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnTweetPopup(string columnId, string chirpId, string columnName, string tweetHtml, int tweetCharacters, string tweetUrl, string quoteUrl){
|
public void OnTweetPopup(string columnId, string chirpId, string columnName, string tweetHtml, int tweetCharacters, string tweetUrl, string quoteUrl){
|
||||||
notification.InvokeAsyncSafe(() => {
|
notification.InvokeAsyncSafe(() => {
|
||||||
form.OnTweetNotification();
|
form.OnTweetNotification();
|
||||||
|
68
Core/Bridge/UpdateBridge.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Updates;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Bridge{
|
||||||
|
class UpdateBridge{
|
||||||
|
private readonly UpdateHandler updates;
|
||||||
|
private readonly Control sync;
|
||||||
|
|
||||||
|
private UpdateInfo nextUpdate = null;
|
||||||
|
|
||||||
|
public event EventHandler<UpdateInfo> UpdateAccepted;
|
||||||
|
public event EventHandler<UpdateInfo> UpdateDelayed;
|
||||||
|
public event EventHandler<UpdateInfo> UpdateDismissed;
|
||||||
|
|
||||||
|
public UpdateBridge(UpdateHandler updates, Control sync){
|
||||||
|
this.sync = sync;
|
||||||
|
|
||||||
|
this.updates = updates;
|
||||||
|
this.updates.CheckFinished += updates_CheckFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Cleanup(){
|
||||||
|
updates.CheckFinished -= updates_CheckFinished;
|
||||||
|
nextUpdate?.DeleteInstaller();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
||||||
|
UpdateInfo foundUpdate = e.Result.HasValue ? e.Result.Value : null;
|
||||||
|
|
||||||
|
if (nextUpdate != null && !nextUpdate.Equals(foundUpdate)){
|
||||||
|
nextUpdate.DeleteInstaller();
|
||||||
|
}
|
||||||
|
|
||||||
|
nextUpdate = foundUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleInteractionEvent(EventHandler<UpdateInfo> eventHandler){
|
||||||
|
UpdateInfo tmpInfo = nextUpdate;
|
||||||
|
|
||||||
|
if (tmpInfo != null){
|
||||||
|
sync.InvokeAsyncSafe(() => eventHandler?.Invoke(this, tmpInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bridge methods
|
||||||
|
|
||||||
|
public void TriggerUpdateCheck(){
|
||||||
|
updates.Check(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnUpdateAccepted(){
|
||||||
|
HandleInteractionEvent(UpdateAccepted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnUpdateDelayed(){
|
||||||
|
HandleInteractionEvent(UpdateDelayed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnUpdateDismissed(){
|
||||||
|
HandleInteractionEvent(UpdateDismissed);
|
||||||
|
|
||||||
|
nextUpdate?.DeleteInstaller();
|
||||||
|
nextUpdate = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
6
Core/FormBrowser.Designer.cs
generated
@@ -39,17 +39,17 @@
|
|||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.BackColor = TweetDuck.Core.Utils.TwitterUtils.BackgroundColor;
|
this.BackColor = TweetDuck.Core.Utils.TwitterUtils.BackgroundColor;
|
||||||
this.ClientSize = new System.Drawing.Size(400, 386);
|
this.ClientSize = new System.Drawing.Size(1008, 730);
|
||||||
this.Icon = Properties.Resources.icon;
|
this.Icon = Properties.Resources.icon;
|
||||||
this.Location = TweetDuck.Core.Controls.ControlExtensions.InvisibleLocation;
|
this.Location = TweetDuck.Core.Controls.ControlExtensions.InvisibleLocation;
|
||||||
this.MinimumSize = new System.Drawing.Size(416, 424);
|
this.MinimumSize = new System.Drawing.Size(348, 424);
|
||||||
this.Name = "FormBrowser";
|
this.Name = "FormBrowser";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
||||||
this.Activated += new System.EventHandler(this.FormBrowser_Activated);
|
this.Activated += new System.EventHandler(this.FormBrowser_Activated);
|
||||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormBrowser_FormClosing);
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormBrowser_FormClosing);
|
||||||
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormBrowser_FormClosed);
|
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormBrowser_FormClosed);
|
||||||
this.LocationChanged += new System.EventHandler(this.FormBrowser_LocationChanged);
|
|
||||||
this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd);
|
this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd);
|
||||||
|
this.LocationChanged += new System.EventHandler(this.FormBrowser_LocationChanged);
|
||||||
this.Resize += new System.EventHandler(this.FormBrowser_Resize);
|
this.Resize += new System.EventHandler(this.FormBrowser_Resize);
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
@@ -5,17 +5,18 @@ using TweetDuck.Configuration;
|
|||||||
using TweetDuck.Core.Bridge;
|
using TweetDuck.Core.Bridge;
|
||||||
using TweetDuck.Core.Controls;
|
using TweetDuck.Core.Controls;
|
||||||
using TweetDuck.Core.Handling;
|
using TweetDuck.Core.Handling;
|
||||||
|
using TweetDuck.Core.Handling.General;
|
||||||
using TweetDuck.Core.Management;
|
using TweetDuck.Core.Management;
|
||||||
using TweetDuck.Core.Notification;
|
using TweetDuck.Core.Notification;
|
||||||
using TweetDuck.Core.Notification.Screenshot;
|
using TweetDuck.Core.Notification.Screenshot;
|
||||||
using TweetDuck.Core.Other;
|
using TweetDuck.Core.Other;
|
||||||
using TweetDuck.Core.Other.Analytics;
|
using TweetDuck.Core.Other.Analytics;
|
||||||
|
using TweetDuck.Core.Other.Settings.Dialogs;
|
||||||
using TweetDuck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
using TweetDuck.Plugins;
|
using TweetDuck.Plugins;
|
||||||
using TweetDuck.Plugins.Enums;
|
using TweetDuck.Plugins.Enums;
|
||||||
using TweetDuck.Plugins.Events;
|
using TweetDuck.Plugins.Events;
|
||||||
using TweetDuck.Updates;
|
using TweetDuck.Updates;
|
||||||
using TweetDuck.Updates.Events;
|
|
||||||
|
|
||||||
namespace TweetDuck.Core{
|
namespace TweetDuck.Core{
|
||||||
sealed partial class FormBrowser : Form, AnalyticsFile.IProvider{
|
sealed partial class FormBrowser : Form, AnalyticsFile.IProvider{
|
||||||
@@ -48,6 +49,7 @@ namespace TweetDuck.Core{
|
|||||||
private readonly UpdateHandler updates;
|
private readonly UpdateHandler updates;
|
||||||
private readonly FormNotificationTweet notification;
|
private readonly FormNotificationTweet notification;
|
||||||
private readonly ContextMenu contextMenu;
|
private readonly ContextMenu contextMenu;
|
||||||
|
private readonly UpdateBridge updateBridge;
|
||||||
|
|
||||||
private bool isLoaded;
|
private bool isLoaded;
|
||||||
private FormWindowState prevState;
|
private FormWindowState prevState;
|
||||||
@@ -69,10 +71,18 @@ namespace TweetDuck.Core{
|
|||||||
this.notification = new FormNotificationTweet(this, plugins);
|
this.notification = new FormNotificationTweet(this, plugins);
|
||||||
this.notification.Show();
|
this.notification.Show();
|
||||||
|
|
||||||
this.browser = new TweetDeckBrowser(this, new TweetDeckBridge.Browser(this, notification));
|
this.updates = new UpdateHandler(Program.InstallerPath);
|
||||||
|
this.updates.CheckFinished += updates_CheckFinished;
|
||||||
|
|
||||||
|
this.updateBridge = new UpdateBridge(updates, this);
|
||||||
|
this.updateBridge.UpdateAccepted += updateBridge_UpdateAccepted;
|
||||||
|
this.updateBridge.UpdateDelayed += updateBridge_UpdateDelayed;
|
||||||
|
this.updateBridge.UpdateDismissed += updateBridge_UpdateDismissed;
|
||||||
|
|
||||||
|
this.browser = new TweetDeckBrowser(this, new TweetDeckBridge.Browser(this, notification), updateBridge);
|
||||||
this.contextMenu = ContextMenuBrowser.CreateMenu(this);
|
this.contextMenu = ContextMenuBrowser.CreateMenu(this);
|
||||||
|
|
||||||
this.plugins.Register(browser, PluginEnvironment.Browser, true);
|
this.plugins.Register(browser, PluginEnvironment.Browser, this, true);
|
||||||
|
|
||||||
Controls.Add(new MenuStrip{ Visible = false }); // fixes Alt freezing the program in Win 10 Anniversary Update
|
Controls.Add(new MenuStrip{ Visible = false }); // fixes Alt freezing the program in Win 10 Anniversary Update
|
||||||
|
|
||||||
@@ -95,12 +105,11 @@ namespace TweetDuck.Core{
|
|||||||
this.trayIcon.ClickClose += trayIcon_ClickClose;
|
this.trayIcon.ClickClose += trayIcon_ClickClose;
|
||||||
Config.TrayBehaviorChanged += Config_TrayBehaviorChanged;
|
Config.TrayBehaviorChanged += Config_TrayBehaviorChanged;
|
||||||
|
|
||||||
UpdateTrayIcon();
|
UpdateTray();
|
||||||
|
|
||||||
this.updates = new UpdateHandler(browser, Program.InstallerPath);
|
if (Config.MuteNotifications){
|
||||||
this.updates.CheckFinished += updates_CheckFinished;
|
UpdateFormIcon();
|
||||||
this.updates.UpdateAccepted += updates_UpdateAccepted;
|
}
|
||||||
this.updates.UpdateDismissed += updates_UpdateDismissed;
|
|
||||||
|
|
||||||
if (Config.AllowDataCollection){
|
if (Config.AllowDataCollection){
|
||||||
analytics = new AnalyticsManager(this, plugins, Program.AnalyticsFilePath);
|
analytics = new AnalyticsManager(this, plugins, Program.AnalyticsFilePath);
|
||||||
@@ -127,7 +136,11 @@ namespace TweetDuck.Core{
|
|||||||
isLoaded = true;
|
isLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateTrayIcon(){
|
private void UpdateFormIcon(){ // TODO fix to show icon in taskbar too
|
||||||
|
Icon = Config.MuteNotifications ? Properties.Resources.icon_muted : Properties.Resources.icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTray(){
|
||||||
trayIcon.Visible = Config.TrayBehavior.ShouldDisplayIcon();
|
trayIcon.Visible = Config.TrayBehavior.ShouldDisplayIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,23 +210,24 @@ namespace TweetDuck.Core{
|
|||||||
|
|
||||||
private void FormBrowser_FormClosed(object sender, FormClosedEventArgs e){
|
private void FormBrowser_FormClosed(object sender, FormClosedEventArgs e){
|
||||||
if (isLoaded && UpdateInstallerPath == null){
|
if (isLoaded && UpdateInstallerPath == null){
|
||||||
updates.CleanupDownload();
|
updateBridge.Cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Config_MuteToggled(object sender, EventArgs e){
|
private void Config_MuteToggled(object sender, EventArgs e){
|
||||||
|
UpdateFormIcon();
|
||||||
AnalyticsFile.NotificationMutes.Trigger();
|
AnalyticsFile.NotificationMutes.Trigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Config_TrayBehaviorChanged(object sender, EventArgs e){
|
private void Config_TrayBehaviorChanged(object sender, EventArgs e){
|
||||||
UpdateTrayIcon();
|
UpdateTray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trayIcon_ClickRestore(object sender, EventArgs e){
|
private void trayIcon_ClickRestore(object sender, EventArgs e){
|
||||||
Show();
|
Show();
|
||||||
RestoreWindow();
|
RestoreWindow();
|
||||||
Activate();
|
Activate();
|
||||||
UpdateTrayIcon();
|
UpdateTray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trayIcon_ClickClose(object sender, EventArgs e){
|
private void trayIcon_ClickClose(object sender, EventArgs e){
|
||||||
@@ -241,7 +255,7 @@ namespace TweetDuck.Core{
|
|||||||
string tag = update.VersionTag;
|
string tag = update.VersionTag;
|
||||||
|
|
||||||
if (tag != Program.VersionTag && tag != Config.DismissedUpdate){
|
if (tag != Program.VersionTag && tag != Config.DismissedUpdate){
|
||||||
updates.PrepareUpdate(update);
|
update.BeginSilentDownload();
|
||||||
browser.ShowUpdateNotification(tag, update.ReleaseNotes);
|
browser.ShowUpdateNotification(tag, update.ReleaseNotes);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -257,38 +271,61 @@ namespace TweetDuck.Core{
|
|||||||
ignoreUpdateCheckError = true;
|
ignoreUpdateCheckError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updates_UpdateAccepted(object sender, UpdateEventArgs e){
|
private void updateBridge_UpdateAccepted(object sender, UpdateInfo update){
|
||||||
this.InvokeAsyncSafe(() => {
|
FormManager.CloseAllDialogs();
|
||||||
FormManager.CloseAllDialogs();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Config.DismissedUpdate)){
|
if (!string.IsNullOrEmpty(Config.DismissedUpdate)){
|
||||||
Config.DismissedUpdate = null;
|
Config.DismissedUpdate = null;
|
||||||
Config.Save();
|
Config.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnFinished(){
|
||||||
|
UpdateDownloadStatus status = update.DownloadStatus;
|
||||||
|
|
||||||
|
if (status == UpdateDownloadStatus.Done){
|
||||||
|
UpdateInstallerPath = update.InstallerPath;
|
||||||
|
ForceClose();
|
||||||
}
|
}
|
||||||
|
else if (status != UpdateDownloadStatus.Canceled && FormMessage.Error("Update Has Failed", "Could not automatically download the update: "+(update.DownloadError?.Message ?? "unknown error")+"\n\nWould you like to open the website and try downloading the update manually?", FormMessage.Yes, FormMessage.No)){
|
||||||
|
BrowserUtils.OpenExternalBrowser(Program.Website);
|
||||||
|
ForceClose();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updates.BeginUpdateDownload(this, e.UpdateInfo, update => {
|
if (update.DownloadStatus.IsFinished(true)){
|
||||||
UpdateDownloadStatus status = update.DownloadStatus;
|
OnFinished();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
FormUpdateDownload downloadForm = new FormUpdateDownload(update);
|
||||||
|
|
||||||
if (status == UpdateDownloadStatus.Done){
|
downloadForm.VisibleChanged += (sender2, args2) => {
|
||||||
UpdateInstallerPath = update.InstallerPath;
|
downloadForm.MoveToCenter(this);
|
||||||
ForceClose();
|
Hide();
|
||||||
|
};
|
||||||
|
|
||||||
|
downloadForm.FormClosed += (sender2, args2) => {
|
||||||
|
if (downloadForm.DialogResult != DialogResult.OK){
|
||||||
|
update.CancelDownload();
|
||||||
}
|
}
|
||||||
else if (status != UpdateDownloadStatus.Canceled && FormMessage.Error("Update Has Failed", "Could not automatically download the update: "+(update.DownloadError?.Message ?? "unknown error")+"\n\nWould you like to open the website and try downloading the update manually?", FormMessage.Yes, FormMessage.No)){
|
|
||||||
BrowserUtils.OpenExternalBrowser(Program.Website);
|
downloadForm.Dispose();
|
||||||
ForceClose();
|
OnFinished();
|
||||||
}
|
};
|
||||||
else{
|
|
||||||
Show();
|
downloadForm.Show();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updates_UpdateDismissed(object sender, UpdateEventArgs e){
|
private void updateBridge_UpdateDelayed(object sender, UpdateInfo update){
|
||||||
this.InvokeAsyncSafe(() => {
|
// stops the timer
|
||||||
Config.DismissedUpdate = e.UpdateInfo.VersionTag;
|
}
|
||||||
Config.Save();
|
|
||||||
});
|
private void updateBridge_UpdateDismissed(object sender, UpdateInfo update){
|
||||||
|
Config.DismissedUpdate = update.VersionTag;
|
||||||
|
Config.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void WndProc(ref Message m){
|
protected override void WndProc(ref Message m){
|
||||||
@@ -360,6 +397,10 @@ namespace TweetDuck.Core{
|
|||||||
AnalyticsFile.UsedROT13.Trigger();
|
AnalyticsFile.UsedROT13.Trigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OpenDevTools(){
|
||||||
|
browser.OpenDevTools();
|
||||||
|
}
|
||||||
|
|
||||||
// callback handlers
|
// callback handlers
|
||||||
|
|
||||||
public void OnIntroductionClosed(bool showGuide, bool allowDataCollection){
|
public void OnIntroductionClosed(bool showGuide, bool allowDataCollection){
|
||||||
@@ -447,6 +488,18 @@ namespace TweetDuck.Core{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OpenProfileImport(){
|
||||||
|
FormManager.TryFind<FormSettings>()?.Close();
|
||||||
|
|
||||||
|
using(DialogSettingsManage dialog = new DialogSettingsManage(plugins, true)){
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK && !dialog.IsRestarting){
|
||||||
|
BrowserProcessHandler.UpdatePrefs();
|
||||||
|
FormManager.TryFind<FormPlugins>()?.Close();
|
||||||
|
plugins.Reload(); // also reloads the browser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void OnTweetNotification(){ // may be called multiple times, once for each type of notification
|
public void OnTweetNotification(){ // may be called multiple times, once for each type of notification
|
||||||
if (Config.EnableTrayHighlight && !ContainsFocus){
|
if (Config.EnableTrayHighlight && !ContainsFocus){
|
||||||
trayIcon.HasNotifications = true;
|
trayIcon.HasNotifications = true;
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDuck.Core.Other;
|
|
||||||
|
|
||||||
namespace TweetDuck.Core{
|
namespace TweetDuck.Core{
|
||||||
static class FormManager{
|
static class FormManager{
|
||||||
@@ -18,12 +17,14 @@ namespace TweetDuck.Core{
|
|||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool HasAnyDialogs => Application.OpenForms.OfType<IAppDialog>().Any();
|
||||||
|
|
||||||
public static void CloseAllDialogs(){
|
public static void CloseAllDialogs(){
|
||||||
foreach(Form form in Application.OpenForms.Cast<Form>().Reverse()){
|
foreach(IAppDialog dialog in Application.OpenForms.OfType<IAppDialog>().Reverse()){
|
||||||
if (form is FormSettings || form is FormPlugins || form is FormAbout || form is FormGuide){
|
((Form)dialog).Close();
|
||||||
form.Close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IAppDialog{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,8 +15,6 @@ using TweetDuck.Resources;
|
|||||||
|
|
||||||
namespace TweetDuck.Core.Handling{
|
namespace TweetDuck.Core.Handling{
|
||||||
abstract class ContextMenuBase : IContextMenuHandler{
|
abstract class ContextMenuBase : IContextMenuHandler{
|
||||||
public static readonly bool HasDevTools = File.Exists(Path.Combine(Program.ProgramPath, "devtools_resources.pak"));
|
|
||||||
|
|
||||||
private static TwitterUtils.ImageQuality ImageQuality => Program.UserConfig.TwitterImageQuality;
|
private static TwitterUtils.ImageQuality ImageQuality => Program.UserConfig.TwitterImageQuality;
|
||||||
|
|
||||||
private const CefMenuCommand MenuOpenLinkUrl = (CefMenuCommand)26500;
|
private const CefMenuCommand MenuOpenLinkUrl = (CefMenuCommand)26500;
|
||||||
@@ -196,6 +194,7 @@ namespace TweetDuck.Core.Handling{
|
|||||||
case MenuReadApplyROT13:
|
case MenuReadApplyROT13:
|
||||||
string selection = parameters.SelectionText;
|
string selection = parameters.SelectionText;
|
||||||
control.InvokeAsyncSafe(() => FormMessage.Information("ROT13", StringUtils.ConvertRot13(selection), FormMessage.OK));
|
control.InvokeAsyncSafe(() => FormMessage.Information("ROT13", StringUtils.ConvertRot13(selection), FormMessage.OK));
|
||||||
|
control.InvokeAsyncSafe(analytics.AnalyticsFile.UsedROT13.Trigger);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuSearchInBrowser:
|
case MenuSearchInBrowser:
|
||||||
@@ -237,7 +236,10 @@ namespace TweetDuck.Core.Handling{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static void AddDebugMenuItems(IMenuModel model){
|
protected static void AddDebugMenuItems(IMenuModel model){
|
||||||
model.AddItem(MenuOpenDevTools, "Open dev tools");
|
if (BrowserUtils.HasDevTools){
|
||||||
|
AddSeparator(model);
|
||||||
|
model.AddItem(MenuOpenDevTools, "Open dev tools");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void RemoveSeparatorIfLast(IMenuModel model){
|
protected static void RemoveSeparatorIfLast(IMenuModel model){
|
||||||
|
@@ -84,10 +84,7 @@ namespace TweetDuck.Core.Handling{
|
|||||||
globalMenu.AddItem(MenuPlugins, TitlePlugins);
|
globalMenu.AddItem(MenuPlugins, TitlePlugins);
|
||||||
globalMenu.AddItem(MenuAbout, TitleAboutProgram);
|
globalMenu.AddItem(MenuAbout, TitleAboutProgram);
|
||||||
|
|
||||||
if (HasDevTools){
|
AddDebugMenuItems(globalMenu);
|
||||||
globalMenu.AddSeparator();
|
|
||||||
AddDebugMenuItems(globalMenu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveSeparatorIfLast(model);
|
RemoveSeparatorIfLast(model);
|
||||||
|
@@ -8,11 +8,7 @@ namespace TweetDuck.Core.Handling{
|
|||||||
public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
||||||
model.Clear();
|
model.Clear();
|
||||||
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
|
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
|
||||||
|
AddDebugMenuItems(model);
|
||||||
if (HasDevTools){
|
|
||||||
AddSeparator(model);
|
|
||||||
AddDebugMenuItems(model);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,11 +47,7 @@ namespace TweetDuck.Core.Handling{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasDevTools){
|
AddDebugMenuItems(model);
|
||||||
AddSeparator(model);
|
|
||||||
AddDebugMenuItems(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveSeparatorIfLast(model);
|
RemoveSeparatorIfLast(model);
|
||||||
|
|
||||||
form.InvokeAsyncSafe(() => {
|
form.InvokeAsyncSafe(() => {
|
||||||
|
@@ -4,11 +4,19 @@ using CefSharp.Enums;
|
|||||||
|
|
||||||
namespace TweetDuck.Core.Handling{
|
namespace TweetDuck.Core.Handling{
|
||||||
sealed class DragHandlerBrowser : IDragHandler{
|
sealed class DragHandlerBrowser : IDragHandler{
|
||||||
|
private readonly RequestHandlerBrowser requestHandler;
|
||||||
|
|
||||||
|
public DragHandlerBrowser(RequestHandlerBrowser requestHandler){
|
||||||
|
this.requestHandler = requestHandler;
|
||||||
|
}
|
||||||
|
|
||||||
public bool OnDragEnter(IWebBrowser browserControl, IBrowser browser, IDragData dragData, DragOperationsMask mask){
|
public bool OnDragEnter(IWebBrowser browserControl, IBrowser browser, IDragData dragData, DragOperationsMask mask){
|
||||||
void TriggerDragStart(string type, string data = null){
|
void TriggerDragStart(string type, string data = null){
|
||||||
browserControl.ExecuteScriptAsync("window.TDGF_onGlobalDragStart", type, data);
|
browserControl.ExecuteScriptAsync("window.TDGF_onGlobalDragStart", type, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requestHandler.BlockNextUserNavUrl = dragData.LinkUrl; // empty if not a link
|
||||||
|
|
||||||
if (dragData.IsLink){
|
if (dragData.IsLink){
|
||||||
TriggerDragStart("link", dragData.LinkUrl);
|
TriggerDragStart("link", dragData.LinkUrl);
|
||||||
}
|
}
|
||||||
|
72
Core/Handling/Filters/ResponseFilterBase.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using CefSharp;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Handling.Filters{
|
||||||
|
abstract class ResponseFilterBase : IResponseFilter{
|
||||||
|
private enum State{
|
||||||
|
Reading, Writing, Done
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Encoding encoding;
|
||||||
|
private byte[] responseData;
|
||||||
|
|
||||||
|
private State state;
|
||||||
|
private int offset;
|
||||||
|
|
||||||
|
protected ResponseFilterBase(int totalBytes, Encoding encoding){
|
||||||
|
this.responseData = new byte[totalBytes];
|
||||||
|
this.encoding = encoding;
|
||||||
|
this.state = State.Reading;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterStatus IResponseFilter.Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten){
|
||||||
|
int responseLength = responseData.Length;
|
||||||
|
|
||||||
|
if (state == State.Reading){
|
||||||
|
int bytesToRead = Math.Min(responseLength-offset, (int)Math.Min(dataIn.Length, int.MaxValue));
|
||||||
|
|
||||||
|
dataIn.Read(responseData, offset, bytesToRead);
|
||||||
|
offset += bytesToRead;
|
||||||
|
|
||||||
|
dataInRead = bytesToRead;
|
||||||
|
dataOutWritten = 0;
|
||||||
|
|
||||||
|
if (offset >= responseLength){
|
||||||
|
responseData = encoding.GetBytes(ProcessResponse(encoding.GetString(responseData)));
|
||||||
|
state = State.Writing;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FilterStatus.NeedMoreData;
|
||||||
|
}
|
||||||
|
else if (state == State.Writing){
|
||||||
|
int bytesToWrite = Math.Min(responseLength-offset, (int)Math.Min(dataOut.Length, int.MaxValue));
|
||||||
|
|
||||||
|
if (bytesToWrite > 0){
|
||||||
|
dataOut.Write(responseData, offset, bytesToWrite);
|
||||||
|
offset += bytesToWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataOutWritten = bytesToWrite;
|
||||||
|
dataInRead = 0;
|
||||||
|
|
||||||
|
if (offset < responseLength){
|
||||||
|
return FilterStatus.NeedMoreData;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
state = State.Done;
|
||||||
|
return FilterStatus.Done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
throw new InvalidOperationException("This resource filter cannot be reused.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract bool InitFilter();
|
||||||
|
protected abstract string ProcessResponse(string text);
|
||||||
|
public abstract void Dispose();
|
||||||
|
}
|
||||||
|
}
|
20
Core/Handling/Filters/ResponseFilterVendor.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Handling.Filters{
|
||||||
|
sealed class ResponseFilterVendor : ResponseFilterBase{
|
||||||
|
private static readonly Regex RegexRestoreJQuery = new Regex(@"(\w+)\.fn=\1\.prototype", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
public ResponseFilterVendor(int totalBytes) : base(totalBytes, Encoding.UTF8){}
|
||||||
|
|
||||||
|
public override bool InitFilter(){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ProcessResponse(string text){
|
||||||
|
return RegexRestoreJQuery.Replace(text, "window.$$=$1;$&", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose(){}
|
||||||
|
}
|
||||||
|
}
|
@@ -7,16 +7,14 @@ using CefSharp;
|
|||||||
|
|
||||||
namespace TweetDuck.Core.Handling.General{
|
namespace TweetDuck.Core.Handling.General{
|
||||||
sealed class FileDialogHandler : IDialogHandler{
|
sealed class FileDialogHandler : IDialogHandler{
|
||||||
public bool OnFileDialog(IWebBrowser browserControl, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, List<string> acceptFilters, int selectedAcceptFilter, IFileDialogCallback callback){
|
public bool OnFileDialog(IWebBrowser browserControl, IBrowser browser, CefFileDialogMode mode, CefFileDialogFlags flags, string title, string defaultFilePath, List<string> acceptFilters, int selectedAcceptFilter, IFileDialogCallback callback){
|
||||||
CefFileDialogMode dialogType = mode & CefFileDialogMode.TypeMask;
|
if (mode == CefFileDialogMode.Open || mode == CefFileDialogMode.OpenMultiple){
|
||||||
|
|
||||||
if (dialogType == CefFileDialogMode.Open || dialogType == CefFileDialogMode.OpenMultiple){
|
|
||||||
string allFilters = string.Join(";", acceptFilters.Select(filter => "*"+filter));
|
string allFilters = string.Join(";", acceptFilters.Select(filter => "*"+filter));
|
||||||
|
|
||||||
using(OpenFileDialog dialog = new OpenFileDialog{
|
using(OpenFileDialog dialog = new OpenFileDialog{
|
||||||
AutoUpgradeEnabled = true,
|
AutoUpgradeEnabled = true,
|
||||||
DereferenceLinks = true,
|
DereferenceLinks = true,
|
||||||
Multiselect = dialogType == CefFileDialogMode.OpenMultiple,
|
Multiselect = mode == CefFileDialogMode.OpenMultiple,
|
||||||
Title = "Open Files",
|
Title = "Open Files",
|
||||||
Filter = $"All Supported Formats ({allFilters})|{allFilters}|All Files (*.*)|*.*"
|
Filter = $"All Supported Formats ({allFilters})|{allFilters}|All Files (*.*)|*.*"
|
||||||
}){
|
}){
|
||||||
|
@@ -2,15 +2,22 @@
|
|||||||
using CefSharp;
|
using CefSharp;
|
||||||
using CefSharp.Handler;
|
using CefSharp.Handler;
|
||||||
using TweetDuck.Core.Handling.General;
|
using TweetDuck.Core.Handling.General;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDuck.Core.Handling{
|
namespace TweetDuck.Core.Handling{
|
||||||
class RequestHandlerBase : DefaultRequestHandler{
|
class RequestHandlerBase : DefaultRequestHandler{
|
||||||
|
private readonly bool autoReload;
|
||||||
|
|
||||||
|
public RequestHandlerBase(bool autoReload){
|
||||||
|
this.autoReload = autoReload;
|
||||||
|
}
|
||||||
|
|
||||||
public override bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture){
|
public override bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture){
|
||||||
return LifeSpanHandler.HandleLinkClick(browserControl, targetDisposition, targetUrl);
|
return LifeSpanHandler.HandleLinkClick(browserControl, targetDisposition, targetUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (ContextMenuBase.HasDevTools){
|
if (BrowserUtils.HasDevTools){
|
||||||
NameValueCollection headers = request.Headers;
|
NameValueCollection headers = request.Headers;
|
||||||
headers.Remove("x-devtools-emulate-network-conditions-client-id");
|
headers.Remove("x-devtools-emulate-network-conditions-client-id");
|
||||||
request.Headers = headers;
|
request.Headers = headers;
|
||||||
@@ -18,5 +25,11 @@ namespace TweetDuck.Core.Handling{
|
|||||||
|
|
||||||
return base.OnBeforeResourceLoad(browserControl, browser, frame, request, callback);
|
return base.OnBeforeResourceLoad(browserControl, browser, frame, request, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status){
|
||||||
|
if (autoReload){
|
||||||
|
browser.Reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,21 @@
|
|||||||
using CefSharp;
|
// Uncomment to force TweetDeck to load a predefined version of the vendor/bundle scripts
|
||||||
|
// #define FREEZE_TWEETDECK_SCRIPTS
|
||||||
|
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using CefSharp;
|
||||||
|
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{
|
||||||
public override void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status){
|
public string BlockNextUserNavUrl { get; set; }
|
||||||
browser.Reload();
|
|
||||||
}
|
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.Script && request.Url.Contains("analytics.")){
|
||||||
@@ -16,13 +26,71 @@ namespace TweetDuck.Core.Handling{
|
|||||||
return base.OnBeforeResourceLoad(browserControl, browser, frame, request, callback);
|
return base.OnBeforeResourceLoad(browserControl, browser, frame, request, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool OnBeforeBrowse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect){
|
||||||
|
if (userGesture && request.TransitionType == TransitionType.LinkClicked){
|
||||||
|
bool block = request.Url == BlockNextUserNavUrl;
|
||||||
|
BlockNextUserNavUrl = string.Empty;
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
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("/backgrounds/spinner_blue")){
|
||||||
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){
|
||||||
|
if (request.ResourceType == ResourceType.Script && request.Url.Contains("/dist/vendor")){
|
||||||
|
NameValueCollection headers = response.ResponseHeaders;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ namespace TweetDuck.Core.Notification.Example{
|
|||||||
public FormNotificationExample(FormBrowser owner, PluginManager pluginManager) : base(owner, pluginManager, false){
|
public FormNotificationExample(FormBrowser owner, PluginManager pluginManager) : base(owner, pluginManager, false){
|
||||||
browser.LoadingStateChanged += browser_LoadingStateChanged;
|
browser.LoadingStateChanged += browser_LoadingStateChanged;
|
||||||
|
|
||||||
string exampleTweetHTML = ScriptLoader.LoadResource("pages/example.html", true)?.Replace("{avatar}", TweetNotification.AppLogo.Url) ?? string.Empty;
|
string exampleTweetHTML = ScriptLoader.LoadResourceSilent("pages/example.html")?.Replace("{avatar}", TweetNotification.AppLogo.Url) ?? string.Empty;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
exampleTweetHTML = exampleTweetHTML.Replace("</p>", @"</p><div style='margin-top:256px'>Scrollbar test padding...</div>");
|
exampleTweetHTML = exampleTweetHTML.Replace("</p>", @"</p><div style='margin-top:256px'>Scrollbar test padding...</div>");
|
||||||
|
@@ -124,7 +124,7 @@ namespace TweetDuck.Core.Notification{
|
|||||||
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()
|
RequestHandler = new RequestHandlerBase(false)
|
||||||
};
|
};
|
||||||
|
|
||||||
this.browser.Dock = DockStyle.None;
|
this.browser.Dock = DockStyle.None;
|
||||||
@@ -185,7 +185,7 @@ namespace TweetDuck.Core.Notification{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected virtual string GetTweetHTML(TweetNotification tweet){
|
protected virtual string GetTweetHTML(TweetNotification tweet){
|
||||||
return tweet.GenerateHtml(IsCursorOverBrowser ? "td-notification td-hover" : "td-notification");
|
return tweet.GenerateHtml(IsCursorOverBrowser ? "td-notification td-hover" : "td-notification", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void LoadTweet(TweetNotification tweet){
|
protected virtual void LoadTweet(TweetNotification tweet){
|
||||||
|
@@ -14,11 +14,6 @@ using TweetDuck.Resources;
|
|||||||
|
|
||||||
namespace TweetDuck.Core.Notification{
|
namespace TweetDuck.Core.Notification{
|
||||||
abstract partial class FormNotificationMain : FormNotificationBase, ITweetDeckBrowser{
|
abstract partial class FormNotificationMain : FormNotificationBase, ITweetDeckBrowser{
|
||||||
private const string NotificationScriptFile = "notification.js";
|
|
||||||
|
|
||||||
private static readonly string NotificationScriptIdentifier = ScriptLoader.GetRootIdentifier(NotificationScriptFile);
|
|
||||||
private static readonly string NotificationJS = ScriptLoader.LoadResource(NotificationScriptFile);
|
|
||||||
|
|
||||||
private readonly PluginManager plugins;
|
private readonly PluginManager plugins;
|
||||||
private readonly int timerBarHeight;
|
private readonly int timerBarHeight;
|
||||||
|
|
||||||
@@ -87,7 +82,7 @@ namespace TweetDuck.Core.Notification{
|
|||||||
browser.LoadingStateChanged += Browser_LoadingStateChanged;
|
browser.LoadingStateChanged += Browser_LoadingStateChanged;
|
||||||
browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
||||||
|
|
||||||
plugins.Register(this, PluginEnvironment.Notification);
|
plugins.Register(this, PluginEnvironment.Notification, this);
|
||||||
|
|
||||||
mouseHookDelegate = MouseHookProc;
|
mouseHookDelegate = MouseHookProc;
|
||||||
Disposed += (sender, args) => StopMouseHook(true);
|
Disposed += (sender, args) => StopMouseHook(true);
|
||||||
@@ -105,7 +100,7 @@ namespace TweetDuck.Core.Notification{
|
|||||||
browser.FrameLoadEnd += (sender, args) => {
|
browser.FrameLoadEnd += (sender, args) => {
|
||||||
IFrame frame = args.Frame;
|
IFrame frame = args.Frame;
|
||||||
|
|
||||||
if (frame.IsMain && NotificationJS != null && browser.Address != "about:blank"){
|
if (frame.IsMain && browser.Address != "about:blank"){
|
||||||
callback(frame);
|
callback(frame);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -186,9 +181,9 @@ namespace TweetDuck.Core.Notification{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
||||||
if (e.Frame.IsMain && NotificationJS != null && browser.Address != "about:blank"){
|
if (e.Frame.IsMain && browser.Address != "about:blank"){
|
||||||
e.Frame.ExecuteJavaScriptAsync(PropertyBridge.GenerateScript(PropertyBridge.Environment.Notification));
|
e.Frame.ExecuteJavaScriptAsync(PropertyBridge.GenerateScript(PropertyBridge.Environment.Notification));
|
||||||
ScriptLoader.ExecuteScript(e.Frame, NotificationJS, NotificationScriptIdentifier);
|
ScriptLoader.ExecuteScript(e.Frame, ScriptLoader.LoadResource("notification.js", this), "root:notification");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +250,7 @@ namespace TweetDuck.Core.Notification{
|
|||||||
string html = base.GetTweetHTML(tweet);
|
string html = base.GetTweetHTML(tweet);
|
||||||
|
|
||||||
foreach(InjectedHTML injection in plugins.NotificationInjections){
|
foreach(InjectedHTML injection in plugins.NotificationInjections){
|
||||||
html = injection.Inject(html);
|
html = injection.InjectInto(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
|
@@ -20,6 +20,8 @@ namespace TweetDuck.Core.Notification.Screenshot{
|
|||||||
public FormNotificationScreenshotable(Action callback, FormBrowser owner, PluginManager pluginManager, string html, int width) : base(owner, false){
|
public FormNotificationScreenshotable(Action callback, FormBrowser owner, PluginManager pluginManager, string html, int width) : base(owner, false){
|
||||||
this.plugins = pluginManager;
|
this.plugins = pluginManager;
|
||||||
|
|
||||||
|
int realWidth = BrowserUtils.Scale(width, DpiScale);
|
||||||
|
|
||||||
browser.RegisterAsyncJsObject("$TD_NotificationScreenshot", new ScreenshotBridge(this, SetScreenshotHeight, callback));
|
browser.RegisterAsyncJsObject("$TD_NotificationScreenshot", new ScreenshotBridge(this, SetScreenshotHeight, callback));
|
||||||
|
|
||||||
browser.LoadingStateChanged += (sender, args) => {
|
browser.LoadingStateChanged += (sender, args) => {
|
||||||
@@ -27,7 +29,7 @@ namespace TweetDuck.Core.Notification.Screenshot{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string script = ScriptLoader.LoadResource("screenshot.js", true);
|
string script = ScriptLoader.LoadResourceSilent("screenshot.js");
|
||||||
|
|
||||||
if (script == null){
|
if (script == null){
|
||||||
this.InvokeAsyncSafe(callback);
|
this.InvokeAsyncSafe(callback);
|
||||||
@@ -35,19 +37,19 @@ namespace TweetDuck.Core.Notification.Screenshot{
|
|||||||
}
|
}
|
||||||
|
|
||||||
using(IFrame frame = args.Browser.MainFrame){
|
using(IFrame frame = args.Browser.MainFrame){
|
||||||
ScriptLoader.ExecuteScript(frame, script.Replace("{width}", BrowserUtils.Scale(width, DpiScale).ToString()).Replace("{frames}", TweetScreenshotManager.WaitFrames.ToString()), "gen:screenshot");
|
ScriptLoader.ExecuteScript(frame, script.Replace("{width}", realWidth.ToString()).Replace("{frames}", TweetScreenshotManager.WaitFrames.ToString()), "gen:screenshot");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
SetNotificationSize(width, 1024);
|
SetNotificationSize(realWidth, 1024);
|
||||||
LoadTweet(new TweetNotification(string.Empty, string.Empty, string.Empty, html, 0, string.Empty, string.Empty));
|
LoadTweet(new TweetNotification(string.Empty, string.Empty, string.Empty, html, 0, string.Empty, string.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string GetTweetHTML(TweetNotification tweet){
|
protected override string GetTweetHTML(TweetNotification tweet){
|
||||||
string html = tweet.GenerateHtml("td-screenshot");
|
string html = tweet.GenerateHtml("td-screenshot", this);
|
||||||
|
|
||||||
foreach(InjectedHTML injection in plugins.NotificationInjections){
|
foreach(InjectedHTML injection in plugins.NotificationInjections){
|
||||||
html = injection.Inject(html);
|
html = injection.InjectInto(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
using CefSharp;
|
using CefSharp;
|
||||||
using TweetDuck.Core.Bridge;
|
using TweetDuck.Core.Bridge;
|
||||||
using TweetDuck.Data;
|
using TweetDuck.Data;
|
||||||
@@ -7,8 +8,7 @@ using TweetDuck.Resources;
|
|||||||
|
|
||||||
namespace TweetDuck.Core.Notification{
|
namespace TweetDuck.Core.Notification{
|
||||||
sealed class TweetNotification{
|
sealed class TweetNotification{
|
||||||
private const string DefaultHeadLayout = @"<html id='tduck' class='os-windows txt-size--14' data-td-font='medium' data-td-theme='dark'><head><meta charset='utf-8'><meta http-equiv='X-UA-Compatible' content='chrome=1'><link rel='stylesheet' href='https://ton.twimg.com/tweetdeck-web/web/css/font.5ef884f9f9.css'><link rel='stylesheet' href='https://ton.twimg.com/tweetdeck-web/web/css/app-dark.5631e0dd42.css'><style type='text/css'>body{background:#222426}</style>";
|
private const string DefaultHeadLayout = @"<html class=""scroll-v os-windows dark txt-size--14"" lang=""en-US"" id=""tduck"" data-td-font=""medium"" data-td-theme=""dark""><head><meta charset=""utf-8""><link href=""https://ton.twimg.com/tweetdeck-web/web/dist/bundle.4b1f87e09d.css"" rel=""stylesheet""><style type='text/css'>body { background: rgb(34, 36, 38) !important }</style>";
|
||||||
private static readonly string CustomCSS = ScriptLoader.LoadResource("styles/notification.css") ?? string.Empty;
|
|
||||||
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", ResourceHandler.FromByteArray(Properties.Resources.avatar, "image/png"));
|
||||||
|
|
||||||
public static TweetNotification Example(string html, int characters){
|
public static TweetNotification Example(string html, int characters){
|
||||||
@@ -53,11 +53,11 @@ namespace TweetDuck.Core.Notification{
|
|||||||
return 2000+Math.Max(1000, value*characters);
|
return 2000+Math.Max(1000, value*characters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GenerateHtml(string bodyClasses){
|
public string GenerateHtml(string bodyClasses, Control sync){
|
||||||
StringBuilder build = new StringBuilder();
|
StringBuilder build = new StringBuilder();
|
||||||
build.Append("<!DOCTYPE html>");
|
build.Append("<!DOCTYPE html>");
|
||||||
build.Append(TweetDeckBridge.NotificationHeadLayout ?? DefaultHeadLayout);
|
build.Append(TweetDeckBridge.NotificationHeadLayout ?? DefaultHeadLayout);
|
||||||
build.Append("<style type='text/css'>").Append(CustomCSS).Append("</style>");
|
build.Append("<style type='text/css'>").Append(ScriptLoader.LoadResource("styles/notification.css", sync) ?? string.Empty).Append("</style>");
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Program.UserConfig.CustomNotificationCSS)){
|
if (!string.IsNullOrEmpty(Program.UserConfig.CustomNotificationCSS)){
|
||||||
build.Append("<style type='text/css'>").Append(Program.UserConfig.CustomNotificationCSS).Append("</style>");
|
build.Append("<style type='text/css'>").Append(Program.UserConfig.CustomNotificationCSS).Append("</style>");
|
||||||
|
@@ -8,7 +8,6 @@ using TweetDuck.Configuration;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Management;
|
using System.Management;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using TweetDuck.Core.Handling;
|
|
||||||
using TweetDuck.Core.Notification;
|
using TweetDuck.Core.Notification;
|
||||||
using TweetDuck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
using TweetDuck.Plugins;
|
using TweetDuck.Plugins;
|
||||||
@@ -22,7 +21,7 @@ namespace TweetDuck.Core.Other.Analytics{
|
|||||||
return new AnalyticsReport{
|
return new AnalyticsReport{
|
||||||
{ "App Version" , Program.VersionTag },
|
{ "App Version" , Program.VersionTag },
|
||||||
{ "App Type" , Program.IsPortable ? "portable" : "installed" },
|
{ "App Type" , Program.IsPortable ? "portable" : "installed" },
|
||||||
{ "App Dev Tools" , Bool(ContextMenuBase.HasDevTools) },
|
{ "App Dev Tools" , Bool(BrowserUtils.HasDevTools) },
|
||||||
0,
|
0,
|
||||||
{ "System Name" , SystemName },
|
{ "System Name" , SystemName },
|
||||||
{ "System Edition" , SystemEdition },
|
{ "System Edition" , SystemEdition },
|
||||||
|
@@ -5,7 +5,7 @@ using System.Windows.Forms;
|
|||||||
using TweetDuck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDuck.Core.Other{
|
namespace TweetDuck.Core.Other{
|
||||||
sealed partial class FormAbout : Form{
|
sealed partial class FormAbout : Form, FormManager.IAppDialog{
|
||||||
private const string TipsLink = "https://github.com/chylex/TweetDuck/wiki";
|
private const string TipsLink = "https://github.com/chylex/TweetDuck/wiki";
|
||||||
private const string IssuesLink = "https://github.com/chylex/TweetDuck/issues";
|
private const string IssuesLink = "https://github.com/chylex/TweetDuck/issues";
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@ using TweetDuck.Data;
|
|||||||
using TweetDuck.Resources;
|
using TweetDuck.Resources;
|
||||||
|
|
||||||
namespace TweetDuck.Core.Other{
|
namespace TweetDuck.Core.Other{
|
||||||
sealed partial class FormGuide : Form{
|
sealed partial class FormGuide : Form, FormManager.IAppDialog{
|
||||||
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+)?(?:/(#.*))?";
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ namespace TweetDuck.Core.Other{
|
|||||||
MenuHandler = new ContextMenuGuide(owner),
|
MenuHandler = new ContextMenuGuide(owner),
|
||||||
JsDialogHandler = new JavaScriptDialogHandler(),
|
JsDialogHandler = new JavaScriptDialogHandler(),
|
||||||
LifeSpanHandler = new LifeSpanHandler(),
|
LifeSpanHandler = new LifeSpanHandler(),
|
||||||
RequestHandler = new RequestHandlerBrowser()
|
RequestHandler = new RequestHandlerBase(true)
|
||||||
};
|
};
|
||||||
|
|
||||||
browser.LoadingStateChanged += browser_LoadingStateChanged;
|
browser.LoadingStateChanged += browser_LoadingStateChanged;
|
||||||
|
@@ -7,7 +7,7 @@ using TweetDuck.Plugins;
|
|||||||
using TweetDuck.Plugins.Controls;
|
using TweetDuck.Plugins.Controls;
|
||||||
|
|
||||||
namespace TweetDuck.Core.Other{
|
namespace TweetDuck.Core.Other{
|
||||||
sealed partial class FormPlugins : Form{
|
sealed partial class FormPlugins : Form, FormManager.IAppDialog{
|
||||||
private readonly PluginManager pluginManager;
|
private readonly PluginManager pluginManager;
|
||||||
|
|
||||||
public FormPlugins(){
|
public FormPlugins(){
|
||||||
|
@@ -13,7 +13,7 @@ using TweetDuck.Plugins;
|
|||||||
using TweetDuck.Updates;
|
using TweetDuck.Updates;
|
||||||
|
|
||||||
namespace TweetDuck.Core.Other{
|
namespace TweetDuck.Core.Other{
|
||||||
sealed partial class FormSettings : Form{
|
sealed partial class FormSettings : Form, FormManager.IAppDialog{
|
||||||
private readonly FormBrowser browser;
|
private readonly FormBrowser browser;
|
||||||
private readonly PluginManager plugins;
|
private readonly PluginManager plugins;
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ namespace TweetDuck.Core.Other{
|
|||||||
AddButton("Notifications", () => new TabSettingsNotifications(new FormNotificationExample(this.browser, this.plugins)));
|
AddButton("Notifications", () => new TabSettingsNotifications(new FormNotificationExample(this.browser, this.plugins)));
|
||||||
AddButton("Sounds", () => new TabSettingsSounds(this.browser.PlaySoundNotification));
|
AddButton("Sounds", () => new TabSettingsSounds(this.browser.PlaySoundNotification));
|
||||||
AddButton("Feedback", () => new TabSettingsFeedback(analytics, AnalyticsReportGenerator.ExternalInfo.From(this.browser), this.plugins));
|
AddButton("Feedback", () => new TabSettingsFeedback(analytics, AnalyticsReportGenerator.ExternalInfo.From(this.browser), this.plugins));
|
||||||
AddButton("Advanced", () => new TabSettingsAdvanced(this.browser.ReinjectCustomCSS));
|
AddButton("Advanced", () => new TabSettingsAdvanced(this.browser.ReinjectCustomCSS, this.browser.OpenDevTools));
|
||||||
|
|
||||||
SelectTab(tabs[startTab ?? typeof(TabSettingsGeneral)]);
|
SelectTab(tabs[startTab ?? typeof(TabSettingsGeneral)]);
|
||||||
}
|
}
|
||||||
|
@@ -27,33 +27,30 @@
|
|||||||
this.textBoxBrowserCSS = new System.Windows.Forms.TextBox();
|
this.textBoxBrowserCSS = new System.Windows.Forms.TextBox();
|
||||||
this.btnCancel = new System.Windows.Forms.Button();
|
this.btnCancel = new System.Windows.Forms.Button();
|
||||||
this.btnApply = new System.Windows.Forms.Button();
|
this.btnApply = new System.Windows.Forms.Button();
|
||||||
this.splitContainer = new System.Windows.Forms.SplitContainer();
|
|
||||||
this.labelBrowser = new System.Windows.Forms.Label();
|
|
||||||
this.labelNotification = new System.Windows.Forms.Label();
|
|
||||||
this.textBoxNotificationCSS = new System.Windows.Forms.TextBox();
|
this.textBoxNotificationCSS = new System.Windows.Forms.TextBox();
|
||||||
this.labelWarning = new System.Windows.Forms.Label();
|
this.btnOpenDevTools = new System.Windows.Forms.Button();
|
||||||
this.btnOpenWiki = new System.Windows.Forms.Button();
|
|
||||||
this.timerTestBrowser = new System.Windows.Forms.Timer(this.components);
|
this.timerTestBrowser = new System.Windows.Forms.Timer(this.components);
|
||||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
|
this.tabPanel = new System.Windows.Forms.TabControl();
|
||||||
this.splitContainer.Panel1.SuspendLayout();
|
this.tabPageBrowser = new System.Windows.Forms.TabPage();
|
||||||
this.splitContainer.Panel2.SuspendLayout();
|
this.tabPageNotification = new System.Windows.Forms.TabPage();
|
||||||
this.splitContainer.SuspendLayout();
|
this.tabPanel.SuspendLayout();
|
||||||
|
this.tabPageBrowser.SuspendLayout();
|
||||||
|
this.tabPageNotification.SuspendLayout();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// textBoxBrowserCSS
|
// textBoxBrowserCSS
|
||||||
//
|
//
|
||||||
this.textBoxBrowserCSS.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
this.textBoxBrowserCSS.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.textBoxBrowserCSS.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
this.textBoxBrowserCSS.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
this.textBoxBrowserCSS.Location = new System.Drawing.Point(0, 16);
|
this.textBoxBrowserCSS.Location = new System.Drawing.Point(3, 3);
|
||||||
this.textBoxBrowserCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
|
this.textBoxBrowserCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
|
||||||
this.textBoxBrowserCSS.Multiline = true;
|
this.textBoxBrowserCSS.Multiline = true;
|
||||||
this.textBoxBrowserCSS.Name = "textBoxBrowserCSS";
|
this.textBoxBrowserCSS.Name = "textBoxBrowserCSS";
|
||||||
this.textBoxBrowserCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
this.textBoxBrowserCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
this.textBoxBrowserCSS.Size = new System.Drawing.Size(378, 251);
|
this.textBoxBrowserCSS.Size = new System.Drawing.Size(426, 332);
|
||||||
this.textBoxBrowserCSS.TabIndex = 1;
|
this.textBoxBrowserCSS.TabIndex = 0;
|
||||||
this.textBoxBrowserCSS.WordWrap = false;
|
this.textBoxBrowserCSS.WordWrap = false;
|
||||||
|
this.textBoxBrowserCSS.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBoxCSS_KeyDown);
|
||||||
this.textBoxBrowserCSS.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textBoxBrowserCSS_KeyUp);
|
this.textBoxBrowserCSS.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textBoxBrowserCSS_KeyUp);
|
||||||
//
|
//
|
||||||
// btnCancel
|
// btnCancel
|
||||||
@@ -61,7 +58,7 @@
|
|||||||
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.btnCancel.AutoSize = true;
|
this.btnCancel.AutoSize = true;
|
||||||
this.btnCancel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
this.btnCancel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.btnCancel.Location = new System.Drawing.Point(657, 285);
|
this.btnCancel.Location = new System.Drawing.Point(337, 384);
|
||||||
this.btnCancel.Name = "btnCancel";
|
this.btnCancel.Name = "btnCancel";
|
||||||
this.btnCancel.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
this.btnCancel.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||||
this.btnCancel.Size = new System.Drawing.Size(57, 25);
|
this.btnCancel.Size = new System.Drawing.Size(57, 25);
|
||||||
@@ -75,7 +72,7 @@
|
|||||||
this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.btnApply.AutoSize = true;
|
this.btnApply.AutoSize = true;
|
||||||
this.btnApply.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
this.btnApply.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.btnApply.Location = new System.Drawing.Point(720, 285);
|
this.btnApply.Location = new System.Drawing.Point(400, 384);
|
||||||
this.btnApply.Name = "btnApply";
|
this.btnApply.Name = "btnApply";
|
||||||
this.btnApply.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
this.btnApply.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||||
this.btnApply.Size = new System.Drawing.Size(52, 25);
|
this.btnApply.Size = new System.Drawing.Size(52, 25);
|
||||||
@@ -84,117 +81,94 @@
|
|||||||
this.btnApply.UseVisualStyleBackColor = true;
|
this.btnApply.UseVisualStyleBackColor = true;
|
||||||
this.btnApply.Click += new System.EventHandler(this.btnApply_Click);
|
this.btnApply.Click += new System.EventHandler(this.btnApply_Click);
|
||||||
//
|
//
|
||||||
// splitContainer
|
|
||||||
//
|
|
||||||
this.splitContainer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.splitContainer.Location = new System.Drawing.Point(12, 12);
|
|
||||||
this.splitContainer.Name = "splitContainer";
|
|
||||||
//
|
|
||||||
// splitContainer.Panel1
|
|
||||||
//
|
|
||||||
this.splitContainer.Panel1.Controls.Add(this.labelBrowser);
|
|
||||||
this.splitContainer.Panel1.Controls.Add(this.textBoxBrowserCSS);
|
|
||||||
this.splitContainer.Panel1MinSize = 64;
|
|
||||||
//
|
|
||||||
// splitContainer.Panel2
|
|
||||||
//
|
|
||||||
this.splitContainer.Panel2.Controls.Add(this.labelNotification);
|
|
||||||
this.splitContainer.Panel2.Controls.Add(this.textBoxNotificationCSS);
|
|
||||||
this.splitContainer.Panel2MinSize = 64;
|
|
||||||
this.splitContainer.Size = new System.Drawing.Size(760, 267);
|
|
||||||
this.splitContainer.SplitterDistance = 378;
|
|
||||||
this.splitContainer.SplitterWidth = 5;
|
|
||||||
this.splitContainer.TabIndex = 0;
|
|
||||||
//
|
|
||||||
// labelBrowser
|
|
||||||
//
|
|
||||||
this.labelBrowser.AutoSize = true;
|
|
||||||
this.labelBrowser.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.labelBrowser.Location = new System.Drawing.Point(-3, 0);
|
|
||||||
this.labelBrowser.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
|
||||||
this.labelBrowser.Name = "labelBrowser";
|
|
||||||
this.labelBrowser.Size = new System.Drawing.Size(49, 15);
|
|
||||||
this.labelBrowser.TabIndex = 0;
|
|
||||||
this.labelBrowser.Text = "Browser";
|
|
||||||
//
|
|
||||||
// labelNotification
|
|
||||||
//
|
|
||||||
this.labelNotification.AutoSize = true;
|
|
||||||
this.labelNotification.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.labelNotification.Location = new System.Drawing.Point(-3, 0);
|
|
||||||
this.labelNotification.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
|
||||||
this.labelNotification.Name = "labelNotification";
|
|
||||||
this.labelNotification.Size = new System.Drawing.Size(70, 15);
|
|
||||||
this.labelNotification.TabIndex = 0;
|
|
||||||
this.labelNotification.Text = "Notification";
|
|
||||||
//
|
|
||||||
// textBoxNotificationCSS
|
// textBoxNotificationCSS
|
||||||
//
|
//
|
||||||
this.textBoxNotificationCSS.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
this.textBoxNotificationCSS.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.textBoxNotificationCSS.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
this.textBoxNotificationCSS.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
this.textBoxNotificationCSS.Location = new System.Drawing.Point(0, 16);
|
this.textBoxNotificationCSS.Location = new System.Drawing.Point(3, 3);
|
||||||
this.textBoxNotificationCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
|
this.textBoxNotificationCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
|
||||||
this.textBoxNotificationCSS.Multiline = true;
|
this.textBoxNotificationCSS.Multiline = true;
|
||||||
this.textBoxNotificationCSS.Name = "textBoxNotificationCSS";
|
this.textBoxNotificationCSS.Name = "textBoxNotificationCSS";
|
||||||
this.textBoxNotificationCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
this.textBoxNotificationCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
this.textBoxNotificationCSS.Size = new System.Drawing.Size(372, 251);
|
this.textBoxNotificationCSS.Size = new System.Drawing.Size(426, 332);
|
||||||
this.textBoxNotificationCSS.TabIndex = 1;
|
this.textBoxNotificationCSS.TabIndex = 0;
|
||||||
this.textBoxNotificationCSS.WordWrap = false;
|
this.textBoxNotificationCSS.WordWrap = false;
|
||||||
|
this.textBoxNotificationCSS.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBoxCSS_KeyDown);
|
||||||
//
|
//
|
||||||
// labelWarning
|
// btnOpenDevTools
|
||||||
//
|
//
|
||||||
this.labelWarning.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.btnOpenDevTools.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.labelWarning.AutoSize = true;
|
this.btnOpenDevTools.AutoSize = true;
|
||||||
this.labelWarning.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
this.btnOpenDevTools.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.labelWarning.Location = new System.Drawing.Point(94, 290);
|
this.btnOpenDevTools.Location = new System.Drawing.Point(12, 384);
|
||||||
this.labelWarning.Name = "labelWarning";
|
this.btnOpenDevTools.Name = "btnOpenDevTools";
|
||||||
this.labelWarning.Size = new System.Drawing.Size(373, 15);
|
this.btnOpenDevTools.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||||
this.labelWarning.TabIndex = 3;
|
this.btnOpenDevTools.Size = new System.Drawing.Size(104, 25);
|
||||||
this.labelWarning.Text = "The code is not validated, please make sure there are no syntax errors.";
|
this.btnOpenDevTools.TabIndex = 3;
|
||||||
//
|
this.btnOpenDevTools.Text = "Open Dev Tools";
|
||||||
// btnOpenWiki
|
this.btnOpenDevTools.UseVisualStyleBackColor = true;
|
||||||
//
|
this.btnOpenDevTools.Click += new System.EventHandler(this.btnOpenDevTools_Click);
|
||||||
this.btnOpenWiki.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
|
||||||
this.btnOpenWiki.AutoSize = true;
|
|
||||||
this.btnOpenWiki.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.btnOpenWiki.Location = new System.Drawing.Point(12, 285);
|
|
||||||
this.btnOpenWiki.Name = "btnOpenWiki";
|
|
||||||
this.btnOpenWiki.Padding = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
|
||||||
this.btnOpenWiki.Size = new System.Drawing.Size(76, 25);
|
|
||||||
this.btnOpenWiki.TabIndex = 4;
|
|
||||||
this.btnOpenWiki.Text = "Open Wiki";
|
|
||||||
this.btnOpenWiki.UseVisualStyleBackColor = true;
|
|
||||||
this.btnOpenWiki.Click += new System.EventHandler(this.btnOpenWiki_Click);
|
|
||||||
//
|
//
|
||||||
// timerTestBrowser
|
// timerTestBrowser
|
||||||
//
|
//
|
||||||
this.timerTestBrowser.Interval = 500;
|
this.timerTestBrowser.Interval = 400;
|
||||||
this.timerTestBrowser.Tick += new System.EventHandler(this.timerTestBrowser_Tick);
|
this.timerTestBrowser.Tick += new System.EventHandler(this.timerTestBrowser_Tick);
|
||||||
//
|
//
|
||||||
|
// tabPanel
|
||||||
|
//
|
||||||
|
this.tabPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.tabPanel.Controls.Add(this.tabPageBrowser);
|
||||||
|
this.tabPanel.Controls.Add(this.tabPageNotification);
|
||||||
|
this.tabPanel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.tabPanel.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.tabPanel.Name = "tabPanel";
|
||||||
|
this.tabPanel.SelectedIndex = 0;
|
||||||
|
this.tabPanel.Size = new System.Drawing.Size(440, 366);
|
||||||
|
this.tabPanel.TabIndex = 0;
|
||||||
|
this.tabPanel.SelectedIndexChanged += new System.EventHandler(this.tabPanel_SelectedIndexChanged);
|
||||||
|
//
|
||||||
|
// tabPageBrowser
|
||||||
|
//
|
||||||
|
this.tabPageBrowser.Controls.Add(this.textBoxBrowserCSS);
|
||||||
|
this.tabPageBrowser.Location = new System.Drawing.Point(4, 24);
|
||||||
|
this.tabPageBrowser.Name = "tabPageBrowser";
|
||||||
|
this.tabPageBrowser.Padding = new System.Windows.Forms.Padding(3);
|
||||||
|
this.tabPageBrowser.Size = new System.Drawing.Size(432, 338);
|
||||||
|
this.tabPageBrowser.TabIndex = 0;
|
||||||
|
this.tabPageBrowser.Text = "Browser";
|
||||||
|
this.tabPageBrowser.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// tabPageNotification
|
||||||
|
//
|
||||||
|
this.tabPageNotification.Controls.Add(this.textBoxNotificationCSS);
|
||||||
|
this.tabPageNotification.Location = new System.Drawing.Point(4, 24);
|
||||||
|
this.tabPageNotification.Name = "tabPageNotification";
|
||||||
|
this.tabPageNotification.Padding = new System.Windows.Forms.Padding(3);
|
||||||
|
this.tabPageNotification.Size = new System.Drawing.Size(432, 338);
|
||||||
|
this.tabPageNotification.TabIndex = 1;
|
||||||
|
this.tabPageNotification.Text = "Notification";
|
||||||
|
this.tabPageNotification.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
// DialogSettingsCSS
|
// DialogSettingsCSS
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(784, 322);
|
this.ClientSize = new System.Drawing.Size(464, 421);
|
||||||
this.Controls.Add(this.btnOpenWiki);
|
this.Controls.Add(this.tabPanel);
|
||||||
this.Controls.Add(this.labelWarning);
|
this.Controls.Add(this.btnOpenDevTools);
|
||||||
this.Controls.Add(this.splitContainer);
|
|
||||||
this.Controls.Add(this.btnApply);
|
this.Controls.Add(this.btnApply);
|
||||||
this.Controls.Add(this.btnCancel);
|
this.Controls.Add(this.btnCancel);
|
||||||
this.MinimumSize = new System.Drawing.Size(620, 160);
|
this.MinimumSize = new System.Drawing.Size(320, 240);
|
||||||
this.Name = "DialogSettingsCSS";
|
this.Name = "DialogSettingsCSS";
|
||||||
this.ShowIcon = false;
|
this.ShowIcon = false;
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
this.splitContainer.Panel1.ResumeLayout(false);
|
this.tabPanel.ResumeLayout(false);
|
||||||
this.splitContainer.Panel1.PerformLayout();
|
this.tabPageBrowser.ResumeLayout(false);
|
||||||
this.splitContainer.Panel2.ResumeLayout(false);
|
this.tabPageBrowser.PerformLayout();
|
||||||
this.splitContainer.Panel2.PerformLayout();
|
this.tabPageNotification.ResumeLayout(false);
|
||||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
|
this.tabPageNotification.PerformLayout();
|
||||||
this.splitContainer.ResumeLayout(false);
|
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
this.PerformLayout();
|
this.PerformLayout();
|
||||||
|
|
||||||
@@ -205,12 +179,11 @@
|
|||||||
private System.Windows.Forms.TextBox textBoxBrowserCSS;
|
private System.Windows.Forms.TextBox textBoxBrowserCSS;
|
||||||
private System.Windows.Forms.Button btnCancel;
|
private System.Windows.Forms.Button btnCancel;
|
||||||
private System.Windows.Forms.Button btnApply;
|
private System.Windows.Forms.Button btnApply;
|
||||||
private System.Windows.Forms.SplitContainer splitContainer;
|
|
||||||
private System.Windows.Forms.TextBox textBoxNotificationCSS;
|
private System.Windows.Forms.TextBox textBoxNotificationCSS;
|
||||||
private System.Windows.Forms.Label labelBrowser;
|
private System.Windows.Forms.Button btnOpenDevTools;
|
||||||
private System.Windows.Forms.Label labelNotification;
|
|
||||||
private System.Windows.Forms.Label labelWarning;
|
|
||||||
private System.Windows.Forms.Button btnOpenWiki;
|
|
||||||
private System.Windows.Forms.Timer timerTestBrowser;
|
private System.Windows.Forms.Timer timerTestBrowser;
|
||||||
|
private System.Windows.Forms.TabControl tabPanel;
|
||||||
|
private System.Windows.Forms.TabPage tabPageBrowser;
|
||||||
|
private System.Windows.Forms.TabPage tabPageNotification;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDuck.Core.Controls;
|
using TweetDuck.Core.Controls;
|
||||||
using TweetDuck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
@@ -9,19 +11,108 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
|
|||||||
public string NotificationCSS => textBoxNotificationCSS.Text;
|
public string NotificationCSS => textBoxNotificationCSS.Text;
|
||||||
|
|
||||||
private readonly Action<string> reinjectBrowserCSS;
|
private readonly Action<string> reinjectBrowserCSS;
|
||||||
|
private readonly Action openDevTools;
|
||||||
|
|
||||||
public DialogSettingsCSS(Action<string> reinjectBrowserCSS){ // TODO high dpi breaks scaling of things inside the panel...
|
public DialogSettingsCSS(Action<string> reinjectBrowserCSS, Action openDevTools){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Text = Program.BrandName+" Options - CSS";
|
Text = Program.BrandName+" Options - CSS";
|
||||||
|
|
||||||
this.reinjectBrowserCSS = reinjectBrowserCSS;
|
this.reinjectBrowserCSS = reinjectBrowserCSS;
|
||||||
|
this.openDevTools = openDevTools;
|
||||||
|
|
||||||
textBoxBrowserCSS.EnableMultilineShortcuts();
|
textBoxBrowserCSS.EnableMultilineShortcuts();
|
||||||
textBoxBrowserCSS.Text = Program.UserConfig.CustomBrowserCSS ?? "";
|
textBoxBrowserCSS.Text = Program.UserConfig.CustomBrowserCSS ?? "";
|
||||||
|
|
||||||
textBoxNotificationCSS.EnableMultilineShortcuts();
|
textBoxNotificationCSS.EnableMultilineShortcuts();
|
||||||
textBoxNotificationCSS.Text = Program.UserConfig.CustomNotificationCSS ?? "";
|
textBoxNotificationCSS.Text = Program.UserConfig.CustomNotificationCSS ?? "";
|
||||||
|
|
||||||
|
if (!BrowserUtils.HasDevTools){
|
||||||
|
btnOpenDevTools.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveControl = textBoxBrowserCSS;
|
||||||
|
textBoxBrowserCSS.Select(textBoxBrowserCSS.TextLength, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tabPanel_SelectedIndexChanged(object sender, EventArgs e){
|
||||||
|
TextBox tb = tabPanel.SelectedTab.Controls.OfType<TextBox>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (tb != null){
|
||||||
|
tb.Focus();
|
||||||
|
tb.Select(tb.TextLength, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void textBoxCSS_KeyDown(object sender, KeyEventArgs e){
|
||||||
|
TextBox tb = (TextBox)sender;
|
||||||
|
string text = tb.Text;
|
||||||
|
|
||||||
|
if (e.KeyCode == Keys.Back && e.Modifiers == Keys.Control){
|
||||||
|
e.SuppressKeyPress = true;
|
||||||
|
|
||||||
|
int deleteTo = tb.SelectionStart;
|
||||||
|
|
||||||
|
if (deleteTo > 0){
|
||||||
|
char initialChar = text[--deleteTo];
|
||||||
|
bool shouldDeleteAlphanumeric = char.IsLetterOrDigit(initialChar);
|
||||||
|
|
||||||
|
while(--deleteTo >= 0){
|
||||||
|
if ((shouldDeleteAlphanumeric && !char.IsLetterOrDigit(text[deleteTo])) ||
|
||||||
|
(!shouldDeleteAlphanumeric && text[deleteTo] != initialChar)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(deleteTo < text.Length-1 && text[deleteTo] == '\r' && text[deleteTo+1] == '\n')){
|
||||||
|
++deleteTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
tb.Select(deleteTo, tb.SelectionLength+tb.SelectionStart-deleteTo);
|
||||||
|
tb.SelectedText = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (e.KeyCode == Keys.Back && e.Modifiers == Keys.None){
|
||||||
|
int deleteTo = tb.SelectionStart;
|
||||||
|
|
||||||
|
if (deleteTo > 1 && text[deleteTo-1] == ' ' && text[deleteTo-2] == ' '){
|
||||||
|
e.SuppressKeyPress = true;
|
||||||
|
|
||||||
|
tb.Select(deleteTo-2, 2);
|
||||||
|
tb.SelectedText = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (e.KeyCode == Keys.Enter && e.Modifiers == Keys.None && tb.SelectionLength == 0){
|
||||||
|
int insertAt = tb.SelectionStart, cursorOffset = 0;
|
||||||
|
string insertText;
|
||||||
|
|
||||||
|
if (insertAt == 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (text[insertAt-1] == '{'){
|
||||||
|
insertText = Environment.NewLine+" ";
|
||||||
|
|
||||||
|
int nextBracket = insertAt < text.Length ? text.IndexOfAny(new char[]{ '{', '}' }, insertAt+1) : -1;
|
||||||
|
|
||||||
|
if (nextBracket == -1 || text[nextBracket] == '{'){
|
||||||
|
string insertExtra = Environment.NewLine+"}";
|
||||||
|
insertText += insertExtra;
|
||||||
|
cursorOffset -= insertExtra.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
int lineStart = text.LastIndexOf('\n', tb.SelectionStart-1);
|
||||||
|
|
||||||
|
Match match = Regex.Match(text.Substring(lineStart == -1 ? 0 : lineStart+1), "^([ \t]+)");
|
||||||
|
insertText = match.Success ? Environment.NewLine+match.Groups[1].Value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(insertText)){
|
||||||
|
e.SuppressKeyPress = true;
|
||||||
|
tb.Text = text.Insert(insertAt, insertText);
|
||||||
|
tb.SelectionStart = insertAt+cursorOffset+insertText.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void textBoxBrowserCSS_KeyUp(object sender, KeyEventArgs e){
|
private void textBoxBrowserCSS_KeyUp(object sender, KeyEventArgs e){
|
||||||
@@ -34,8 +125,8 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
|
|||||||
timerTestBrowser.Stop();
|
timerTestBrowser.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnOpenWiki_Click(object sender, EventArgs e){
|
private void btnOpenDevTools_Click(object sender, EventArgs e){
|
||||||
BrowserUtils.OpenExternalBrowser("https://github.com/chylex/TweetDuck/wiki");
|
openDevTools();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnApply_Click(object sender, EventArgs e){
|
private void btnApply_Click(object sender, EventArgs e){
|
||||||
|
@@ -34,7 +34,7 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
|
|||||||
|
|
||||||
private ProfileManager.Items _selectedItems = ProfileManager.Items.None;
|
private ProfileManager.Items _selectedItems = ProfileManager.Items.None;
|
||||||
|
|
||||||
public DialogSettingsManage(PluginManager plugins){
|
public DialogSettingsManage(PluginManager plugins, bool openImportImmediately = false){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.plugins = plugins;
|
this.plugins = plugins;
|
||||||
@@ -44,6 +44,11 @@ namespace TweetDuck.Core.Other.Settings.Dialogs{
|
|||||||
this.checkBoxMap[cbSystemConfig] = ProfileManager.Items.SystemConfig;
|
this.checkBoxMap[cbSystemConfig] = ProfileManager.Items.SystemConfig;
|
||||||
this.checkBoxMap[cbSession] = ProfileManager.Items.Session;
|
this.checkBoxMap[cbSession] = ProfileManager.Items.Session;
|
||||||
this.checkBoxMap[cbPluginData] = ProfileManager.Items.PluginData;
|
this.checkBoxMap[cbPluginData] = ProfileManager.Items.PluginData;
|
||||||
|
|
||||||
|
if (openImportImmediately){
|
||||||
|
radioImport.Checked = true;
|
||||||
|
btnContinue_Click(null, EventArgs.Empty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void radioDecision_CheckedChanged(object sender, EventArgs e){
|
private void radioDecision_CheckedChanged(object sender, EventArgs e){
|
||||||
|
@@ -13,18 +13,20 @@ namespace TweetDuck.Core.Other.Settings{
|
|||||||
private static SystemConfig SysConfig => Program.SystemConfig;
|
private static SystemConfig SysConfig => Program.SystemConfig;
|
||||||
|
|
||||||
private readonly Action<string> reinjectBrowserCSS;
|
private readonly Action<string> reinjectBrowserCSS;
|
||||||
|
private readonly Action openDevTools;
|
||||||
|
|
||||||
public TabSettingsAdvanced(Action<string> reinjectBrowserCSS){
|
public TabSettingsAdvanced(Action<string> reinjectBrowserCSS, Action openDevTools){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.reinjectBrowserCSS = reinjectBrowserCSS;
|
this.reinjectBrowserCSS = reinjectBrowserCSS;
|
||||||
|
this.openDevTools = openDevTools;
|
||||||
|
|
||||||
toolTip.SetToolTip(btnOpenAppFolder, "Opens the folder where the app is located.");
|
toolTip.SetToolTip(btnOpenAppFolder, "Opens the folder where the app is located.");
|
||||||
toolTip.SetToolTip(btnOpenDataFolder, "Opens the folder where your profile data is located.");
|
toolTip.SetToolTip(btnOpenDataFolder, "Opens the folder where your profile data is located.");
|
||||||
toolTip.SetToolTip(btnRestart, "Restarts the program using the same command\r\nline arguments that were used at launch.");
|
toolTip.SetToolTip(btnRestart, "Restarts the program using the same command\r\nline arguments that were used at launch.");
|
||||||
toolTip.SetToolTip(btnRestartArgs, "Restarts the program with customizable\r\ncommand line arguments.");
|
toolTip.SetToolTip(btnRestartArgs, "Restarts the program with customizable\r\ncommand line arguments.");
|
||||||
|
|
||||||
toolTip.SetToolTip(checkHardwareAcceleration, "Uses graphics card to improve performance. Disable if you experience\r\nvisual glitches. This option will not be exported in a profile.");
|
toolTip.SetToolTip(checkHardwareAcceleration, "Uses graphics card to improve performance. Disable if you experience visual glitches, or to save a small amount of RAM.");
|
||||||
|
|
||||||
toolTip.SetToolTip(btnClearCache, "Clearing cache will free up space taken by downloaded images and other resources.");
|
toolTip.SetToolTip(btnClearCache, "Clearing cache will free up space taken by downloaded images and other resources.");
|
||||||
toolTip.SetToolTip(checkClearCacheAuto, "Automatically clears cache when its size exceeds the set threshold. Note that cache can only be cleared when closing TweetDuck.");
|
toolTip.SetToolTip(checkClearCacheAuto, "Automatically clears cache when its size exceeds the set threshold. Note that cache can only be cleared when closing TweetDuck.");
|
||||||
@@ -32,13 +34,7 @@ namespace TweetDuck.Core.Other.Settings{
|
|||||||
toolTip.SetToolTip(btnEditCefArgs, "Set custom command line arguments for Chromium Embedded Framework.");
|
toolTip.SetToolTip(btnEditCefArgs, "Set custom command line arguments for Chromium Embedded Framework.");
|
||||||
toolTip.SetToolTip(btnEditCSS, "Set custom CSS for browser and notification windows.");
|
toolTip.SetToolTip(btnEditCSS, "Set custom CSS for browser and notification windows.");
|
||||||
|
|
||||||
if (SystemConfig.IsHardwareAccelerationSupported){
|
checkHardwareAcceleration.Checked = SysConfig.HardwareAcceleration;
|
||||||
checkHardwareAcceleration.Checked = SysConfig.HardwareAcceleration;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
checkHardwareAcceleration.Enabled = false;
|
|
||||||
checkHardwareAcceleration.Checked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkClearCacheAuto.Checked = SysConfig.ClearCacheAutomatically;
|
checkClearCacheAuto.Checked = SysConfig.ClearCacheAutomatically;
|
||||||
numClearCacheThreshold.Enabled = checkClearCacheAuto.Checked;
|
numClearCacheThreshold.Enabled = checkClearCacheAuto.Checked;
|
||||||
@@ -109,7 +105,7 @@ namespace TweetDuck.Core.Other.Settings{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void btnEditCSS_Click(object sender, EventArgs e){
|
private void btnEditCSS_Click(object sender, EventArgs e){
|
||||||
DialogSettingsCSS form = new DialogSettingsCSS(reinjectBrowserCSS);
|
DialogSettingsCSS form = new DialogSettingsCSS(reinjectBrowserCSS, openDevTools);
|
||||||
|
|
||||||
form.VisibleChanged += (sender2, args2) => {
|
form.VisibleChanged += (sender2, args2) => {
|
||||||
form.MoveToCenter(ParentForm);
|
form.MoveToCenter(ParentForm);
|
||||||
|
@@ -7,7 +7,6 @@ using TweetDuck.Core.Handling.General;
|
|||||||
using TweetDuck.Core.Other.Settings.Dialogs;
|
using TweetDuck.Core.Other.Settings.Dialogs;
|
||||||
using TweetDuck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
using TweetDuck.Updates;
|
using TweetDuck.Updates;
|
||||||
using TweetDuck.Updates.Events;
|
|
||||||
|
|
||||||
namespace TweetDuck.Core.Other.Settings{
|
namespace TweetDuck.Core.Other.Settings{
|
||||||
sealed partial class TabSettingsGeneral : BaseTabSettings{
|
sealed partial class TabSettingsGeneral : BaseTabSettings{
|
||||||
@@ -210,11 +209,6 @@ namespace TweetDuck.Core.Other.Settings{
|
|||||||
|
|
||||||
btnCheckUpdates.Enabled = false;
|
btnCheckUpdates.Enabled = false;
|
||||||
updateCheckEventId = updates.Check(true);
|
updateCheckEventId = updates.Check(true);
|
||||||
|
|
||||||
if (updateCheckEventId == UpdateHandler.CheckCodeNotOnTweetDeck){
|
|
||||||
FormMessage.Error("Update Check", "Updates can only be checked once TweetDeck is fully loaded.", FormMessage.OK);
|
|
||||||
btnCheckUpdates.Enabled = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Configuration;
|
||||||
|
using Res = TweetDuck.Properties.Resources;
|
||||||
|
|
||||||
namespace TweetDuck.Core.Other{
|
namespace TweetDuck.Core.Other{
|
||||||
sealed partial class TrayIcon : Component{
|
sealed partial class TrayIcon : Component{
|
||||||
@@ -8,6 +10,8 @@ namespace TweetDuck.Core.Other{
|
|||||||
Disabled, DisplayOnly, MinimizeToTray, CloseToTray, Combined
|
Disabled, DisplayOnly, MinimizeToTray, CloseToTray, Combined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static UserConfig Config => Program.UserConfig;
|
||||||
|
|
||||||
public event EventHandler ClickRestore;
|
public event EventHandler ClickRestore;
|
||||||
public event EventHandler ClickClose;
|
public event EventHandler ClickClose;
|
||||||
|
|
||||||
@@ -17,12 +21,9 @@ namespace TweetDuck.Core.Other{
|
|||||||
}
|
}
|
||||||
|
|
||||||
set{
|
set{
|
||||||
if (value){
|
|
||||||
notifyIcon.Icon = Properties.Resources.icon_tray;
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyIcon.Visible = value;
|
notifyIcon.Visible = value;
|
||||||
hasNotifications = false;
|
hasNotifications = false;
|
||||||
|
UpdateIcon();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,9 +33,9 @@ namespace TweetDuck.Core.Other{
|
|||||||
}
|
}
|
||||||
|
|
||||||
set{
|
set{
|
||||||
if (hasNotifications != value && Visible){
|
if (hasNotifications != value){
|
||||||
notifyIcon.Icon = value ? Properties.Resources.icon_tray_new : Properties.Resources.icon_tray;
|
|
||||||
hasNotifications = value;
|
hasNotifications = value;
|
||||||
|
UpdateIcon();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,14 +54,26 @@ namespace TweetDuck.Core.Other{
|
|||||||
|
|
||||||
this.notifyIcon.ContextMenu = contextMenu;
|
this.notifyIcon.ContextMenu = contextMenu;
|
||||||
this.notifyIcon.Text = Program.BrandName;
|
this.notifyIcon.Text = Program.BrandName;
|
||||||
|
|
||||||
|
Config.MuteToggled += Config_MuteToggled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrayIcon(IContainer container) : this(){
|
public TrayIcon(IContainer container) : this(){
|
||||||
container.Add(this);
|
container.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateIcon(){
|
||||||
|
if (Visible){
|
||||||
|
notifyIcon.Icon = hasNotifications ? Res.icon_tray_new : Config.MuteNotifications ? Res.icon_tray_muted : Res.icon_tray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// event handlers
|
// event handlers
|
||||||
|
|
||||||
|
private void Config_MuteToggled(object sender, EventArgs e){
|
||||||
|
UpdateIcon();
|
||||||
|
}
|
||||||
|
|
||||||
private void trayIcon_MouseClick(object sender, MouseEventArgs e){
|
private void trayIcon_MouseClick(object sender, MouseEventArgs e){
|
||||||
if (e.Button == MouseButtons.Left){
|
if (e.Button == MouseButtons.Left){
|
||||||
menuItemRestore_Click(sender, e);
|
menuItemRestore_Click(sender, e);
|
||||||
@@ -68,7 +81,7 @@ namespace TweetDuck.Core.Other{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void contextMenu_Popup(object sender, EventArgs e){
|
private void contextMenu_Popup(object sender, EventArgs e){
|
||||||
contextMenu.MenuItems[1].Checked = Program.UserConfig.MuteNotifications;
|
contextMenu.MenuItems[1].Checked = Config.MuteNotifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void menuItemRestore_Click(object sender, EventArgs e){
|
private void menuItemRestore_Click(object sender, EventArgs e){
|
||||||
@@ -76,8 +89,8 @@ namespace TweetDuck.Core.Other{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void menuItemMuteNotifications_Click(object sender, EventArgs e){
|
private void menuItemMuteNotifications_Click(object sender, EventArgs e){
|
||||||
Program.UserConfig.MuteNotifications = !contextMenu.MenuItems[1].Checked;
|
Config.MuteNotifications = !contextMenu.MenuItems[1].Checked;
|
||||||
Program.UserConfig.Save();
|
Config.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void menuItemClose_Click(object sender, EventArgs e){
|
private void menuItemClose_Click(object sender, EventArgs e){
|
||||||
|
@@ -39,15 +39,17 @@ namespace TweetDuck.Core{
|
|||||||
|
|
||||||
private string prevSoundNotificationPath = null;
|
private string prevSoundNotificationPath = null;
|
||||||
|
|
||||||
public TweetDeckBrowser(FormBrowser owner, TweetDeckBridge bridge){
|
public TweetDeckBrowser(FormBrowser owner, TweetDeckBridge tdBridge, UpdateBridge updateBridge){
|
||||||
|
RequestHandlerBrowser requestHandler = new RequestHandlerBrowser();
|
||||||
|
|
||||||
this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){
|
this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){
|
||||||
DialogHandler = new FileDialogHandler(),
|
DialogHandler = new FileDialogHandler(),
|
||||||
DragHandler = new DragHandlerBrowser(),
|
DragHandler = new DragHandlerBrowser(requestHandler),
|
||||||
MenuHandler = new ContextMenuBrowser(owner),
|
MenuHandler = new ContextMenuBrowser(owner),
|
||||||
JsDialogHandler = new JavaScriptDialogHandler(),
|
JsDialogHandler = new JavaScriptDialogHandler(),
|
||||||
KeyboardHandler = new KeyboardHandlerBrowser(owner),
|
KeyboardHandler = new KeyboardHandlerBrowser(owner),
|
||||||
LifeSpanHandler = new LifeSpanHandler(),
|
LifeSpanHandler = new LifeSpanHandler(),
|
||||||
RequestHandler = new RequestHandlerBrowser()
|
RequestHandler = requestHandler
|
||||||
};
|
};
|
||||||
|
|
||||||
this.browser.LoadingStateChanged += browser_LoadingStateChanged;
|
this.browser.LoadingStateChanged += browser_LoadingStateChanged;
|
||||||
@@ -55,7 +57,8 @@ namespace TweetDuck.Core{
|
|||||||
this.browser.FrameLoadEnd += browser_FrameLoadEnd;
|
this.browser.FrameLoadEnd += browser_FrameLoadEnd;
|
||||||
this.browser.LoadError += browser_LoadError;
|
this.browser.LoadError += browser_LoadError;
|
||||||
|
|
||||||
this.browser.RegisterAsyncJsObject("$TD", bridge);
|
this.browser.RegisterAsyncJsObject("$TD", tdBridge);
|
||||||
|
this.browser.RegisterAsyncJsObject("$TDU", updateBridge);
|
||||||
|
|
||||||
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;
|
||||||
@@ -143,25 +146,28 @@ namespace TweetDuck.Core{
|
|||||||
private void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
private void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
||||||
IFrame frame = e.Frame;
|
IFrame frame = e.Frame;
|
||||||
|
|
||||||
if (frame.IsMain && TwitterUtils.IsTweetDeckWebsite(frame)){
|
if (frame.IsMain){
|
||||||
UpdateProperties();
|
if (TwitterUtils.IsTweetDeckWebsite(frame)){
|
||||||
TweetDeckBridge.RestoreSessionData(frame);
|
UpdateProperties();
|
||||||
ScriptLoader.ExecuteFile(frame, "code.js", browser);
|
TweetDeckBridge.RestoreSessionData(frame);
|
||||||
|
ScriptLoader.ExecuteFile(frame, "code.js", browser);
|
||||||
|
|
||||||
|
InjectBrowserCSS();
|
||||||
|
ReinjectCustomCSS(Program.UserConfig.CustomBrowserCSS);
|
||||||
|
UserConfig_SoundNotificationInfoChanged(null, EventArgs.Empty);
|
||||||
|
|
||||||
|
TweetDeckBridge.ResetStaticProperties();
|
||||||
|
|
||||||
|
if (Arguments.HasFlag(Arguments.ArgIgnoreGDPR)){
|
||||||
|
ScriptLoader.ExecuteScript(frame, "TD.storage.Account.prototype.requiresConsent = function(){ return false; }", "gen:gdpr");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Program.UserConfig.FirstRun){
|
||||||
|
ScriptLoader.ExecuteFile(frame, "introduction.js", browser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ScriptLoader.ExecuteFile(frame, "update.js", browser);
|
ScriptLoader.ExecuteFile(frame, "update.js", browser);
|
||||||
|
|
||||||
InjectBrowserCSS();
|
|
||||||
ReinjectCustomCSS(Program.UserConfig.CustomBrowserCSS);
|
|
||||||
UserConfig_SoundNotificationInfoChanged(null, EventArgs.Empty);
|
|
||||||
|
|
||||||
TweetDeckBridge.ResetStaticProperties();
|
|
||||||
|
|
||||||
if (Arguments.HasFlag(Arguments.ArgIgnoreGDPR)){
|
|
||||||
ScriptLoader.ExecuteScript(frame, @"TD.storage.Account.prototype.requiresConsent = function(){ return false; }", "gen:gdpr");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Program.UserConfig.FirstRun){
|
|
||||||
ScriptLoader.ExecuteFile(frame, "introduction.js", browser);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +177,7 @@ namespace TweetDuck.Core{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!e.FailedUrl.StartsWith("http://td/", StringComparison.Ordinal)){
|
if (!e.FailedUrl.StartsWith("http://td/", StringComparison.Ordinal)){
|
||||||
string errorPage = ScriptLoader.LoadResource("pages/error.html", true);
|
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");
|
browser.LoadHtml(errorPage.Replace("{err}", BrowserUtils.GetErrorName(e.ErrorCode)), "http://td/error");
|
||||||
@@ -220,7 +226,7 @@ namespace TweetDuck.Core{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void InjectBrowserCSS(){
|
public void InjectBrowserCSS(){
|
||||||
browser.ExecuteScriptAsync("TDGF_injectBrowserCSS", ScriptLoader.LoadResource("styles/browser.css", false, browser)?.TrimEnd() ?? string.Empty);
|
browser.ExecuteScriptAsync("TDGF_injectBrowserCSS", ScriptLoader.LoadResource("styles/browser.css", browser)?.TrimEnd() ?? string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReinjectCustomCSS(string css){
|
public void ReinjectCustomCSS(string css){
|
||||||
@@ -258,5 +264,9 @@ namespace TweetDuck.Core{
|
|||||||
public void ShowUpdateNotification(string versionTag, string releaseNotes){
|
public void ShowUpdateNotification(string versionTag, string releaseNotes){
|
||||||
browser.ExecuteScriptAsync("TDUF_displayNotification", versionTag, Convert.ToBase64String(Encoding.GetEncoding("iso-8859-1").GetBytes(releaseNotes)));
|
browser.ExecuteScriptAsync("TDUF_displayNotification", versionTag, Convert.ToBase64String(Encoding.GetEncoding("iso-8859-1").GetBytes(releaseNotes)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OpenDevTools(){
|
||||||
|
browser.ShowDevTools();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,13 +14,25 @@ namespace TweetDuck.Core.Utils{
|
|||||||
public static string UserAgentVanilla => Program.BrandName+" "+Application.ProductVersion;
|
public static string UserAgentVanilla => Program.BrandName+" "+Application.ProductVersion;
|
||||||
public static string UserAgentChrome => "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/"+Cef.ChromiumVersion+" Safari/537.36";
|
public static string UserAgentChrome => "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/"+Cef.ChromiumVersion+" Safari/537.36";
|
||||||
|
|
||||||
|
public static readonly bool HasDevTools = File.Exists(Path.Combine(Program.ProgramPath, "devtools_resources.pak"));
|
||||||
|
|
||||||
public static void SetupCefArgs(IDictionary<string, string> args){
|
public static void SetupCefArgs(IDictionary<string, string> args){
|
||||||
if (!Program.SystemConfig.HardwareAcceleration){
|
if (!Program.SystemConfig.HardwareAcceleration){
|
||||||
args["disable-gpu"] = "1";
|
args["disable-gpu"] = "1";
|
||||||
args["disable-gpu-vsync"] = "1";
|
args["disable-gpu-vsync"] = "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Program.UserConfig.EnableSmoothScrolling){
|
if (Program.UserConfig.EnableSmoothScrolling){
|
||||||
|
args["disable-threaded-scrolling"] = "1";
|
||||||
|
|
||||||
|
if (args.TryGetValue("disable-features", out string disabledFeatures)){
|
||||||
|
args["disable-features"] = "TouchpadAndWheelScrollLatching,"+disabledFeatures;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
args["disable-features"] = "TouchpadAndWheelScrollLatching";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
args["disable-smooth-scrolling"] = "1";
|
args["disable-smooth-scrolling"] = "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,10 +28,14 @@ namespace TweetDuck.Core.Utils{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int CountOccurrences(string source, string substring){
|
public static int CountOccurrences(string source, string substring){
|
||||||
int count = 0, index = 0;
|
if (substring.Length == 0){
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(substring), "Searched substring must not be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0, index = 0, length = substring.Length;
|
||||||
|
|
||||||
while((index = source.IndexOf(substring, index)) != -1){
|
while((index = source.IndexOf(substring, index)) != -1){
|
||||||
index += substring.Length;
|
index += length;
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -76,22 +76,14 @@ namespace TweetDuck.Core.Utils{
|
|||||||
string firstImageLink = GetMediaLink(urls[0], quality);
|
string firstImageLink = GetMediaLink(urls[0], quality);
|
||||||
int qualityIndex = firstImageLink.IndexOf(':', firstImageLink.LastIndexOf('/'));
|
int qualityIndex = firstImageLink.IndexOf(':', firstImageLink.LastIndexOf('/'));
|
||||||
|
|
||||||
string file = GetImageFileName(firstImageLink);
|
string filename = GetImageFileName(firstImageLink);
|
||||||
string ext = Path.GetExtension(file); // includes dot
|
string ext = Path.GetExtension(filename); // includes dot
|
||||||
|
|
||||||
string[] fileNameParts = qualityIndex == -1 ? new string[]{
|
|
||||||
Path.ChangeExtension(file, null)
|
|
||||||
} : new string[]{
|
|
||||||
username,
|
|
||||||
Path.ChangeExtension(file, null),
|
|
||||||
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 = $"{string.Join(" ", fileNameParts.Where(part => !string.IsNullOrEmpty(part)))}{ext}",
|
FileName = qualityIndex == -1 ? filename : $"{username} {Path.ChangeExtension(filename, null)} {firstImageLink.Substring(qualityIndex+1)}".Trim()+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){
|
||||||
@@ -122,12 +114,12 @@ namespace TweetDuck.Core.Utils{
|
|||||||
AutoUpgradeEnabled = true,
|
AutoUpgradeEnabled = true,
|
||||||
OverwritePrompt = true,
|
OverwritePrompt = true,
|
||||||
Title = "Save Video",
|
Title = "Save Video",
|
||||||
FileName = string.IsNullOrEmpty(username) ? filename : $"{username} {filename}",
|
FileName = string.IsNullOrEmpty(username) ? filename : $"{username} {filename}".TrimStart(),
|
||||||
Filter = "Video"+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
|
Filter = "Video"+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
|
||||||
}){
|
}){
|
||||||
if (dialog.ShowDialog() == DialogResult.OK){
|
if (dialog.ShowDialog() == DialogResult.OK){
|
||||||
BrowserUtils.DownloadFileAsync(url, dialog.FileName, null, ex => {
|
BrowserUtils.DownloadFileAsync(url, dialog.FileName, null, ex => {
|
||||||
FormMessage.Error("Image Download", "An error occurred while downloading the image: "+ex.Message, FormMessage.OK);
|
FormMessage.Error("Video Download", "An error occurred while downloading the video: "+ex.Message, FormMessage.OK);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,7 @@ namespace TweetDuck.Data{
|
|||||||
this.html = html;
|
this.html = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Inject(string targetHTML){
|
public string InjectInto(string targetHTML){
|
||||||
int index = targetHTML.IndexOf(search, StringComparison.Ordinal);
|
int index = targetHTML.IndexOf(search, StringComparison.Ordinal);
|
||||||
|
|
||||||
if (index == -1){
|
if (index == -1){
|
||||||
|
@@ -24,15 +24,6 @@ namespace TweetDuck.Plugins.Enums{
|
|||||||
return environment == PluginEnvironment.Browser;
|
return environment == PluginEnvironment.Browser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetScriptIdentifier(this PluginEnvironment environment){
|
|
||||||
switch(environment){
|
|
||||||
case PluginEnvironment.None: return "root:plugins";
|
|
||||||
case PluginEnvironment.Browser: return "root:plugins.browser";
|
|
||||||
case PluginEnvironment.Notification: return "root:plugins.notification";
|
|
||||||
default: return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetPluginScriptFile(this PluginEnvironment environment){
|
public static string GetPluginScriptFile(this PluginEnvironment environment){
|
||||||
switch(environment){
|
switch(environment){
|
||||||
case PluginEnvironment.Browser: return "browser.js";
|
case PluginEnvironment.Browser: return "browser.js";
|
||||||
|
@@ -84,14 +84,20 @@ namespace TweetDuck.Plugins{
|
|||||||
|
|
||||||
try{
|
try{
|
||||||
string folderPathName = new DirectoryInfo(rootFolder).FullName;
|
string folderPathName = new DirectoryInfo(rootFolder).FullName;
|
||||||
DirectoryInfo currentInfo = new DirectoryInfo(fullPath);
|
DirectoryInfo currentInfo = new DirectoryInfo(fullPath); // initially points to the file, which is convenient for the Attributes check below
|
||||||
|
DirectoryInfo parentInfo = currentInfo.Parent;
|
||||||
|
|
||||||
while(currentInfo.Parent != null){
|
while(parentInfo != null){
|
||||||
if (currentInfo.Parent.FullName == folderPathName){
|
if (currentInfo.Exists && currentInfo.Attributes.HasFlag(FileAttributes.ReparsePoint)){
|
||||||
|
return string.Empty; // no reason why a plugin should have files/folders with symlinks, junctions, or any other crap
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentInfo.FullName == folderPathName){
|
||||||
return fullPath;
|
return fullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentInfo = currentInfo.Parent;
|
currentInfo = parentInfo;
|
||||||
|
parentInfo = currentInfo.Parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch{
|
catch{
|
||||||
|
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
using TweetDuck.Core.Other.Interfaces;
|
using TweetDuck.Core.Other.Interfaces;
|
||||||
using TweetDuck.Data;
|
using TweetDuck.Data;
|
||||||
using TweetDuck.Plugins.Enums;
|
using TweetDuck.Plugins.Enums;
|
||||||
@@ -12,15 +13,7 @@ using TweetDuck.Resources;
|
|||||||
|
|
||||||
namespace TweetDuck.Plugins{
|
namespace TweetDuck.Plugins{
|
||||||
sealed class PluginManager{
|
sealed class PluginManager{
|
||||||
private static IReadOnlyDictionary<PluginEnvironment, string> LoadSetupScripts(){
|
private static readonly IReadOnlyDictionary<PluginEnvironment, string> PluginSetupScriptNames = PluginEnvironmentExtensions.Map(null, "plugins.browser.js", "plugins.notification.js");
|
||||||
return PluginEnvironmentExtensions.Map(
|
|
||||||
ScriptLoader.LoadResource("plugins.js"),
|
|
||||||
ScriptLoader.LoadResource("plugins.browser.js"),
|
|
||||||
ScriptLoader.LoadResource("plugins.notification.js")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly IReadOnlyDictionary<PluginEnvironment, string> PluginSetupScripts = LoadSetupScripts();
|
|
||||||
|
|
||||||
public string PathOfficialPlugins => Path.Combine(rootPath, "official");
|
public string PathOfficialPlugins => Path.Combine(rootPath, "official");
|
||||||
public string PathCustomPlugins => Path.Combine(rootPath, "user");
|
public string PathCustomPlugins => Path.Combine(rootPath, "user");
|
||||||
@@ -54,8 +47,8 @@ namespace TweetDuck.Plugins{
|
|||||||
Config.PluginChangedState += Config_PluginChangedState;
|
Config.PluginChangedState += Config_PluginChangedState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Register(ITweetDeckBrowser browser, PluginEnvironment environment, bool asMainBrowser = false){
|
public void Register(ITweetDeckBrowser browser, PluginEnvironment environment, Control sync, bool asMainBrowser = false){
|
||||||
browser.OnFrameLoaded(frame => ExecutePlugins(frame, environment));
|
browser.OnFrameLoaded(frame => ExecutePlugins(frame, environment, sync));
|
||||||
browser.RegisterBridge("$TDP", bridge);
|
browser.RegisterBridge("$TDP", bridge);
|
||||||
|
|
||||||
if (asMainBrowser){
|
if (asMainBrowser){
|
||||||
@@ -152,14 +145,11 @@ namespace TweetDuck.Plugins{
|
|||||||
Reloaded?.Invoke(this, new PluginErrorEventArgs(loadErrors));
|
Reloaded?.Invoke(this, new PluginErrorEventArgs(loadErrors));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExecutePlugins(IFrame frame, PluginEnvironment environment){
|
private void ExecutePlugins(IFrame frame, PluginEnvironment environment, Control sync){
|
||||||
if (!HasAnyPlugin(environment)){
|
if (!HasAnyPlugin(environment) || !ScriptLoader.ExecuteFile(frame, PluginSetupScriptNames[environment], sync)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptLoader.ExecuteScript(frame, PluginSetupScripts[environment], environment.GetScriptIdentifier());
|
|
||||||
ScriptLoader.ExecuteScript(frame, PluginSetupScripts[PluginEnvironment.None], PluginEnvironment.None.GetScriptIdentifier());
|
|
||||||
|
|
||||||
bool includeDisabled = environment.IncludesDisabledPlugins();
|
bool includeDisabled = environment.IncludesDisabledPlugins();
|
||||||
|
|
||||||
if (includeDisabled){
|
if (includeDisabled){
|
||||||
|
@@ -19,7 +19,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.14.2";
|
public const string VersionTag = "1.15.1";
|
||||||
|
|
||||||
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"));
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Resources;
|
using System.Resources;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
@@ -42,5 +42,6 @@ using TweetDuck;
|
|||||||
[assembly: CLSCompliant(true)]
|
[assembly: CLSCompliant(true)]
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("UnitTests")]
|
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("TweetTest.System")]
|
||||||
|
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("TweetTest.Unit")]
|
||||||
#endif
|
#endif
|
||||||
|
20
Properties/Resources.Designer.cs
generated
@@ -80,6 +80,16 @@ namespace TweetDuck.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||||
|
/// </summary>
|
||||||
|
internal static System.Drawing.Icon icon_muted {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("icon_muted", resourceCulture);
|
||||||
|
return ((System.Drawing.Icon)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -90,6 +100,16 @@ namespace TweetDuck.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||||
|
/// </summary>
|
||||||
|
internal static System.Drawing.Icon icon_tray_muted {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("icon_tray_muted", resourceCulture);
|
||||||
|
return ((System.Drawing.Icon)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -119,18 +119,24 @@
|
|||||||
</resheader>
|
</resheader>
|
||||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||||
<data name="avatar" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="avatar" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\avatar.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>..\Resources\Images\avatar.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\Images\icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="icon_muted" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\Images\icon-muted.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="icon_tray" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="icon_tray" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\icon-tray.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\Images\icon-tray.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="icon_tray_muted" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\Images\icon-tray-muted.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="icon_tray_new" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="icon_tray_new" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\icon-tray-new.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\Images\icon-tray-new.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="spinner" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="spinner" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\spinner.apng;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>..\Resources\Images\spinner.apng;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
@@ -9,12 +9,13 @@
|
|||||||
The program was built using Visual Studio 2017. Before opening the solution, please make sure you have the following workloads and components installed (optional components that are not listed can be deselected to save space):
|
The program was built using Visual Studio 2017. Before opening the solution, please make sure you have the following workloads and components installed (optional components that are not listed can be deselected to save space):
|
||||||
* **.NET desktop development**
|
* **.NET desktop development**
|
||||||
* .NET Framework 4 – 4.6 development tools
|
* .NET Framework 4 – 4.6 development tools
|
||||||
|
* F# desktop language support
|
||||||
* **Desktop development with C++**
|
* **Desktop development with C++**
|
||||||
* VC++ 2017 v141 toolset
|
* VC++ 2017 latest v141 tools
|
||||||
|
|
||||||
After opening the solution, right-click the solution and select **Restore NuGet Packages**, or manually run this command in the **Package Manager Console**:
|
After opening the solution, right-click the solution and select **Restore NuGet Packages**, or manually run this command in the **Package Manager Console**:
|
||||||
```
|
```
|
||||||
PM> Install-Package CefSharp.WinForms -Version 66.0.0-CI2629 -Source https://www.myget.org/F/cefsharp/api/v3/index.json
|
PM> Install-Package CefSharp.WinForms -Version 67.0.0-CI2662 -Source https://www.myget.org/F/cefsharp/api/v3/index.json
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that some pre-release builds of CefSharp are not available on NuGet. To correctly restore packages in that case, open **Package Manager Settings**, and add `https://www.myget.org/F/cefsharp/api/v3/index.json` to the list of package sources.
|
Note that some pre-release builds of CefSharp are not available on NuGet. To correctly restore packages in that case, open **Package Manager Settings**, and add `https://www.myget.org/F/cefsharp/api/v3/index.json` to the list of package sources.
|
||||||
@@ -27,7 +28,7 @@ While debugging, opening the main menu and clicking **Reload browser** automatic
|
|||||||
|
|
||||||
### Release
|
### Release
|
||||||
|
|
||||||
Open **Batch Build**, tick all `Release` configurations with `x86` platform except for the `UnitTest` project, and click **Rebuild**. Check the status bar to make sure it says **Rebuild All succeeded**; if not, see the [Troubleshooting](#troubleshooting) section.
|
Open **Batch Build**, tick all `Release` configurations with `x86` platform, and click **Rebuild**. Check the status bar to make sure it says **Rebuild All succeeded**; if not, see the [Troubleshooting](#troubleshooting) section.
|
||||||
|
|
||||||
After the build succeeds, the `bin/x86/Release` folder will contain files intended for distribution (no debug symbols or other unnecessary files). You may package these files yourself, or see the [Installers](#installers) section for automated installer generation.
|
After the build succeeds, the `bin/x86/Release` folder will contain files intended for distribution (no debug symbols or other unnecessary files). You may package these files yourself, or see the [Installers](#installers) section for automated installer generation.
|
||||||
|
|
||||||
@@ -63,6 +64,8 @@ After the window closes, three installers will be generated inside the `bld/Outp
|
|||||||
|
|
||||||
#### Notes
|
#### Notes
|
||||||
|
|
||||||
|
> When opening **Batch Build**, you will also see `x64` and `AnyCPU` configurations. These are visible due to what I consider a Visual Studio bug, and will not work without significant changes to the project. Manually running the `Resources/PostCefUpdate.ps1` PowerShell script modifies the downloaded CefSharp packages, and removes the invalid configurations.
|
||||||
|
|
||||||
> There is a small chance running `RUN BUILD.bat` immediately shows a resource error. If that happens, close the console window (which terminates all Inno Setup processes and leaves corrupted installers in the output folder), and run it again.
|
> There is a small chance running `RUN BUILD.bat` immediately shows a resource error. If that happens, close the console window (which terminates all Inno Setup processes and leaves corrupted installers in the output folder), and run it again.
|
||||||
|
|
||||||
> Running `RUN BUILD.bat` uses about 400 MB of RAM due to high compression. You can lower this to about 140 MB by opening `gen_full.iss` and `gen_port.iss`, and changing `LZMADictionarySize=15360` to `LZMADictionarySize=4096`.
|
> Running `RUN BUILD.bat` uses about 400 MB of RAM due to high compression. You can lower this to about 140 MB by opening `gen_full.iss` and `gen_port.iss`, and changing `LZMADictionarySize=15360` to `LZMADictionarySize=4096`.
|
||||||
|
13
Reporter.cs
@@ -47,7 +47,8 @@ namespace TweetDuck{
|
|||||||
public void HandleException(string caption, string message, bool canIgnore, Exception e){
|
public void HandleException(string caption, string message, bool canIgnore, Exception e){
|
||||||
bool loggedSuccessfully = Log(e.ToString());
|
bool loggedSuccessfully = Log(e.ToString());
|
||||||
|
|
||||||
FormMessage form = new FormMessage(caption, message+"\nError: "+e.Message, canIgnore ? MessageBoxIcon.Warning : MessageBoxIcon.Error);
|
string exceptionText = e is ExpandedLogException ? e.Message+"\n\nDetails with potentially sensitive information are in the Error Log." : e.Message;
|
||||||
|
FormMessage form = new FormMessage(caption, message+"\nError: "+exceptionText, canIgnore ? MessageBoxIcon.Warning : MessageBoxIcon.Error);
|
||||||
|
|
||||||
Button btnExit = form.AddButton(FormMessage.Exit);
|
Button btnExit = form.AddButton(FormMessage.Exit);
|
||||||
Button btnIgnore = form.AddButton(FormMessage.Ignore, DialogResult.Ignore, ControlType.Cancel);
|
Button btnIgnore = form.AddButton(FormMessage.Ignore, DialogResult.Ignore, ControlType.Cancel);
|
||||||
@@ -95,5 +96,15 @@ namespace TweetDuck{
|
|||||||
Environment.FailFast(message, new Exception(message));
|
Environment.FailFast(message, new Exception(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class ExpandedLogException : Exception{
|
||||||
|
private readonly string details;
|
||||||
|
|
||||||
|
public ExpandedLogException(Exception source, string details) : base(source.Message, source){
|
||||||
|
this.details = details;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => base.ToString()+"\r\n"+details;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
Resources/..code-workspace
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"name": "Installers",
|
||||||
|
"path": "..\\bld"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Resources",
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"editor.tabSize": 2,
|
||||||
|
"javascript.validate.enable": false,
|
||||||
|
"files.autoGuessEncoding": false,
|
||||||
|
"files.insertFinalNewline": true,
|
||||||
|
"files.trimFinalNewlines": true,
|
||||||
|
"files.encoding": "utf8",
|
||||||
|
}
|
||||||
|
}
|
BIN
Resources/Design/app_logos_large.afdesign
Normal file
BIN
Resources/Design/app_logos_small.afdesign
Normal file
BIN
Resources/Design/icon_pushpin.afdesign
Normal file
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
BIN
Resources/Images/icon-muted.ico
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
Resources/Images/icon-small.ico
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
Resources/Images/icon-tray-muted.ico
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
Resources/Images/icon-tray-new.ico
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
Resources/Images/icon-tray.ico
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
Resources/Images/icon.ico
Normal file
After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -2,6 +2,7 @@ enabled(){
|
|||||||
this.isDebugging = false;
|
this.isDebugging = false;
|
||||||
|
|
||||||
this.onKeyDown = (e) => {
|
this.onKeyDown = (e) => {
|
||||||
|
|
||||||
// ==========================
|
// ==========================
|
||||||
// F4 key - toggle debug mode
|
// F4 key - toggle debug mode
|
||||||
// ==========================
|
// ==========================
|
||||||
@@ -11,8 +12,6 @@ enabled(){
|
|||||||
$(".nav-user-info").first().css("background-color", this.isDebugging ? "#5A6B75" : "#292F33");
|
$(".nav-user-info").first().css("background-color", this.isDebugging ? "#5A6B75" : "#292F33");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug mode handling
|
|
||||||
|
|
||||||
else if (this.isDebugging){
|
else if (this.isDebugging){
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
@@ -22,15 +21,16 @@ enabled(){
|
|||||||
// ===================================
|
// ===================================
|
||||||
|
|
||||||
if (e.keyCode === 78 || e.keyCode === 83){
|
if (e.keyCode === 78 || e.keyCode === 83){
|
||||||
var col = TD.controller.columnManager.getAllOrdered()[0];
|
let col = TD.controller.columnManager.getAllOrdered()[0];
|
||||||
|
let model = col.model;
|
||||||
|
|
||||||
var prevPopup = col.model.getHasNotification();
|
let prevPopup = model.getHasNotification();
|
||||||
var prevSound = col.model.getHasSound();
|
let prevSound = model.getHasSound();
|
||||||
|
|
||||||
col.model.setHasNotification(e.keyCode === 78);
|
model.setHasNotification(e.keyCode === 78);
|
||||||
col.model.setHasSound(e.keyCode === 83);
|
model.setHasSound(e.keyCode === 83);
|
||||||
|
|
||||||
$.publish("/notifications/new",[{
|
$.publish("/notifications/new", [{
|
||||||
column: col,
|
column: col,
|
||||||
items: [
|
items: [
|
||||||
col.updateArray[Math.floor(Math.random()*col.updateArray.length)]
|
col.updateArray[Math.floor(Math.random()*col.updateArray.length)]
|
||||||
@@ -38,8 +38,8 @@ enabled(){
|
|||||||
}]);
|
}]);
|
||||||
|
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
col.model.setHasNotification(prevPopup);
|
model.setHasNotification(prevPopup);
|
||||||
col.model.setHasSound(prevSound);
|
model.setHasSound(prevSound);
|
||||||
}, 1);
|
}, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,29 +1,22 @@
|
|||||||
constructor(){
|
|
||||||
super({
|
|
||||||
requiresPageReload: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
enabled(){
|
enabled(){
|
||||||
// prepare variables and functions
|
const clearColumn = (columnName) => {
|
||||||
var clearColumn = (columnName) => {
|
|
||||||
TD.controller.columnManager.get(columnName).clear();
|
TD.controller.columnManager.get(columnName).clear();
|
||||||
TD.controller.stats.columnActionClick("clear");
|
TD.controller.stats.columnActionClick("clear");
|
||||||
};
|
};
|
||||||
|
|
||||||
var resetColumn = (columnName) => {
|
const resetColumn = (columnName) => {
|
||||||
let col = TD.controller.columnManager.get(columnName);
|
let col = TD.controller.columnManager.get(columnName);
|
||||||
col.model.setClearedTimestamp(0);
|
col.model.setClearedTimestamp(0);
|
||||||
col.reloadTweets();
|
col.reloadTweets();
|
||||||
};
|
};
|
||||||
|
|
||||||
var forEachColumn = (func) => {
|
const forEachColumn = (func) => {
|
||||||
Object.keys(TD.controller.columnManager.getAll()).forEach(func);
|
Object.keys(TD.controller.columnManager.getAll()).forEach(func);
|
||||||
};
|
};
|
||||||
|
|
||||||
var wasShiftPressed = false;
|
let wasShiftPressed = false;
|
||||||
|
|
||||||
var updateShiftState = (pressed) => {
|
const updateShiftState = (pressed) => {
|
||||||
if (pressed != wasShiftPressed){
|
if (pressed != wasShiftPressed){
|
||||||
wasShiftPressed = pressed;
|
wasShiftPressed = pressed;
|
||||||
|
|
||||||
@@ -38,10 +31,17 @@ enabled(){
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// prepare event handlers
|
// event handlers
|
||||||
this.eventClickSingle = function(e){
|
|
||||||
var name = $(this).closest(".js-column").attr("data-column");
|
this.eventClickOneCapture = function(e){
|
||||||
e.shiftKey ? resetColumn(name) : clearColumn(name);
|
if (e.target.getAttribute("data-action") === "td-clearcolumns-dosingle"){
|
||||||
|
let name = $(e.target).closest(".js-column").attr("data-column");
|
||||||
|
e.shiftKey ? resetColumn(name) : clearColumn(name);
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.eventClickAll = function(e){
|
this.eventClickAll = function(e){
|
||||||
@@ -58,10 +58,10 @@ enabled(){
|
|||||||
forEachColumn(e.shiftKey ? resetColumn : clearColumn);
|
forEachColumn(e.shiftKey ? resetColumn : clearColumn);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
var focusedColumn = $(".js-column.is-focused");
|
let focusedColumn = $(".js-column.is-focused");
|
||||||
|
|
||||||
if (focusedColumn.length){
|
if (focusedColumn.length){
|
||||||
var name = focusedColumn.attr("data-column");
|
let name = focusedColumn.attr("data-column");
|
||||||
e.shiftKey ? resetColumn(name) : clearColumn(name);
|
e.shiftKey ? resetColumn(name) : clearColumn(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,59 +74,86 @@ enabled(){
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// setup clear all button
|
this.eventKeyboardShortcuts = function(e){
|
||||||
|
$(".keyboard-shortcut-list").first().append(`
|
||||||
|
<dd class="keyboard-shortcut-definition" style="white-space:nowrap">
|
||||||
|
<span class="text-like-keyboard-key">1</span> … <span class="text-like-keyboard-key">9</span> + <span class="text-like-keyboard-key">Del</span> Clear column 1-9
|
||||||
|
</dd>
|
||||||
|
<dd class="keyboard-shortcut-definition">
|
||||||
|
<span class="text-like-keyboard-key">Alt</span> + <span class="text-like-keyboard-key">Del</span> Clear all columns
|
||||||
|
</dd>`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// update UI
|
||||||
|
|
||||||
this.btnClearAllHTML = `
|
this.btnClearAllHTML = `
|
||||||
<a class="clear-columns-btn-all-parent js-header-action link-clean cf app-nav-link padding-h--10" data-title="Clear columns (hold Shift to restore)" data-action="td-clearcolumns-doall">
|
<a class="clear-columns-btn-all-parent js-header-action link-clean cf app-nav-link padding-h--10" data-title="Clear columns (hold Shift to restore)" data-action="td-clearcolumns-doall">
|
||||||
<div class="obj-left margin-l--2"><i class="icon icon-medium icon-clear-timeline"></i></div>
|
<div class="obj-left margin-l--2"><i class="icon icon-medium icon-clear-timeline"></i></div>
|
||||||
<div class="clear-columns-btn-all nbfc padding-ts hide-condensed txt-size--16 app-nav-link-text">Clear columns</div>
|
<div class="clear-columns-btn-all nbfc padding-ts hide-condensed txt-size--16 app-nav-link-text">Clear columns</div>
|
||||||
</a>`;
|
</a>`;
|
||||||
|
|
||||||
// add column buttons and keyboard shortcut info to UI
|
this.btnClearOneHTML = `
|
||||||
window.TDPF_injectMustache("column/column_header.mustache", "prepend", "<a data-testid=\"optionsToggle\"", `
|
|
||||||
<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)"></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>`;
|
||||||
|
|
||||||
window.TDPF_injectMustache("keyboard_shortcut_list.mustache", "prepend", "</dl> <dl", `
|
this.prevNavMenuMustache = TD.mustaches["menus/column_nav_menu.mustache"];
|
||||||
<dd class="keyboard-shortcut-definition" style="white-space:nowrap">
|
window.TDPF_injectMustache("menus/column_nav_menu.mustache", "replace", "{{_i}}Add column{{/i}}</div> </a> </div>", `{{_i}}Add column{{/i}}</div></a>${this.btnClearAllHTML}</div>`);
|
||||||
<span class="text-like-keyboard-key">1</span> … <span class="text-like-keyboard-key">9</span> + <span class="text-like-keyboard-key">Del</span> Clear column 1-9
|
|
||||||
</dd><dd class="keyboard-shortcut-definition">
|
|
||||||
<span class="text-like-keyboard-key">Alt</span> + <span class="text-like-keyboard-key">Del</span> Clear all columns
|
|
||||||
</dd>`);
|
|
||||||
|
|
||||||
window.TDPF_injectMustache("menus/column_nav_menu.mustache", "replace", "{{_i}}Add column{{/i}}</div> </a> </div>", `{{_i}}Add column{{/i}}</div></a>${this.btnClearAllHTML}</div>`)
|
this.prevColumnHeaderMustache = TD.mustaches["column/column_header.mustache"];
|
||||||
|
window.TDPF_injectMustache("column/column_header.mustache", "prepend", "<a data-testid=\"optionsToggle\"", this.btnClearOneHTML);
|
||||||
|
|
||||||
// load custom style
|
if (TD.ready){
|
||||||
var css = window.TDPF_createCustomStyle(this);
|
$(".js-header-add-column").after(this.btnClearAllHTML);
|
||||||
css.insert(".js-app-add-column.is-hidden + .clear-columns-btn-all-parent { display: none; }");
|
$("a[data-testid='optionsToggle']", ".js-column-header").before(this.btnClearOneHTML);
|
||||||
css.insert(".column-header-links { min-width: 51px !important; }");
|
}
|
||||||
css.insert("[data-td-icon='icon-message'] .column-header-links { min-width: 110px !important; }");
|
|
||||||
css.insert(".column-navigator-overflow .clear-columns-btn-all-parent { display: none !important; }");
|
// styles
|
||||||
css.insert(".column-navigator-overflow { bottom: 224px !important; }");
|
|
||||||
css.insert("[data-action='td-clearcolumns-dosingle'] { padding: 3px 0 !important; }");
|
this.css = window.TDPF_createCustomStyle(this);
|
||||||
css.insert("[data-action='clear'].btn-options-tray { display: none !important; }");
|
this.css.insert(".js-app-add-column.is-hidden + .clear-columns-btn-all-parent { display: none; }");
|
||||||
css.insert("[data-td-icon='icon-schedule'] .td-clear-column-shortcut { display: none; }");
|
this.css.insert(".column-header-links { min-width: 51px !important; }");
|
||||||
css.insert("[data-td-icon='icon-custom-timeline'] .td-clear-column-shortcut { display: none; }");
|
this.css.insert("[data-td-icon='icon-message'] .column-header-links { min-width: 110px !important; }");
|
||||||
|
this.css.insert(".column-navigator-overflow .clear-columns-btn-all-parent { display: none !important; }");
|
||||||
|
this.css.insert(".column-navigator-overflow { bottom: 224px !important; }");
|
||||||
|
this.css.insert("[data-action='td-clearcolumns-dosingle'] { padding: 3px 0 !important; }");
|
||||||
|
this.css.insert("[data-action='clear'].btn-options-tray { display: none !important; }");
|
||||||
|
this.css.insert("[data-td-icon='icon-schedule'] .td-clear-column-shortcut { display: none; }");
|
||||||
|
this.css.insert("[data-td-icon='icon-custom-timeline'] .td-clear-column-shortcut { display: none; }");
|
||||||
}
|
}
|
||||||
|
|
||||||
ready(){
|
ready(){
|
||||||
// setup events
|
document.addEventListener("click", this.eventClickOneCapture, true);
|
||||||
$(document).on("click", "[data-action='td-clearcolumns-dosingle']", this.eventClickSingle);
|
|
||||||
$(document).on("click", "[data-action='td-clearcolumns-doall']", this.eventClickAll);
|
$(document).on("click", "[data-action='td-clearcolumns-doall']", this.eventClickAll);
|
||||||
$(document).on("keydown", this.eventKeyDown);
|
$(document).on("keydown", this.eventKeyDown);
|
||||||
$(document).on("keyup", this.eventKeyUp);
|
$(document).on("keyup", this.eventKeyUp);
|
||||||
|
$(document).on("uiShowKeyboardShortcutList", this.eventKeyboardShortcuts);
|
||||||
|
|
||||||
// setup clear all button for nav overflow
|
|
||||||
$(".js-app-add-column").first().after(this.btnClearAllHTML);
|
$(".js-app-add-column").first().after(this.btnClearAllHTML);
|
||||||
|
|
||||||
// setup tooltip handling
|
// fix tooltip
|
||||||
var tooltipEvents = $._data($(".js-header-action")[0]).events;
|
|
||||||
|
let tooltipEvents = $._data($(".js-header-action")[0], "events");
|
||||||
|
|
||||||
if (tooltipEvents.mouseover && tooltipEvents.mouseover.length && tooltipEvents.mouseout && tooltipEvents.mouseout.length){
|
if (tooltipEvents.mouseover && tooltipEvents.mouseover.length && tooltipEvents.mouseout && tooltipEvents.mouseout.length){
|
||||||
$(".clear-columns-btn-all-parent").on("mouseover", tooltipEvents.mouseover[0].handler).on("mouseout", tooltipEvents.mouseout[0].handler);
|
$(".clear-columns-btn-all-parent").on({
|
||||||
|
mouseover: tooltipEvents.mouseover[0].handler,
|
||||||
|
mouseout: tooltipEvents.mouseout[0].handler
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
disabled(){
|
disabled(){
|
||||||
// not needed, plugin reloads the page when enabled or disabled
|
this.css.remove();
|
||||||
|
|
||||||
|
document.removeEventListener("click", this.eventClickOneCapture);
|
||||||
|
$(document).off("click", "[data-action='td-clearcolumns-doall']", this.eventClickAll);
|
||||||
|
$(document).off("keydown", this.eventKeyDown);
|
||||||
|
$(document).off("keyup", this.eventKeyUp);
|
||||||
|
$(document).off("uiShowKeyboardShortcutList", this.eventKeyboardShortcuts);
|
||||||
|
|
||||||
|
TD.mustaches["menus/column_nav_menu.mustache"] = this.prevNavMenuMustache;
|
||||||
|
TD.mustaches["column/column_header.mustache"] = this.prevColumnHeaderMustache;
|
||||||
|
|
||||||
|
$("[data-action^='td-clearcolumns-']").remove();
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ enabled(){
|
|||||||
avatarRadius: 2
|
avatarRadius: 2
|
||||||
};
|
};
|
||||||
|
|
||||||
var prepareDefaultConfig = () => {
|
const prepareDefaultConfig = () => {
|
||||||
this.defaultConfig._theme = TD.settings.getTheme();
|
this.defaultConfig._theme = TD.settings.getTheme();
|
||||||
|
|
||||||
switch(TD.settings.getColumnWidth()){
|
switch(TD.settings.getColumnWidth()){
|
||||||
@@ -39,7 +39,7 @@ enabled(){
|
|||||||
|
|
||||||
this.firstTimeLoad = null;
|
this.firstTimeLoad = null;
|
||||||
|
|
||||||
var me = this;
|
const me = this;
|
||||||
|
|
||||||
// modal dialog loading
|
// modal dialog loading
|
||||||
$TDP.readFileRoot(this.$token, "modal.html").then(contents => {
|
$TDP.readFileRoot(this.$token, "modal.html").then(contents => {
|
||||||
@@ -72,7 +72,7 @@ enabled(){
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var loadConfigObject = obj => {
|
const loadConfigObject = obj => {
|
||||||
this.tmpConfig = obj || {};
|
this.tmpConfig = obj || {};
|
||||||
this.firstTimeLoad = obj === null;
|
this.firstTimeLoad = obj === null;
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ enabled(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
// modal dialog setup
|
// modal dialog setup
|
||||||
var updateKey = function(key, value){
|
const updateKey = function(key, value){
|
||||||
me.config[key] = value;
|
me.config[key] = value;
|
||||||
|
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
@@ -396,8 +396,10 @@ enabled(){
|
|||||||
switch(currentTheme){
|
switch(currentTheme){
|
||||||
case "black":
|
case "black":
|
||||||
this.css.insert(".app-content, .app-columns-container { background-color: #444448 !important }");
|
this.css.insert(".app-content, .app-columns-container { background-color: #444448 !important }");
|
||||||
|
this.css.insert(".column-header-temp { background-color: transparent !important }");
|
||||||
this.css.insert(".column-drag-handle { opacity: 0.5 !important }");
|
this.css.insert(".column-drag-handle { opacity: 0.5 !important }");
|
||||||
this.css.insert(".column-drag-handle:hover { opacity: 1 !important }");
|
this.css.insert(".column-drag-handle:hover { opacity: 1 !important }");
|
||||||
|
this.css.insert(".column-message.is-actionable span:hover > .icon-small-valigned { filter: saturate(20) }");
|
||||||
this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover), .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover) { background-color: #666 !important }");
|
this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover), .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-thumb:not(:hover) { background-color: #666 !important }");
|
||||||
notificationScrollbarColor = "666";
|
notificationScrollbarColor = "666";
|
||||||
break;
|
break;
|
||||||
@@ -539,7 +541,7 @@ ${iconData.map(entry => `#tduck .icon-${entry[0]}:before{content:\"\\f0${entry[1
|
|||||||
#tduck .js-docked-compose .js-drawer-close { margin: 20px 0 0 !important }
|
#tduck .js-docked-compose .js-drawer-close { margin: 20px 0 0 !important }
|
||||||
#tduck .search-input-control .icon { font-size: 20px !important; top: -4px !important }
|
#tduck .search-input-control .icon { font-size: 20px !important; top: -4px !important }
|
||||||
|
|
||||||
.column-type-icon { margin-top: -1px !important }
|
.js-column-header .column-type-icon { margin-top: -1px !important }
|
||||||
.inline-reply .pull-left .Button--link { margin-top: 3px !important }
|
.inline-reply .pull-left .Button--link { margin-top: 3px !important }
|
||||||
|
|
||||||
.tweet-action-item .icon-favorite-toggle { font-size: 16px !important; }
|
.tweet-action-item .icon-favorite-toggle { font-size: 16px !important; }
|
||||||
@@ -561,7 +563,7 @@ ${iconData.map(entry => `#tduck .icon-${entry[0]}:before{content:\"\\f0${entry[1
|
|||||||
if (this.config.columnWidth[0] === '/'){
|
if (this.config.columnWidth[0] === '/'){
|
||||||
let cols = this.config.columnWidth.slice(1);
|
let cols = this.config.columnWidth.slice(1);
|
||||||
|
|
||||||
this.css.insert(".column { width: calc((100vw - 205px) / "+cols+" - 6px) !important }");
|
this.css.insert(".column { width: calc((100vw - 205px) / "+cols+" - 6px) !important; min-width: 160px }");
|
||||||
this.css.insert(".is-condensed .column { width: calc((100vw - 55px) / "+cols+" - 6px) !important }");
|
this.css.insert(".is-condensed .column { width: calc((100vw - 55px) / "+cols+" - 6px) !important }");
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -641,7 +643,7 @@ ready(){
|
|||||||
$(".js-app").append('<div id="td-design-plugin-modal" class="js-modal settings-modal ovl scroll-v scroll-styled-v"></div>');
|
$(".js-app").append('<div id="td-design-plugin-modal" class="js-modal settings-modal ovl scroll-v scroll-styled-v"></div>');
|
||||||
|
|
||||||
// global settings override
|
// global settings override
|
||||||
var me = this;
|
const me = this;
|
||||||
|
|
||||||
this.prevFuncSettingsGetInfo = TD.components.GlobalSettings.prototype.getInfo;
|
this.prevFuncSettingsGetInfo = TD.components.GlobalSettings.prototype.getInfo;
|
||||||
this.prevFuncSettingsSwitchTab = TD.components.GlobalSettings.prototype.switchTab;
|
this.prevFuncSettingsSwitchTab = TD.components.GlobalSettings.prototype.switchTab;
|
||||||
|
@@ -44,6 +44,8 @@
|
|||||||
</optgroup>
|
</optgroup>
|
||||||
<option disabled></option>
|
<option disabled></option>
|
||||||
<optgroup label="Dynamic width">
|
<optgroup label="Dynamic width">
|
||||||
|
<option value="/1">1 column on screen</option>
|
||||||
|
<option value="/2">2 columns on screen</option>
|
||||||
<option value="/3">3 columns on screen</option>
|
<option value="/3">3 columns on screen</option>
|
||||||
<option value="/4">4 columns on screen</option>
|
<option value="/4">4 columns on screen</option>
|
||||||
<option value="/5">5 columns on screen</option>
|
<option value="/5">5 columns on screen</option>
|
||||||
|
@@ -13,7 +13,6 @@ html.dark .color-twitter-blue{color:#1DA1F2}
|
|||||||
html.dark .color-twitter-red{color:#E0245E}
|
html.dark .color-twitter-red{color:#E0245E}
|
||||||
html.dark .color-twitter-deep-red{color:#A01744}
|
html.dark .color-twitter-deep-red{color:#A01744}
|
||||||
html.dark .color-twitter-green{color:#17BF63}
|
html.dark .color-twitter-green{color:#17BF63}
|
||||||
html.dark .color-twitter-deep-green{color:#008951}
|
|
||||||
html.dark .color-twitter-deep-black{color:#14171A}
|
html.dark .color-twitter-deep-black{color:#14171A}
|
||||||
html.dark .color-twitter-dark-black{color:#292F33}
|
html.dark .color-twitter-dark-black{color:#292F33}
|
||||||
html.dark .color-twitter-dark-gray{color:#8899A6}
|
html.dark .color-twitter-dark-gray{color:#8899A6}
|
||||||
@@ -22,7 +21,6 @@ html.dark .color-twitter-yellow{color:#FFAD1F}
|
|||||||
html.dark .bg-color-twitter-white{background-color:#fff}
|
html.dark .bg-color-twitter-white{background-color:#fff}
|
||||||
html.dark .bg-color-twitter-blue{background-color:#1DA1F2}
|
html.dark .bg-color-twitter-blue{background-color:#1DA1F2}
|
||||||
html.dark .bg-color-twitter-medium-blue{background-color:#1DA1F2}
|
html.dark .bg-color-twitter-medium-blue{background-color:#1DA1F2}
|
||||||
html.dark .bg-color-twitter-faded-yellow{background-color:#FFE8B6}
|
|
||||||
html.dark .bg-color-twitter-deep-black{background-color:#292F33}
|
html.dark .bg-color-twitter-deep-black{background-color:#292F33}
|
||||||
html.dark .bg-color-twitter-lightest-gray{background-color:#F5F8FA}
|
html.dark .bg-color-twitter-lightest-gray{background-color:#F5F8FA}
|
||||||
html.dark .link-hover-override:hover .link-hover-target{color:#8bd}
|
html.dark .link-hover-override:hover .link-hover-target{color:#8bd}
|
||||||
@@ -113,9 +111,6 @@ html.dark .btn-on-blue[disabled],html.dark .btn-on-blue[disabled]:hover,html.dar
|
|||||||
html.dark .btn-options-tray{color:#e1e8ed}
|
html.dark .btn-options-tray{color:#e1e8ed}
|
||||||
html.dark .btn-options-tray:hover,html.dark .btn-options-tray:focus{color:#8bd}
|
html.dark .btn-options-tray:hover,html.dark .btn-options-tray:focus{color:#8bd}
|
||||||
html.dark .btn-options-tray[disabled],html.dark .btn-options-tray[disabled]:hover,html.dark .btn-options-tray[disabled]:active,html.dark .btn-options-tray.is-disabled,html.dark .btn-options-tray.is-disabled:hover,html.dark .btn-options-tray.is-disabled:focus,html.dark .btn-options-tray.is-disabled:active{color:#8bd}
|
html.dark .btn-options-tray[disabled],html.dark .btn-options-tray[disabled]:hover,html.dark .btn-options-tray[disabled]:active,html.dark .btn-options-tray.is-disabled,html.dark .btn-options-tray.is-disabled:hover,html.dark .btn-options-tray.is-disabled:focus,html.dark .btn-options-tray.is-disabled:active{color:#8bd}
|
||||||
html.dark .btn-bg-positive{background-color:rgba(102,117,127,0.5)}
|
|
||||||
html.dark .btn-bg-positive:hover,html.dark .btn-bg-positive:focus{background-color:rgba(102,117,127,0.5)}
|
|
||||||
html.dark .btn-bg-positive[disabled],html.dark .btn-bg-positive[disabled]:hover,html.dark .btn-bg-positive[disabled]:active,html.dark .btn-bg-positive.is-disabled,html.dark .btn-bg-positive.is-disabled:hover,html.dark .btn-bg-positive.is-disabled:focus,html.dark .btn-bg-positive.is-disabled:active{background-color:rgba(102,117,127,0.5)}
|
|
||||||
html.dark .follow-btn .icon,html.dark .follow-btn .Icon{color:#1DA1F2}
|
html.dark .follow-btn .icon,html.dark .follow-btn .Icon{color:#1DA1F2}
|
||||||
html.dark .account-profile-header{background-color:#1DA1F2}
|
html.dark .account-profile-header{background-color:#1DA1F2}
|
||||||
html.dark .account-settings-bt{border-top:1px solid #e1e8ed}
|
html.dark .account-settings-bt{border-top:1px solid #e1e8ed}
|
||||||
@@ -190,8 +185,6 @@ html.dark .is-touch-search .list-item:hover,html.dark .is-touch-search .list-ite
|
|||||||
html.dark .is-touch-search .list-item:hover .list-icon,html.dark .is-touch-search .list-item:active .list-icon,html.dark .is-touch-search .list-item.is-selected .list-icon{color:#fff}
|
html.dark .is-touch-search .list-item:hover .list-icon,html.dark .is-touch-search .list-item:active .list-icon,html.dark .is-touch-search .list-item.is-selected .list-icon{color:#fff}
|
||||||
html.dark .avatar-border--2{border:2px solid #fff;background-color:#fff}
|
html.dark .avatar-border--2{border:2px solid #fff;background-color:#fff}
|
||||||
html.dark .account-link{color:#e1e8ed}
|
html.dark .account-link{color:#e1e8ed}
|
||||||
.on-blue html.dark .account-link{color:#fff}
|
|
||||||
.compose .quoted-tweet html.dark .account-link{color:#66757f}
|
|
||||||
html.dark .media-badge{border:1px solid #292F33;color:#999}
|
html.dark .media-badge{border:1px solid #292F33;color:#999}
|
||||||
html.dark .media-badge:hover{background-color:#14171A}
|
html.dark .media-badge:hover{background-color:#14171A}
|
||||||
html.dark .media-size-large-height::after,html.dark .media-item.media-size-large::after{background-image:linear-gradient(rgba(17,17,17,0.25),rgba(17,17,17,0))}
|
html.dark .media-size-large-height::after,html.dark .media-item.media-size-large::after{background-image:linear-gradient(rgba(17,17,17,0.25),rgba(17,17,17,0))}
|
||||||
@@ -219,7 +212,7 @@ html.dark .is-minimalist .tweet-img{background:#292F33}
|
|||||||
html.dark .is-selected-tweet{background:#292F33}
|
html.dark .is-selected-tweet{background:#292F33}
|
||||||
html.dark .in-tweet-divider:before{background:#292F33}
|
html.dark .in-tweet-divider:before{background:#292F33}
|
||||||
html.dark .tweet-translation-original-text{color:#8899a6}
|
html.dark .tweet-translation-original-text{color:#8899a6}
|
||||||
html.dark .quoted-tweet{border:1px solid #E1E8ED;color:#66757f;border-color:#292F33;color:#999}
|
html.dark .quoted-tweet{border-color:#292F33;color:#999}
|
||||||
html.dark .scheduled-tweet{border:1px solid #292F33;color:#8899A6}
|
html.dark .scheduled-tweet{border:1px solid #292F33;color:#8899A6}
|
||||||
html.dark .stream-item .icon-edit,html.dark .stream-item .icon-trash{color:#657786}
|
html.dark .stream-item .icon-edit,html.dark .stream-item .icon-trash{color:#657786}
|
||||||
html.dark .stream-item .icon-edit:hover,html.dark .stream-item .icon-trash:hover{color:#8899A6}
|
html.dark .stream-item .icon-edit:hover,html.dark .stream-item .icon-trash:hover{color:#8899A6}
|
||||||
@@ -398,7 +391,7 @@ html.dark .mdl-column-rhs{border-left:1px solid #ccd6dd;background:#fff}
|
|||||||
html.dark .s-minimal .mdl-header{border-bottom:1px solid #e1e8ed}
|
html.dark .s-minimal .mdl-header{border-bottom:1px solid #e1e8ed}
|
||||||
html.dark .lst-launcher .top-row{border-bottom:1px solid #e1e8ed}
|
html.dark .lst-launcher .top-row{border-bottom:1px solid #e1e8ed}
|
||||||
html.dark .lst-launcher .is-disabled a,html.dark .lst-launcher .is-disabled a:hover,html.dark .lst-launcher .is-disabled a:focus,html.dark .lst-launcher .is-disabled a:active{background:#fff}
|
html.dark .lst-launcher .is-disabled a,html.dark .lst-launcher .is-disabled a:hover,html.dark .lst-launcher .is-disabled a:focus,html.dark .lst-launcher .is-disabled a:active{background:#fff}
|
||||||
html.dark .lst-launcher a:hover,html.dark .lst-launcher a:focus,html.dark .lst-launcher a:active{background:#f2f9ff;border:1px solid #bbddf5}
|
html.dark .lst-launcher a:hover,html.dark .lst-launcher a:focus,html.dark .lst-launcher a:active{background:#f2f9ff}
|
||||||
html.dark .lst-profile a,html.dark .lst-profile a:hover,html.dark .lst-profile a:focus,html.dark .lst-profile a:active{color:#657786}
|
html.dark .lst-profile a,html.dark .lst-profile a:hover,html.dark .lst-profile a:focus,html.dark .lst-profile a:active{color:#657786}
|
||||||
html.dark .mdl-col-settings{background-color:#fff;border-left:1px solid #E1E8ED}
|
html.dark .mdl-col-settings{background-color:#fff;border-left:1px solid #E1E8ED}
|
||||||
html.dark .mdl-links{color:#8899a6}
|
html.dark .mdl-links{color:#8899a6}
|
||||||
@@ -435,7 +428,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-image:url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='18' height='8' viewBox='0 0 18 8'><path fill='#aaa' d='M9.82875,0.840168025 C9.59875,0.608328018 9.22625,0.608328018 8.99625,0.840168025 L5.00125,4.86964815 L1.00375,0.840168025 C0.77375,0.608328018 0.40125,0.608328018 0.17125,0.840168025 C-0.05875,1.07200803 -0.05625,1.44748804 0.17125,1.67932805 L4.58375,6.12712819 C4.69875,6.24304819 4.84875,6.30100819 5.00125,6.30100819 C5.15125,6.30100819 5.30125,6.24304819 5.41625,6.12712819 L9.82875,1.67932805 C10.05875,1.44748804 10.05875,1.07200803 9.82875,0.840168025'></path></svg>");background-color:#fff}
|
html.dark select{background-color:#fff}
|
||||||
html.dark input,html.dark textarea,html.dark select{color:#111;border:1px solid #e1e8ed}
|
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}
|
||||||
@@ -613,46 +606,45 @@ html.dark .Dropdown-divider{background-color:#ccd6dd}
|
|||||||
html.dark .Dropdown-menuItem .Dropdown-menuItemContent,html.dark .Dropdown-menuGroupLabel{color:#14171a}
|
html.dark .Dropdown-menuItem .Dropdown-menuItemContent,html.dark .Dropdown-menuGroupLabel{color:#14171a}
|
||||||
html.dark .Dropdown-menuItem .Dropdown-menuItemContent .Icon--check{color:#1da1f2}
|
html.dark .Dropdown-menuItem .Dropdown-menuItemContent .Icon--check{color:#1da1f2}
|
||||||
html.dark .Dropdown-menuItem.is-focus{background-color:#1da1f2}
|
html.dark .Dropdown-menuItem.is-focus{background-color:#1da1f2}
|
||||||
html.dark .Dropdown-menuItem.is-focus .User .Icon--verified::before{color:#1da1f2}
|
|
||||||
html.dark .Dropdown-menuGroupLabel{color:#657786}
|
html.dark .Dropdown-menuGroupLabel{color:#657786}
|
||||||
html.dark .ButtonGroup>.Button.is-selected,html.dark .ButtonGroup>.Button.is-selected:visited{background-color:#1da1f2;border:1px solid #1da1f2}
|
html.dark .ButtonGroup>.Button.is-selected,html.dark .ButtonGroup>.Button.is-selected:visited{background-color:#1da1f2;border:1px solid #1da1f2}
|
||||||
html.dark .ButtonGroup>.Button.is-selected:focus,html.dark .ButtonGroup>.Button.is-selected.is-focus{box-shadow:0 0 0 2px white,0 0 0 4px #71c9f8;background:#1da1f2;border-color:#1da1f2}
|
html.dark .ButtonGroup>.Button.is-selected:focus,html.dark .ButtonGroup>.Button.is-selected.is-focus{box-shadow:0 0 0 2px #fff,0 0 0 4px #71c9f8;background:#1da1f2;border-color:#1da1f2}
|
||||||
html.dark .ButtonGroup>.Button.is-selected:hover,html.dark .ButtonGroup>.Button.is-selected.is-hover{background-color:#1da1f2;border-color:#1da1f2}
|
html.dark .ButtonGroup>.Button.is-selected:hover,html.dark .ButtonGroup>.Button.is-selected.is-hover{background-color:#1da1f2;border-color:#1da1f2}
|
||||||
html.dark .ButtonGroup>.Button.is-selected:active,html.dark .ButtonGroup>.Button.is-selected.is-active{box-shadow:0 0 0 2px white,0 0 0 4px #1da1f2;background-color:#1da1f2;border-color:#1da1f2}
|
html.dark .ButtonGroup>.Button.is-selected:active,html.dark .ButtonGroup>.Button.is-selected.is-active{box-shadow:0 0 0 2px #fff,0 0 0 4px #1da1f2;background-color:#1da1f2;border-color:#1da1f2}
|
||||||
html.dark .ButtonGroup>.Button.is-selected[disabled],html.dark .ButtonGroup>.Button.is-selected.is-disabled,html.dark fieldset[disabled] .ButtonGroup>.Button.is-selected{background-color:#1da1f2;border-color:#1da1f2}
|
html.dark .ButtonGroup>.Button.is-selected[disabled],html.dark .ButtonGroup>.Button.is-selected.is-disabled,html.dark fieldset[disabled] .ButtonGroup>.Button.is-selected{background-color:#1da1f2;border-color:#1da1f2}
|
||||||
html.dark .ButtonGroup--tertiary>.Button.is-selected,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected,html.dark .ButtonGroup--tertiary>.Button.is-selected:visited,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected:visited{background-color:#657786;border:1px solid #657786}
|
html.dark .ButtonGroup--tertiary>.Button.is-selected,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected,html.dark .ButtonGroup--tertiary>.Button.is-selected:visited,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected:visited{background-color:#657786;border:1px solid #657786}
|
||||||
html.dark .ButtonGroup--tertiary>.Button.is-selected:focus,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected:focus,html.dark .ButtonGroup--tertiary>.Button.is-selected.is-focus,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected.is-focus{box-shadow:0 0 0 2px white,0 0 0 4px #ccd6dd;background:#657786;border-color:#657786}
|
html.dark .ButtonGroup--tertiary>.Button.is-selected:focus,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected:focus,html.dark .ButtonGroup--tertiary>.Button.is-selected.is-focus,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected.is-focus{box-shadow:0 0 0 2px #fff,0 0 0 4px #ccd6dd;background:#657786;border-color:#657786}
|
||||||
html.dark .ButtonGroup--tertiary>.Button.is-selected:hover,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected:hover,html.dark .ButtonGroup--tertiary>.Button.is-selected.is-hover,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected.is-hover{background-color:#657786;border-color:#657786}
|
html.dark .ButtonGroup--tertiary>.Button.is-selected:hover,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected:hover,html.dark .ButtonGroup--tertiary>.Button.is-selected.is-hover,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected.is-hover{background-color:#657786;border-color:#657786}
|
||||||
html.dark .ButtonGroup--tertiary>.Button.is-selected:active,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected:active,html.dark .ButtonGroup--tertiary>.Button.is-selected.is-active,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected.is-active{box-shadow:0 0 0 2px white,0 0 0 4px #aab8c2;background-color:#657786;border-color:#657786}
|
html.dark .ButtonGroup--tertiary>.Button.is-selected:active,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected:active,html.dark .ButtonGroup--tertiary>.Button.is-selected.is-active,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected.is-active{box-shadow:0 0 0 2px #fff,0 0 0 4px #aab8c2;background-color:#657786;border-color:#657786}
|
||||||
html.dark .ButtonGroup--tertiary>.Button.is-selected[disabled],html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected[disabled],html.dark .ButtonGroup--tertiary>.Button.is-selected.is-disabled,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected.is-disabled,html.dark fieldset[disabled] .ButtonGroup--tertiary>.Button.is-selected,html.dark fieldset[disabled] .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected{background-color:#657786;border-color:#657786}
|
html.dark .ButtonGroup--tertiary>.Button.is-selected[disabled],html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected[disabled],html.dark .ButtonGroup--tertiary>.Button.is-selected.is-disabled,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected.is-disabled,html.dark fieldset[disabled] .ButtonGroup--tertiary>.Button.is-selected,html.dark fieldset[disabled] .ButtonGroup--tertiary>.ButtonGroup>.Button.is-selected{background-color:#657786;border-color:#657786}
|
||||||
html.dark .Button,html.dark .Button:visited,html.dark .Button.is-visited{border:1px solid #1da1f2;color:#1da1f2}
|
html.dark .Button,html.dark .Button:visited,html.dark .Button.is-visited{border:1px solid #1da1f2;color:#1da1f2}
|
||||||
html.dark .Button:focus,html.dark .Button.is-focus{box-shadow:0 0 0 2px white,0 0 0 4px #71c9f8;border-color:#1da1f2;color:#1da1f2}
|
html.dark .Button:focus,html.dark .Button.is-focus{box-shadow:0 0 0 2px #fff,0 0 0 4px #71c9f8;border-color:#1da1f2;color:#1da1f2}
|
||||||
html.dark .Button:hover,html.dark .Button.is-hover{background-color:#eaf5fd;color:#1da1f2}
|
html.dark .Button:hover,html.dark .Button.is-hover{background-color:#eaf5fd;color:#1da1f2}
|
||||||
html.dark .Button:active,html.dark .Button.is-active{box-shadow:0 0 0 2px white,0 0 0 4px #1da1f2;background:#eaf5fd;border-color:#1da1f2;color:#1da1f2}
|
html.dark .Button:active,html.dark .Button.is-active{box-shadow:0 0 0 2px #fff,0 0 0 4px #1da1f2;background:#eaf5fd;border-color:#1da1f2;color:#1da1f2}
|
||||||
html.dark .Button.Button--primary,html.dark .Button.Button--primary:visited,html.dark .ButtonGroup--primary>.Button,html.dark .ButtonGroup--primary>.Button:visited,html.dark .ButtonGroup--primary>.ButtonGroup>.Button,html.dark .ButtonGroup--primary>.ButtonGroup>.Button:visited{background-color:#1da1f2;border:1px solid #1da1f2}
|
html.dark .Button.Button--primary,html.dark .Button.Button--primary:visited,html.dark .ButtonGroup--primary>.Button,html.dark .ButtonGroup--primary>.Button:visited,html.dark .ButtonGroup--primary>.ButtonGroup>.Button,html.dark .ButtonGroup--primary>.ButtonGroup>.Button:visited{background-color:#1da1f2;border:1px solid #1da1f2}
|
||||||
html.dark .Button.Button--primary:focus,html.dark .Button.Button--primary.is-focus,html.dark .ButtonGroup--primary>.Button:focus,html.dark .ButtonGroup--primary>.Button.is-focus,html.dark .ButtonGroup--primary>.ButtonGroup>.Button:focus,html.dark .ButtonGroup--primary>.ButtonGroup>.Button.is-focus{box-shadow:0 0 0 2px white,0 0 0 4px #71c9f8;background:#1da1f2;border-color:#1da1f2}
|
html.dark .Button.Button--primary:focus,html.dark .Button.Button--primary.is-focus,html.dark .ButtonGroup--primary>.Button:focus,html.dark .ButtonGroup--primary>.Button.is-focus,html.dark .ButtonGroup--primary>.ButtonGroup>.Button:focus,html.dark .ButtonGroup--primary>.ButtonGroup>.Button.is-focus{box-shadow:0 0 0 2px #fff,0 0 0 4px #71c9f8;background:#1da1f2;border-color:#1da1f2}
|
||||||
html.dark .Button.Button--primary:hover,html.dark .Button.Button--primary.is-hover,html.dark .ButtonGroup--primary>.Button:hover,html.dark .ButtonGroup--primary>.Button.is-hover,html.dark .ButtonGroup--primary>.ButtonGroup>.Button:hover,html.dark .ButtonGroup--primary>.ButtonGroup>.Button.is-hover{background-color:#005fd1;border-color:#005fd1}
|
html.dark .Button.Button--primary:hover,html.dark .Button.Button--primary.is-hover,html.dark .ButtonGroup--primary>.Button:hover,html.dark .ButtonGroup--primary>.Button.is-hover,html.dark .ButtonGroup--primary>.ButtonGroup>.Button:hover,html.dark .ButtonGroup--primary>.ButtonGroup>.Button.is-hover{background-color:#005fd1;border-color:#005fd1}
|
||||||
html.dark .Button.Button--primary:active,html.dark .Button.Button--primary.is-active,html.dark .ButtonGroup--primary>.Button:active,html.dark .ButtonGroup--primary>.Button.is-active,html.dark .ButtonGroup--primary>.ButtonGroup>.Button:active,html.dark .ButtonGroup--primary>.ButtonGroup>.Button.is-active{box-shadow:0 0 0 2px white,0 0 0 4px #1da1f2;background-color:#005fd1;border-color:#005fd1}
|
html.dark .Button.Button--primary:active,html.dark .Button.Button--primary.is-active,html.dark .ButtonGroup--primary>.Button:active,html.dark .ButtonGroup--primary>.Button.is-active,html.dark .ButtonGroup--primary>.ButtonGroup>.Button:active,html.dark .ButtonGroup--primary>.ButtonGroup>.Button.is-active{box-shadow:0 0 0 2px #fff,0 0 0 4px #1da1f2;background-color:#005fd1;border-color:#005fd1}
|
||||||
html.dark .Button.Button--primary[disabled],html.dark .Button.Button--primary.is-disabled,html.dark fieldset[disabled] .Button.Button--primary,html.dark .ButtonGroup--primary>.Button[disabled],html.dark .ButtonGroup--primary>.Button.is-disabled,html.dark fieldset[disabled] .ButtonGroup--primary>.Button,html.dark .ButtonGroup--primary>.ButtonGroup>.Button[disabled],html.dark .ButtonGroup--primary>.ButtonGroup>.Button.is-disabled,html.dark fieldset[disabled] .ButtonGroup--primary>.ButtonGroup>.Button{background-color:#1da1f2;border-color:#1da1f2}
|
html.dark .Button.Button--primary[disabled],html.dark .Button.Button--primary.is-disabled,html.dark fieldset[disabled] .Button.Button--primary,html.dark .ButtonGroup--primary>.Button[disabled],html.dark .ButtonGroup--primary>.Button.is-disabled,html.dark fieldset[disabled] .ButtonGroup--primary>.Button,html.dark .ButtonGroup--primary>.ButtonGroup>.Button[disabled],html.dark .ButtonGroup--primary>.ButtonGroup>.Button.is-disabled,html.dark fieldset[disabled] .ButtonGroup--primary>.ButtonGroup>.Button{background-color:#1da1f2;border-color:#1da1f2}
|
||||||
html.dark .Button.Button--tertiary,html.dark .Button.Button--tertiary:visited,html.dark .ButtonGroup--tertiary>.Button,html.dark .ButtonGroup--tertiary>.Button:visited,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button:visited{border:1px solid #657786;color:#657786}
|
html.dark .Button.Button--tertiary,html.dark .Button.Button--tertiary:visited,html.dark .ButtonGroup--tertiary>.Button,html.dark .ButtonGroup--tertiary>.Button:visited,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button:visited{border:1px solid #657786;color:#657786}
|
||||||
html.dark .Button.Button--tertiary:focus,html.dark .Button.Button--tertiary.is-focus,html.dark .ButtonGroup--tertiary>.Button:focus,html.dark .ButtonGroup--tertiary>.Button.is-focus,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button:focus,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-focus{box-shadow:0 0 0 2px white,0 0 0 4px #ccd6dd;border-color:#657786;color:#657786}
|
html.dark .Button.Button--tertiary:focus,html.dark .Button.Button--tertiary.is-focus,html.dark .ButtonGroup--tertiary>.Button:focus,html.dark .ButtonGroup--tertiary>.Button.is-focus,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button:focus,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-focus{box-shadow:0 0 0 2px #fff,0 0 0 4px #ccd6dd;border-color:#657786;color:#657786}
|
||||||
html.dark .Button.Button--tertiary:hover,html.dark .Button.Button--tertiary.is-hover,html.dark .ButtonGroup--tertiary>.Button:hover,html.dark .ButtonGroup--tertiary>.Button.is-hover,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button:hover,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-hover{background-color:#f5f8fa;border-color:#657786;color:#657786}
|
html.dark .Button.Button--tertiary:hover,html.dark .Button.Button--tertiary.is-hover,html.dark .ButtonGroup--tertiary>.Button:hover,html.dark .ButtonGroup--tertiary>.Button.is-hover,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button:hover,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-hover{background-color:#f5f8fa;border-color:#657786;color:#657786}
|
||||||
html.dark .Button.Button--tertiary:active,html.dark .Button.Button--tertiary.is-active,html.dark .ButtonGroup--tertiary>.Button:active,html.dark .ButtonGroup--tertiary>.Button.is-active,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button:active,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-active{box-shadow:0 0 0 2px white,0 0 0 4px #657786;background-color:#f5f8fa;border-color:#657786;color:#657786}
|
html.dark .Button.Button--tertiary:active,html.dark .Button.Button--tertiary.is-active,html.dark .ButtonGroup--tertiary>.Button:active,html.dark .ButtonGroup--tertiary>.Button.is-active,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button:active,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-active{box-shadow:0 0 0 2px #fff,0 0 0 4px #657786;background-color:#f5f8fa;border-color:#657786;color:#657786}
|
||||||
html.dark .Button.Button--tertiary[disabled],html.dark .Button.Button--tertiary.is-disabled,html.dark fieldset[disabled] .Button.Button--tertiary,html.dark .ButtonGroup--tertiary>.Button[disabled],html.dark .ButtonGroup--tertiary>.Button.is-disabled,html.dark fieldset[disabled] .ButtonGroup--tertiary>.Button,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button[disabled],html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-disabled,html.dark fieldset[disabled] .ButtonGroup--tertiary>.ButtonGroup>.Button{border-color:#657786}
|
html.dark .Button.Button--tertiary[disabled],html.dark .Button.Button--tertiary.is-disabled,html.dark fieldset[disabled] .Button.Button--tertiary,html.dark .ButtonGroup--tertiary>.Button[disabled],html.dark .ButtonGroup--tertiary>.Button.is-disabled,html.dark fieldset[disabled] .ButtonGroup--tertiary>.Button,html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button[disabled],html.dark .ButtonGroup--tertiary>.ButtonGroup>.Button.is-disabled,html.dark fieldset[disabled] .ButtonGroup--tertiary>.ButtonGroup>.Button{border-color:#657786}
|
||||||
html.dark .Button.Button--success,html.dark .Button.Button--success:visited{background-color:#17bf63;border:1px solid #17bf63}
|
html.dark .Button.Button--success,html.dark .Button.Button--success:visited{background-color:#17bf63;border:1px solid #17bf63}
|
||||||
html.dark .Button.Button--success:focus,html.dark .Button.Button--success.is-focus{box-shadow:0 0 0 2px white,0 0 0 4px #68e090;background:#17bf63;border-color:#17bf63}
|
html.dark .Button.Button--success:focus,html.dark .Button.Button--success.is-focus{box-shadow:0 0 0 2px #fff,0 0 0 4px #68e090;background:#17bf63;border-color:#17bf63}
|
||||||
html.dark .Button.Button--success:hover,html.dark .Button.Button--success.is-hover{background-color:#008951;border-color:#008951}
|
html.dark .Button.Button--success:hover,html.dark .Button.Button--success.is-hover{background-color:#008951;border-color:#008951}
|
||||||
html.dark .Button.Button--success:active,html.dark .Button.Button--success.is-active{box-shadow:0 0 0 2px white,0 0 0 4px #17bf63;background-color:#008951;border-color:#008951}
|
html.dark .Button.Button--success:active,html.dark .Button.Button--success.is-active{box-shadow:0 0 0 2px #fff,0 0 0 4px #17bf63;background-color:#008951;border-color:#008951}
|
||||||
html.dark .Button.Button--success[disabled],html.dark .Button.Button--success.is-disabled,html.dark fieldset[disabled] .Button.Button--success{background-color:#17bf63;border-color:#17bf63}
|
html.dark .Button.Button--success[disabled],html.dark .Button.Button--success.is-disabled,html.dark fieldset[disabled] .Button.Button--success{background-color:#17bf63;border-color:#17bf63}
|
||||||
html.dark .Button.Button--warning,html.dark .Button.Button--warning:visited{background-color:#ffad1f;border:1px solid #ffad1f}
|
html.dark .Button.Button--warning,html.dark .Button.Button--warning:visited{background-color:#ffad1f;border:1px solid #ffad1f}
|
||||||
html.dark .Button.Button--warning:focus,html.dark .Button.Button--warning.is-focus{box-shadow:0 0 0 2px white,0 0 0 4px #ffd03f;background:#ffad1f;border-color:#ffad1f}
|
html.dark .Button.Button--warning:focus,html.dark .Button.Button--warning.is-focus{box-shadow:0 0 0 2px #fff,0 0 0 4px #ffd03f;background:#ffad1f;border-color:#ffad1f}
|
||||||
html.dark .Button.Button--warning:hover,html.dark .Button.Button--warning.is-hover{background-color:#f98e00;border-color:#f98e00}
|
html.dark .Button.Button--warning:hover,html.dark .Button.Button--warning.is-hover{background-color:#f98e00;border-color:#f98e00}
|
||||||
html.dark .Button.Button--warning:active,html.dark .Button.Button--warning.is-active{box-shadow:0 0 0 2px white,0 0 0 4px #ffad1f;background-color:#f98e00;border-color:#f98e00}
|
html.dark .Button.Button--warning:active,html.dark .Button.Button--warning.is-active{box-shadow:0 0 0 2px #fff,0 0 0 4px #ffad1f;background-color:#f98e00;border-color:#f98e00}
|
||||||
html.dark .Button.Button--warning[disabled],html.dark .Button.Button--warning.is-disabled,html.dark fieldset[disabled] .Button.Button--warning{background-color:#ffad1f;border-color:#ffad1f}
|
html.dark .Button.Button--warning[disabled],html.dark .Button.Button--warning.is-disabled,html.dark fieldset[disabled] .Button.Button--warning{background-color:#ffad1f;border-color:#ffad1f}
|
||||||
html.dark .Button.Button--danger,html.dark .Button.Button--danger:visited{background-color:#e0245e;border:1px solid #e0245e}
|
html.dark .Button.Button--danger,html.dark .Button.Button--danger:visited{background-color:#e0245e;border:1px solid #e0245e}
|
||||||
html.dark .Button.Button--danger:focus,html.dark .Button.Button--danger.is-focus{box-shadow:0 0 0 2px white,0 0 0 4px #f6809a;background:#e0245e;border-color:#e0245e}
|
html.dark .Button.Button--danger:focus,html.dark .Button.Button--danger.is-focus{box-shadow:0 0 0 2px #fff,0 0 0 4px #f6809a;background:#e0245e;border-color:#e0245e}
|
||||||
html.dark .Button.Button--danger:hover,html.dark .Button.Button--danger.is-hover{background-color:#a01744;border-color:#a01744}
|
html.dark .Button.Button--danger:hover,html.dark .Button.Button--danger.is-hover{background-color:#a01744;border-color:#a01744}
|
||||||
html.dark .Button.Button--danger:active,html.dark .Button.Button--danger.is-active{box-shadow:0 0 0 2px white,0 0 0 4px #e0245e;background-color:#a01744;border-color:#a01744}
|
html.dark .Button.Button--danger:active,html.dark .Button.Button--danger.is-active{box-shadow:0 0 0 2px #fff,0 0 0 4px #e0245e;background-color:#a01744;border-color:#a01744}
|
||||||
html.dark .Button.Button--danger[disabled],html.dark .Button.Button--danger.is-disabled,html.dark fieldset[disabled] .Button.Button--danger{background-color:#e0245e;border-color:#e0245e}
|
html.dark .Button.Button--danger[disabled],html.dark .Button.Button--danger.is-disabled,html.dark fieldset[disabled] .Button.Button--danger{background-color:#e0245e;border-color:#e0245e}
|
||||||
html.dark .Button.Button--link{color:#1b95e0}
|
html.dark .Button.Button--link{color:#1b95e0}
|
||||||
html.dark .Button.Button--dangerLink{color:#e0245e}
|
html.dark .Button.Button--dangerLink{color:#e0245e}
|
||||||
@@ -730,8 +722,8 @@ html.dark .DateRange[dir='rtl'] .DateRange-pickersRow:first-child .DateRange-pic
|
|||||||
html.dark .PillGroup .Pill.is-selected{background:#005fd1}
|
html.dark .PillGroup .Pill.is-selected{background:#005fd1}
|
||||||
html.dark .PillGroup .Pill>a,html.dark .PillGroup .Pill>button{color:#1b95e0}
|
html.dark .PillGroup .Pill>a,html.dark .PillGroup .Pill>button{color:#1b95e0}
|
||||||
html.dark .PillGroup .Pill>a:hover,html.dark .PillGroup .Pill>button:hover{background:#eaf5fd}
|
html.dark .PillGroup .Pill>a:hover,html.dark .PillGroup .Pill>button:hover{background:#eaf5fd}
|
||||||
html.dark .PillGroup .Pill>a:focus,html.dark .PillGroup .Pill>button:focus{box-shadow:0 0 0 2px white,0 0 0 4px #71c9f8}
|
html.dark .PillGroup .Pill>a:focus,html.dark .PillGroup .Pill>button:focus{box-shadow:0 0 0 2px #fff,0 0 0 4px #71c9f8}
|
||||||
html.dark .PillGroup .Pill>a:active,html.dark .PillGroup .Pill>button:active{box-shadow:0 0 0 2px white,0 0 0 4px #1da1f2}
|
html.dark .PillGroup .Pill>a:active,html.dark .PillGroup .Pill>button:active{box-shadow:0 0 0 2px #fff,0 0 0 4px #1da1f2}
|
||||||
html.dark .PillGroup .Pill.is-selected>a,html.dark .PillGroup .Pill.is-selected>button{color:#FFF}
|
html.dark .PillGroup .Pill.is-selected>a,html.dark .PillGroup .Pill.is-selected>button{color:#FFF}
|
||||||
html.dark .FormInput,html.dark .FormTextarea{border:1px solid #ccd6dd;color:#14171a}
|
html.dark .FormInput,html.dark .FormTextarea{border:1px solid #ccd6dd;color:#14171a}
|
||||||
html.dark .FormInput-characterCount{color:#ccd6dd}
|
html.dark .FormInput-characterCount{color:#ccd6dd}
|
||||||
@@ -751,51 +743,51 @@ html.dark .FormInputWrapper-startAdornment,html.dark .FormInputWrapper-endAdornm
|
|||||||
html.dark .FormField.is-invalid .FormField-validationMessage{color:#e0245e}
|
html.dark .FormField.is-invalid .FormField-validationMessage{color:#e0245e}
|
||||||
html.dark .FormField.is-valid .FormField-validationMessage{color:#008951}
|
html.dark .FormField.is-valid .FormField-validationMessage{color:#008951}
|
||||||
html.dark .FormField-description{color:#657786}
|
html.dark .FormField-description{color:#657786}
|
||||||
html.dark .Token-checkbox input[type="checkbox"]:focus+.Icon{box-shadow:0 0 0 5px white,0 0 0 7px #71c9f8}
|
html.dark .Token-checkbox input[type="checkbox"]:focus+.Icon{box-shadow:0 0 0 5px #fff,0 0 0 7px #71c9f8}
|
||||||
html.dark .Token--small .Token-trigger input[type="checkbox"]:focus+.Icon,html.dark .TokenGroup--small>.Token .Token-trigger input[type="checkbox"]:focus+.Icon,html.dark .TokenGroup--small>.TokenGroup>.Token .Token-trigger input[type="checkbox"]:focus+.Icon{box-shadow:0 0 0 3px white,0 0 0 5px #71c9f8}
|
html.dark .Token--small .Token-trigger input[type="checkbox"]:focus+.Icon,html.dark .TokenGroup--small>.Token .Token-trigger input[type="checkbox"]:focus+.Icon,html.dark .TokenGroup--small>.TokenGroup>.Token .Token-trigger input[type="checkbox"]:focus+.Icon{box-shadow:0 0 0 3px #fff,0 0 0 5px #71c9f8}
|
||||||
html.dark .Token--xsmall .Token-trigger input[type="checkbox"]:focus+.Icon,html.dark .TokenGroup--xsmall>.Token .Token-trigger input[type="checkbox"]:focus+.Icon,html.dark .TokenGroup--xsmall>.TokenGroup>.Token .Token-trigger input[type="checkbox"]:focus+.Icon{box-shadow:0 0 0 0 white,0 0 0 2px #71c9f8}
|
html.dark .Token--xsmall .Token-trigger input[type="checkbox"]:focus+.Icon,html.dark .TokenGroup--xsmall>.Token .Token-trigger input[type="checkbox"]:focus+.Icon,html.dark .TokenGroup--xsmall>.TokenGroup>.Token .Token-trigger input[type="checkbox"]:focus+.Icon{box-shadow:0 0 0 0 #fff,0 0 0 2px #71c9f8}
|
||||||
html.dark .Token,html.dark .Token--blue{border-color:#1da1f2;color:#1da1f2}
|
html.dark .Token,html.dark .Token--blue{border-color:#1da1f2;color:#1da1f2}
|
||||||
html.dark .Token .Token-adornment,html.dark .Token--blue .Token-adornment{background-color:#1da1f2}
|
html.dark .Token .Token-adornment,html.dark .Token--blue .Token-adornment{background-color:#1da1f2}
|
||||||
html.dark .Token:hover,html.dark .Token--blue:hover{background-color:#97e3ff;color:#005fd1}
|
html.dark .Token:hover,html.dark .Token--blue:hover{background-color:#97e3ff;color:#005fd1}
|
||||||
html.dark .Token.is-selected,html.dark .Token--blue.is-selected{background-color:#1da1f2}
|
html.dark .Token.is-selected,html.dark .Token--blue.is-selected{background-color:#1da1f2}
|
||||||
html.dark .Token.is-selected .Token-adornment,html.dark .Token--blue.is-selected .Token-adornment{color:#1da1f2}
|
html.dark .Token.is-selected .Token-adornment,html.dark .Token--blue.is-selected .Token-adornment{color:#1da1f2}
|
||||||
html.dark .Token.is-selected:hover,html.dark .Token--blue.is-selected:hover{background-color:#005fd1;border-color:#005fd1}
|
html.dark .Token.is-selected:hover,html.dark .Token--blue.is-selected:hover{background-color:#005fd1;border-color:#005fd1}
|
||||||
html.dark .Token:focus,html.dark .Token--blue:focus,html.dark .Token.is-focused,html.dark .Token--blue.is-focused{box-shadow:0 0 0 1px white,0 0 0 3px #71c9f8}
|
html.dark .Token:focus,html.dark .Token--blue:focus,html.dark .Token.is-focused,html.dark .Token--blue.is-focused{box-shadow:0 0 0 1px #fff,0 0 0 3px #71c9f8}
|
||||||
html.dark .Token--green{border-color:#17bf63;color:#17bf63}
|
html.dark .Token--green{border-color:#17bf63;color:#17bf63}
|
||||||
html.dark .Token--green .Token-adornment{background-color:#17bf63}
|
html.dark .Token--green .Token-adornment{background-color:#17bf63}
|
||||||
html.dark .Token--green:hover{background-color:#a5f2aa;color:#008951}
|
html.dark .Token--green:hover{background-color:#a5f2aa;color:#008951}
|
||||||
html.dark .Token--green.is-selected{background-color:#17bf63}
|
html.dark .Token--green.is-selected{background-color:#17bf63}
|
||||||
html.dark .Token--green.is-selected .Token-adornment{color:#17bf63}
|
html.dark .Token--green.is-selected .Token-adornment{color:#17bf63}
|
||||||
html.dark .Token--green.is-selected:hover{background-color:#008951;border-color:#008951}
|
html.dark .Token--green.is-selected:hover{background-color:#008951;border-color:#008951}
|
||||||
html.dark .Token--green:focus,html.dark .Token--green.is-focused{box-shadow:0 0 0 1px white,0 0 0 3px #68e090}
|
html.dark .Token--green:focus,html.dark .Token--green.is-focused{box-shadow:0 0 0 1px #fff,0 0 0 3px #68e090}
|
||||||
html.dark .Token--red{border-color:#e0245e;color:#e0245e}
|
html.dark .Token--red{border-color:#e0245e;color:#e0245e}
|
||||||
html.dark .Token--red .Token-adornment{background-color:#e0245e}
|
html.dark .Token--red .Token-adornment{background-color:#e0245e}
|
||||||
html.dark .Token--red:hover{background-color:#ffb8c2;color:#a01744}
|
html.dark .Token--red:hover{background-color:#ffb8c2;color:#a01744}
|
||||||
html.dark .Token--red.is-selected{background-color:#e0245e}
|
html.dark .Token--red.is-selected{background-color:#e0245e}
|
||||||
html.dark .Token--red.is-selected .Token-adornment{color:#e0245e}
|
html.dark .Token--red.is-selected .Token-adornment{color:#e0245e}
|
||||||
html.dark .Token--red.is-selected:hover{background-color:#a01744;border-color:#a01744}
|
html.dark .Token--red.is-selected:hover{background-color:#a01744;border-color:#a01744}
|
||||||
html.dark .Token--red:focus,html.dark .Token--red.is-focused{box-shadow:0 0 0 1px white,0 0 0 3px #f6809a}
|
html.dark .Token--red:focus,html.dark .Token--red.is-focused{box-shadow:0 0 0 1px #fff,0 0 0 3px #f6809a}
|
||||||
html.dark .Token--purple{border-color:#794bc4;color:#794bc4}
|
html.dark .Token--purple{border-color:#794bc4;color:#794bc4}
|
||||||
html.dark .Token--purple .Token-adornment{background-color:#794bc4}
|
html.dark .Token--purple .Token-adornment{background-color:#794bc4}
|
||||||
html.dark .Token--purple:hover{background-color:#c7b4fa;color:#4f0299}
|
html.dark .Token--purple:hover{background-color:#c7b4fa;color:#4f0299}
|
||||||
html.dark .Token--purple.is-selected{background-color:#794bc4}
|
html.dark .Token--purple.is-selected{background-color:#794bc4}
|
||||||
html.dark .Token--purple.is-selected .Token-adornment{color:#794bc4}
|
html.dark .Token--purple.is-selected .Token-adornment{color:#794bc4}
|
||||||
html.dark .Token--purple.is-selected:hover{background-color:#4f0299;border-color:#4f0299}
|
html.dark .Token--purple.is-selected:hover{background-color:#4f0299;border-color:#4f0299}
|
||||||
html.dark .Token--purple:focus,html.dark .Token--purple.is-focused{box-shadow:0 0 0 1px white,0 0 0 3px #a37ced}
|
html.dark .Token--purple:focus,html.dark .Token--purple.is-focused{box-shadow:0 0 0 1px #fff,0 0 0 3px #a37ced}
|
||||||
html.dark .Token--yellow{border-color:#ffad1f;color:#ffad1f}
|
html.dark .Token--yellow{border-color:#ffad1f;color:#ffad1f}
|
||||||
html.dark .Token--yellow .Token-adornment{background-color:#ffad1f}
|
html.dark .Token--yellow .Token-adornment{background-color:#ffad1f}
|
||||||
html.dark .Token--yellow:hover{background-color:#ffe76e;color:#f98e00}
|
html.dark .Token--yellow:hover{background-color:#ffe76e;color:#f98e00}
|
||||||
html.dark .Token--yellow.is-selected{background-color:#ffad1f}
|
html.dark .Token--yellow.is-selected{background-color:#ffad1f}
|
||||||
html.dark .Token--yellow.is-selected .Token-adornment{color:#ffad1f}
|
html.dark .Token--yellow.is-selected .Token-adornment{color:#ffad1f}
|
||||||
html.dark .Token--yellow.is-selected:hover{background-color:#f98e00;border-color:#f98e00}
|
html.dark .Token--yellow.is-selected:hover{background-color:#f98e00;border-color:#f98e00}
|
||||||
html.dark .Token--yellow:focus,html.dark .Token--yellow.is-focused{box-shadow:0 0 0 1px white,0 0 0 3px #ffd03f}
|
html.dark .Token--yellow:focus,html.dark .Token--yellow.is-focused{box-shadow:0 0 0 1px #fff,0 0 0 3px #ffd03f}
|
||||||
html.dark .Token--gray{border-color:#657786;color:#657786}
|
html.dark .Token--gray{border-color:#657786;color:#657786}
|
||||||
html.dark .Token--gray .Token-adornment{background-color:#657786}
|
html.dark .Token--gray .Token-adornment{background-color:#657786}
|
||||||
html.dark .Token--gray:hover{background-color:#e6ecf0;color:#657786}
|
html.dark .Token--gray:hover{background-color:#e6ecf0;color:#657786}
|
||||||
html.dark .Token--gray.is-selected{background-color:#657786}
|
html.dark .Token--gray.is-selected{background-color:#657786}
|
||||||
html.dark .Token--gray.is-selected .Token-adornment{color:#657786}
|
html.dark .Token--gray.is-selected .Token-adornment{color:#657786}
|
||||||
html.dark .Token--gray.is-selected:hover{background-color:#aab8c2;border-color:#aab8c2}
|
html.dark .Token--gray.is-selected:hover{background-color:#aab8c2;border-color:#aab8c2}
|
||||||
html.dark .Token--gray:focus,html.dark .Token--gray.is-focused{box-shadow:0 0 0 1px white,0 0 0 3px #aab8c2}
|
html.dark .Token--gray:focus,html.dark .Token--gray.is-focused{box-shadow:0 0 0 1px #fff,0 0 0 3px #aab8c2}
|
||||||
html.dark .FormTokenInput-input::-webkit-input-placeholder{color:#aab8c2}
|
html.dark .FormTokenInput-input::-webkit-input-placeholder{color:#aab8c2}
|
||||||
html.dark .DataPoint .DataPoint-label{color:#657786}
|
html.dark .DataPoint .DataPoint-label{color:#657786}
|
||||||
html.dark .DataPoint .DataPoint-info{color:#14171a}
|
html.dark .DataPoint .DataPoint-info{color:#14171a}
|
||||||
@@ -805,7 +797,7 @@ html.dark .DataPoint--withBottomBorder{border-bottom:1px solid #ccd6dd}
|
|||||||
html.dark .FormTokenInput.FormTextarea::-webkit-input-placeholder{color:#8899A6}
|
html.dark .FormTokenInput.FormTextarea::-webkit-input-placeholder{color:#8899A6}
|
||||||
html.dark .FormTokenInput.FormTextarea::placeholder{color:#8899A6}
|
html.dark .FormTokenInput.FormTextarea::placeholder{color:#8899A6}
|
||||||
html.dark .DatePicker.date-unselected .is-rangeStart,html.dark .DatePicker.date-unselected .is-rangeEnd{color:#14171a}
|
html.dark .DatePicker.date-unselected .is-rangeStart,html.dark .DatePicker.date-unselected .is-rangeEnd{color:#14171a}
|
||||||
html.dark .DatePicker.date-unselected .is-rangeStart:hover,html.dark .DatePicker.date-unselected .is-rangeEnd:hover{background-color:#005091;color:#ffffff}
|
html.dark .DatePicker.date-unselected .is-rangeStart:hover,html.dark .DatePicker.date-unselected .is-rangeEnd:hover{background-color:#005091;color:#fff}
|
||||||
html.dark .NotificationList .Notification-body{color:#14171A}
|
html.dark .NotificationList .Notification-body{color:#14171A}
|
||||||
html.dark .DrawerModal{color:#14171A}
|
html.dark .DrawerModal{color:#14171A}
|
||||||
/* fixes */
|
/* fixes */
|
||||||
|
@@ -26,7 +26,7 @@ enabled(){
|
|||||||
this.emojiData3 = []; // no skin tones, appended
|
this.emojiData3 = []; // no skin tones, appended
|
||||||
this.emojiNames = [];
|
this.emojiNames = [];
|
||||||
|
|
||||||
var me = this;
|
const me = this;
|
||||||
|
|
||||||
// styles
|
// styles
|
||||||
|
|
||||||
@@ -51,12 +51,12 @@ enabled(){
|
|||||||
|
|
||||||
// layout
|
// layout
|
||||||
|
|
||||||
var buttonHTML = '<button class="needsclick btn btn-on-blue txt-left padding-v--6 padding-h--8 emoji-keyboard-popup-btn"><i class="icon icon-heart"></i></button>';
|
let buttonHTML = '<button class="needsclick btn btn-on-blue txt-left padding-v--6 padding-h--8 emoji-keyboard-popup-btn"><i class="icon icon-heart"></i></button>';
|
||||||
|
|
||||||
this.prevComposeMustache = TD.mustaches["compose/docked_compose.mustache"];
|
this.prevComposeMustache = TD.mustaches["compose/docked_compose.mustache"];
|
||||||
window.TDPF_injectMustache("compose/docked_compose.mustache", "append", '<div class="cf margin-t--12 margin-b--30">', buttonHTML);
|
window.TDPF_injectMustache("compose/docked_compose.mustache", "append", '<div class="cf margin-t--12 margin-b--30">', buttonHTML);
|
||||||
|
|
||||||
var maybeDockedComposePanel = $(".js-docked-compose");
|
let maybeDockedComposePanel = $(".js-docked-compose");
|
||||||
|
|
||||||
if (maybeDockedComposePanel.length){
|
if (maybeDockedComposePanel.length){
|
||||||
maybeDockedComposePanel.find(".cf.margin-t--12.margin-b--30").first().append(buttonHTML);
|
maybeDockedComposePanel.find(".cf.margin-t--12.margin-b--30").first().append(buttonHTML);
|
||||||
@@ -67,10 +67,10 @@ enabled(){
|
|||||||
this.currentKeyboard = null;
|
this.currentKeyboard = null;
|
||||||
this.currentSpanner = null;
|
this.currentSpanner = null;
|
||||||
|
|
||||||
var wasSearchFocused = false;
|
let wasSearchFocused = false;
|
||||||
var lastEmojiKeyword, lastEmojiPosition, lastEmojiLength;
|
let lastEmojiKeyword, lastEmojiPosition, lastEmojiLength;
|
||||||
|
|
||||||
var hideKeyboard = (refocus) => {
|
const hideKeyboard = (refocus) => {
|
||||||
$(this.currentKeyboard).remove();
|
$(this.currentKeyboard).remove();
|
||||||
this.currentKeyboard = null;
|
this.currentKeyboard = null;
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ enabled(){
|
|||||||
lastEmojiKeyword = null;
|
lastEmojiKeyword = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
var generateEmojiHTML = skinTone => {
|
const generateEmojiHTML = skinTone => {
|
||||||
let index = 0;
|
let index = 0;
|
||||||
let html = [ "<p style='font-size:13px;color:#444;margin:4px;text-align:center'>Please, note that some emoji may not show up correctly in the text box above, but they will display in the tweet.</p>" ];
|
let html = [ "<p style='font-size:13px;color:#444;margin:4px;text-align:center'>Please, note that some emoji may not show up correctly in the text box above, but they will display in the tweet.</p>" ];
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ enabled(){
|
|||||||
return html.join("");
|
return html.join("");
|
||||||
};
|
};
|
||||||
|
|
||||||
var updateFilters = () => {
|
const updateFilters = () => {
|
||||||
let keywords = this.currentKeywords;
|
let keywords = this.currentKeywords;
|
||||||
let container = $(this.currentKeyboard.children[1]);
|
let container = $(this.currentKeyboard.children[1]);
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ enabled(){
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var selectSkinTone = skinTone => {
|
const selectSkinTone = skinTone => {
|
||||||
let selectedEle = this.currentKeyboard.children[2].querySelector("[data-tone='"+this.selectedSkinTone+"']");
|
let selectedEle = this.currentKeyboard.children[2].querySelector("[data-tone='"+this.selectedSkinTone+"']");
|
||||||
selectedEle && selectedEle.classList.remove("sel");
|
selectedEle && selectedEle.classList.remove("sel");
|
||||||
|
|
||||||
@@ -146,12 +146,12 @@ enabled(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.generateKeyboard = (left, top) => {
|
this.generateKeyboard = (left, top) => {
|
||||||
var outer = document.createElement("div");
|
let outer = document.createElement("div");
|
||||||
outer.classList.add("emoji-keyboard");
|
outer.classList.add("emoji-keyboard");
|
||||||
outer.style.left = left+"px";
|
outer.style.left = left+"px";
|
||||||
outer.style.top = top+"px";
|
outer.style.top = top+"px";
|
||||||
|
|
||||||
var keyboard = document.createElement("div");
|
let keyboard = document.createElement("div");
|
||||||
keyboard.classList.add("emoji-keyboard-list");
|
keyboard.classList.add("emoji-keyboard-list");
|
||||||
|
|
||||||
keyboard.addEventListener("click", function(e){
|
keyboard.addEventListener("click", function(e){
|
||||||
@@ -164,11 +164,11 @@ enabled(){
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
});
|
});
|
||||||
|
|
||||||
var search = document.createElement("div");
|
let search = document.createElement("div");
|
||||||
search.innerHTML = "<input type='text' placeholder='Search...'>";
|
search.innerHTML = "<input type='text' placeholder='Search...'>";
|
||||||
search.classList.add("emoji-keyboard-search");
|
search.classList.add("emoji-keyboard-search");
|
||||||
|
|
||||||
var skintones = document.createElement("div");
|
let skintones = document.createElement("div");
|
||||||
skintones.innerHTML = me.skinToneData.map(entry => "<div data-tone='"+entry[0]+"' style='background-color:"+entry[1]+"'></div>").join("");
|
skintones.innerHTML = me.skinToneData.map(entry => "<div data-tone='"+entry[0]+"' style='background-color:"+entry[1]+"'></div>").join("");
|
||||||
skintones.classList.add("emoji-keyboard-skintones");
|
skintones.classList.add("emoji-keyboard-skintones");
|
||||||
|
|
||||||
@@ -189,7 +189,7 @@ enabled(){
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
});
|
});
|
||||||
|
|
||||||
var searchInput = search.children[0];
|
let searchInput = search.children[0];
|
||||||
searchInput.focus();
|
searchInput.focus();
|
||||||
|
|
||||||
wasSearchFocused = false;
|
wasSearchFocused = false;
|
||||||
@@ -232,12 +232,12 @@ enabled(){
|
|||||||
this.composePanelScroller.trigger("scroll");
|
this.composePanelScroller.trigger("scroll");
|
||||||
};
|
};
|
||||||
|
|
||||||
var getKeyboardTop = () => {
|
const getKeyboardTop = () => {
|
||||||
let button = $(".emoji-keyboard-popup-btn");
|
let button = $(".emoji-keyboard-popup-btn");
|
||||||
return button.offset().top+button.outerHeight()+me.composePanelScroller.scrollTop()+8;
|
return button.offset().top+button.outerHeight()+me.composePanelScroller.scrollTop()+8;
|
||||||
};
|
};
|
||||||
|
|
||||||
var insertEmoji = (src, alt) => {
|
const insertEmoji = (src, alt) => {
|
||||||
let input = this.composeInput;
|
let input = this.composeInput;
|
||||||
|
|
||||||
let val = input.val();
|
let val = input.val();
|
||||||
@@ -418,7 +418,7 @@ ready(){
|
|||||||
|
|
||||||
// HTML generation
|
// HTML generation
|
||||||
|
|
||||||
var convUnicode = function(codePt){
|
const convUnicode = function(codePt){
|
||||||
if (codePt > 0xFFFF){
|
if (codePt > 0xFFFF){
|
||||||
codePt -= 0x10000;
|
codePt -= 0x10000;
|
||||||
return String.fromCharCode(0xD800+(codePt>>10), 0xDC00+(codePt&0x3FF));
|
return String.fromCharCode(0xD800+(codePt>>10), 0xDC00+(codePt&0x3FF));
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
enabled(){
|
enabled(){
|
||||||
var configuration = { defaultAccount: "#preferred" };
|
let configuration = { defaultAccount: "#preferred" };
|
||||||
|
|
||||||
window.TDPF_loadConfigurationFile(this, "configuration.js", "configuration.default.js", obj => configuration = obj);
|
window.TDPF_loadConfigurationFile(this, "configuration.js", "configuration.default.js", obj => configuration = obj);
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ enabled(){
|
|||||||
this.uiComposeTweetEvent = (e, data) => {
|
this.uiComposeTweetEvent = (e, data) => {
|
||||||
return if !(data.type === "reply" || (data.type === "tweet" && "quotedTweet" in data)) || data.popFromInline || !("element" in data);
|
return if !(data.type === "reply" || (data.type === "tweet" && "quotedTweet" in data)) || data.popFromInline || !("element" in data);
|
||||||
|
|
||||||
var query;
|
let query;
|
||||||
|
|
||||||
if (configuration.useAdvancedSelector){
|
if (configuration.useAdvancedSelector){
|
||||||
if (configuration.customSelector){
|
if (configuration.customSelector){
|
||||||
@@ -88,7 +88,7 @@ enabled(){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var identifier = null;
|
let identifier = null;
|
||||||
|
|
||||||
switch(query){
|
switch(query){
|
||||||
case "#preferred":
|
case "#preferred":
|
||||||
@@ -106,7 +106,7 @@ enabled(){
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
if (query[0] === '@'){
|
if (query[0] === '@'){
|
||||||
var obj = TD.storage.accountController.getAccountFromUsername(query.substring(1));
|
let obj = TD.storage.accountController.getAccountFromUsername(query.substring(1));
|
||||||
|
|
||||||
if (obj.length === 0){
|
if (obj.length === 0){
|
||||||
$TD.alert("warning", "Plugin reply-account has invalid configuration: requested account not found: "+query);
|
$TD.alert("warning", "Plugin reply-account has invalid configuration: requested account not found: "+query);
|
||||||
@@ -126,7 +126,7 @@ enabled(){
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.onSelectedAccountChanged = () => {
|
this.onSelectedAccountChanged = () => {
|
||||||
var selected = $(".js-account-item.is-selected", ".js-account-list");
|
let selected = $(".js-account-item.is-selected", ".js-account-list");
|
||||||
this.lastSelectedAccount = selected.length === 1 ? selected.attr("data-account-key") : null;
|
this.lastSelectedAccount = selected.length === 1 ? selected.attr("data-account-key") : null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -32,62 +32,32 @@ enabled(){
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// setup
|
||||||
|
|
||||||
|
this.htmlModal = null;
|
||||||
|
|
||||||
|
$TDP.readFileRoot(this.$token, "modal.html").then(contents => {
|
||||||
|
this.htmlModal = contents;
|
||||||
|
}).catch(err => {
|
||||||
|
$TD.alert("error", "Problem loading data for the template plugin: "+err.message);
|
||||||
|
});
|
||||||
|
|
||||||
// button
|
// button
|
||||||
|
|
||||||
var buttonHTML = '<button class="manage-templates-btn needsclick btn btn-on-blue full-width txt-left margin-b--12 padding-v--6 padding-h--12"><i class="icon icon-bookmark"></i><span class="label padding-ls">Manage templates</span></button>';
|
let buttonHTML = '<button class="manage-templates-btn needsclick btn btn-on-blue full-width txt-left margin-b--12 padding-v--6 padding-h--12"><i class="icon icon-bookmark"></i><span class="label padding-ls">Manage templates</span></button>';
|
||||||
|
|
||||||
this.prevComposeMustache = TD.mustaches["compose/docked_compose.mustache"];
|
this.prevComposeMustache = TD.mustaches["compose/docked_compose.mustache"];
|
||||||
window.TDPF_injectMustache("compose/docked_compose.mustache", "prepend", '<div class="js-tweet-type-button">', buttonHTML);
|
window.TDPF_injectMustache("compose/docked_compose.mustache", "prepend", '<div class="js-tweet-type-button">', buttonHTML);
|
||||||
|
|
||||||
var dockedComposePanel = $(".js-docked-compose");
|
let dockedComposePanel = $(".js-docked-compose");
|
||||||
|
|
||||||
if (dockedComposePanel.length){
|
if (dockedComposePanel.length){
|
||||||
dockedComposePanel.find(".js-tweet-type-button").first().before(buttonHTML);
|
dockedComposePanel.find(".js-tweet-type-button").first().before(buttonHTML);
|
||||||
}
|
}
|
||||||
|
|
||||||
// css
|
|
||||||
|
|
||||||
this.css = window.TDPF_createCustomStyle(this);
|
|
||||||
this.css.insert(".manage-templates-btn.active { color: #fff; box-shadow: 0 0 2px 3px #50a5e6; outline: 0; }");
|
|
||||||
|
|
||||||
this.css.insert("#templates-modal-wrap { width: 100%; height: 100%; padding: 49px; position: absolute; z-index: 999; box-sizing: border-box; background-color: rgba(0, 0, 0, 0.5); }");
|
|
||||||
this.css.insert("#templates-modal { width: 100%; height: 100%; background-color: #fff; display: flex; }");
|
|
||||||
this.css.insert("#templates-modal > div { display: flex; flex-direction: column; }");
|
|
||||||
|
|
||||||
this.css.insert(".templates-modal-bottom { flex: 0 0 auto; padding: 16px; }");
|
|
||||||
this.css.insert("#template-list .templates-modal-bottom { display: flex; justify-content: space-between; }");
|
|
||||||
this.css.insert("#template-editor .templates-modal-bottom { text-align: right; }");
|
|
||||||
|
|
||||||
this.css.insert("#template-list { height: 100%; flex: 1 1 auto; }");
|
|
||||||
this.css.insert("#template-list ul { list-style-type: none; font-size: 24px; color: #222; flex: 1 1 auto; padding: 12px; overflow-y: auto; }");
|
|
||||||
this.css.insert("#template-list li { display: block; width: 100%; padding: 4px 8px; box-sizing: border-box; }");
|
|
||||||
this.css.insert("#template-list li[data-template] { cursor: pointer; }");
|
|
||||||
this.css.insert("#template-list li[data-template]:hover { background-color: #d8d8d8; }");
|
|
||||||
this.css.insert("#template-list li span { white-space: nowrap; }");
|
|
||||||
this.css.insert("#template-list li .icon { opacity: 0.6; margin-left: 4px; padding: 3px; }");
|
|
||||||
this.css.insert("#template-list li .icon:hover { opacity: 1; }");
|
|
||||||
this.css.insert("#template-list li .template-actions { float: right; }");
|
|
||||||
|
|
||||||
this.css.insert("#template-editor { height: 100%; flex: 0 0 auto; width: 25vw; min-width: 150px; max-width: 400px; background-color: #485865; }");
|
|
||||||
this.css.insert(".template-editor-form { flex: 1 1 auto; padding: 12px 16px; font-size: 14px; overflow-y: auto; }");
|
|
||||||
this.css.insert(".template-editor-form .compose-text-title { margin: 24px 0 9px; }");
|
|
||||||
this.css.insert(".template-editor-form .compose-text-title:first-child { margin-top: 0; }");
|
|
||||||
this.css.insert(".template-editor-form input, .template-editor-form textarea { color: #111; background-color: #fff; border: none; border-radius: 0; }");
|
|
||||||
this.css.insert(".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); }");
|
|
||||||
this.css.insert(".template-editor-form textarea { height: 146px; font-size: 14px; padding: 10px; resize: none; }");
|
|
||||||
this.css.insert(".template-editor-form .template-editor-tips-button { cursor: pointer; }");
|
|
||||||
this.css.insert(".template-editor-form .template-editor-tips-button .icon { font-size: 12px; vertical-align: -5%; margin-left: 4px; }");
|
|
||||||
this.css.insert(".template-editor-form .template-editor-tips { display: none; }");
|
|
||||||
this.css.insert(".template-editor-form .template-editor-tips p { margin: 10px 0; }");
|
|
||||||
this.css.insert(".template-editor-form .template-editor-tips p:first-child { margin-top: 0; }");
|
|
||||||
this.css.insert(".template-editor-form .template-editor-tips li:nth-child(2n+1) { margin-top: 5px; padding-left: 6px; font-family: monospace; }");
|
|
||||||
this.css.insert(".template-editor-form .template-editor-tips li:nth-child(2n) { margin-top: 1px; padding-left: 14px; opacity: 0.66; }");
|
|
||||||
|
|
||||||
this.css.insert(".invisible { display: none !important; }");
|
|
||||||
|
|
||||||
// template implementation
|
// template implementation
|
||||||
|
|
||||||
var readTemplateTokens = (contents, tokenData) => {
|
const readTemplateTokens = (contents, tokenData) => {
|
||||||
let startIndex = -1;
|
let startIndex = -1;
|
||||||
let endIndex = -1;
|
let endIndex = -1;
|
||||||
|
|
||||||
@@ -155,7 +125,7 @@ enabled(){
|
|||||||
return [ contents, data ];
|
return [ contents, data ];
|
||||||
};
|
};
|
||||||
|
|
||||||
var doAjaxRequest = (index, url, evaluator) => {
|
const doAjaxRequest = (index, url, evaluator) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!url){
|
if (!url){
|
||||||
resolve([ index, "{ajax}" ]);
|
resolve([ index, "{ajax}" ]);
|
||||||
@@ -175,7 +145,7 @@ enabled(){
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var useTemplate = (contents, append) => {
|
const useTemplate = (contents, append) => {
|
||||||
let ele = $(".js-compose-text");
|
let ele = $(".js-compose-text");
|
||||||
return if ele.length === 0;
|
return if ele.length === 0;
|
||||||
|
|
||||||
@@ -257,68 +227,19 @@ enabled(){
|
|||||||
|
|
||||||
this.editingTemplate = null;
|
this.editingTemplate = null;
|
||||||
|
|
||||||
var showTemplateModal = () => {
|
const showTemplateModal = () => {
|
||||||
$(".manage-templates-btn").addClass("active");
|
$(".js-app-content").prepend(this.htmlModal);
|
||||||
|
|
||||||
let html = `
|
/* TODO possibly implement this later
|
||||||
<div id="templates-modal-wrap">
|
|
||||||
<div id="templates-modal">
|
|
||||||
<div id="template-list">
|
|
||||||
<ul></ul>
|
|
||||||
|
|
||||||
<div class="templates-modal-bottom">
|
<li>{paste}</li>
|
||||||
<button data-action="close" class="Button--secondary"><i class="icon icon-close icon-small padding-rs"></i><span class="label">Close</span></button>
|
<li>Paste text or an image from clipboard</li>
|
||||||
<button data-action="new-template" class="Button--primary"><i class="icon icon-plus icon-small padding-rs"></i><span class="label">New Template</span></button>
|
<li>{paste#text}</li>
|
||||||
</div>
|
<li>Paste only if clipboard has text</li>
|
||||||
</div>
|
<li>{paste#image}</li>
|
||||||
|
<li>Paste only if clipboard has an image</li>
|
||||||
|
|
||||||
<div id="template-editor" class="invisible">
|
*/
|
||||||
<div class="template-editor-form">
|
|
||||||
<div class="compose-text-title">Template Name</div>
|
|
||||||
<input name="template-name" type="text">
|
|
||||||
|
|
||||||
<div class="compose-text-title">Contents</div>
|
|
||||||
<textarea name="template-contents" class="compose-text scroll-v scroll-styled-v scroll-styled-h scroll-alt"></textarea>
|
|
||||||
|
|
||||||
<div class="compose-text-title template-editor-tips-button">Advanced <i class="icon icon-arrow-d"></i></div>
|
|
||||||
<div class="template-editor-tips">
|
|
||||||
<p>You can use the following tokens. All tokens except for <span style="font-family: monospace">{ajax}</span> can only be used once.</p>
|
|
||||||
<ul>
|
|
||||||
<li>{cursor}</li>
|
|
||||||
<li>Location where the cursor is placed</li>
|
|
||||||
<li>{cursor#<selectionlength>}</li>
|
|
||||||
<li>Places cursor and selects a set amount of characters</li>
|
|
||||||
<li>{ajax#<url>}</li>
|
|
||||||
<li>Replaced with the result of a cross-origin ajax request</li>
|
|
||||||
<li>{ajax#<eval>#<url>}</li>
|
|
||||||
<li>Allows parsing the ajax request using <span style="font-family: monospace">$</span> as the placeholder for the result<br>Example: <span style="font-family: monospace">$.substring(0,5)</span></li>
|
|
||||||
</ul>
|
|
||||||
<p>To use special characters in the tweet text, escape them with a backslash:
|
|
||||||
<br><span style="font-family: monospace"> \\{ \\} \\# \\\\</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="templates-modal-bottom">
|
|
||||||
<button data-action="editor-cancel" class="Button--secondary"><i class="icon icon-close icon-small padding-rs"></i><span class="label">Cancel</span></button>
|
|
||||||
<button data-action="editor-confirm" class="Button--primary" style="margin-left:4px"><i class="icon icon-check icon-small padding-rs"></i><span class="label">Confirm</span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
/* TODO possibly implement this later
|
|
||||||
|
|
||||||
<li>{paste}</li>
|
|
||||||
<li>Paste text or an image from clipboard</li>
|
|
||||||
<li>{paste#text}</li>
|
|
||||||
<li>Paste only if clipboard has text</li>
|
|
||||||
<li>{paste#image}</li>
|
|
||||||
<li>Paste only if clipboard has an image</li>
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(".js-app-content").prepend(html);
|
|
||||||
|
|
||||||
let ele = $("#templates-modal-wrap").first();
|
let ele = $("#templates-modal-wrap").first();
|
||||||
|
|
||||||
@@ -407,12 +328,11 @@ enabled(){
|
|||||||
onTemplatesUpdated(false);
|
onTemplatesUpdated(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
var hideTemplateModal = function(){
|
const hideTemplateModal = () => {
|
||||||
$("#templates-modal-wrap").remove();
|
$("#templates-modal-wrap").remove();
|
||||||
$(".manage-templates-btn").removeClass("active");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var toggleEditor = function(){
|
const toggleEditor = () => {
|
||||||
let editor = $("#template-editor");
|
let editor = $("#template-editor");
|
||||||
$("[name]", editor).val("");
|
$("[name]", editor).val("");
|
||||||
|
|
||||||
@@ -421,7 +341,7 @@ enabled(){
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var onTemplatesUpdated = (save) => {
|
const onTemplatesUpdated = (save) => {
|
||||||
let eles = [];
|
let eles = [];
|
||||||
|
|
||||||
for(let identifier of Object.keys(this.config.templates)){
|
for(let identifier of Object.keys(this.config.templates)){
|
||||||
@@ -468,8 +388,6 @@ ready(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
disabled(){
|
disabled(){
|
||||||
this.css.remove();
|
|
||||||
|
|
||||||
$(".manage-templates-btn").remove();
|
$(".manage-templates-btn").remove();
|
||||||
$("#templates-modal-wrap").remove();
|
$("#templates-modal-wrap").remove();
|
||||||
|
|
||||||
|
227
Resources/Plugins/templates/modal.html
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
<div id="templates-modal-wrap" class="scroll-v scroll-styled-v">
|
||||||
|
<div id="templates-modal">
|
||||||
|
<div id="template-list">
|
||||||
|
<ul></ul>
|
||||||
|
|
||||||
|
<div class="templates-modal-bottom">
|
||||||
|
<button data-action="close" class="Button--secondary"><i class="icon icon-close icon-small padding-rs"></i><span class="label">Close</span></button>
|
||||||
|
<button data-action="new-template" class="Button--primary"><i class="icon icon-plus icon-small padding-rs"></i><span class="label">New Template</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="template-editor" class="invisible">
|
||||||
|
<div class="template-editor-form">
|
||||||
|
<div class="compose-text-title">Template Name</div>
|
||||||
|
<input name="template-name" type="text">
|
||||||
|
|
||||||
|
<div class="compose-text-title">Contents</div>
|
||||||
|
<textarea name="template-contents" class="compose-text scroll-v scroll-styled-v scroll-styled-h scroll-alt"></textarea>
|
||||||
|
|
||||||
|
<div class="compose-text-title template-editor-tips-button">Advanced <i class="icon icon-arrow-d"></i></div>
|
||||||
|
<div class="template-editor-tips">
|
||||||
|
<p>You can use the following tokens. All tokens except for <span style="font-family: monospace">{ajax}</span> can only be used once.</p>
|
||||||
|
<ul>
|
||||||
|
<li>{cursor}</li>
|
||||||
|
<li>Location where the cursor is placed</li>
|
||||||
|
<li>{cursor#<selectionlength>}</li>
|
||||||
|
<li>Places cursor and selects a set amount of characters</li>
|
||||||
|
<li>{ajax#<url>}</li>
|
||||||
|
<li>Replaced with the result of a cross-origin ajax request</li>
|
||||||
|
<li>{ajax#<eval>#<url>}</li>
|
||||||
|
<li>Allows parsing the ajax request using <span style="font-family: monospace">$</span> as the placeholder for the result<br>Example: <span style="font-family: monospace">$.substring(0,5)</span></li>
|
||||||
|
</ul>
|
||||||
|
<p>To use special characters in the tweet text, escape them with a backslash:
|
||||||
|
<br><span style="font-family: monospace"> \{ \} \# \\</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="templates-modal-bottom">
|
||||||
|
<button data-action="editor-cancel" class="Button--secondary"><i class="icon icon-close icon-small padding-rs"></i><span class="label">Cancel</span></button>
|
||||||
|
<button data-action="editor-confirm" class="Button--primary" style="margin-left:4px"><i class="icon icon-check icon-small padding-rs"></i><span class="label">Confirm</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
/* General */
|
||||||
|
|
||||||
|
#templates-modal-wrap {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 49px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#templates-modal {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-width: 500px;
|
||||||
|
background-color: #fff;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#templates-modal > div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.templates-modal-bottom {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template-list .templates-modal-bottom {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template-editor .templates-modal-bottom {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manage-templates-btn {
|
||||||
|
/* modifies the Manage Templates button while open */
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 0 2px 3px #50a5e6;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Template list */
|
||||||
|
|
||||||
|
#template-list {
|
||||||
|
height: 100%;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template-list ul {
|
||||||
|
list-style-type: none;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #222;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
padding: 12px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template-list li {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
padding: 4px 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template-list li[data-template] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template-list li[data-template]:hover {
|
||||||
|
background-color: #d8d8d8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template-list li span {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template-list li .icon {
|
||||||
|
opacity: 0.6;
|
||||||
|
margin-left: 4px;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template-list li .icon:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template-list li .template-actions {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Template editor */
|
||||||
|
|
||||||
|
#template-editor {
|
||||||
|
height: 100%;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 25vw;
|
||||||
|
min-width: 225px;
|
||||||
|
max-width: 400px;
|
||||||
|
background-color: #485865;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template-editor.invisible {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-editor-form {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
padding: 12px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-editor-form .compose-text-title {
|
||||||
|
margin: 24px 0 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-editor-form .compose-text-title:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-editor-form input, .template-editor-form textarea {
|
||||||
|
color: #111;
|
||||||
|
background-color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-editor-form textarea {
|
||||||
|
height: 146px;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 10px;
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Template tips */
|
||||||
|
|
||||||
|
.template-editor-form .template-editor-tips-button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-editor-form .template-editor-tips-button .icon {
|
||||||
|
font-size: 12px;
|
||||||
|
vertical-align: -5%;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-editor-form .template-editor-tips {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-editor-form .template-editor-tips p {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-editor-form .template-editor-tips p:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-editor-form .template-editor-tips li:nth-child(2n+1) {
|
||||||
|
margin-top: 5px;
|
||||||
|
padding-left: 6px;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-editor-form .template-editor-tips li:nth-child(2n) {
|
||||||
|
margin-top: 1px;
|
||||||
|
padding-left: 14px;
|
||||||
|
opacity: 0.66;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</div>
|
@@ -38,7 +38,7 @@ enabled(){
|
|||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
|
|
||||||
var funcs = {
|
const funcs = {
|
||||||
TwitterStatus: TD.services.TwitterStatus.prototype.render,
|
TwitterStatus: TD.services.TwitterStatus.prototype.render,
|
||||||
TwitterActionOnTweet: TD.services.TwitterActionOnTweet.prototype.render,
|
TwitterActionOnTweet: TD.services.TwitterActionOnTweet.prototype.render,
|
||||||
TweetDetailView: TD.components.TweetDetailView.prototype._renderChirp
|
TweetDetailView: TD.components.TweetDetailView.prototype._renderChirp
|
||||||
|
@@ -9,14 +9,13 @@ $ErrorActionPreference = "Stop"
|
|||||||
|
|
||||||
try{
|
try{
|
||||||
$sw = [Diagnostics.Stopwatch]::StartNew()
|
$sw = [Diagnostics.Stopwatch]::StartNew()
|
||||||
Write-Host "--------------------------"
|
|
||||||
|
|
||||||
if ($version.Equals("")){
|
if ($version.Equals("")){
|
||||||
$version = (Get-Item (Join-Path $targetDir "TweetDuck.exe")).VersionInfo.FileVersion
|
$version = (Get-Item (Join-Path $targetDir "TweetDuck.exe")).VersionInfo.FileVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write-Host "--------------------------"
|
||||||
Write-Host "TweetDuck version" $version
|
Write-Host "TweetDuck version" $version
|
||||||
|
|
||||||
Write-Host "--------------------------"
|
Write-Host "--------------------------"
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
@@ -47,7 +46,7 @@ try{
|
|||||||
function Remove-Empty-Lines{
|
function Remove-Empty-Lines{
|
||||||
Param([Parameter(Mandatory = $True, Position = 1)] $lines)
|
Param([Parameter(Mandatory = $True, Position = 1)] $lines)
|
||||||
|
|
||||||
ForEach($line in $lines){
|
foreach($line in $lines){
|
||||||
if ($line -ne ''){
|
if ($line -ne ''){
|
||||||
$line
|
$line
|
||||||
}
|
}
|
||||||
@@ -62,7 +61,7 @@ try{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((Get-Content -Path $file -Raw).Contains("`r")){
|
if ((Get-Content -Path $file -Raw).Contains("`r")){
|
||||||
Throw "$file cannot contain carriage return"
|
Throw "$file must not have any carriage return characters"
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Verified" $file.Substring($targetDir.Length)
|
Write-Host "Verified" $file.Substring($targetDir.Length)
|
||||||
@@ -70,11 +69,19 @@ try{
|
|||||||
|
|
||||||
function Rewrite-File{
|
function Rewrite-File{
|
||||||
Param([Parameter(Mandatory = $True, Position = 1)] $file,
|
Param([Parameter(Mandatory = $True, Position = 1)] $file,
|
||||||
[Parameter(Mandatory = $True, Position = 2)] $lines)
|
[Parameter(Mandatory = $True, Position = 2)] $lines,
|
||||||
|
[Parameter(Mandatory = $True, Position = 3)] $imports)
|
||||||
|
|
||||||
$lines = Remove-Empty-Lines($lines)
|
$lines = Remove-Empty-Lines($lines)
|
||||||
$relativePath = $file.FullName.Substring($targetDir.Length)
|
$relativePath = $file.FullName.Substring($targetDir.Length)
|
||||||
|
|
||||||
|
foreach($line in $lines){
|
||||||
|
if ($line.Contains('#import ')){
|
||||||
|
$imports.Add($file.FullName)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($relativePath.StartsWith("scripts\")){
|
if ($relativePath.StartsWith("scripts\")){
|
||||||
$lines = (,("#" + $version) + $lines)
|
$lines = (,("#" + $version) + $lines)
|
||||||
}
|
}
|
||||||
@@ -83,43 +90,75 @@ try{
|
|||||||
Write-Host "Processed" $relativePath
|
Write-Host "Processed" $relativePath
|
||||||
}
|
}
|
||||||
|
|
||||||
# Post processing
|
# Validation
|
||||||
|
|
||||||
Check-Carriage-Return(Join-Path $targetDir "plugins\official\emoji-keyboard\emoji-ordering.txt")
|
Check-Carriage-Return(Join-Path $targetDir "plugins\official\emoji-keyboard\emoji-ordering.txt")
|
||||||
|
|
||||||
ForEach($file in Get-ChildItem -Path $targetDir -Filter "*.js" -Exclude "configuration.default.js" -Recurse){
|
# Processing
|
||||||
|
|
||||||
|
$imports = New-Object "System.Collections.Generic.List[string]"
|
||||||
|
|
||||||
|
foreach($file in Get-ChildItem -Path $targetDir -Filter "*.js" -Exclude "configuration.default.js" -Recurse){
|
||||||
$lines = [IO.File]::ReadLines($file.FullName)
|
$lines = [IO.File]::ReadLines($file.FullName)
|
||||||
$lines = $lines | % { $_.TrimStart() }
|
$lines = $lines | ForEach-Object { $_.TrimStart() }
|
||||||
$lines = $lines -Replace '^(.*?)((?<=^|[;{}()])\s?//(?:\s.*|$))?$', '$1'
|
$lines = $lines -Replace '^(.*?)((?<=^|[;{}()])\s?//(?:\s.*|$))?$', '$1'
|
||||||
$lines = $lines -Replace '(?<!\w)return(\s.*?)? if (.*?);', 'if ($2)return$1;'
|
$lines = $lines -Replace '(?<!\w)(return|throw)(\s.*?)? if (.*?);', 'if ($3)$1$2;'
|
||||||
Rewrite-File $file $lines
|
Rewrite-File $file $lines $imports
|
||||||
}
|
}
|
||||||
|
|
||||||
ForEach($file in Get-ChildItem -Path $targetDir -Filter "*.css" -Recurse){
|
foreach($file in Get-ChildItem -Path $targetDir -Filter "*.css" -Recurse){
|
||||||
$lines = [IO.File]::ReadLines($file.FullName)
|
$lines = [IO.File]::ReadLines($file.FullName)
|
||||||
$lines = $lines -Replace '\s*/\*.*?\*/', ''
|
$lines = $lines -Replace '\s*/\*.*?\*/', ''
|
||||||
$lines = $lines -Replace '^(\S.*) {$', '$1{'
|
$lines = $lines -Replace '^(\S.*) {$', '$1{'
|
||||||
$lines = $lines -Replace '^\s+(.+?):\s*(.+?)(?:\s*(!important))?;$', '$1:$2$3;'
|
$lines = $lines -Replace '^\s+(.+?):\s*(.+?)(?:\s*(!important))?;$', '$1:$2$3;'
|
||||||
$lines = @((Remove-Empty-Lines($lines)) -Join ' ')
|
$lines = @((Remove-Empty-Lines($lines)) -Join ' ')
|
||||||
Rewrite-File $file $lines
|
$lines = $lines -Replace '([{};])\s', '$1'
|
||||||
|
$lines = $lines -Replace ';}', '}'
|
||||||
|
Rewrite-File $file $lines $imports
|
||||||
}
|
}
|
||||||
|
|
||||||
ForEach($file in Get-ChildItem -Path $targetDir -Filter "*.html" -Recurse){
|
foreach($file in Get-ChildItem -Path $targetDir -Filter "*.html" -Recurse){
|
||||||
$lines = [IO.File]::ReadLines($file.FullName)
|
$lines = [IO.File]::ReadLines($file.FullName)
|
||||||
$lines = $lines | % { $_.TrimStart() }
|
$lines = $lines | ForEach-Object { $_.TrimStart() }
|
||||||
Rewrite-File $file $lines
|
Rewrite-File $file $lines $imports
|
||||||
}
|
}
|
||||||
|
|
||||||
ForEach($file in Get-ChildItem -Path (Join-Path $targetDir "plugins") -Filter "*.meta" -Recurse){
|
foreach($file in Get-ChildItem -Path (Join-Path $targetDir "plugins") -Filter "*.meta" -Recurse){
|
||||||
$lines = [IO.File]::ReadLines($file.FullName)
|
$lines = [IO.File]::ReadLines($file.FullName)
|
||||||
$lines = $lines -Replace '\{version\}', $version
|
$lines = $lines -Replace '\{version\}', $version
|
||||||
Rewrite-File $file $lines
|
Rewrite-File $file $lines $imports
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "------------------"
|
# Imports
|
||||||
|
|
||||||
|
$importFolder = Join-Path $targetDir "scripts\imports"
|
||||||
|
|
||||||
|
foreach($path in $imports){
|
||||||
|
$text = [IO.File]::ReadAllText($path)
|
||||||
|
$text = [Regex]::Replace($text, '#import "(.*?)"', {
|
||||||
|
$importPath = Join-Path $importFolder ($args[0].Groups[1].Value.Trim())
|
||||||
|
$importStr = [IO.File]::ReadAllText($importPath).TrimEnd()
|
||||||
|
|
||||||
|
if ($importStr[0] -eq '#'){
|
||||||
|
$importStr = $importStr.Substring($importStr.IndexOf("`n") + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return $importStr
|
||||||
|
}, [System.Text.RegularExpressions.RegexOptions]::MultiLine)
|
||||||
|
|
||||||
|
[IO.File]::WriteAllText($path, $text)
|
||||||
|
Write-Host "Resolved" $path.Substring($targetDir.Length)
|
||||||
|
}
|
||||||
|
|
||||||
|
[IO.Directory]::Delete($importFolder, $True)
|
||||||
|
|
||||||
|
# Finished
|
||||||
|
|
||||||
$sw.Stop()
|
$sw.Stop()
|
||||||
|
Write-Host "------------------"
|
||||||
Write-Host "Finished in" $([math]::Round($sw.Elapsed.TotalMilliseconds)) "ms"
|
Write-Host "Finished in" $([math]::Round($sw.Elapsed.TotalMilliseconds)) "ms"
|
||||||
Write-Host "------------------"
|
Write-Host "------------------"
|
||||||
|
|
||||||
}catch{
|
}catch{
|
||||||
Write-Host "Encountered an error while running PostBuild.ps1 on line" $_.InvocationInfo.ScriptLineNumber
|
Write-Host "Encountered an error while running PostBuild.ps1 on line" $_.InvocationInfo.ScriptLineNumber
|
||||||
Write-Host $_
|
Write-Host $_
|
||||||
|
@@ -1,18 +1,60 @@
|
|||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
$MainProj = "..\TweetDuck.csproj"
|
try{
|
||||||
$BrowserProj = "..\subprocess\TweetDuck.Browser.csproj"
|
$mainProj = "..\TweetDuck.csproj"
|
||||||
|
$browserProj = "..\subprocess\TweetDuck.Browser.csproj"
|
||||||
|
|
||||||
$Match = Select-String -Path $MainProj '<Import Project="packages\\cef\.redist\.x86\.(.*?)\\'
|
$cefMatch = Select-String -Path $mainProj '<Import Project="packages\\cef\.redist\.x86\.(.*?)\\'
|
||||||
$Version = $Match.Matches[0].Groups[1].Value
|
$cefVersion = $cefMatch.Matches[0].Groups[1].Value
|
||||||
|
|
||||||
Copy-Item "..\packages\cef.redist.x86.${Version}\CEF\devtools_resources.pak" -Destination "..\bld\Resources\" -Force
|
$sharpMatch = Select-String -Path $mainProj '<Import Project="packages\\CefSharp\.Common\.(.*?)\\'
|
||||||
|
$sharpVersion = $sharpMatch.Matches[0].Groups[1].Value
|
||||||
|
|
||||||
$Match = Select-String -Path $MainProj '<Import Project="packages\\CefSharp\.Common\.(.*?)\\'
|
$propsFiles = "..\packages\CefSharp.Common.${sharpVersion}\build\CefSharp.Common.props",
|
||||||
$Version = $Match.Matches[0].Groups[1].Value
|
"..\packages\CefSharp.WinForms.${sharpVersion}\build\CefSharp.WinForms.props"
|
||||||
|
|
||||||
$Contents = [IO.File]::ReadAllText($BrowserProj)
|
# Greetings
|
||||||
$Contents = $Contents -Replace '(?<=<HintPath>\.\.\\packages\\CefSharp\.Common\.)(.*?)(?=\\)', $Version
|
|
||||||
$Contents = $Contents -Replace '(?<=<Reference Include="CefSharp\.BrowserSubprocess\.Core, Version=)(\d+)', $Version.Split(".")[0]
|
|
||||||
|
|
||||||
[IO.File]::WriteAllText($BrowserProj, $Contents)
|
$title = "CEF ${cefVersion}, CefSharp ${sharpVersion}"
|
||||||
|
|
||||||
|
Write-Host ("-" * $title.Length)
|
||||||
|
Write-Host $title
|
||||||
|
Write-Host ("-" * $title.Length)
|
||||||
|
|
||||||
|
# Perform update
|
||||||
|
|
||||||
|
Write-Host "Copying dev tools to repository..."
|
||||||
|
|
||||||
|
Copy-Item "..\packages\cef.redist.x86.${cefVersion}\CEF\devtools_resources.pak" -Destination "..\bld\Resources\" -Force
|
||||||
|
|
||||||
|
Write-Host "Updating browser subprocess reference..."
|
||||||
|
|
||||||
|
$contents = [IO.File]::ReadAllText($browserProj)
|
||||||
|
$contents = $contents -Replace '(?<=<HintPath>\.\.\\packages\\CefSharp\.Common\.)(.*?)(?=\\)', $sharpVersion
|
||||||
|
$contents = $contents -Replace '(?<=<Reference Include="CefSharp\.BrowserSubprocess\.Core, Version=)(\d+)', $sharpVersion.Split(".")[0]
|
||||||
|
|
||||||
|
[IO.File]::WriteAllText($browserProj, $contents)
|
||||||
|
|
||||||
|
Write-Host "Removing x64 and AnyCPU from CefSharp props..."
|
||||||
|
|
||||||
|
foreach($file in $propsFiles){
|
||||||
|
$contents = [IO.File]::ReadAllText($file)
|
||||||
|
$contents = $contents -Replace '(?<=<When Condition=")(''\$\(Platform\)'' == ''(AnyCPU|x64)'')(?=">)', 'false'
|
||||||
|
|
||||||
|
[IO.File]::WriteAllText($file, $contents)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Finished
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Finished. Exiting in 6 seconds..."
|
||||||
|
Start-Sleep -Seconds 6
|
||||||
|
|
||||||
|
}catch{
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Encountered an error while running PostBuild.ps1 on line" $_.InvocationInfo.ScriptLineNumber
|
||||||
|
Write-Host $_
|
||||||
|
|
||||||
|
$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
||||||
|
Exit 1
|
||||||
|
}
|
||||||
|
@@ -1,10 +1,12 @@
|
|||||||
using CefSharp;
|
using CefSharp;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDuck.Core.Controls;
|
using TweetDuck.Core.Controls;
|
||||||
using TweetDuck.Core.Other;
|
using TweetDuck.Core.Other;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@@ -14,17 +16,29 @@ using TweetDuck.Plugins;
|
|||||||
|
|
||||||
namespace TweetDuck.Resources{
|
namespace TweetDuck.Resources{
|
||||||
static class ScriptLoader{
|
static class ScriptLoader{
|
||||||
public static string LoadResource(string name, bool silent = false, Control sync = null){
|
private static readonly Dictionary<string, string> CachedData = new Dictionary<string, string>(16);
|
||||||
|
|
||||||
|
public static string LoadResourceSilent(string name){
|
||||||
|
return LoadResource(name, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string LoadResource(string name, Control sync){
|
||||||
|
if (CachedData.TryGetValue(name, out string resourceData)){
|
||||||
|
return resourceData;
|
||||||
|
}
|
||||||
|
|
||||||
|
string path = Program.ScriptPath;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (Directory.Exists(HotSwapTargetDir)){
|
||||||
|
path = Path.Combine(HotSwapTargetDir, "scripts");
|
||||||
|
Debug.WriteLine("Hot swap active, redirecting "+name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
string resource;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
string path = Program.ScriptPath;
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
if (Directory.Exists(HotSwapTargetDir)){
|
|
||||||
path = Path.Combine(HotSwapTargetDir, "scripts");
|
|
||||||
Debug.WriteLine("Hot swap active, redirecting "+name);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
string contents = File.ReadAllText(Path.Combine(path, name), Encoding.UTF8);
|
string contents = File.ReadAllText(Path.Combine(path, name), Encoding.UTF8);
|
||||||
int separator;
|
int separator;
|
||||||
|
|
||||||
@@ -33,7 +47,7 @@ namespace TweetDuck.Resources{
|
|||||||
// #<version>\n
|
// #<version>\n
|
||||||
|
|
||||||
if (contents[0] != '#'){
|
if (contents[0] != '#'){
|
||||||
ShowLoadError(silent, sync, $"File {name} appears to be corrupted, please try reinstalling the app.");
|
ShowLoadError(sync, $"File {name} appears to be corrupted, please try reinstalling the app.");
|
||||||
separator = 0;
|
separator = 0;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -41,44 +55,33 @@ namespace TweetDuck.Resources{
|
|||||||
string fileVersion = contents.Substring(1, separator-1).TrimEnd();
|
string fileVersion = contents.Substring(1, separator-1).TrimEnd();
|
||||||
|
|
||||||
if (fileVersion != Program.VersionTag){
|
if (fileVersion != Program.VersionTag){
|
||||||
ShowLoadError(silent, sync, $"File {name} is made for a different version of TweetDuck ({fileVersion}) and may not function correctly in this version, please try reinstalling the app.");
|
ShowLoadError(sync, $"File {name} is made for a different version of TweetDuck ({fileVersion}) and may not function correctly in this version, please try reinstalling the app.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return contents.Substring(separator).TrimStart();
|
resource = contents.Substring(separator).TrimStart();
|
||||||
}catch(Exception ex){
|
}catch(Exception ex){
|
||||||
ShowLoadError(silent, sync, $"Could not load {name}. The program will continue running with limited functionality.\n\n{ex.Message}");
|
ShowLoadError(sync, $"Could not load {name}. The program will continue running with limited functionality.\n\n{ex.Message}");
|
||||||
return null;
|
resource = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return CachedData[name] = resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ExecuteFile(IFrame frame, string file, Control sync = null){
|
public static bool ExecuteFile(IFrame frame, string file, Control sync){
|
||||||
string script = LoadResource(file, sync == null, sync);
|
string script = LoadResource(file, sync);
|
||||||
ExecuteScript(frame, script, GetRootIdentifier(file));
|
ExecuteScript(frame, script, "root:"+Path.GetFileNameWithoutExtension(file));
|
||||||
return script != null;
|
return script != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ExecuteScript(IFrame frame, string script, string identifier){
|
public static void ExecuteScript(IFrame frame, string script, string identifier){
|
||||||
if (script != null){
|
if (script != null){
|
||||||
frame.ExecuteJavaScriptAsync(script, "td:"+identifier, 1);
|
frame.ExecuteJavaScriptAsync(script, identifier, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetRootIdentifier(string file){
|
private static void ShowLoadError(Control sync, string message){
|
||||||
return "root:"+Path.GetFileNameWithoutExtension(file);
|
sync?.InvokeSafe(() => FormMessage.Error("Resource Error", message, FormMessage.OK));
|
||||||
}
|
|
||||||
|
|
||||||
private static void ShowLoadError(bool silent, Control sync, string message){
|
|
||||||
if (silent){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sync == null){
|
|
||||||
FormMessage.Error("Resource Error", message, FormMessage.OK);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
sync.InvokeSafe(() => FormMessage.Error("Resource Error", message, FormMessage.OK));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@@ -88,7 +91,7 @@ namespace TweetDuck.Resources{
|
|||||||
|
|
||||||
static ScriptLoader(){
|
static ScriptLoader(){
|
||||||
if (File.Exists(HotSwapRebuildScript)){
|
if (File.Exists(HotSwapRebuildScript)){
|
||||||
Debug.WriteLine("Activating resource hot swap");
|
Debug.WriteLine("Activating resource hot swap...");
|
||||||
|
|
||||||
ResetHotSwap();
|
ResetHotSwap();
|
||||||
Application.ApplicationExit += (sender, args) => ResetHotSwap();
|
Application.ApplicationExit += (sender, args) => ResetHotSwap();
|
||||||
@@ -104,6 +107,8 @@ namespace TweetDuck.Resources{
|
|||||||
ResetHotSwap();
|
ResetHotSwap();
|
||||||
Directory.CreateDirectory(HotSwapTargetDir);
|
Directory.CreateDirectory(HotSwapTargetDir);
|
||||||
|
|
||||||
|
Stopwatch sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
using(Process process = Process.Start(new ProcessStartInfo{
|
using(Process process = Process.Start(new ProcessStartInfo{
|
||||||
FileName = "powershell",
|
FileName = "powershell",
|
||||||
Arguments = $"-ExecutionPolicy Unrestricted -File \"{HotSwapRebuildScript}\" \"{HotSwapTargetDir}\\\" \"{HotSwapProjectRoot}\\\" \"Debug\" \"{Program.VersionTag}\"",
|
Arguments = $"-ExecutionPolicy Unrestricted -File \"{HotSwapRebuildScript}\" \"{HotSwapTargetDir}\\\" \"{HotSwapProjectRoot}\\\" \"Debug\" \"{Program.VersionTag}\"",
|
||||||
@@ -120,20 +125,21 @@ namespace TweetDuck.Resources{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sw.Stop();
|
||||||
|
Debug.WriteLine("Finished rebuild script in "+sw.ElapsedMilliseconds+" ms");
|
||||||
|
|
||||||
|
CachedData.Clear();
|
||||||
|
|
||||||
// Force update plugin manager setup scripts
|
// Force update plugin manager setup scripts
|
||||||
|
|
||||||
string newPluginRoot = Path.Combine(HotSwapTargetDir, "plugins");
|
string newPluginRoot = Path.Combine(HotSwapTargetDir, "plugins");
|
||||||
|
|
||||||
const BindingFlags flagsInstance = BindingFlags.Instance | BindingFlags.NonPublic;
|
const BindingFlags flagsInstance = BindingFlags.Instance | BindingFlags.NonPublic;
|
||||||
const BindingFlags flagsStatic = BindingFlags.Static | BindingFlags.NonPublic;
|
|
||||||
|
|
||||||
Type typePluginManager = typeof(PluginManager);
|
Type typePluginManager = typeof(PluginManager);
|
||||||
Type typeFormBrowser = typeof(FormBrowser);
|
Type typeFormBrowser = typeof(FormBrowser);
|
||||||
|
|
||||||
// ReSharper disable PossibleNullReferenceException
|
// ReSharper disable PossibleNullReferenceException
|
||||||
object pluginSetupScripts = typePluginManager.GetMethod("LoadSetupScripts", flagsStatic).Invoke(null, new object[0]);
|
|
||||||
typePluginManager.GetField("PluginSetupScripts", flagsStatic).SetValue(null, pluginSetupScripts);
|
|
||||||
|
|
||||||
object instPluginManager = typeFormBrowser.GetField("plugins", flagsInstance).GetValue(FormManager.TryFind<FormBrowser>());
|
object instPluginManager = typeFormBrowser.GetField("plugins", flagsInstance).GetValue(FormManager.TryFind<FormBrowser>());
|
||||||
typePluginManager.GetField("rootPath", flagsInstance).SetValue(instPluginManager, newPluginRoot);
|
typePluginManager.GetField("rootPath", flagsInstance).SetValue(instPluginManager, newPluginRoot);
|
||||||
|
|
||||||
|
26
Resources/Scripts/imports/markup/introduction.html
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<div id="td-introduction-modal" class="ovl scroll-v scroll-styled-v">
|
||||||
|
<div class="mdl is-inverted-dark">
|
||||||
|
<header class="mdl-header">
|
||||||
|
<h3 class="mdl-header-title">Welcome to TweetDuck</h3>
|
||||||
|
<a href="#" class="mdl-dismiss link-normal-dark"><i class="icon icon-close"></i></a>
|
||||||
|
</header>
|
||||||
|
<div class="mdl-inner">
|
||||||
|
<div class="mdl-content">
|
||||||
|
<p>Thank you for downloading TweetDuck!</p>
|
||||||
|
<p><a id="td-introduction-follow" href="#">Follow @TryMyAwesomeApp</a> for latest news and updates about the app.</p>
|
||||||
|
<div class="main-menu"></div>
|
||||||
|
<p><strong>Right-click anywhere</strong> or click <strong>Settings – TweetDuck</strong> in the left panel to open the main menu. You can also right-click links, tweets, images and videos, and desktop notifications to access their respective context menus.</p>
|
||||||
|
<p>Click <strong>Show Guide</strong> to see awesome features TweetDuck offers, or view the guide later by going to <strong>About TweetDuck</strong> and clicking the help button on top.</p>
|
||||||
|
</div>
|
||||||
|
<footer class="txt-right">
|
||||||
|
<div class="anondata">
|
||||||
|
<input id="td-anonymous-data" type="checkbox" checked>
|
||||||
|
<label for="td-anonymous-data">Send anonymous usage data</label>
|
||||||
|
<label> (<a href="https://github.com/chylex/TweetDuck/wiki/Send-anonymous-data" rel="nofollow">learn more</a>)</label>
|
||||||
|
</div>
|
||||||
|
<button class="Button--primary" data-guide><span class="label">Show Guide</span></button>
|
||||||
|
<button class="Button--secondary"><span class="label">Close</span></button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -3,14 +3,14 @@
|
|||||||
// Block: Setup a simple JavaScript object configuration loader.
|
// Block: Setup a simple JavaScript object configuration loader.
|
||||||
//
|
//
|
||||||
window.TDPF_loadConfigurationFile = function(pluginObject, fileNameUser, fileNameDefault, onSuccess, onFailure){
|
window.TDPF_loadConfigurationFile = function(pluginObject, fileNameUser, fileNameDefault, onSuccess, onFailure){
|
||||||
var identifier = pluginObject.$id;
|
let identifier = pluginObject.$id;
|
||||||
var token = pluginObject.$token;
|
let token = pluginObject.$token;
|
||||||
|
|
||||||
$TDP.checkFileExists(token, fileNameUser).then(exists => {
|
$TDP.checkFileExists(token, fileNameUser).then(exists => {
|
||||||
var fileName = exists ? fileNameUser : fileNameDefault;
|
let fileName = exists ? fileNameUser : fileNameDefault;
|
||||||
|
|
||||||
(exists ? $TDP.readFile(token, fileName, true) : $TDP.readFileRoot(token, fileName)).then(contents => {
|
(exists ? $TDP.readFile(token, fileName, true) : $TDP.readFileRoot(token, fileName)).then(contents => {
|
||||||
var obj;
|
let obj;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
obj = eval("("+contents+")");
|
obj = eval("("+contents+")");
|
||||||
@@ -39,16 +39,14 @@
|
|||||||
// Block: Setup a function to add/remove custom CSS.
|
// Block: Setup a function to add/remove custom CSS.
|
||||||
//
|
//
|
||||||
window.TDPF_createCustomStyle = function(pluginObject){
|
window.TDPF_createCustomStyle = function(pluginObject){
|
||||||
var element = document.createElement("style");
|
let element = document.createElement("style");
|
||||||
element.id = "plugin-"+pluginObject.$id+"-"+Math.random().toString(36).substring(2, 7);
|
element.id = "plugin-"+pluginObject.$id+"-"+Math.random().toString(36).substring(2, 7);
|
||||||
document.head.appendChild(element);
|
document.head.appendChild(element);
|
||||||
|
|
||||||
var obj = {
|
return {
|
||||||
insert: (rule) => element.sheet.insertRule(rule, 0),
|
insert: (rule) => element.sheet.insertRule(rule, 0),
|
||||||
remove: () => $(element).remove()
|
remove: () => element.remove(),
|
||||||
|
element: element
|
||||||
};
|
};
|
||||||
|
|
||||||
obj.element = element;
|
|
||||||
return obj;
|
|
||||||
};
|
};
|
||||||
})($TDP);
|
})($TDP);
|
69
Resources/Scripts/imports/styles/introduction.css
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#td-introduction-modal {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal .mdl {
|
||||||
|
width: 90%;
|
||||||
|
min-width: 515px;
|
||||||
|
max-width: 835px;
|
||||||
|
height: 328px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal .mdl-inner {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal .mdl-header-title {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal .mdl-content {
|
||||||
|
padding: 4px 16px 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal p {
|
||||||
|
margin: 12px 0;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal p strong {
|
||||||
|
font-weight: normal;
|
||||||
|
text-shadow: 0 0 #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal .main-menu {
|
||||||
|
float: left;
|
||||||
|
width: 187px;
|
||||||
|
height: 124px;
|
||||||
|
margin-right: 12px;
|
||||||
|
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.33);
|
||||||
|
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALsAAAB8CAMAAAAGozFUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACZUExURQAAAAAANgAAYQA2YQA2iABhYQBhrDYAADYANjYAYTY2ADY2NjY2YTY2iDZhrDaIiDaIz2EAAGEANmEAYWE2NmE2iGFhNmFhYWGs8og2AIg2Nog2YYiIYYisiIjPrIjPz4jP8qxhAKxhNqzPiKzyrKzy8szMzM+INs/PiM/yrM/yz8/y8tfX1/Dw8PKsYfLPiPLyrPLyz/Ly8nG9GIQAAARDSURBVHja7ZyPd9IwEMdDxbI5cemcWJjbWrWrDi2Q//+PM7m7pOGHfcORlD6v7w1ok2wfwqXkvrs78TTcQzypoR6DZ//dcTA7szM7s8dgX2dCiJxGrG+Kvd+C1w619M+uoZqkGiy7AxvivI+XajURSWVO9AtjQ6UQqTIn18R+PxFSP82SCnuUOYxdfdjMzSmNn9mPMJa9p/QWpH5cZ5rjgqbanNQjOMnGS315nWl+7NGkqrmSqpb6hRuvm+PO++qygtkWKZ2YOW2EGBWr6dK3mTKHmcYeuu3r/fR5UawmUrXjY9tMLRFItez6abPYYd/MffbN4uHT89033UPVInfje1ir+Glbm7msGjKR1mbg/UFv7KFqYzGfwUhq6cbHZle1Jp3QZ65fjMwcize3hbEcu1ZnZkVCb+wBq8L86D4JGl1sm+E9AbMzO7MzO7MzO7Mze586QQqdcav7ggO3juMfF8Whlsj+6hXuzx17x0aWmswO/nBLbPaZ8RqatzdHsO/36In94WOltAOnXSZwoR7A+Qa3H5q/CEH+aA5+OfaQ6ASCYGAuZq3nAi4KjML2oH6T9qxX05+W3T5pt5+WQ5NUpA1s99jMpZt05zpiPxzVpOF1gukSFACPDN3+1p0l/3qbHf1rVBQO9gMFISz7ZnE/Xe6wX3oqXzc7KgoH+4GCEFoXA8VL20CuGprCTG6xkzZwyGZIUTjUDxSEwOybu4regzC3mxLXqm8zVhsoYUXai2aF5qQolL7KQB1QQeDvVWZndmZndmZn9nNn/3WuB9sMszM7szM7sw+WXXvEQgYTRYOyNxA9IEMJiyHZjSijWi1pUOxIDcqWiao6uSgalN0E70BYT7YncJ1CFI0074Uvg55KFI1i715U1SlF0bD3maRSGH4nfbn0VKJo+Pt77qKqTi2KRvlePZObI7PzXozZmZ3ZmZ3Zmf1/YjdO3qjY3xH0rBW8PN9jvDyv3cyR+R7DZvdCNq7pQk8iwfE243l7NUTR9CYSHLNWk8qPRsKcJu9CdJHgmHlXqos9vkhwPLsNuWptpi+R4Hh2G3KF+Vgte3yR4FXfq620Orw9QTleDpLd3M6Tvqed95HMzuzMzuzMzuw9sJep6v7XQSnEXsyBd0AZmN3WVzrAL2Rfvb8t/vK3OgukKM/ddelpkdlraVyLV7LvbZujsLuyG1CkxcURtGlalsQVbaHELfP43YYfeP9WRmGBfPWw7Bpc47dFWnaTsBy7K9ri6r3Q4w47BrSsbx7neeh5NwZTp7ZIy34ik2P3iraYxK22aguyb+c46RfvZGibgZsElfzRc9fB7oq2uJysHXvfZs+u0tDspl4RhqBgOAHGEXhpWu3Ks0VbqF6Lq9piC7vQIGszRSkDs+MfqFMbTkBJWF6almO3RVsocQsfS0yihOxXGgQpW2D4/+728p6A2Zmd2Zmd2c+SfaCHZh/u8QdspaeBZ15I7gAAAABJRU5ErkJggg==);
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal .main-menu + p {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal footer {
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal button {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal .anondata {
|
||||||
|
float: left;
|
||||||
|
margin: 5px 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal .anondata input {
|
||||||
|
vertical-align: -10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#td-introduction-modal .anondata label {
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
67
Resources/Scripts/imports/styles/twitter.base.css
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*********************/
|
||||||
|
/* Center everything */
|
||||||
|
/*********************/
|
||||||
|
|
||||||
|
#doc {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-outer {
|
||||||
|
display: table-cell;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-container {
|
||||||
|
padding: 0 20px !important;
|
||||||
|
width: 100% !important;
|
||||||
|
box-sizing: border-box !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-canvas {
|
||||||
|
margin: 0 auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************/
|
||||||
|
/* General styling */
|
||||||
|
/*******************/
|
||||||
|
|
||||||
|
body {
|
||||||
|
/* remove scrollbar */
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-canvas {
|
||||||
|
/* tweak page shadow */
|
||||||
|
box-shadow: 0 0 150px rgba(255, 255, 255, 0.3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar {
|
||||||
|
/* hide top bar */
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-canvas, .buttons, .btn, input {
|
||||||
|
/* sharpen borders */
|
||||||
|
border-radius: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
/* tweak input padding */
|
||||||
|
padding: 5px 8px 4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
button[type='submit'] {
|
||||||
|
/* style buttons */
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.3) !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tweetduck-helper {
|
||||||
|
/* custom login text */
|
||||||
|
margin-top: 15px !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
}
|
38
Resources/Scripts/imports/styles/twitter.logout.css
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*****************************/
|
||||||
|
/* 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;
|
||||||
|
}
|
134
Resources/Scripts/imports/styles/update.css
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
#tweetduck-update {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
width: 200px;
|
||||||
|
height: 178px;
|
||||||
|
z-index: 9999;
|
||||||
|
color: #fff;
|
||||||
|
background-color: rgb(32, 94, 138);
|
||||||
|
font-family: Helvetica, Arial, Verdana, sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
|
||||||
|
line-height: 1.28578;
|
||||||
|
transition: transform 400ms cubic-bezier(.02, .01, .47, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-update.hidden-below {
|
||||||
|
transform: translateY(178px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-update .tdu-title {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 8px 0 2px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-update .tdu-info {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 3px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-update .tdu-showlog {
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-update .tdu-buttons button {
|
||||||
|
display: block;
|
||||||
|
margin: 7px auto 0;
|
||||||
|
padding: 4px 10px;
|
||||||
|
width: 80%;
|
||||||
|
height: 30px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 1px;
|
||||||
|
outline: none;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #419de0;
|
||||||
|
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
|
||||||
|
box-shadow: 1px 1px 1px rgba(17, 17, 17, 0.5) !important;
|
||||||
|
transition: box-shadow 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-update .tdu-buttons button:hover {
|
||||||
|
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.75);
|
||||||
|
box-shadow: 1px 1px 1px rgba(17, 17, 17, 0.75), 0 -2px 0 rgba(17, 17, 17, 0.33) inset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-update .tdu-buttons button.tdu-btn-ignore, .tdu-buttons button.tdu-btn-later {
|
||||||
|
background-color: #607a8e;
|
||||||
|
color: #dfdfdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-changelog {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
font-family: Helvetica, Arial, Verdana, sans-serif;
|
||||||
|
line-height: 1.28578;
|
||||||
|
z-index: 9998;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-changelog-box {
|
||||||
|
position: absolute;
|
||||||
|
width: 60%;
|
||||||
|
height: 75%;
|
||||||
|
max-width: calc(90% - 200px);
|
||||||
|
max-height: 90%;
|
||||||
|
left: calc(50% + 100px);
|
||||||
|
top: 50%;
|
||||||
|
padding: 12px;
|
||||||
|
overflow-y: auto;
|
||||||
|
transform: translateX(-50%) translateY(-50%);
|
||||||
|
font-size: 14px;
|
||||||
|
color: #2f2f2f;
|
||||||
|
background-color: #fff;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-changelog h2 {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
color: #5c6973;
|
||||||
|
font-size: 23px;
|
||||||
|
line-height: 1.28578;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-changelog h2 + br {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-changelog h3 {
|
||||||
|
margin: 0 0 5px 7px;
|
||||||
|
color: #065b9c;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1.28578;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-changelog p {
|
||||||
|
margin: 8px 8px 0 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-changelog p.li {
|
||||||
|
margin: 0 8px 2px 30px;
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-changelog p.l2 {
|
||||||
|
margin-left: 50px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-changelog a {
|
||||||
|
color: #247fbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tweetduck-changelog code {
|
||||||
|
padding: 0 4px;
|
||||||
|
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||||
|
color: #24292e;
|
||||||
|
background-color: rgba(27, 31, 35, 0.05);
|
||||||
|
}
|
@@ -1,104 +1,7 @@
|
|||||||
(function($, $TD){
|
(function($, $TD){
|
||||||
$(document).one("TD.ready", function(){
|
$(document).one("TD.ready", function(){
|
||||||
let css = $(`
|
let css = $(`<style>#import "styles/introduction.css"</style>`).appendTo(document.head);
|
||||||
<style>
|
let ele = $(`#import "markup/introduction.html"`).appendTo(".js-app");
|
||||||
#td-introduction-modal {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal .mdl {
|
|
||||||
width: 90%;
|
|
||||||
max-width: 830px;
|
|
||||||
height: 328px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal .mdl-inner {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal .mdl-header-title {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal .mdl-content {
|
|
||||||
padding: 4px 16px 0;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal p {
|
|
||||||
margin: 12px 0;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal p strong {
|
|
||||||
font-weight: normal;
|
|
||||||
text-shadow: 0 0 #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal .main-menu {
|
|
||||||
float: left;
|
|
||||||
width: 187px;
|
|
||||||
height: 124px;
|
|
||||||
margin-right: 12px;
|
|
||||||
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.33);
|
|
||||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALsAAAB8CAMAAAAGozFUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACZUExURQAAAAAANgAAYQA2YQA2iABhYQBhrDYAADYANjYAYTY2ADY2NjY2YTY2iDZhrDaIiDaIz2EAAGEANmEAYWE2NmE2iGFhNmFhYWGs8og2AIg2Nog2YYiIYYisiIjPrIjPz4jP8qxhAKxhNqzPiKzyrKzy8szMzM+INs/PiM/yrM/yz8/y8tfX1/Dw8PKsYfLPiPLyrPLyz/Ly8nG9GIQAAARDSURBVHja7ZyPd9IwEMdDxbI5cemcWJjbWrWrDi2Q//+PM7m7pOGHfcORlD6v7w1ok2wfwqXkvrs78TTcQzypoR6DZ//dcTA7szM7s8dgX2dCiJxGrG+Kvd+C1w619M+uoZqkGiy7AxvivI+XajURSWVO9AtjQ6UQqTIn18R+PxFSP82SCnuUOYxdfdjMzSmNn9mPMJa9p/QWpH5cZ5rjgqbanNQjOMnGS315nWl+7NGkqrmSqpb6hRuvm+PO++qygtkWKZ2YOW2EGBWr6dK3mTKHmcYeuu3r/fR5UawmUrXjY9tMLRFItez6abPYYd/MffbN4uHT89033UPVInfje1ir+Glbm7msGjKR1mbg/UFv7KFqYzGfwUhq6cbHZle1Jp3QZ65fjMwcize3hbEcu1ZnZkVCb+wBq8L86D4JGl1sm+E9AbMzO7MzO7MzO7Mze586QQqdcav7ggO3juMfF8Whlsj+6hXuzx17x0aWmswO/nBLbPaZ8RqatzdHsO/36In94WOltAOnXSZwoR7A+Qa3H5q/CEH+aA5+OfaQ6ASCYGAuZq3nAi4KjML2oH6T9qxX05+W3T5pt5+WQ5NUpA1s99jMpZt05zpiPxzVpOF1gukSFACPDN3+1p0l/3qbHf1rVBQO9gMFISz7ZnE/Xe6wX3oqXzc7KgoH+4GCEFoXA8VL20CuGprCTG6xkzZwyGZIUTjUDxSEwOybu4regzC3mxLXqm8zVhsoYUXai2aF5qQolL7KQB1QQeDvVWZndmZndmZn9nNn/3WuB9sMszM7szM7sw+WXXvEQgYTRYOyNxA9IEMJiyHZjSijWi1pUOxIDcqWiao6uSgalN0E70BYT7YncJ1CFI0074Uvg55KFI1i715U1SlF0bD3maRSGH4nfbn0VKJo+Pt77qKqTi2KRvlePZObI7PzXozZmZ3ZmZ3Zmf1/YjdO3qjY3xH0rBW8PN9jvDyv3cyR+R7DZvdCNq7pQk8iwfE243l7NUTR9CYSHLNWk8qPRsKcJu9CdJHgmHlXqos9vkhwPLsNuWptpi+R4Hh2G3KF+Vgte3yR4FXfq620Orw9QTleDpLd3M6Tvqed95HMzuzMzuzMzuw9sJep6v7XQSnEXsyBd0AZmN3WVzrAL2Rfvb8t/vK3OgukKM/ddelpkdlraVyLV7LvbZujsLuyG1CkxcURtGlalsQVbaHELfP43YYfeP9WRmGBfPWw7Bpc47dFWnaTsBy7K9ri6r3Q4w47BrSsbx7neeh5NwZTp7ZIy34ik2P3iraYxK22aguyb+c46RfvZGibgZsElfzRc9fB7oq2uJysHXvfZs+u0tDspl4RhqBgOAHGEXhpWu3Ks0VbqF6Lq9piC7vQIGszRSkDs+MfqFMbTkBJWF6almO3RVsocQsfS0yihOxXGgQpW2D4/+728p6A2Zmd2Zmd2c+SfaCHZh/u8QdspaeBZ15I7gAAAABJRU5ErkJggg==);
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal .main-menu + p {
|
|
||||||
margin-top: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal footer {
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal button {
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal .anondata {
|
|
||||||
float: left;
|
|
||||||
margin: 5px 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal .anondata input {
|
|
||||||
vertical-align: -10%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#td-introduction-modal .anondata label {
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
</style>`).appendTo(document.head);
|
|
||||||
|
|
||||||
let ele = $(`
|
|
||||||
<div id="td-introduction-modal" class="ovl">
|
|
||||||
<div class="mdl is-inverted-dark">
|
|
||||||
<header class="mdl-header">
|
|
||||||
<h3 class="mdl-header-title">Welcome to TweetDuck</h3>
|
|
||||||
<a href="#" class="mdl-dismiss link-normal-dark"><i class="icon icon-close"></i></a>
|
|
||||||
</header>
|
|
||||||
<div class="mdl-inner">
|
|
||||||
<div class="mdl-content">
|
|
||||||
<p>Thank you for downloading TweetDuck!</p>
|
|
||||||
<p><a id="td-introduction-follow" href="#">Follow @TryMyAwesomeApp</a> for latest news and updates about the app.</p>
|
|
||||||
<div class="main-menu"></div>
|
|
||||||
<p><strong>Right-click anywhere</strong> or click <strong>Settings – TweetDuck</strong> in the left panel to open the main menu. You can also right-click links, tweets, images and videos, and desktop notifications to access their respective context menus.</p>
|
|
||||||
<p>Click <strong>Show Guide</strong> to see awesome features TweetDuck offers, or view the guide later by going to <strong>About TweetDuck</strong> and clicking the help button on top.</p>
|
|
||||||
</div>
|
|
||||||
<footer class="txt-right">
|
|
||||||
<div class="anondata">
|
|
||||||
<input id="td-anonymous-data" type="checkbox" checked>
|
|
||||||
<label for="td-anonymous-data">Send anonymous usage data</label>
|
|
||||||
<label> (<a href="https://github.com/chylex/TweetDuck/wiki/Send-anonymous-data" rel="nofollow">learn more</a>)</label>
|
|
||||||
</div>
|
|
||||||
<button class="Button--primary" data-guide><span class="label">Show Guide</span></button>
|
|
||||||
<button class="Button--secondary"><span class="label">Close</span</button>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`).appendTo(".js-app");
|
|
||||||
|
|
||||||
let tdUser = null;
|
let tdUser = null;
|
||||||
let loadTweetDuckUser = (onSuccess, onError) => {
|
let loadTweetDuckUser = (onSuccess, onError) => {
|
||||||
|
@@ -2,26 +2,26 @@
|
|||||||
//
|
//
|
||||||
// Variable: Collection of all <a> tags.
|
// Variable: Collection of all <a> tags.
|
||||||
//
|
//
|
||||||
var links = document.getElementsByTagName("A");
|
const links = document.getElementsByTagName("A");
|
||||||
|
|
||||||
//
|
//
|
||||||
// Function: Adds an event listener to all elements in the array or collection.
|
// Function: Adds an event listener to all elements in the array or collection.
|
||||||
//
|
//
|
||||||
var addEventListener = function(collection, type, listener){
|
const addEventListener = function(collection, type, listener){
|
||||||
for(let index = 0; index < collection.length; index++){
|
for(let ele of collection){
|
||||||
collection[index].addEventListener(type, listener);
|
ele.addEventListener(type, listener);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Block: Hook into links to bypass default open function and t.co, and handle skipping notification when opening links.
|
// Block: Hook into links to bypass default open function, and handle skipping notification when opening links.
|
||||||
//
|
//
|
||||||
(function(){
|
(function(){
|
||||||
const onLinkClick = function(e){
|
const onLinkClick = function(e){
|
||||||
if (e.button === 0 || e.button === 1){
|
if (e.button === 0 || e.button === 1){
|
||||||
let ele = e.currentTarget;
|
let ele = e.currentTarget;
|
||||||
|
|
||||||
$TD.openBrowser(ele.hasAttribute("data-full-url") ? ele.getAttribute("data-full-url") : ele.getAttribute("href"));
|
$TD.openBrowser(ele.href);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if ($TDX.skipOnLinkClick){
|
if ($TDX.skipOnLinkClick){
|
||||||
@@ -38,27 +38,20 @@
|
|||||||
addEventListener(links, "auxclick", onLinkClick);
|
addEventListener(links, "auxclick", onLinkClick);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
//
|
|
||||||
// Block: Allow bypassing of t.co in context menus.
|
|
||||||
//
|
|
||||||
addEventListener(links, "contextmenu", function(e){
|
|
||||||
$TD.setLastRightClickInfo("link", e.currentTarget.getAttribute("data-full-url"));
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Block: Expand shortened links on hover or display tooltip.
|
// Block: Expand shortened links on hover or display tooltip.
|
||||||
//
|
//
|
||||||
(function(){
|
(function(){
|
||||||
var prevMouseX = -1, prevMouseY = -1;
|
let prevMouseX = -1, prevMouseY = -1;
|
||||||
var tooltipTimer, tooltipDisplayed;
|
let tooltipTimer, tooltipDisplayed;
|
||||||
|
|
||||||
addEventListener(links, "mouseenter", function(e){
|
addEventListener(links, "mouseenter", function(e){
|
||||||
var me = e.currentTarget;
|
let me = e.currentTarget;
|
||||||
|
|
||||||
var url = me.getAttribute("data-full-url");
|
let url = me.getAttribute("data-full-url");
|
||||||
return if !url;
|
return if !url;
|
||||||
|
|
||||||
var text = me.textContent;
|
let text = me.textContent;
|
||||||
return if text.charCodeAt(text.length-1) !== 8230 && text.charCodeAt(0) !== 8230; // horizontal ellipsis
|
return if text.charCodeAt(text.length-1) !== 8230 && text.charCodeAt(0) !== 8230; // horizontal ellipsis
|
||||||
|
|
||||||
if ($TDX.expandLinksOnHover){
|
if ($TDX.expandLinksOnHover){
|
||||||
@@ -79,7 +72,7 @@
|
|||||||
return if !e.currentTarget.hasAttribute("data-full-url");
|
return if !e.currentTarget.hasAttribute("data-full-url");
|
||||||
|
|
||||||
if ($TDX.expandLinksOnHover){
|
if ($TDX.expandLinksOnHover){
|
||||||
var prevText = e.currentTarget.getAttribute("td-prev-text");
|
let prevText = e.currentTarget.getAttribute("td-prev-text");
|
||||||
|
|
||||||
if (prevText){
|
if (prevText){
|
||||||
e.currentTarget.innerHTML = prevText;
|
e.currentTarget.innerHTML = prevText;
|
||||||
@@ -96,7 +89,7 @@
|
|||||||
|
|
||||||
addEventListener(links, "mousemove", function(e){
|
addEventListener(links, "mousemove", function(e){
|
||||||
if (tooltipDisplayed && (prevMouseX !== e.clientX || prevMouseY !== e.clientY)){
|
if (tooltipDisplayed && (prevMouseX !== e.clientX || prevMouseY !== e.clientY)){
|
||||||
var url = e.currentTarget.getAttribute("data-full-url");
|
let url = e.currentTarget.getAttribute("data-full-url");
|
||||||
return if !url;
|
return if !url;
|
||||||
|
|
||||||
$TD.displayTooltip(url);
|
$TD.displayTooltip(url);
|
||||||
@@ -117,7 +110,7 @@
|
|||||||
// Block: Setup a handler for 'Show this thread'.
|
// Block: Setup a handler for 'Show this thread'.
|
||||||
//
|
//
|
||||||
(function(){
|
(function(){
|
||||||
var btn = document.getElementById("tduck-show-thread");
|
let btn = document.getElementById("tduck-show-thread");
|
||||||
return if !btn;
|
return if !btn;
|
||||||
|
|
||||||
btn.addEventListener("click", function(){
|
btn.addEventListener("click", function(){
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
(function(){
|
(function(){
|
||||||
var isReloading = false;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Class: Abstract plugin base class.
|
// Class: Abstract plugin base class.
|
||||||
//
|
//
|
||||||
@@ -107,12 +105,16 @@
|
|||||||
//
|
//
|
||||||
// Block: Setup a function to reload the page.
|
// Block: Setup a function to reload the page.
|
||||||
//
|
//
|
||||||
window.TDPF_requestReload = function(){
|
(function(){
|
||||||
if (!isReloading){
|
let isReloading = false;
|
||||||
window.setTimeout(window.TDGF_reload, 1);
|
|
||||||
isReloading = true;
|
window.TDPF_requestReload = function(){
|
||||||
}
|
if (!isReloading){
|
||||||
};
|
window.setTimeout(window.TDGF_reload, 1);
|
||||||
|
isReloading = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Block: Setup bridges to global functions.
|
// Block: Setup bridges to global functions.
|
||||||
@@ -122,4 +124,6 @@
|
|||||||
window.TDPF_reloadColumns = window.TDGF_reloadColumns;
|
window.TDPF_reloadColumns = window.TDGF_reloadColumns;
|
||||||
window.TDPF_prioritizeNewestEvent = window.TDGF_prioritizeNewestEvent;
|
window.TDPF_prioritizeNewestEvent = window.TDGF_prioritizeNewestEvent;
|
||||||
window.TDPF_injectMustache = window.TDGF_injectMustache;
|
window.TDPF_injectMustache = window.TDGF_injectMustache;
|
||||||
|
|
||||||
|
#import "scripts/plugins.base.js"
|
||||||
})();
|
})();
|
||||||
|
@@ -14,3 +14,5 @@ window.TD_PLUGINS = {
|
|||||||
plugin.obj.run();
|
plugin.obj.run();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#import "scripts/plugins.base.js"
|
||||||
|
@@ -42,7 +42,7 @@ button, .btn, .mdl, .mdl-content, .popover, .lst-modal, .tooltip-inner {
|
|||||||
border-radius: 1px !important;
|
border-radius: 1px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-item, .media-preview, .media-image, .js-media-added .br--4 {
|
.media-item, .media-preview, .media-image, .js-media-added .br--4, #tduck .compose-message-recipient img {
|
||||||
border-radius: 1px !important;
|
border-radius: 1px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +100,15 @@ button {
|
|||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#tduck .lst-launcher a {
|
||||||
|
border: 1px solid transparent !important;
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tduck .lst-launcher a:hover, #tduck .lst-launcher a:focus, #tduck .lst-launcher a:active {
|
||||||
|
border-color: #bbddf5 !important;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************/
|
/***********************/
|
||||||
/* Hide TweetDeck logo */
|
/* Hide TweetDeck logo */
|
||||||
/***********************/
|
/***********************/
|
||||||
@@ -244,6 +253,27 @@ a[data-full-url] {
|
|||||||
min-width: 86px;
|
min-width: 86px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************/
|
||||||
|
/* Fix modal dialogs breaking when window size is too small */
|
||||||
|
/************************************************************/
|
||||||
|
|
||||||
|
.ovl:before, .overlay:before {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ovl, .overlay {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ovl[style="display: block;"] {
|
||||||
|
display: flex !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tduck .overlay {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************/
|
/*******************************************/
|
||||||
/* Fix general visual issues or annoyances */
|
/* Fix general visual issues or annoyances */
|
||||||
/*******************************************/
|
/*******************************************/
|
||||||
@@ -278,6 +308,12 @@ a[data-full-url] {
|
|||||||
height: calc(1em + 8px) !important;
|
height: calc(1em + 8px) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.column-header-temp:not(.js-column-header) {
|
||||||
|
/* fix missing column header padding in Edit List dialog */
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.js-column-options .btn-options-tray {
|
.js-column-options .btn-options-tray {
|
||||||
/* fix underline on buttons in column options */
|
/* fix underline on buttons in column options */
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
@@ -290,7 +326,7 @@ a[data-full-url] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
html[data-td-font='smallest'] .sprite-verified-mini {
|
html[data-td-font='smallest'] .sprite-verified-mini {
|
||||||
/* fix cut off badge when zoomed in */
|
/* fix cut off badge in timelines */
|
||||||
width: 13px !important;
|
width: 13px !important;
|
||||||
height: 13px !important;
|
height: 13px !important;
|
||||||
background-position: -223px -99px !important;
|
background-position: -223px -99px !important;
|
||||||
@@ -310,11 +346,21 @@ html[data-td-font='smallest'] .tweet-detail-wrapper .badge-verified:before {
|
|||||||
background-position: -223px -97px !important;
|
background-position: -223px -97px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html[data-td-font='smallest'] .fullname-badged:before, html[data-td-font='small'] .fullname-badged:before {
|
||||||
|
/* fix cut off badge in follow chirps */
|
||||||
|
margin-top: -7px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.keyboard-shortcut-list {
|
.keyboard-shortcut-list {
|
||||||
/* fix keyboard navigation alignment */
|
/* fix keyboard navigation alignment */
|
||||||
vertical-align: top !important;
|
vertical-align: top !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.column-message.is-actionable span:hover > .icon-small-valigned {
|
||||||
|
/* add a visual response when hovering individual filter icons; black theme uses a value of 20 */
|
||||||
|
filter: saturate(10);
|
||||||
|
}
|
||||||
|
|
||||||
.tweet-detail-wrapper .js-media-gif-container {
|
.tweet-detail-wrapper .js-media-gif-container {
|
||||||
/* GIFs in detail view don't trigger the pointer cursor */
|
/* GIFs in detail view don't trigger the pointer cursor */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@@ -61,13 +61,25 @@ a[data-full-url] {
|
|||||||
/* Fix general visual issues or annoyances */
|
/* Fix general visual issues or annoyances */
|
||||||
/*******************************************/
|
/*******************************************/
|
||||||
|
|
||||||
|
html[data-td-font='smallest'] .sprite-verified-mini {
|
||||||
|
/* fix cut off badge in timelines */
|
||||||
|
width: 13px !important;
|
||||||
|
height: 13px !important;
|
||||||
|
background-position: -223px -99px !important;
|
||||||
|
}
|
||||||
|
|
||||||
html[data-td-font='smallest'] .badge-verified:before {
|
html[data-td-font='smallest'] .badge-verified:before {
|
||||||
/* fix cut off badge icon */
|
/* fix cut off badge in notifications */
|
||||||
width: 13px !important;
|
width: 13px !important;
|
||||||
height: 13px !important;
|
height: 13px !important;
|
||||||
background-position: -223px -98px !important;
|
background-position: -223px -98px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html[data-td-font='smallest'] .fullname-badged:before, html[data-td-font='small'] .fullname-badged:before {
|
||||||
|
/* fix cut off badge in follow chirps */
|
||||||
|
margin-top: -7px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.account-inline .username {
|
.account-inline .username {
|
||||||
vertical-align: 10% !important;
|
vertical-align: 10% !important;
|
||||||
}
|
}
|
||||||
|
@@ -2,40 +2,21 @@
|
|||||||
//
|
//
|
||||||
// Function: Inject custom CSS into the page.
|
// Function: Inject custom CSS into the page.
|
||||||
//
|
//
|
||||||
var injectCSS = function(){
|
const injectCSS = function(){
|
||||||
if (!document.head){
|
if (!document.head){
|
||||||
setTimeout(injectCSS, 5);
|
setTimeout(injectCSS, 5);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var style = document.createElement("style");
|
let style = document.createElement("style");
|
||||||
document.head.appendChild(style);
|
|
||||||
|
|
||||||
let addRule = (rule) => {
|
style.innerText = `#import "styles/twitter.base.css"`;
|
||||||
style.sheet.insertRule(rule, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
addRule("body { overflow: hidden !important; }"); // remove scrollbar
|
|
||||||
addRule(".page-canvas { box-shadow: 0 0 150px rgba(255, 255, 255, 0.3) !important; }"); // change page box shadow
|
|
||||||
addRule(".topbar { display: none !important; }"); // hide top bar
|
|
||||||
|
|
||||||
addRule(".page-canvas, .buttons, .btn, input { border-radius: 0 !important; }"); // sharpen borders
|
|
||||||
addRule("input { padding: 5px 8px 4px !important; }"); // tweak input padding
|
|
||||||
addRule("button[type='submit'] { border: 1px solid rgba(0, 0, 0, 0.3) !important; border-radius: 0 !important; }"); // style buttons
|
|
||||||
|
|
||||||
addRule("#doc { width: 100%; height: 100%; margin: 0; position: absolute; display: table; }"); // center everything
|
|
||||||
addRule("#page-outer { display: table-cell; vertical-align: middle; }"); // center everything
|
|
||||||
addRule("#page-container { padding: 0 20px !important; width: 100% !important; box-sizing: border-box !important; }"); // center everything
|
|
||||||
addRule(".page-canvas { margin: 0 auto !important; }"); // center everything
|
|
||||||
|
|
||||||
if (location.pathname === "/logout"){
|
if (location.pathname === "/logout"){
|
||||||
addRule(".page-canvas { width: auto !important; max-width: 888px; }"); // fix min width
|
style.innerText += `#import "styles/twitter.logout.css"`;
|
||||||
addRule(".signout-wrapper { width: auto !important; margin: 0 auto !important; }"); // fix min width and margins
|
|
||||||
addRule(".signout { margin: 60px 0 54px !important; }"); // fix dialog margins
|
|
||||||
addRule(".buttons { padding-bottom: 0 !important; }"); // fix dialog margins
|
|
||||||
addRule(".aside { display: none; }"); // hide elements around logout dialog
|
|
||||||
addRule(".buttons button, .buttons a { display: inline-block; margin: 0 4px !important; border: 1px solid rgba(0, 0, 0, 0.3) !important; border-radius: 0 !important; }"); // style buttons
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.head.appendChild(style);
|
||||||
};
|
};
|
||||||
|
|
||||||
setTimeout(injectCSS, 1);
|
setTimeout(injectCSS, 1);
|
||||||
@@ -45,7 +26,7 @@
|
|||||||
//
|
//
|
||||||
if (location.pathname === "/login"){
|
if (location.pathname === "/login"){
|
||||||
document.addEventListener("DOMContentLoaded", function(){
|
document.addEventListener("DOMContentLoaded", function(){
|
||||||
let openLinkExternally = function(e){
|
const openLinkExternally = function(e){
|
||||||
let href = e.currentTarget.getAttribute("href");
|
let href = e.currentTarget.getAttribute("href");
|
||||||
$TD.openBrowser(href[0] === '/' ? location.origin+href : href);
|
$TD.openBrowser(href[0] === '/' ? location.origin+href : href);
|
||||||
|
|
||||||
@@ -53,10 +34,18 @@
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
let links = document.getElementsByTagName("A");
|
for(let link of document.getElementsByTagName("A")){
|
||||||
|
link.addEventListener("click", openLinkExternally);
|
||||||
|
}
|
||||||
|
|
||||||
for(let index = 0; index < links.length; index++){
|
let texts = document.querySelector(".page-canvas > div:last-child");
|
||||||
links[index].addEventListener("click", openLinkExternally);
|
|
||||||
|
if (texts){
|
||||||
|
texts.insertAdjacentHTML("beforeend", `<p class="tweetduck-helper">Used the TweetDuck app before? <a href="#">Import your profile »</a></p>`);
|
||||||
|
|
||||||
|
texts.querySelector(".tweetduck-helper > a").addEventListener("click", function(){
|
||||||
|
$TD.openProfileImport();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,215 +1,110 @@
|
|||||||
(function($, $TDU){
|
(function($TDU){
|
||||||
//
|
//
|
||||||
// Function: Creates the update notification element. Removes the old one if already exists.
|
// Function: Creates the update notification element. Removes the old one if already exists.
|
||||||
//
|
//
|
||||||
var displayNotification = function(version, changelog){
|
const displayNotification = function(version, changelog){
|
||||||
|
|
||||||
// styles
|
// styles
|
||||||
var css = $("#tweetduck-update-css");
|
let css = document.getElementById("tweetduck-update-css");
|
||||||
|
|
||||||
if (!css.length){
|
if (!css){
|
||||||
css = $(`
|
css = document.createElement("style");
|
||||||
<style id='tweetduck-update-css'>
|
css.id = "tweetduck-update-css";
|
||||||
#tweetduck-update {
|
css.innerText = `#import "styles/update.css"`;
|
||||||
position: absolute;
|
document.head.appendChild(css);
|
||||||
bottom: 0;
|
|
||||||
width: 200px;
|
|
||||||
height: 178px;
|
|
||||||
z-index: 9999;
|
|
||||||
color: #fff;
|
|
||||||
background-color: rgb(32, 94, 138);
|
|
||||||
text-align: center;
|
|
||||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-update .tdu-title {
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 8px 0 2px;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-update .tdu-info {
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 14px;
|
|
||||||
margin: 3px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-update .tdu-showlog {
|
|
||||||
text-decoration: underline;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-update .tdu-buttons button {
|
|
||||||
display: block;
|
|
||||||
margin: 7px auto 0;
|
|
||||||
padding: 4px 10px;
|
|
||||||
width: 80%;
|
|
||||||
height: 30px;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 1px;
|
|
||||||
outline: none;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #fff;
|
|
||||||
background-color: #419de0;
|
|
||||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
|
|
||||||
box-shadow: 1px 1px 1px rgba(17, 17, 17, 0.5) !important;
|
|
||||||
transition: box-shadow 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-update .tdu-buttons button:hover {
|
|
||||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.75);
|
|
||||||
box-shadow: 1px 1px 1px rgba(17, 17, 17, 0.75), 0 -2px 0 rgba(17, 17, 17, 0.33) inset !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-update .tdu-buttons button.tdu-btn-ignore, .tdu-buttons button.tdu-btn-later {
|
|
||||||
background-color: #607a8e;
|
|
||||||
color: #dfdfdf;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-changelog {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
z-index: 9998;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-changelog-box {
|
|
||||||
position: absolute;
|
|
||||||
width: 60%;
|
|
||||||
height: 75%;
|
|
||||||
max-width: calc(90% - 200px);
|
|
||||||
max-height: 90%;
|
|
||||||
left: calc(50% + 100px);
|
|
||||||
top: 50%;
|
|
||||||
padding: 12px;
|
|
||||||
overflow-y: auto;
|
|
||||||
transform: translateX(-50%) translateY(-50%);
|
|
||||||
font-size: 14px;
|
|
||||||
color: #000;
|
|
||||||
background-color: #fff;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-changelog h2 {
|
|
||||||
margin: 0 0 7px;
|
|
||||||
font-size: 23px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-changelog h2 + br {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-changelog h3 {
|
|
||||||
margin: 0 0 5px 7px;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-changelog p {
|
|
||||||
margin: 8px 8px 0 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-changelog p.li {
|
|
||||||
margin: 0 8px 2px 30px;
|
|
||||||
display: list-item;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-changelog p.l2 {
|
|
||||||
margin-left: 50px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-changelog a {
|
|
||||||
color: #247fbb;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tweetduck-changelog code {
|
|
||||||
padding: 0 4px;
|
|
||||||
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
|
||||||
color: #24292e;
|
|
||||||
background-color: rgba(27, 31, 35, 0.05);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
`).appendTo(document.head);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// changelog
|
// changelog
|
||||||
var log = $("#tweetduck-changelog");
|
let log = document.getElementById("tweetduck-changelog");
|
||||||
|
|
||||||
if (!log.length){
|
if (!log){
|
||||||
var log = $(`
|
log = document.createElement("div");
|
||||||
<div id='tweetduck-changelog'>
|
log.id = "tweetduck-changelog";
|
||||||
<div id='tweetduck-changelog-box'>
|
log.style.display = "none";
|
||||||
<h2>TweetDuck Update ${version}</h2>
|
log.innerHTML = `
|
||||||
${markdown(atob(changelog))}
|
<div id='tweetduck-changelog-box'>
|
||||||
</div>
|
<h2>TweetDuck Update ${version}</h2>
|
||||||
</div>
|
${markdown(atob(changelog))}
|
||||||
`).appendTo(document.body).css("display", "none");
|
</div>`;
|
||||||
|
|
||||||
|
document.body.appendChild(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
// notification
|
// notification
|
||||||
var ele = $("#tweetduck-update");
|
let ele = document.getElementById("tweetduck-update");
|
||||||
var existed = ele.length > 0;
|
let existed = !!ele;
|
||||||
|
|
||||||
if (existed){
|
if (existed){
|
||||||
ele.remove();
|
ele.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
ele = $(`
|
ele = document.createElement("div");
|
||||||
<div id='tweetduck-update'>
|
ele.id = "tweetduck-update";
|
||||||
<p class='tdu-title'>T weetDuck Update ${version}</p>
|
ele.innerHTML = `
|
||||||
<p class='tdu-info tdu-showlog'>View update information</p>
|
<p class='tdu-title'>T weetDuck Update ${version}</p>
|
||||||
<div class='tdu-buttons'>
|
<p class='tdu-info tdu-showlog'>View update information</p>
|
||||||
<button class='tdu-btn-download'>Update now</button>
|
<div class='tdu-buttons'>
|
||||||
<button class='tdu-btn-later'>Remind me later</button>
|
<button class='tdu-btn-download'>Update now</button>
|
||||||
<button class='tdu-btn-ignore'>Ignore this update</button>
|
<button class='tdu-btn-later'>Remind me later</button>
|
||||||
</div>
|
<button class='tdu-btn-ignore'>Ignore this update</button>
|
||||||
</div>
|
</div>`;
|
||||||
`).appendTo(document.body).css("display", existed ? "block" : "none");
|
|
||||||
|
|
||||||
// ui logic
|
if (!existed){
|
||||||
var hide = function(){
|
ele.classList.add("hidden-below");
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.appendChild(ele);
|
||||||
|
|
||||||
|
// ui functions
|
||||||
|
const exitNow = function(){
|
||||||
ele.remove();
|
ele.remove();
|
||||||
log.remove();
|
log.remove();
|
||||||
css.remove();
|
css.remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
var slide = function(){
|
const exitSlide = function(){
|
||||||
log.hide();
|
log.style.display = "none";
|
||||||
ele.slideUp(hide);
|
|
||||||
|
ele.classList.add("hidden-below");
|
||||||
|
setTimeout(exitNow, 400);
|
||||||
};
|
};
|
||||||
|
|
||||||
ele.children(".tdu-showlog").click(function(){
|
const onClick = function(element, callback){
|
||||||
log.toggle();
|
element.addEventListener("click", callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ui listeners
|
||||||
|
onClick(ele.querySelector(".tdu-showlog"), function(){
|
||||||
|
log.style.display = window.getComputedStyle(log).display === "none" ? "block" : "none";
|
||||||
});
|
});
|
||||||
|
|
||||||
log.click(function(){
|
onClick(log, function(){
|
||||||
log.hide();
|
log.style.display = "none";
|
||||||
}).children().first().click(function(e){
|
});
|
||||||
|
|
||||||
|
onClick(log.children[0], function(e){
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
});
|
});
|
||||||
|
|
||||||
var buttonDiv = ele.children(".tdu-buttons").first();
|
onClick(ele.querySelector(".tdu-btn-download"), function(){
|
||||||
|
exitNow();
|
||||||
buttonDiv.children(".tdu-btn-download").click(function(){
|
|
||||||
hide();
|
|
||||||
$TDU.onUpdateAccepted();
|
$TDU.onUpdateAccepted();
|
||||||
});
|
});
|
||||||
|
|
||||||
buttonDiv.children(".tdu-btn-later").click(function(){
|
onClick(ele.querySelector(".tdu-btn-later"), function(){
|
||||||
$TDU.onUpdateDelayed();
|
$TDU.onUpdateDelayed();
|
||||||
slide();
|
exitSlide();
|
||||||
});
|
});
|
||||||
|
|
||||||
buttonDiv.children(".tdu-btn-ignore").click(function(){
|
onClick(ele.querySelector(".tdu-btn-ignore"), function(){
|
||||||
$TDU.onUpdateDismissed();
|
$TDU.onUpdateDismissed();
|
||||||
slide();
|
exitSlide();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// finalize notification
|
||||||
if (!existed){
|
if (!existed){
|
||||||
ele.slideDown();
|
ele.getBoundingClientRect(); // reflow
|
||||||
|
ele.classList.remove("hidden-below");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ele;
|
return ele;
|
||||||
@@ -218,7 +113,7 @@
|
|||||||
//
|
//
|
||||||
// Function: Ghetto-converts markdown to HTML.
|
// Function: Ghetto-converts markdown to HTML.
|
||||||
//
|
//
|
||||||
var markdown = function(md){
|
const markdown = function(md){
|
||||||
return md.replace(/&/g, "&")
|
return md.replace(/&/g, "&")
|
||||||
.replace(/</g, "<")
|
.replace(/</g, "<")
|
||||||
.replace(/>/g, ">")
|
.replace(/>/g, ">")
|
||||||
@@ -237,12 +132,20 @@
|
|||||||
//
|
//
|
||||||
// Block: Check updates on startup.
|
// Block: Check updates on startup.
|
||||||
//
|
//
|
||||||
$(document).one("TD.ready", function(){
|
const triggerCheck = function(){
|
||||||
$TDU.triggerUpdateCheck();
|
$TDU.triggerUpdateCheck();
|
||||||
});
|
};
|
||||||
|
|
||||||
|
try{
|
||||||
|
throw false if !($._data(document, "events").TD.some(obj => obj.namespace === "ready"));
|
||||||
|
|
||||||
|
$(document).one("TD.ready", triggerCheck);
|
||||||
|
}catch(err){
|
||||||
|
setTimeout(triggerCheck, 500);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Block: Setup global functions.
|
// Block: Setup global functions.
|
||||||
//
|
//
|
||||||
window.TDUF_displayNotification = displayNotification;
|
window.TDUF_displayNotification = displayNotification;
|
||||||
})($, $TDU);
|
})($TDU);
|
||||||
|
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 31 KiB |
@@ -1,9 +1,9 @@
|
|||||||
<?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.66.0.0-CI2629\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.66.0.0-CI2629\build\CefSharp.WinForms.props')" />
|
<Import Project="packages\CefSharp.WinForms.67.0.0-CI2662\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.67.0.0-CI2662\build\CefSharp.WinForms.props')" />
|
||||||
<Import Project="packages\CefSharp.Common.66.0.0-CI2629\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.66.0.0-CI2629\build\CefSharp.Common.props')" />
|
<Import Project="packages\CefSharp.Common.67.0.0-CI2662\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.67.0.0-CI2662\build\CefSharp.Common.props')" />
|
||||||
<Import Project="packages\cef.redist.x86.3.3359.1772\build\cef.redist.x86.props" Condition="Exists('packages\cef.redist.x86.3.3359.1772\build\cef.redist.x86.props')" />
|
<Import Project="packages\cef.redist.x86.3.3396.1777\build\cef.redist.x86.props" Condition="Exists('packages\cef.redist.x86.3.3396.1777\build\cef.redist.x86.props')" />
|
||||||
<Import Project="packages\cef.redist.x64.3.3359.1772\build\cef.redist.x64.props" Condition="Exists('packages\cef.redist.x64.3.3359.1772\build\cef.redist.x64.props')" />
|
<Import Project="packages\cef.redist.x64.3.3396.1777\build\cef.redist.x64.props" Condition="Exists('packages\cef.redist.x64.3.3396.1777\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')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
@@ -15,25 +15,10 @@
|
|||||||
<AssemblyName>TweetDuck</AssemblyName>
|
<AssemblyName>TweetDuck</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
|
<ApplicationIcon>Resources\Images\icon.ico</ApplicationIcon>
|
||||||
<NuGetPackageImportStamp>
|
<NuGetPackageImportStamp>
|
||||||
</NuGetPackageImportStamp>
|
</NuGetPackageImportStamp>
|
||||||
<TargetFrameworkProfile>
|
|
||||||
</TargetFrameworkProfile>
|
|
||||||
<PublishUrl>publish\</PublishUrl>
|
|
||||||
<Install>true</Install>
|
|
||||||
<InstallFrom>Disk</InstallFrom>
|
|
||||||
<UpdateEnabled>false</UpdateEnabled>
|
|
||||||
<UpdateMode>Foreground</UpdateMode>
|
|
||||||
<UpdateInterval>7</UpdateInterval>
|
|
||||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
|
||||||
<UpdatePeriodically>false</UpdatePeriodically>
|
|
||||||
<UpdateRequired>false</UpdateRequired>
|
|
||||||
<MapFileExtensions>true</MapFileExtensions>
|
|
||||||
<ApplicationRevision>0</ApplicationRevision>
|
|
||||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
|
||||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
|
||||||
<UseApplicationTrust>false</UseApplicationTrust>
|
|
||||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||||
<StartArguments>-datafolder TweetDuckDebug</StartArguments>
|
<StartArguments>-datafolder TweetDuckDebug</StartArguments>
|
||||||
@@ -47,23 +32,15 @@
|
|||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<LangVersion>7</LangVersion>
|
<LangVersion>7</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
|
||||||
<ApplicationIcon>Resources\icon.ico</ApplicationIcon>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
<OutputPath>bin\x86\Release\</OutputPath>
|
<OutputPath>bin\x86\Release\</OutputPath>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
<DefineConstants>
|
|
||||||
</DefineConstants>
|
|
||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
<LangVersion>7</LangVersion>
|
<LangVersion>7</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -81,6 +58,7 @@
|
|||||||
<Compile Include="Configuration\SystemConfig.cs" />
|
<Compile Include="Configuration\SystemConfig.cs" />
|
||||||
<Compile Include="Configuration\UserConfig.cs" />
|
<Compile Include="Configuration\UserConfig.cs" />
|
||||||
<Compile Include="Core\Bridge\PropertyBridge.cs" />
|
<Compile Include="Core\Bridge\PropertyBridge.cs" />
|
||||||
|
<Compile Include="Core\Bridge\UpdateBridge.cs" />
|
||||||
<Compile Include="Core\Controls\ControlExtensions.cs" />
|
<Compile Include="Core\Controls\ControlExtensions.cs" />
|
||||||
<Compile Include="Core\Controls\FlatButton.cs">
|
<Compile Include="Core\Controls\FlatButton.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
@@ -97,6 +75,8 @@
|
|||||||
<Compile Include="Core\FormManager.cs" />
|
<Compile Include="Core\FormManager.cs" />
|
||||||
<Compile Include="Core\Handling\ContextMenuGuide.cs" />
|
<Compile Include="Core\Handling\ContextMenuGuide.cs" />
|
||||||
<Compile Include="Core\Handling\DragHandlerBrowser.cs" />
|
<Compile Include="Core\Handling\DragHandlerBrowser.cs" />
|
||||||
|
<Compile Include="Core\Handling\Filters\ResponseFilterBase.cs" />
|
||||||
|
<Compile Include="Core\Handling\Filters\ResponseFilterVendor.cs" />
|
||||||
<Compile Include="Core\Handling\General\BrowserProcessHandler.cs" />
|
<Compile Include="Core\Handling\General\BrowserProcessHandler.cs" />
|
||||||
<Compile Include="Core\Handling\ContextMenuBase.cs" />
|
<Compile Include="Core\Handling\ContextMenuBase.cs" />
|
||||||
<Compile Include="Core\Handling\ContextMenuBrowser.cs" />
|
<Compile Include="Core\Handling\ContextMenuBrowser.cs" />
|
||||||
@@ -304,7 +284,7 @@
|
|||||||
<DependentUpon>Resources.resx</DependentUpon>
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Reporter.cs" />
|
<Compile Include="Reporter.cs" />
|
||||||
<Compile Include="Updates\Events\UpdateCheckEventArgs.cs" />
|
<Compile Include="Updates\UpdateCheckEventArgs.cs" />
|
||||||
<Compile Include="Updates\FormUpdateDownload.cs">
|
<Compile Include="Updates\FormUpdateDownload.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -327,14 +307,8 @@
|
|||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Resources\ScriptLoader.cs" />
|
<Compile Include="Resources\ScriptLoader.cs" />
|
||||||
<Compile Include="Updates\Events\UpdateEventArgs.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
|
|
||||||
<Visible>False</Visible>
|
|
||||||
<ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName>
|
|
||||||
<Install>true</Install>
|
|
||||||
</BootstrapperPackage>
|
|
||||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||||
<Visible>False</Visible>
|
<Visible>False</Visible>
|
||||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||||
@@ -345,11 +319,6 @@
|
|||||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
<Install>false</Install>
|
<Install>false</Install>
|
||||||
</BootstrapperPackage>
|
</BootstrapperPackage>
|
||||||
<BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">
|
|
||||||
<Visible>False</Visible>
|
|
||||||
<ProductName>Windows Installer 4.5</ProductName>
|
|
||||||
<Install>true</Install>
|
|
||||||
</BootstrapperPackage>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Core\FormBrowser.resx">
|
<EmbeddedResource Include="Core\FormBrowser.resx">
|
||||||
@@ -363,17 +332,15 @@
|
|||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ContentWithTargetPath Include="Resources\icon.ico">
|
|
||||||
<TargetPath>icon.ico</TargetPath>
|
|
||||||
</ContentWithTargetPath>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="Resources\avatar.png" />
|
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
<None Include="Resources\icon-small.ico" />
|
<None Include="Resources\Images\avatar.png" />
|
||||||
<None Include="Resources\icon-tray-new.ico" />
|
<None Include="Resources\Images\icon.ico" />
|
||||||
<None Include="Resources\icon-tray.ico" />
|
<None Include="Resources\Images\icon-tray-muted.ico" />
|
||||||
<None Include="Resources\spinner.apng" />
|
<None Include="Resources\Images\icon-muted.ico" />
|
||||||
|
<None Include="Resources\Images\icon-small.ico" />
|
||||||
|
<None Include="Resources\Images\icon-tray-new.ico" />
|
||||||
|
<None Include="Resources\Images\icon-tray.ico" />
|
||||||
|
<None Include="Resources\Images\spinner.apng" />
|
||||||
<None Include="Resources\PostBuild.ps1" />
|
<None Include="Resources\PostBuild.ps1" />
|
||||||
<None Include="Resources\Plugins\.debug\.meta" />
|
<None Include="Resources\Plugins\.debug\.meta" />
|
||||||
<None Include="Resources\Plugins\.debug\browser.js" />
|
<None Include="Resources\Plugins\.debug\browser.js" />
|
||||||
@@ -392,15 +359,20 @@
|
|||||||
<None Include="Resources\Plugins\reply-account\configuration.default.js" />
|
<None Include="Resources\Plugins\reply-account\configuration.default.js" />
|
||||||
<None Include="Resources\Plugins\templates\.meta" />
|
<None Include="Resources\Plugins\templates\.meta" />
|
||||||
<None Include="Resources\Plugins\templates\browser.js" />
|
<None Include="Resources\Plugins\templates\browser.js" />
|
||||||
|
<None Include="Resources\Plugins\templates\modal.html" />
|
||||||
<None Include="Resources\Plugins\timeline-polls\.meta" />
|
<None Include="Resources\Plugins\timeline-polls\.meta" />
|
||||||
<None Include="Resources\Plugins\timeline-polls\browser.js" />
|
<None Include="Resources\Plugins\timeline-polls\browser.js" />
|
||||||
<None Include="Resources\Scripts\code.js" />
|
<None Include="Resources\Scripts\code.js" />
|
||||||
|
<None Include="Resources\Scripts\imports\scripts\plugins.base.js" />
|
||||||
|
<None Include="Resources\Scripts\imports\styles\introduction.css" />
|
||||||
|
<None Include="Resources\Scripts\imports\styles\twitter.base.css" />
|
||||||
|
<None Include="Resources\Scripts\imports\styles\twitter.logout.css" />
|
||||||
|
<None Include="Resources\Scripts\imports\styles\update.css" />
|
||||||
<None Include="Resources\Scripts\introduction.js" />
|
<None Include="Resources\Scripts\introduction.js" />
|
||||||
<None Include="Resources\Scripts\notification.js" />
|
<None Include="Resources\Scripts\notification.js" />
|
||||||
<None Include="Resources\Scripts\pages\error.html" />
|
<None Include="Resources\Scripts\pages\error.html" />
|
||||||
<None Include="Resources\Scripts\pages\example.html" />
|
<None Include="Resources\Scripts\pages\example.html" />
|
||||||
<None Include="Resources\Scripts\plugins.browser.js" />
|
<None Include="Resources\Scripts\plugins.browser.js" />
|
||||||
<None Include="Resources\Scripts\plugins.js" />
|
|
||||||
<None Include="Resources\Scripts\plugins.notification.js" />
|
<None Include="Resources\Scripts\plugins.notification.js" />
|
||||||
<None Include="Resources\Scripts\screenshot.js" />
|
<None Include="Resources\Scripts\screenshot.js" />
|
||||||
<None Include="Resources\Scripts\styles\browser.css" />
|
<None Include="Resources\Scripts\styles\browser.css" />
|
||||||
@@ -438,6 +410,7 @@ powershell -ExecutionPolicy Unrestricted -File "$(ProjectDir)Resources\PostBuild
|
|||||||
<Exec Command="del "$(TargetDir)*.xml"" />
|
<Exec Command="del "$(TargetDir)*.xml"" />
|
||||||
<Delete Files="$(TargetDir)CefSharp.BrowserSubprocess.exe" />
|
<Delete Files="$(TargetDir)CefSharp.BrowserSubprocess.exe" />
|
||||||
<Delete Files="$(TargetDir)widevinecdmadapter.dll" />
|
<Delete Files="$(TargetDir)widevinecdmadapter.dll" />
|
||||||
|
<Exec Command=""$(ProjectDir)bld\UPDATE ONLY.bat"" WorkingDirectory="$(ProjectDir)bld\" IgnoreExitCode="true" />
|
||||||
</Target>
|
</Target>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PreBuildEvent>powershell Get-Process TweetDuck.Browser -ErrorAction SilentlyContinue ^| Where-Object {$_.Path -eq '$(TargetDir)TweetDuck.Browser.exe'} ^| Stop-Process; Exit 0</PreBuildEvent>
|
<PreBuildEvent>powershell Get-Process TweetDuck.Browser -ErrorAction SilentlyContinue ^| Where-Object {$_.Path -eq '$(TargetDir)TweetDuck.Browser.exe'} ^| Stop-Process; Exit 0</PreBuildEvent>
|
||||||
@@ -446,11 +419,11 @@ powershell -ExecutionPolicy Unrestricted -File "$(ProjectDir)Resources\PostBuild
|
|||||||
<PropertyGroup>
|
<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>
|
<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>
|
</PropertyGroup>
|
||||||
<Error Condition="!Exists('packages\cef.redist.x64.3.3359.1772\build\cef.redist.x64.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.3359.1772\build\cef.redist.x64.props'))" />
|
<Error Condition="!Exists('packages\cef.redist.x64.3.3396.1777\build\cef.redist.x64.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.3396.1777\build\cef.redist.x64.props'))" />
|
||||||
<Error Condition="!Exists('packages\cef.redist.x86.3.3359.1772\build\cef.redist.x86.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.3359.1772\build\cef.redist.x86.props'))" />
|
<Error Condition="!Exists('packages\cef.redist.x86.3.3396.1777\build\cef.redist.x86.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.3396.1777\build\cef.redist.x86.props'))" />
|
||||||
<Error Condition="!Exists('packages\CefSharp.Common.66.0.0-CI2629\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.66.0.0-CI2629\build\CefSharp.Common.props'))" />
|
<Error Condition="!Exists('packages\CefSharp.Common.67.0.0-CI2662\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.67.0.0-CI2662\build\CefSharp.Common.props'))" />
|
||||||
<Error Condition="!Exists('packages\CefSharp.Common.66.0.0-CI2629\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.66.0.0-CI2629\build\CefSharp.Common.targets'))" />
|
<Error Condition="!Exists('packages\CefSharp.Common.67.0.0-CI2662\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.67.0.0-CI2662\build\CefSharp.Common.targets'))" />
|
||||||
<Error Condition="!Exists('packages\CefSharp.WinForms.66.0.0-CI2629\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.66.0.0-CI2629\build\CefSharp.WinForms.props'))" />
|
<Error Condition="!Exists('packages\CefSharp.WinForms.67.0.0-CI2662\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.67.0.0-CI2662\build\CefSharp.WinForms.props'))" />
|
||||||
</Target>
|
</Target>
|
||||||
<Import Project="packages\CefSharp.Common.66.0.0-CI2629\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.66.0.0-CI2629\build\CefSharp.Common.targets')" />
|
<Import Project="packages\CefSharp.Common.67.0.0-CI2662\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.67.0.0-CI2662\build\CefSharp.Common.targets')" />
|
||||||
</Project>
|
</Project>
|
@@ -6,12 +6,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDuck", "TweetDuck.cspr
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDuck.Browser", "subprocess\TweetDuck.Browser.csproj", "{B10B0017-819E-4F71-870F-8256B36A26AA}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDuck.Browser", "subprocess\TweetDuck.Browser.csproj", "{B10B0017-819E-4F71-870F-8256B36A26AA}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "tests\UnitTests.csproj", "{A958FA7A-4A2C-42A7-BFA0-159343483F4E}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDuck.Video", "video\TweetDuck.Video.csproj", "{278B2D11-402D-44B6-B6A1-8FA67DB65565}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDuck.Video", "video\TweetDuck.Video.csproj", "{278B2D11-402D-44B6-B6A1-8FA67DB65565}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Communication", "lib\TweetLib.Communication\TweetLib.Communication.csproj", "{72473763-4B9D-4FB6-A923-9364B2680F06}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Communication", "lib\TweetLib.Communication\TweetLib.Communication.csproj", "{72473763-4B9D-4FB6-A923-9364B2680F06}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetTest.System", "lib\TweetTest.System\TweetTest.System.csproj", "{A958FA7A-4A2C-42A7-BFA0-159343483F4E}"
|
||||||
|
EndProject
|
||||||
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TweetTest.Unit", "lib\TweetTest.Unit\TweetTest.Unit.fsproj", "{EEE1071A-28FA-48B1-82A1-9CBDC5C3F2C3}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
@@ -26,9 +28,6 @@ Global
|
|||||||
{B10B0017-819E-4F71-870F-8256B36A26AA}.Debug|x86.Build.0 = Debug|x86
|
{B10B0017-819E-4F71-870F-8256B36A26AA}.Debug|x86.Build.0 = Debug|x86
|
||||||
{B10B0017-819E-4F71-870F-8256B36A26AA}.Release|x86.ActiveCfg = Release|x86
|
{B10B0017-819E-4F71-870F-8256B36A26AA}.Release|x86.ActiveCfg = Release|x86
|
||||||
{B10B0017-819E-4F71-870F-8256B36A26AA}.Release|x86.Build.0 = Release|x86
|
{B10B0017-819E-4F71-870F-8256B36A26AA}.Release|x86.Build.0 = Release|x86
|
||||||
{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Debug|x86.ActiveCfg = Debug|x86
|
{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Debug|x86.Build.0 = Debug|x86
|
{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Debug|x86.Build.0 = Debug|x86
|
||||||
{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Release|x86.ActiveCfg = Release|x86
|
{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Release|x86.ActiveCfg = Release|x86
|
||||||
@@ -37,6 +36,12 @@ Global
|
|||||||
{72473763-4B9D-4FB6-A923-9364B2680F06}.Debug|x86.Build.0 = Debug|x86
|
{72473763-4B9D-4FB6-A923-9364B2680F06}.Debug|x86.Build.0 = Debug|x86
|
||||||
{72473763-4B9D-4FB6-A923-9364B2680F06}.Release|x86.ActiveCfg = Release|x86
|
{72473763-4B9D-4FB6-A923-9364B2680F06}.Release|x86.ActiveCfg = Release|x86
|
||||||
{72473763-4B9D-4FB6-A923-9364B2680F06}.Release|x86.Build.0 = Release|x86
|
{72473763-4B9D-4FB6-A923-9364B2680F06}.Release|x86.Build.0 = Release|x86
|
||||||
|
{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Release|x86.ActiveCfg = Debug|x86
|
||||||
|
{EEE1071A-28FA-48B1-82A1-9CBDC5C3F2C3}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{EEE1071A-28FA-48B1-82A1-9CBDC5C3F2C3}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{EEE1071A-28FA-48B1-82A1-9CBDC5C3F2C3}.Release|x86.ActiveCfg = Debug|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace TweetDuck.Updates.Events{
|
|
||||||
sealed class UpdateEventArgs : EventArgs{
|
|
||||||
public UpdateInfo UpdateInfo { get; }
|
|
||||||
|
|
||||||
public UpdateEventArgs(UpdateInfo updateInfo){
|
|
||||||
this.UpdateInfo = updateInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -20,7 +20,7 @@ namespace TweetDuck.Updates{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void timerDownloadCheck_Tick(object sender, EventArgs e){
|
private void timerDownloadCheck_Tick(object sender, EventArgs e){
|
||||||
if (updateInfo.DownloadStatus.IsFinished()){
|
if (updateInfo.DownloadStatus.IsFinished(false)){
|
||||||
timerDownloadCheck.Stop();
|
timerDownloadCheck.Stop();
|
||||||
DialogResult = DialogResult.OK;
|
DialogResult = DialogResult.OK;
|
||||||
Close();
|
Close();
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web.Script.Serialization;
|
using System.Web.Script.Serialization;
|
||||||
using TweetDuck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
@@ -28,7 +30,7 @@ namespace TweetDuck.Updates{
|
|||||||
result.SetCanceled();
|
result.SetCanceled();
|
||||||
}
|
}
|
||||||
else if (task.IsFaulted){
|
else if (task.IsFaulted){
|
||||||
result.SetException(task.Exception.InnerException);
|
result.SetException(ExpandWebException(task.Exception.InnerException));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
try{
|
try{
|
||||||
@@ -59,5 +61,20 @@ namespace TweetDuck.Updates{
|
|||||||
|
|
||||||
return new UpdateInfo(versionTag, releaseNotes, downloadUrl, installerFolder);
|
return new UpdateInfo(versionTag, releaseNotes, downloadUrl, installerFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Exception ExpandWebException(Exception e){
|
||||||
|
if (e is WebException we && we.Response is HttpWebResponse response){
|
||||||
|
try{
|
||||||
|
using(Stream stream = response.GetResponseStream())
|
||||||
|
using(StreamReader reader = new StreamReader(stream, Encoding.GetEncoding(response.CharacterSet ?? "utf-8"))){
|
||||||
|
return new Reporter.ExpandedLogException(e, reader.ReadToEnd());
|
||||||
|
}
|
||||||
|
}catch{
|
||||||
|
// whatever
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using TweetDuck.Data;
|
using TweetDuck.Data;
|
||||||
|
|
||||||
namespace TweetDuck.Updates.Events{
|
namespace TweetDuck.Updates{
|
||||||
sealed class UpdateCheckEventArgs : EventArgs{
|
sealed class UpdateCheckEventArgs : EventArgs{
|
||||||
public int EventId { get; }
|
public int EventId { get; }
|
||||||
public Result<UpdateInfo> Result { get; }
|
public Result<UpdateInfo> Result { get; }
|
@@ -9,8 +9,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class UpdateDownloadStatusExtensions{
|
public static class UpdateDownloadStatusExtensions{
|
||||||
public static bool IsFinished(this UpdateDownloadStatus status){
|
public static bool IsFinished(this UpdateDownloadStatus status, bool canRetry){
|
||||||
return status == UpdateDownloadStatus.AssetMissing || status == UpdateDownloadStatus.Done || status == UpdateDownloadStatus.Failed;
|
return status == UpdateDownloadStatus.AssetMissing || status == UpdateDownloadStatus.Done || (status == UpdateDownloadStatus.Failed && !canRetry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,38 +1,24 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
|
||||||
using TweetDuck.Core.Controls;
|
|
||||||
using TweetDuck.Core.Other.Interfaces;
|
|
||||||
using TweetDuck.Data;
|
using TweetDuck.Data;
|
||||||
using TweetDuck.Updates.Events;
|
|
||||||
using Timer = System.Windows.Forms.Timer;
|
using Timer = System.Windows.Forms.Timer;
|
||||||
|
|
||||||
namespace TweetDuck.Updates{
|
namespace TweetDuck.Updates{
|
||||||
sealed class UpdateHandler : IDisposable{
|
sealed class UpdateHandler : IDisposable{
|
||||||
public const int CheckCodeUpdatesDisabled = -1;
|
public const int CheckCodeUpdatesDisabled = -1;
|
||||||
public const int CheckCodeNotOnTweetDeck = -2;
|
|
||||||
|
|
||||||
private readonly UpdateCheckClient client;
|
private readonly UpdateCheckClient client;
|
||||||
private readonly TaskScheduler scheduler;
|
private readonly TaskScheduler scheduler;
|
||||||
private readonly ITweetDeckBrowser browser;
|
|
||||||
private readonly Timer timer;
|
private readonly Timer timer;
|
||||||
|
|
||||||
public event EventHandler<UpdateEventArgs> UpdateAccepted;
|
|
||||||
public event EventHandler<UpdateEventArgs> UpdateDelayed;
|
|
||||||
public event EventHandler<UpdateEventArgs> UpdateDismissed;
|
|
||||||
public event EventHandler<UpdateCheckEventArgs> CheckFinished;
|
public event EventHandler<UpdateCheckEventArgs> CheckFinished;
|
||||||
|
|
||||||
private ushort lastEventId;
|
private ushort lastEventId;
|
||||||
private UpdateInfo lastUpdateInfo;
|
|
||||||
|
|
||||||
public UpdateHandler(ITweetDeckBrowser browser, string installerFolder){
|
public UpdateHandler(string installerFolder){
|
||||||
this.client = new UpdateCheckClient(installerFolder);
|
this.client = new UpdateCheckClient(installerFolder);
|
||||||
this.scheduler = TaskScheduler.FromCurrentSynchronizationContext();
|
this.scheduler = TaskScheduler.FromCurrentSynchronizationContext();
|
||||||
|
|
||||||
this.browser = browser;
|
|
||||||
this.browser.RegisterBridge("$TDU", new Bridge(this));
|
|
||||||
|
|
||||||
this.timer = new Timer();
|
this.timer = new Timer();
|
||||||
this.timer.Tick += timer_Tick;
|
this.timer.Tick += timer_Tick;
|
||||||
}
|
}
|
||||||
@@ -68,10 +54,6 @@ namespace TweetDuck.Updates{
|
|||||||
|
|
||||||
public int Check(bool force){
|
public int Check(bool force){
|
||||||
if (Program.UserConfig.EnableUpdateCheck || force){
|
if (Program.UserConfig.EnableUpdateCheck || force){
|
||||||
if (!browser.IsTweetDeckWebsite){
|
|
||||||
return CheckCodeNotOnTweetDeck;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nextEventId = unchecked(++lastEventId);
|
int nextEventId = unchecked(++lastEventId);
|
||||||
Task<UpdateInfo> checkTask = client.Check();
|
Task<UpdateInfo> checkTask = client.Check();
|
||||||
|
|
||||||
@@ -84,46 +66,6 @@ namespace TweetDuck.Updates{
|
|||||||
return CheckCodeUpdatesDisabled;
|
return CheckCodeUpdatesDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrepareUpdate(UpdateInfo info){
|
|
||||||
CleanupDownload();
|
|
||||||
lastUpdateInfo = info;
|
|
||||||
lastUpdateInfo.BeginSilentDownload();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void BeginUpdateDownload(Form ownerForm, UpdateInfo updateInfo, Action<UpdateInfo> onFinished){
|
|
||||||
UpdateDownloadStatus status = updateInfo.DownloadStatus;
|
|
||||||
|
|
||||||
if (status == UpdateDownloadStatus.Done || status == UpdateDownloadStatus.AssetMissing){
|
|
||||||
onFinished(updateInfo);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
FormUpdateDownload downloadForm = new FormUpdateDownload(updateInfo);
|
|
||||||
|
|
||||||
downloadForm.VisibleChanged += (sender, args) => {
|
|
||||||
downloadForm.MoveToCenter(ownerForm);
|
|
||||||
ownerForm.Hide();
|
|
||||||
};
|
|
||||||
|
|
||||||
downloadForm.FormClosed += (sender, args) => {
|
|
||||||
if (downloadForm.DialogResult != DialogResult.OK){
|
|
||||||
updateInfo.CancelDownload();
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadForm.Dispose();
|
|
||||||
onFinished(updateInfo);
|
|
||||||
};
|
|
||||||
|
|
||||||
downloadForm.Show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CleanupDownload(){
|
|
||||||
if (lastUpdateInfo != null){
|
|
||||||
lastUpdateInfo.DeleteInstaller();
|
|
||||||
lastUpdateInfo = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleUpdateCheckSuccessful(int eventId, UpdateInfo info){
|
private void HandleUpdateCheckSuccessful(int eventId, UpdateInfo info){
|
||||||
CheckFinished?.Invoke(this, new UpdateCheckEventArgs(eventId, new Result<UpdateInfo>(info)));
|
CheckFinished?.Invoke(this, new UpdateCheckEventArgs(eventId, new Result<UpdateInfo>(info)));
|
||||||
}
|
}
|
||||||
@@ -131,48 +73,5 @@ namespace TweetDuck.Updates{
|
|||||||
private void HandleUpdateCheckFailed(int eventId, Exception exception){
|
private void HandleUpdateCheckFailed(int eventId, Exception exception){
|
||||||
CheckFinished?.Invoke(this, new UpdateCheckEventArgs(eventId, new Result<UpdateInfo>(exception)));
|
CheckFinished?.Invoke(this, new UpdateCheckEventArgs(eventId, new Result<UpdateInfo>(exception)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TriggerUpdateAcceptedEvent(){
|
|
||||||
if (lastUpdateInfo != null){
|
|
||||||
UpdateAccepted?.Invoke(this, new UpdateEventArgs(lastUpdateInfo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TriggerUpdateDelayedEvent(){
|
|
||||||
if (lastUpdateInfo != null){
|
|
||||||
UpdateDelayed?.Invoke(this, new UpdateEventArgs(lastUpdateInfo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TriggerUpdateDismissedEvent(){
|
|
||||||
if (lastUpdateInfo != null){
|
|
||||||
UpdateDismissed?.Invoke(this, new UpdateEventArgs(lastUpdateInfo));
|
|
||||||
CleanupDownload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class Bridge{
|
|
||||||
private readonly UpdateHandler owner;
|
|
||||||
|
|
||||||
public Bridge(UpdateHandler owner){
|
|
||||||
this.owner = owner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void TriggerUpdateCheck(){
|
|
||||||
owner.Check(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnUpdateAccepted(){
|
|
||||||
owner.TriggerUpdateAcceptedEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnUpdateDelayed(){
|
|
||||||
owner.TriggerUpdateDelayedEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnUpdateDismissed(){
|
|
||||||
owner.TriggerUpdateDismissedEvent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,11 @@ namespace TweetDuck.Updates{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void BeginSilentDownload(){
|
public void BeginSilentDownload(){
|
||||||
|
if (File.Exists(InstallerPath)){
|
||||||
|
DownloadStatus = UpdateDownloadStatus.Done;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (DownloadStatus == UpdateDownloadStatus.None || DownloadStatus == UpdateDownloadStatus.Failed){
|
if (DownloadStatus == UpdateDownloadStatus.None || DownloadStatus == UpdateDownloadStatus.Failed){
|
||||||
DownloadStatus = UpdateDownloadStatus.InProgress;
|
DownloadStatus = UpdateDownloadStatus.InProgress;
|
||||||
|
|
||||||
|