Compare commits
58 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 |
@@ -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;
|
||||||
|
@@ -50,6 +50,10 @@ namespace TweetDuck.Core.Bridge{
|
|||||||
public void OpenContextMenu(){
|
public void OpenContextMenu(){
|
||||||
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(() => {
|
||||||
|
@@ -5,11 +5,13 @@ 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;
|
||||||
@@ -72,7 +74,7 @@ namespace TweetDuck.Core{
|
|||||||
this.browser = new TweetDeckBrowser(this, new TweetDeckBridge.Browser(this, notification));
|
this.browser = new TweetDeckBrowser(this, new TweetDeckBridge.Browser(this, notification));
|
||||||
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,7 +97,11 @@ namespace TweetDuck.Core{
|
|||||||
this.trayIcon.ClickClose += trayIcon_ClickClose;
|
this.trayIcon.ClickClose += trayIcon_ClickClose;
|
||||||
Config.TrayBehaviorChanged += Config_TrayBehaviorChanged;
|
Config.TrayBehaviorChanged += Config_TrayBehaviorChanged;
|
||||||
|
|
||||||
UpdateTrayIcon();
|
UpdateTray();
|
||||||
|
|
||||||
|
if (Config.MuteNotifications){
|
||||||
|
UpdateFormIcon();
|
||||||
|
}
|
||||||
|
|
||||||
this.updates = new UpdateHandler(browser, Program.InstallerPath);
|
this.updates = new UpdateHandler(browser, Program.InstallerPath);
|
||||||
this.updates.CheckFinished += updates_CheckFinished;
|
this.updates.CheckFinished += updates_CheckFinished;
|
||||||
@@ -127,7 +133,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,18 +212,19 @@ namespace TweetDuck.Core{
|
|||||||
}
|
}
|
||||||
|
|
||||||
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){
|
||||||
@@ -360,6 +371,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){
|
||||||
@@ -385,13 +400,13 @@ namespace TweetDuck.Core{
|
|||||||
public void OpenSettings(){
|
public void OpenSettings(){
|
||||||
OpenSettings(null);
|
OpenSettings(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenSettings(Type startTab){
|
public void OpenSettings(Type startTab){
|
||||||
if (!FormManager.TryBringToFront<FormSettings>()){
|
if (!FormManager.TryBringToFront<FormSettings>()){
|
||||||
bool prevEnableUpdateCheck = Config.EnableUpdateCheck;
|
bool prevEnableUpdateCheck = Config.EnableUpdateCheck;
|
||||||
|
|
||||||
FormSettings form = new FormSettings(this, plugins, updates, analytics, startTab);
|
FormSettings form = new FormSettings(this, plugins, updates, analytics, startTab);
|
||||||
|
|
||||||
form.FormClosed += (sender, args) => {
|
form.FormClosed += (sender, args) => {
|
||||||
if (!prevEnableUpdateCheck && Config.EnableUpdateCheck){
|
if (!prevEnableUpdateCheck && Config.EnableUpdateCheck){
|
||||||
Config.DismissedUpdate = null;
|
Config.DismissedUpdate = null;
|
||||||
@@ -447,6 +462,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;
|
||||||
@@ -238,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){
|
||||||
|
@@ -83,11 +83,8 @@ namespace TweetDuck.Core.Handling{
|
|||||||
globalMenu.AddItem(MenuSettings, TitleSettings);
|
globalMenu.AddItem(MenuSettings, TitleSettings);
|
||||||
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(() => {
|
||||||
|
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,6 +2,7 @@
|
|||||||
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{
|
||||||
@@ -16,7 +17,7 @@ namespace TweetDuck.Core.Handling{
|
|||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@@ -1,6 +1,16 @@
|
|||||||
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 string BlockNextUserNavUrl { get; set; }
|
public string BlockNextUserNavUrl { get; set; }
|
||||||
@@ -26,13 +36,61 @@ namespace TweetDuck.Core.Handling{
|
|||||||
return base.OnBeforeBrowse(browserControl, browser, frame, request, userGesture, isRedirect);
|
return base.OnBeforeBrowse(browserControl, browser, frame, request, userGesture, isRedirect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FREEZE_TWEETDECK_SCRIPTS
|
||||||
|
private static readonly Regex TweetDeckScriptUrl = new Regex(@"/dist/(.*?)\.(.*?)\.js$", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
private static readonly SortedList<string, string> TweetDeckHashes = new SortedList<string, string>(2){
|
||||||
|
{ "vendor", "942c0a20e8" },
|
||||||
|
{ "bundle", "1bd75b5854" }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
public override bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response){
|
public override bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response){
|
||||||
if (request.ResourceType == ResourceType.Image && request.Url.Contains("backgrounds/spinner_blue")){
|
if (request.ResourceType == ResourceType.Image && request.Url.Contains("/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>");
|
||||||
|
@@ -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){
|
||||||
|
@@ -15,11 +15,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;
|
||||||
|
|
||||||
@@ -88,7 +83,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);
|
||||||
@@ -106,7 +101,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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -194,9 +189,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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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,16 +37,16 @@ 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.InjectInto(html);
|
html = injection.InjectInto(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;
|
||||||
@@ -8,7 +9,6 @@ using TweetDuck.Resources;
|
|||||||
namespace TweetDuck.Core.Notification{
|
namespace TweetDuck.Core.Notification{
|
||||||
sealed class TweetNotification{
|
sealed class TweetNotification{
|
||||||
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 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+)?(?:/(#.*))?";
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
@@ -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){
|
||||||
|
@@ -9,6 +9,7 @@ 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.Handling.General;
|
||||||
|
using TweetDuck.Core.Management;
|
||||||
using TweetDuck.Core.Notification;
|
using TweetDuck.Core.Notification;
|
||||||
using TweetDuck.Core.Other.Interfaces;
|
using TweetDuck.Core.Other.Interfaces;
|
||||||
using TweetDuck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
@@ -41,7 +42,7 @@ namespace TweetDuck.Core{
|
|||||||
|
|
||||||
public TweetDeckBrowser(FormBrowser owner, TweetDeckBridge bridge){
|
public TweetDeckBrowser(FormBrowser owner, TweetDeckBridge bridge){
|
||||||
RequestHandlerBrowser requestHandler = new RequestHandlerBrowser();
|
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(requestHandler),
|
DragHandler = new DragHandlerBrowser(requestHandler),
|
||||||
@@ -158,7 +159,7 @@ namespace TweetDuck.Core{
|
|||||||
TweetDeckBridge.ResetStaticProperties();
|
TweetDeckBridge.ResetStaticProperties();
|
||||||
|
|
||||||
if (Arguments.HasFlag(Arguments.ArgIgnoreGDPR)){
|
if (Arguments.HasFlag(Arguments.ArgIgnoreGDPR)){
|
||||||
ScriptLoader.ExecuteScript(frame, @"TD.storage.Account.prototype.requiresConsent = function(){ return false; }", "gen:gdpr");
|
ScriptLoader.ExecuteScript(frame, "TD.storage.Account.prototype.requiresConsent = function(){ return false; }", "gen:gdpr");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Program.UserConfig.FirstRun){
|
if (Program.UserConfig.FirstRun){
|
||||||
@@ -173,7 +174,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");
|
||||||
@@ -222,7 +223,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){
|
||||||
@@ -260,5 +261,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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,8 @@ namespace TweetDuck.Core.Utils{
|
|||||||
static class BrowserUtils{
|
static class BrowserUtils{
|
||||||
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){
|
||||||
|
@@ -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";
|
||||||
|
@@ -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.4";
|
public const string VersionTag = "1.15";
|
||||||
|
|
||||||
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,6 +42,6 @@ using TweetDuck;
|
|||||||
[assembly: CLSCompliant(true)]
|
[assembly: CLSCompliant(true)]
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("TweetTest.System")]
|
||||||
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("TweetTest.Unit")]
|
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("TweetTest.Unit")]
|
||||||
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("UnitTests")]
|
|
||||||
#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>
|
@@ -15,7 +15,7 @@ The program was built using Visual Studio 2017. Before opening the solution, ple
|
|||||||
|
|
||||||
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.
|
||||||
@@ -64,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`.
|
||||||
|
15
Reporter.cs
@@ -46,8 +46,9 @@ 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
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(){
|
||||||
@@ -228,7 +228,7 @@ enabled(){
|
|||||||
if (value == me.config[key]){
|
if (value == me.config[key]){
|
||||||
item.addClass("selected");
|
item.addClass("selected");
|
||||||
}
|
}
|
||||||
|
|
||||||
item.click(function(){
|
item.click(function(){
|
||||||
modal.find("[data-td-key='"+key+"']").removeClass("selected");
|
modal.find("[data-td-key='"+key+"']").removeClass("selected");
|
||||||
item.addClass("selected");
|
item.addClass("selected");
|
||||||
@@ -407,7 +407,7 @@ enabled(){
|
|||||||
case "dark":
|
case "dark":
|
||||||
this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-track, .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-track { border-left-color: #14171A !important }");
|
this.css.insert(".scroll-styled-v:not(.scroll-alt)::-webkit-scrollbar-track, .scroll-styled-h:not(.scroll-alt)::-webkit-scrollbar-track { border-left-color: #14171A !important }");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "light":
|
case "light":
|
||||||
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: #d2d6da !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: #d2d6da !important }");
|
||||||
this.css.insert(".app-columns-container.scroll-styled-h::-webkit-scrollbar-thumb:not(:hover) { background-color: #a5aeb5 !important }");
|
this.css.insert(".app-columns-container.scroll-styled-h::-webkit-scrollbar-thumb:not(:hover) { background-color: #a5aeb5 !important }");
|
||||||
@@ -541,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; }
|
||||||
@@ -643,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;
|
||||||
|
@@ -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}
|
||||||
@@ -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,21 +232,21 @@ 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();
|
||||||
let posStart = input[0].selectionStart;
|
let posStart = input[0].selectionStart;
|
||||||
let posEnd = input[0].selectionEnd;
|
let posEnd = input[0].selectionEnd;
|
||||||
|
|
||||||
input.val(val.slice(0, posStart)+alt+val.slice(posEnd));
|
input.val(val.slice(0, posStart)+alt+val.slice(posEnd));
|
||||||
input.trigger("change");
|
input.trigger("change");
|
||||||
|
|
||||||
input[0].selectionStart = posStart+alt.length;
|
input[0].selectionStart = posStart+alt.length;
|
||||||
input[0].selectionEnd = posStart+alt.length;
|
input[0].selectionEnd = posStart+alt.length;
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ enabled(){
|
|||||||
if (ele.selectionStart === lastEmojiPosition){
|
if (ele.selectionStart === lastEmojiPosition){
|
||||||
ele.selectionStart -= lastEmojiLength; // selects the emoji
|
ele.selectionStart -= lastEmojiLength; // selects the emoji
|
||||||
document.execCommand("insertText", false, lastEmojiKeyword);
|
document.execCommand("insertText", false, lastEmojiKeyword);
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
@@ -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));
|
||||||
@@ -489,7 +489,7 @@ ready(){
|
|||||||
|
|
||||||
if (skinToneState === 1){
|
if (skinToneState === 1){
|
||||||
let skinIndex = decl.indexOf('$');
|
let skinIndex = decl.indexOf('$');
|
||||||
|
|
||||||
if (skinIndex !== -1){
|
if (skinIndex !== -1){
|
||||||
let declPre = decl.slice(0, skinIndex);
|
let declPre = decl.slice(0, skinIndex);
|
||||||
let declPost = decl.slice(skinIndex+1);
|
let declPost = decl.slice(skinIndex+1);
|
||||||
|
@@ -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%; min-width: 500px; 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: 225px; 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;
|
||||||
|
|
||||||
@@ -213,7 +183,7 @@ enabled(){
|
|||||||
url = evaluator;
|
url = evaluator;
|
||||||
evaluator = null;
|
evaluator = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
promises.push(doAjaxRequest(index2, url, evaluator));
|
promises.push(doAjaxRequest(index2, url, evaluator));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -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" 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>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
/* TODO possibly implement this later
|
<li>{paste}</li>
|
||||||
|
<li>Paste text or an image from clipboard</li>
|
||||||
<li>{paste}</li>
|
<li>{paste#text}</li>
|
||||||
<li>Paste text or an image from clipboard</li>
|
<li>Paste only if clipboard has text</li>
|
||||||
<li>{paste#text}</li>
|
<li>{paste#image}</li>
|
||||||
<li>Paste only if clipboard has text</li>
|
<li>Paste only if clipboard has an image</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
|
||||||
|
@@ -46,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
|
||||||
}
|
}
|
||||||
@@ -69,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)
|
||||||
}
|
}
|
||||||
@@ -82,39 +90,68 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 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
|
# Finished
|
||||||
|
|
||||||
$sw.Stop()
|
$sw.Stop()
|
||||||
|
@@ -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\.(.*?)\\'
|
|
||||||
$Version = $Match.Matches[0].Groups[1].Value
|
$cefMatch = Select-String -Path $mainProj '<Import Project="packages\\cef\.redist\.x86\.(.*?)\\'
|
||||||
|
$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\.(.*?)\\'
|
||||||
$Match = Select-String -Path $MainProj '<Import Project="packages\\CefSharp\.Common\.(.*?)\\'
|
$sharpVersion = $sharpMatch.Matches[0].Groups[1].Value
|
||||||
$Version = $Match.Matches[0].Groups[1].Value
|
|
||||||
|
$propsFiles = "..\packages\CefSharp.Common.${sharpVersion}\build\CefSharp.Common.props",
|
||||||
$Contents = [IO.File]::ReadAllText($BrowserProj)
|
"..\packages\CefSharp.WinForms.${sharpVersion}\build\CefSharp.WinForms.props"
|
||||||
$Contents = $Contents -Replace '(?<=<HintPath>\.\.\\packages\\CefSharp\.Common\.)(.*?)(?=\\)', $Version
|
|
||||||
$Contents = $Contents -Replace '(?<=<Reference Include="CefSharp\.BrowserSubprocess\.Core, Version=)(\d+)', $Version.Split(".")[0]
|
# Greetings
|
||||||
|
|
||||||
[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,25 +3,25 @@
|
|||||||
// 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+")");
|
||||||
}catch(err){
|
}catch(err){
|
||||||
if (!(onFailure && onFailure(err))){
|
if (!(onFailure && onFailure(err))){
|
||||||
$TD.alert("warning", "Problem loading '"+fileName+"' file for '"+identifier+"' plugin, the JavaScript syntax is invalid: "+err.message);
|
$TD.alert("warning", "Problem loading '"+fileName+"' file for '"+identifier+"' plugin, the JavaScript syntax is invalid: "+err.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSuccess && onSuccess(obj);
|
onSuccess && onSuccess(obj);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
if (!(onFailure && onFailure(err))){
|
if (!(onFailure && onFailure(err))){
|
||||||
@@ -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;
|
||||||
|
}
|
126
Resources/Scripts/imports/styles/update.css
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#tweetduck-update {
|
||||||
|
position: fixed;
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
}
|
@@ -1,105 +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: 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;
|
|
||||||
}
|
|
||||||
</style>`).appendTo(document.head);
|
|
||||||
|
|
||||||
let ele = $(`
|
|
||||||
<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>`).appendTo(".js-app");
|
|
||||||
|
|
||||||
let tdUser = null;
|
let tdUser = null;
|
||||||
let loadTweetDuckUser = (onSuccess, onError) => {
|
let loadTweetDuckUser = (onSuccess, onError) => {
|
||||||
|
@@ -2,14 +2,14 @@
|
|||||||
//
|
//
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -20,13 +20,13 @@
|
|||||||
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.href);
|
$TD.openBrowser(ele.href);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if ($TDX.skipOnLinkClick){
|
if ($TDX.skipOnLinkClick){
|
||||||
let parentClasses = ele.parentNode.classList;
|
let parentClasses = ele.parentNode.classList;
|
||||||
|
|
||||||
if (parentClasses.contains("js-tweet-text") || parentClasses.contains("js-quoted-tweet-text") || parentClasses.contains("js-timestamp")){
|
if (parentClasses.contains("js-tweet-text") || parentClasses.contains("js-quoted-tweet-text") || parentClasses.contains("js-timestamp")){
|
||||||
$TD.loadNextNotification();
|
$TD.loadNextNotification();
|
||||||
}
|
}
|
||||||
@@ -42,18 +42,18 @@
|
|||||||
// 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){
|
||||||
tooltipTimer = window.setTimeout(function(){
|
tooltipTimer = window.setTimeout(function(){
|
||||||
me.setAttribute("td-prev-text", text);
|
me.setAttribute("td-prev-text", text);
|
||||||
@@ -72,8 +72,8 @@
|
|||||||
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;
|
||||||
}
|
}
|
||||||
@@ -89,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);
|
||||||
@@ -110,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(){
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
document.body.addEventListener("mouseenter", function(){
|
document.body.addEventListener("mouseenter", function(){
|
||||||
document.body.classList.add("td-hover");
|
document.body.classList.add("td-hover");
|
||||||
});
|
});
|
||||||
|
|
||||||
document.body.addEventListener("mouseleave", function(){
|
document.body.addEventListener("mouseleave", function(){
|
||||||
document.body.classList.remove("td-hover");
|
document.body.classList.remove("td-hover");
|
||||||
});
|
});
|
||||||
|
@@ -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"
|
||||||
|
@@ -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,18 +26,26 @@
|
|||||||
//
|
//
|
||||||
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);
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
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++){
|
}
|
||||||
links[index].addEventListener("click", openLinkExternally);
|
|
||||||
|
let texts = document.querySelector(".page-canvas > div:last-child");
|
||||||
|
|
||||||
|
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();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -66,7 +55,7 @@
|
|||||||
else if (location.pathname === "/logout"){
|
else if (location.pathname === "/logout"){
|
||||||
document.addEventListener("DOMContentLoaded", function(){
|
document.addEventListener("DOMContentLoaded", function(){
|
||||||
let cancel = document.querySelector(".buttons .cancel");
|
let cancel = document.querySelector(".buttons .cancel");
|
||||||
|
|
||||||
if (cancel && cancel.tagName === "A"){
|
if (cancel && cancel.tagName === "A"){
|
||||||
cancel.href = "https://tweetdeck.twitter.com/";
|
cancel.href = "https://tweetdeck.twitter.com/";
|
||||||
}
|
}
|
||||||
|
@@ -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(){
|
|
||||||
$TDU.onUpdateDismissed();
|
|
||||||
slide();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onClick(ele.querySelector(".tdu-btn-ignore"), function(){
|
||||||
|
$TDU.onUpdateDismissed();
|
||||||
|
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,17 @@
|
|||||||
//
|
//
|
||||||
// Block: Check updates on startup.
|
// Block: Check updates on startup.
|
||||||
//
|
//
|
||||||
$(document).one("TD.ready", function(){
|
if ("$" in window && typeof $._data === "function" && "TD" in $._data(document, "events")){
|
||||||
|
$(document).one("TD.ready", function(){
|
||||||
|
$TDU.triggerUpdateCheck();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else{
|
||||||
$TDU.triggerUpdateCheck();
|
$TDU.triggerUpdateCheck();
|
||||||
});
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// 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>
|
||||||
@@ -97,6 +74,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" />
|
||||||
@@ -330,11 +309,6 @@
|
|||||||
<Compile Include="Updates\Events\UpdateEventArgs.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,12 @@ 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}"
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TweetTest.Unit", "lib\TweetTest.Unit\TweetTest.Unit.fsproj", "{EEE1071A-28FA-48B1-82A1-9CBDC5C3F2C3}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
@@ -28,10 +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 = Debug|x86
|
|
||||||
{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Release|x86.Build.0 = Debug|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
|
||||||
@@ -40,10 +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.ActiveCfg = Debug|x86
|
||||||
{EEE1071A-28FA-48B1-82A1-9CBDC5C3F2C3}.Debug|x86.Build.0 = Debug|x86
|
{EEE1071A-28FA-48B1-82A1-9CBDC5C3F2C3}.Debug|x86.Build.0 = Debug|x86
|
||||||
{EEE1071A-28FA-48B1-82A1-9CBDC5C3F2C3}.Release|x86.ActiveCfg = Debug|x86
|
{EEE1071A-28FA-48B1-82A1-9CBDC5C3F2C3}.Release|x86.ActiveCfg = Debug|x86
|
||||||
{EEE1071A-28FA-48B1-82A1-9CBDC5C3F2C3}.Release|x86.Build.0 = Debug|x86
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,9 +5,9 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|||||||
using TweetDuck.Configuration;
|
using TweetDuck.Configuration;
|
||||||
using TweetDuck.Core.Other;
|
using TweetDuck.Core.Other;
|
||||||
|
|
||||||
namespace UnitTests.Configuration{
|
namespace TweetTest.Configuration{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class TestUserConfig : UnitTestIO{
|
public class TestUserConfig : TestIO{
|
||||||
private static void WriteTestConfig(string file, bool withBackup){
|
private static void WriteTestConfig(string file, bool withBackup){
|
||||||
UserConfig cfg = UserConfig.Load(file);
|
UserConfig cfg = UserConfig.Load(file);
|
||||||
cfg.ZoomLevel = 123;
|
cfg.ZoomLevel = 123;
|
@@ -4,9 +4,9 @@ using System.Linq;
|
|||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using TweetDuck.Data;
|
using TweetDuck.Data;
|
||||||
|
|
||||||
namespace UnitTests.Data{
|
namespace TweetTest.Data{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class TestCombinedFileStream : UnitTestIO{
|
public class TestCombinedFileStream : TestIO{
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestNoFiles(){
|
public void TestNoFiles(){
|
||||||
using(CombinedFileStream cfs = new CombinedFileStream(File.OpenWrite("empty"))){
|
using(CombinedFileStream cfs = new CombinedFileStream(File.OpenWrite("empty"))){
|
@@ -3,9 +3,9 @@ using System.IO;
|
|||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using TweetDuck.Data.Serialization;
|
using TweetDuck.Data.Serialization;
|
||||||
|
|
||||||
namespace UnitTests.Data{
|
namespace TweetTest.Data{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class TestFileSerializer : UnitTestIO{
|
public class TestFileSerializer : TestIO{
|
||||||
private enum TestEnum{
|
private enum TestEnum{
|
||||||
A, B, C, D, E
|
A, B, C, D, E
|
||||||
}
|
}
|
@@ -1,14 +1,14 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
// General Information about an assembly is controlled through the following
|
||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle("UnitTests")]
|
[assembly: AssemblyTitle("TweetTest.System")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct("UnitTests")]
|
[assembly: AssemblyProduct("TweetTest.System")]
|
||||||
[assembly: AssemblyCopyright("")]
|
[assembly: AssemblyCopyright("")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
@@ -6,8 +6,8 @@
|
|||||||
<ProjectGuid>{A958FA7A-4A2C-42A7-BFA0-159343483F4E}</ProjectGuid>
|
<ProjectGuid>{A958FA7A-4A2C-42A7-BFA0-159343483F4E}</ProjectGuid>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>UnitTests</RootNamespace>
|
<RootNamespace>TweetTest</RootNamespace>
|
||||||
<AssemblyName>UnitTests</AssemblyName>
|
<AssemblyName>TweetTest.System</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
@@ -45,14 +45,12 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Configuration\TestUserConfig.cs" />
|
<Compile Include="Configuration\TestUserConfig.cs" />
|
||||||
<Compile Include="Data\TestCombinedFileStream.cs" />
|
<Compile Include="Data\TestCombinedFileStream.cs" />
|
||||||
<Compile Include="Data\TestCommandLineArgs.cs" />
|
|
||||||
<Compile Include="Data\TestFileSerializer.cs" />
|
<Compile Include="Data\TestFileSerializer.cs" />
|
||||||
<Compile Include="Data\TestTwoKeyDictionary.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="UnitTestIO.cs" />
|
<Compile Include="UnitTestIO.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\TweetDuck.csproj">
|
<ProjectReference Include="..\..\TweetDuck.csproj">
|
||||||
<Project>{2389a7cd-e0d3-4706-8294-092929a33a2d}</Project>
|
<Project>{2389a7cd-e0d3-4706-8294-092929a33a2d}</Project>
|
||||||
<Name>TweetDuck</Name>
|
<Name>TweetDuck</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
@@ -3,9 +3,9 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
namespace UnitTests{
|
namespace TweetTest{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class UnitTestIO{
|
public class TestIO{
|
||||||
private static readonly HashSet<string> CreatedFolders = new HashSet<string>();
|
private static readonly HashSet<string> CreatedFolders = new HashSet<string>();
|
||||||
|
|
||||||
[TestInitialize]
|
[TestInitialize]
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Unit.Core.BrowserUtils
|
namespace TweetTest.Core.BrowserUtils
|
||||||
|
|
||||||
open Xunit
|
open Xunit
|
||||||
open TweetDuck.Core.Utils
|
open TweetDuck.Core.Utils
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Unit.Core.StringUtils
|
namespace TweetTest.Core.StringUtils
|
||||||
|
|
||||||
open Xunit
|
open Xunit
|
||||||
open TweetDuck.Core.Utils
|
open TweetDuck.Core.Utils
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Unit.Core.TwitterUtils
|
namespace TweetTest.Core.TwitterUtils
|
||||||
|
|
||||||
open Xunit
|
open Xunit
|
||||||
open TweetDuck.Core.Utils
|
open TweetDuck.Core.Utils
|
||||||
|
368
lib/TweetTest.Unit/Data/TestCommandLineArgs.fs
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
namespace TweetTest.Data.CommandLineArgs
|
||||||
|
|
||||||
|
open Xunit
|
||||||
|
open TweetDuck.Data
|
||||||
|
|
||||||
|
|
||||||
|
type _TestData =
|
||||||
|
|
||||||
|
static member empty
|
||||||
|
with get() = CommandLineArgs()
|
||||||
|
|
||||||
|
static member flags
|
||||||
|
with get() =
|
||||||
|
let args = CommandLineArgs()
|
||||||
|
args.AddFlag("flag1")
|
||||||
|
args.AddFlag("flag2")
|
||||||
|
args.AddFlag("flag3")
|
||||||
|
args
|
||||||
|
|
||||||
|
static member values
|
||||||
|
with get() =
|
||||||
|
let args = CommandLineArgs()
|
||||||
|
args.SetValue("val1", "hello")
|
||||||
|
args.SetValue("val2", "world")
|
||||||
|
args
|
||||||
|
|
||||||
|
static member mixed
|
||||||
|
with get() =
|
||||||
|
let args = CommandLineArgs()
|
||||||
|
args.AddFlag("flag1")
|
||||||
|
args.AddFlag("flag2")
|
||||||
|
args.AddFlag("flag3")
|
||||||
|
args.SetValue("val1", "hello")
|
||||||
|
args.SetValue("val2", "world")
|
||||||
|
args
|
||||||
|
|
||||||
|
static member duplicate
|
||||||
|
with get() =
|
||||||
|
let args = CommandLineArgs()
|
||||||
|
args.AddFlag("duplicate")
|
||||||
|
args.SetValue("duplicate", "value")
|
||||||
|
args
|
||||||
|
|
||||||
|
|
||||||
|
module Count =
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``counts nothing correctly`` () =
|
||||||
|
Assert.Equal(0, _TestData.empty.Count)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``counts flags correctly`` () =
|
||||||
|
Assert.Equal(3, _TestData.flags.Count)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``counts values correctly`` () =
|
||||||
|
Assert.Equal(2, _TestData.values.Count)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``counts mixed flags and values correctly`` () =
|
||||||
|
Assert.Equal(5, _TestData.mixed.Count)
|
||||||
|
|
||||||
|
|
||||||
|
module Flags =
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("flag1")>]
|
||||||
|
[<InlineData("flag2")>]
|
||||||
|
[<InlineData("flag3")>]
|
||||||
|
let ``HasFlag returns false if flag is missing`` (flag: string) =
|
||||||
|
Assert.False(_TestData.empty.HasFlag(flag))
|
||||||
|
Assert.False(_TestData.values.HasFlag(flag))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("val1")>]
|
||||||
|
[<InlineData("val2")>]
|
||||||
|
let ``HasFlag returns false if the name only specifies a key`` (flag: string) =
|
||||||
|
Assert.False(_TestData.values.HasFlag(flag))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``HasFlag returns true if the name specifies both a flag and a value key`` () =
|
||||||
|
Assert.True(_TestData.duplicate.HasFlag("duplicate"))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("flag1")>]
|
||||||
|
[<InlineData("flag2")>]
|
||||||
|
[<InlineData("flag3")>]
|
||||||
|
let ``HasFlag returns true if flag is present`` (flag: string) =
|
||||||
|
Assert.True(_TestData.flags.HasFlag(flag))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("FLAG1")>]
|
||||||
|
[<InlineData("FlAg1")>]
|
||||||
|
let ``HasFlag is case-insensitive`` (flag: string) =
|
||||||
|
Assert.True(_TestData.flags.HasFlag(flag))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``AddFlag adds new flag`` () =
|
||||||
|
let args = _TestData.flags
|
||||||
|
args.AddFlag("flag4")
|
||||||
|
|
||||||
|
Assert.Equal(4, args.Count)
|
||||||
|
Assert.True(args.HasFlag("flag4"))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``AddFlag does nothing if flag is already present`` () =
|
||||||
|
let args = _TestData.flags
|
||||||
|
args.AddFlag("flag1")
|
||||||
|
|
||||||
|
Assert.Equal(3, args.Count)
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("flag1")>]
|
||||||
|
[<InlineData("flag2")>]
|
||||||
|
[<InlineData("flag3")>]
|
||||||
|
let ``RemoveFlag removes existing flag`` (flag: string) =
|
||||||
|
let args = _TestData.flags
|
||||||
|
args.RemoveFlag(flag)
|
||||||
|
|
||||||
|
Assert.Equal(2, args.Count)
|
||||||
|
Assert.False(args.HasFlag(flag))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("FLAG1")>]
|
||||||
|
[<InlineData("FlAg1")>]
|
||||||
|
let ``RemoveFlag is case-insensitive`` (flag: string) =
|
||||||
|
let args = _TestData.flags
|
||||||
|
args.RemoveFlag(flag)
|
||||||
|
|
||||||
|
Assert.Equal(2, args.Count)
|
||||||
|
Assert.False(args.HasFlag(flag))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``RemoveFlag does nothing if flag is missing`` () =
|
||||||
|
let args = _TestData.flags
|
||||||
|
args.RemoveFlag("missing")
|
||||||
|
|
||||||
|
Assert.Equal(3, args.Count)
|
||||||
|
|
||||||
|
|
||||||
|
module Values =
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("val1")>]
|
||||||
|
[<InlineData("val2")>]
|
||||||
|
let ``HasValue returns false if key is missing`` (key: string) =
|
||||||
|
Assert.False(_TestData.empty.HasValue(key))
|
||||||
|
Assert.False(_TestData.flags.HasValue(key))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("flag1")>]
|
||||||
|
[<InlineData("flag2")>]
|
||||||
|
[<InlineData("flag3")>]
|
||||||
|
let ``HasValue returns false if the name specifies a flag`` (key: string) =
|
||||||
|
Assert.False(_TestData.flags.HasValue(key))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``HasValue returns true if the name specifies both a flag and a value key`` () =
|
||||||
|
Assert.True(_TestData.duplicate.HasValue("duplicate"))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("val1")>]
|
||||||
|
[<InlineData("val2")>]
|
||||||
|
let ``HasValue returns true if key is present`` (key: string) =
|
||||||
|
Assert.True(_TestData.values.HasValue(key))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("VAL1")>]
|
||||||
|
[<InlineData("VaL1")>]
|
||||||
|
let ``HasValue is case-insensitive`` (key: string) =
|
||||||
|
Assert.True(_TestData.values.HasValue(key))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("val1", "hello")>]
|
||||||
|
[<InlineData("val2", "world")>]
|
||||||
|
let ``GetValue returns correct value if key is present`` (key: string, expectedValue: string) =
|
||||||
|
Assert.Equal(expectedValue, _TestData.values.GetValue(key, ""))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("VAL1", "hello")>]
|
||||||
|
[<InlineData("VaL1", "hello")>]
|
||||||
|
let ``GetValue is case-insensitive`` (key: string, expectedValue: string) =
|
||||||
|
Assert.Equal(expectedValue, _TestData.values.GetValue(key, ""))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``GetValue returns default value if key is missing`` () =
|
||||||
|
Assert.Equal("oh no", _TestData.values.GetValue("missing", "oh no"))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``SetValue adds new value`` () =
|
||||||
|
let args = _TestData.values
|
||||||
|
args.SetValue("val3", "this is nice")
|
||||||
|
|
||||||
|
Assert.Equal(3, args.Count)
|
||||||
|
Assert.Equal("this is nice", args.GetValue("val3", ""))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``SetValue replaces existing value`` () =
|
||||||
|
let args = _TestData.values
|
||||||
|
args.SetValue("val2", "mom")
|
||||||
|
|
||||||
|
Assert.Equal(2, args.Count)
|
||||||
|
Assert.Equal("mom", args.GetValue("val2", ""))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("val1")>]
|
||||||
|
[<InlineData("val2")>]
|
||||||
|
let ``RemoveValue removes existing key`` (key: string) =
|
||||||
|
let args = _TestData.values
|
||||||
|
args.RemoveValue(key)
|
||||||
|
|
||||||
|
Assert.Equal(1, args.Count)
|
||||||
|
Assert.False(args.HasValue(key))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("VAL1")>]
|
||||||
|
[<InlineData("VaL1")>]
|
||||||
|
let ``RemoveValue is case-insensitive`` (key: string) =
|
||||||
|
let args = _TestData.values
|
||||||
|
args.RemoveValue(key)
|
||||||
|
|
||||||
|
Assert.Equal(1, args.Count)
|
||||||
|
Assert.False(args.HasValue(key))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``RemoveValue does nothing if key is missing`` () =
|
||||||
|
let args = _TestData.values
|
||||||
|
args.RemoveValue("missing")
|
||||||
|
|
||||||
|
Assert.Equal(2, args.Count)
|
||||||
|
|
||||||
|
|
||||||
|
module Clone =
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``clones flags and values correctly`` () =
|
||||||
|
let clone = _TestData.mixed.Clone()
|
||||||
|
|
||||||
|
Assert.True(clone.HasFlag("flag1"))
|
||||||
|
Assert.True(clone.HasFlag("flag2"))
|
||||||
|
Assert.True(clone.HasFlag("flag3"))
|
||||||
|
Assert.Equal("hello", clone.GetValue("val1", ""))
|
||||||
|
Assert.Equal("world", clone.GetValue("val2", ""))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``cloning creates a new object`` () =
|
||||||
|
let args = _TestData.mixed
|
||||||
|
|
||||||
|
Assert.NotSame(args.Clone(), args)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``modifying a clone does not modify the original`` () =
|
||||||
|
let original = _TestData.mixed
|
||||||
|
let clone = original.Clone()
|
||||||
|
|
||||||
|
clone.RemoveFlag("flag1")
|
||||||
|
clone.AddFlag("flag4")
|
||||||
|
clone.SetValue("val1", "goodbye")
|
||||||
|
|
||||||
|
Assert.True(original.HasFlag("flag1"))
|
||||||
|
Assert.False(original.HasFlag("flag4"))
|
||||||
|
Assert.Equal("hello", original.GetValue("val1", ""))
|
||||||
|
|
||||||
|
|
||||||
|
module ToDictionary =
|
||||||
|
open System.Collections.Generic
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``does nothing with empty args`` () =
|
||||||
|
let dict = Dictionary<string, string>()
|
||||||
|
_TestData.empty.ToDictionary(dict)
|
||||||
|
|
||||||
|
Assert.Equal(0, dict.Count)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``converts flags and values correctly`` () =
|
||||||
|
let dict = Dictionary<string, string>()
|
||||||
|
_TestData.mixed.ToDictionary(dict)
|
||||||
|
|
||||||
|
Assert.Equal(5, dict.Count)
|
||||||
|
Assert.Equal("1", dict.["flag1"])
|
||||||
|
Assert.Equal("1", dict.["flag2"])
|
||||||
|
Assert.Equal("1", dict.["flag3"])
|
||||||
|
Assert.Equal("hello", dict.["val1"])
|
||||||
|
Assert.Equal("world", dict.["val2"])
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``prefers value if the same name is used for a flag and value`` () =
|
||||||
|
let dict = Dictionary<string, string>()
|
||||||
|
_TestData.duplicate.ToDictionary(dict)
|
||||||
|
|
||||||
|
Assert.Equal(1, dict.Count)
|
||||||
|
Assert.Equal("value", dict.["duplicate"])
|
||||||
|
|
||||||
|
|
||||||
|
module ToString =
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns empty string for empty args`` () =
|
||||||
|
Assert.Equal("", _TestData.empty.ToString())
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``converts flags and values correctly`` () =
|
||||||
|
Assert.Equal("flag1 flag2 flag3 val1 \"hello\" val2 \"world\"", _TestData.mixed.ToString())
|
||||||
|
// not guaranteed to be in order but works for now
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``handle duplicate names in a probably pretty decent way tbh`` () =
|
||||||
|
Assert.Equal("duplicate duplicate \"value\"", _TestData.duplicate.ToString())
|
||||||
|
|
||||||
|
|
||||||
|
module FromStringArray =
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns empty args if input array is empty`` () =
|
||||||
|
Assert.Equal(0, CommandLineArgs.FromStringArray('-', Array.empty).Count)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns empty args if no entry starts with entry char`` () =
|
||||||
|
Assert.Equal(0, CommandLineArgs.FromStringArray('-', [| ""; "~nope"; ":fail" |]).Count)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``reads flags and values correctly`` () =
|
||||||
|
let args = CommandLineArgs.FromStringArray('-', [| "-flag1"; "-flag2"; "-flag3"; "-val1"; "first value"; "-val2"; "second value" |])
|
||||||
|
|
||||||
|
Assert.Equal(5, args.Count)
|
||||||
|
Assert.True(args.HasFlag("-flag1"))
|
||||||
|
Assert.True(args.HasFlag("-flag2"))
|
||||||
|
Assert.True(args.HasFlag("-flag3"))
|
||||||
|
Assert.Equal("first value", args.GetValue("-val1", ""))
|
||||||
|
Assert.Equal("second value", args.GetValue("-val2", ""))
|
||||||
|
|
||||||
|
|
||||||
|
module ReadCefArguments =
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns empty args if input string is empty`` () =
|
||||||
|
Assert.Equal(0, CommandLineArgs.ReadCefArguments("").Count)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns empty args if input string is whitespace`` () =
|
||||||
|
Assert.Equal(0, CommandLineArgs.ReadCefArguments(" \r\n \t").Count)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``reads values correctly`` () =
|
||||||
|
let args = CommandLineArgs.ReadCefArguments("--first-value=10 --second-value=\"long string with spaces\"")
|
||||||
|
|
||||||
|
Assert.Equal(2, args.Count)
|
||||||
|
Assert.Equal("10", args.GetValue("first-value", ""))
|
||||||
|
Assert.Equal("long string with spaces", args.GetValue("second-value", ""))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``reads flags as value keys with values of 1`` () =
|
||||||
|
let args = CommandLineArgs.ReadCefArguments("--first-flag-as-value --second-flag-as-value")
|
||||||
|
|
||||||
|
Assert.Equal(2, args.Count)
|
||||||
|
Assert.Equal("1", args.GetValue("first-flag-as-value", ""))
|
||||||
|
Assert.Equal("1", args.GetValue("second-flag-as-value", ""))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``reads complex string with whitespace correctly`` () =
|
||||||
|
let args = CommandLineArgs.ReadCefArguments("\t--first-value=55.5\r\n--first-flag-as-value\r\n --second-value=\"long string\"\t--second-flag-as-value ")
|
||||||
|
|
||||||
|
Assert.Equal(4, args.Count)
|
||||||
|
Assert.Equal("55.5", args.GetValue("first-value", ""))
|
||||||
|
Assert.Equal("long string", args.GetValue("second-value", ""))
|
||||||
|
Assert.Equal("1", args.GetValue("first-flag-as-value", ""))
|
||||||
|
Assert.Equal("1", args.GetValue("second-flag-as-value", ""))
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Unit.Data.InjectedHTML
|
namespace TweetTest.Data.InjectedHTML
|
||||||
|
|
||||||
open Xunit
|
open Xunit
|
||||||
open TweetDuck.Data
|
open TweetDuck.Data
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
namespace Unit.Data
|
namespace TweetTest.Data.Result
|
||||||
|
|
||||||
open Xunit
|
open Xunit
|
||||||
open TweetDuck.Data
|
open TweetDuck.Data
|
||||||
open System
|
open System
|
||||||
|
|
||||||
|
|
||||||
module TestResult_WithValue =
|
module Result_WithValue =
|
||||||
let result = Result<int>(10)
|
let result = Result<int>(10)
|
||||||
|
|
||||||
[<Fact>]
|
[<Fact>]
|
||||||
@@ -31,7 +31,7 @@ module TestResult_WithValue =
|
|||||||
Assert.Equal(20, result.Select(fun x -> x * 2).Value)
|
Assert.Equal(20, result.Select(fun x -> x * 2).Value)
|
||||||
|
|
||||||
|
|
||||||
module TestResult_WithException =
|
module Result_WithException =
|
||||||
let result = Result<int>(IndexOutOfRangeException("bad"))
|
let result = Result<int>(IndexOutOfRangeException("bad"))
|
||||||
|
|
||||||
[<Fact>]
|
[<Fact>]
|
||||||
|
233
lib/TweetTest.Unit/Data/TestTwoKeyDictionary.fs
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
namespace TweetTest.Data.TwoKeyDictionary
|
||||||
|
|
||||||
|
open Xunit
|
||||||
|
open TweetDuck.Data
|
||||||
|
open System.Collections.Generic
|
||||||
|
|
||||||
|
|
||||||
|
type _TestData =
|
||||||
|
|
||||||
|
static member empty
|
||||||
|
with get() = TwoKeyDictionary<string, int, float>()
|
||||||
|
|
||||||
|
static member uniquevals
|
||||||
|
with get() =
|
||||||
|
let dict = TwoKeyDictionary<string, int, float>()
|
||||||
|
dict.Add("first", 1, 10.0)
|
||||||
|
dict.Add("first", 2, 20.0)
|
||||||
|
dict.Add("first", 3, 30.0)
|
||||||
|
dict.Add("second", 1, 100.0)
|
||||||
|
dict.Add("second", 2, 200.0)
|
||||||
|
dict.Add("third", 1, 1000.0)
|
||||||
|
dict
|
||||||
|
|
||||||
|
static member duplicatevals
|
||||||
|
with get() =
|
||||||
|
let dict = TwoKeyDictionary<string, int, float>()
|
||||||
|
dict.Add("first", 1, 10.0)
|
||||||
|
dict.Add("first", 2, 20.0)
|
||||||
|
dict.Add("first", 3, 30.0)
|
||||||
|
dict.Add("second", 1, 10.0)
|
||||||
|
dict.Add("second", 2, 20.0)
|
||||||
|
dict.Add("third", 1, 10.0)
|
||||||
|
dict
|
||||||
|
|
||||||
|
|
||||||
|
module Indexer =
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("first", 3, 30.0)>]
|
||||||
|
[<InlineData("second", 2, 200.0)>]
|
||||||
|
[<InlineData("third", 1, 1000.0)>]
|
||||||
|
let ``get returns correct value`` (outerKey: string, innerKey: int, value: float) =
|
||||||
|
Assert.Equal(value, _TestData.uniquevals.[outerKey, innerKey])
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``get throws if outer key is missing`` () =
|
||||||
|
Assert.Throws<KeyNotFoundException>(fun () -> _TestData.uniquevals.["missing", 1] |> ignore)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``get throws if inner key is missing`` () =
|
||||||
|
Assert.Throws<KeyNotFoundException>(fun () -> _TestData.uniquevals.["first", 0] |> ignore)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``set correctly updates value`` () =
|
||||||
|
let copy = _TestData.uniquevals
|
||||||
|
copy.["first", 1] <- 50.0
|
||||||
|
|
||||||
|
Assert.Equal(50.0, copy.["first", 1])
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``set creates new inner key`` () =
|
||||||
|
let copy = _TestData.uniquevals
|
||||||
|
copy.["second", 3] <- 300.0
|
||||||
|
|
||||||
|
Assert.Equal(300.0, copy.["second", 3])
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``set creates new outer key`` () =
|
||||||
|
let copy = _TestData.uniquevals
|
||||||
|
copy.["fourth", 1] <- 10000.0
|
||||||
|
|
||||||
|
Assert.Equal(10000.0, copy.["fourth", 1])
|
||||||
|
|
||||||
|
|
||||||
|
module InnerValues =
|
||||||
|
open System.Linq
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns empty collection for empty dictionary`` () =
|
||||||
|
Assert.Equal<IEnumerable<float>>(Enumerable.Empty<float>(), _TestData.empty.InnerValues)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns all values for dictionary with unique values`` () =
|
||||||
|
Assert.Equal([ 10.0; 20.0; 30.0; 100.0; 200.0; 1000.0 ], _TestData.uniquevals.InnerValues)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns all values for dictionary with duplicated values`` () =
|
||||||
|
Assert.Equal([ 10.0; 20.0; 30.0; 10.0; 20.0; 10.0 ], _TestData.duplicatevals.InnerValues)
|
||||||
|
|
||||||
|
|
||||||
|
module TryGetValue =
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns true and correct value for existing key`` () =
|
||||||
|
let (success, result) = _TestData.uniquevals.TryGetValue("first", 3)
|
||||||
|
|
||||||
|
Assert.True(success)
|
||||||
|
Assert.Equal(30.0, result)
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns false for missing inner key`` () =
|
||||||
|
Assert.False(_TestData.uniquevals.TryGetValue("first", 0, ref 0.0))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns false for missing outer key`` () =
|
||||||
|
Assert.False(_TestData.uniquevals.TryGetValue("missing", 0, ref 0.0))
|
||||||
|
|
||||||
|
|
||||||
|
module Add =
|
||||||
|
open System
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``creates new inner key`` () =
|
||||||
|
let copy = _TestData.uniquevals
|
||||||
|
copy.Add("first", 4, 40.0)
|
||||||
|
|
||||||
|
Assert.Equal(40.0, copy.["first", 4])
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``creates new outer key`` () =
|
||||||
|
let copy = _TestData.uniquevals
|
||||||
|
copy.Add("fourth", 1, 10000.0)
|
||||||
|
|
||||||
|
Assert.Equal(10000.0, copy.["fourth", 1])
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``throw on duplicate key`` () =
|
||||||
|
Assert.Throws<ArgumentException>(fun () -> _TestData.uniquevals.Add("first", 2, 25.0))
|
||||||
|
|
||||||
|
|
||||||
|
module Contains =
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("first")>]
|
||||||
|
[<InlineData("second")>]
|
||||||
|
[<InlineData("third")>]
|
||||||
|
let ``returns true if outer key exists`` (outerKey: string) =
|
||||||
|
Assert.True(_TestData.uniquevals.Contains(outerKey))
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData(1)>]
|
||||||
|
[<InlineData(2)>]
|
||||||
|
[<InlineData(3)>]
|
||||||
|
let ``returns true if inner key exists`` (innerKey: int) =
|
||||||
|
Assert.True(_TestData.uniquevals.Contains("first", innerKey))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns false if outer key does not exist`` () =
|
||||||
|
Assert.False(_TestData.uniquevals.Contains("missing"))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns false if inner key does not exist`` () =
|
||||||
|
Assert.False(_TestData.uniquevals.Contains("first", 0))
|
||||||
|
|
||||||
|
|
||||||
|
module Count =
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``counts all values for dictionary with unique values`` () =
|
||||||
|
Assert.Equal(6, _TestData.uniquevals.Count())
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``counts all values for dictionary with duplicated values`` () =
|
||||||
|
Assert.Equal(6, _TestData.duplicatevals.Count())
|
||||||
|
|
||||||
|
[<Theory>]
|
||||||
|
[<InlineData("first", 3)>]
|
||||||
|
[<InlineData("second", 2)>]
|
||||||
|
[<InlineData("third", 1)>]
|
||||||
|
let ``counts all values for specified key`` (outerKey: string, expectedCount: int) =
|
||||||
|
Assert.Equal(expectedCount, _TestData.uniquevals.Count(outerKey))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``throws on missing key`` () =
|
||||||
|
Assert.Throws<KeyNotFoundException>(fun () -> _TestData.uniquevals.Count("missing") |> ignore)
|
||||||
|
|
||||||
|
|
||||||
|
module Clear =
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``clears all values for all keys`` () =
|
||||||
|
let copy = _TestData.uniquevals
|
||||||
|
copy.Clear()
|
||||||
|
|
||||||
|
Assert.Equal(0, copy.Count())
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``clears all values for specified key`` () =
|
||||||
|
let copy = _TestData.uniquevals
|
||||||
|
copy.Clear("first")
|
||||||
|
|
||||||
|
Assert.True(copy.Contains("first"))
|
||||||
|
Assert.Equal(0, copy.Count("first"))
|
||||||
|
Assert.Equal(3, copy.Count())
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``throws on missing key`` () =
|
||||||
|
Assert.Throws<KeyNotFoundException>(fun () -> _TestData.uniquevals.Clear("missing") |> ignore)
|
||||||
|
|
||||||
|
|
||||||
|
module Remove =
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``removes value by key pair`` () =
|
||||||
|
let copy = _TestData.uniquevals
|
||||||
|
Assert.True(copy.Remove("first", 3))
|
||||||
|
|
||||||
|
Assert.False(copy.Contains("first", 3))
|
||||||
|
Assert.Equal(5, copy.Count())
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``removes inner key and its values`` () =
|
||||||
|
let copy = _TestData.uniquevals
|
||||||
|
Assert.True(copy.Remove("first"))
|
||||||
|
|
||||||
|
Assert.False(copy.Contains("first"))
|
||||||
|
Assert.Equal(3, copy.Count())
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``removing all inner keys deletes the outer key`` () =
|
||||||
|
let copy = _TestData.uniquevals
|
||||||
|
Assert.True(copy.Remove("first", 1))
|
||||||
|
Assert.True(copy.Remove("first", 2))
|
||||||
|
Assert.True(copy.Remove("first", 3))
|
||||||
|
Assert.False(copy.Contains("first"))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns false on missing inner key`` () =
|
||||||
|
Assert.False(_TestData.uniquevals.Remove("first", 0))
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``returns false on missing outer key`` () =
|
||||||
|
Assert.False(_TestData.uniquevals.Remove("missing"))
|
@@ -65,8 +65,10 @@
|
|||||||
<Compile Include="Core\TestBrowserUtils.fs" />
|
<Compile Include="Core\TestBrowserUtils.fs" />
|
||||||
<Compile Include="Core\TestStringUtils.fs" />
|
<Compile Include="Core\TestStringUtils.fs" />
|
||||||
<Compile Include="Core\TestTwitterUtils.fs" />
|
<Compile Include="Core\TestTwitterUtils.fs" />
|
||||||
|
<Compile Include="Data\TestCommandLineArgs.fs" />
|
||||||
<Compile Include="Data\TestInjectedHTML.fs" />
|
<Compile Include="Data\TestInjectedHTML.fs" />
|
||||||
<Compile Include="Data\TestResult.fs" />
|
<Compile Include="Data\TestResult.fs" />
|
||||||
|
<Compile Include="Data\TestTwoKeyDictionary.fs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.VisualStudio.CodeCoverage.Shim">
|
<Reference Include="Microsoft.VisualStudio.CodeCoverage.Shim">
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="cef.redist.x64" version="3.3359.1772" targetFramework="net452" />
|
<package id="cef.redist.x64" version="3.3396.1777" targetFramework="net452" />
|
||||||
<package id="cef.redist.x86" version="3.3359.1772" targetFramework="net452" />
|
<package id="cef.redist.x86" version="3.3396.1777" targetFramework="net452" />
|
||||||
<package id="CefSharp.Common" version="66.0.0-CI2629" targetFramework="net452" />
|
<package id="CefSharp.Common" version="67.0.0-CI2662" targetFramework="net452" />
|
||||||
<package id="CefSharp.WinForms" version="66.0.0-CI2629" targetFramework="net452" />
|
<package id="CefSharp.WinForms" version="67.0.0-CI2662" targetFramework="net452" />
|
||||||
</packages>
|
</packages>
|
@@ -26,9 +26,9 @@
|
|||||||
<StartupObject />
|
<StartupObject />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CefSharp.BrowserSubprocess.Core, Version=66.0.0.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138, processorArchitecture=x86">
|
<Reference Include="CefSharp.BrowserSubprocess.Core, Version=67.0.0.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138, processorArchitecture=x86">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CefSharp.Common.66.0.0-CI2629\CefSharp\x86\CefSharp.BrowserSubprocess.Core.dll</HintPath>
|
<HintPath>..\packages\CefSharp.Common.67.0.0-CI2662\CefSharp\x86\CefSharp.BrowserSubprocess.Core.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@@ -1,182 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using TweetDuck.Data;
|
|
||||||
|
|
||||||
namespace UnitTests.Data{
|
|
||||||
[TestClass]
|
|
||||||
public class TestCommandLineArgs{
|
|
||||||
[TestMethod]
|
|
||||||
public void TestEmpty(){
|
|
||||||
CommandLineArgs args = new CommandLineArgs();
|
|
||||||
|
|
||||||
Assert.AreEqual(0, args.Count);
|
|
||||||
Assert.AreEqual(string.Empty, args.ToString());
|
|
||||||
|
|
||||||
Assert.IsFalse(args.HasFlag("x"));
|
|
||||||
Assert.IsFalse(args.HasValue("x"));
|
|
||||||
Assert.AreEqual("default", args.GetValue("x", "default"));
|
|
||||||
|
|
||||||
args.RemoveFlag("x");
|
|
||||||
args.RemoveValue("x");
|
|
||||||
|
|
||||||
var dict = new Dictionary<string, string>();
|
|
||||||
args.ToDictionary(dict);
|
|
||||||
Assert.AreEqual(0, dict.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void TestFlags(){
|
|
||||||
CommandLineArgs args = new CommandLineArgs();
|
|
||||||
|
|
||||||
args.AddFlag("my_test_flag_1");
|
|
||||||
args.AddFlag("my_test_flag_2");
|
|
||||||
args.AddFlag("aAaAa");
|
|
||||||
|
|
||||||
Assert.IsFalse(args.HasValue("aAaAa"));
|
|
||||||
|
|
||||||
Assert.AreEqual(3, args.Count);
|
|
||||||
Assert.IsTrue(args.HasFlag("my_test_flag_1"));
|
|
||||||
Assert.IsTrue(args.HasFlag("my_test_flag_2"));
|
|
||||||
Assert.IsTrue(args.HasFlag("aaaaa"));
|
|
||||||
Assert.IsTrue(args.HasFlag("AAAAA"));
|
|
||||||
Assert.AreEqual("my_test_flag_1 my_test_flag_2 aaaaa", args.ToString());
|
|
||||||
|
|
||||||
args.RemoveFlag("Aaaaa");
|
|
||||||
|
|
||||||
Assert.AreEqual(2, args.Count);
|
|
||||||
Assert.IsTrue(args.HasFlag("my_test_flag_1"));
|
|
||||||
Assert.IsTrue(args.HasFlag("my_test_flag_2"));
|
|
||||||
Assert.IsFalse(args.HasFlag("aaaaa"));
|
|
||||||
Assert.AreEqual("my_test_flag_1 my_test_flag_2", args.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void TestValues(){
|
|
||||||
CommandLineArgs args = new CommandLineArgs();
|
|
||||||
|
|
||||||
args.SetValue("test_value", "My Test Value");
|
|
||||||
args.SetValue("aAaAa", "aaaaa");
|
|
||||||
|
|
||||||
Assert.IsFalse(args.HasFlag("aAaAa"));
|
|
||||||
|
|
||||||
Assert.AreEqual(2, args.Count);
|
|
||||||
Assert.IsTrue(args.HasValue("test_value"));
|
|
||||||
Assert.IsTrue(args.HasValue("aaaaa"));
|
|
||||||
Assert.IsTrue(args.HasValue("AAAAA"));
|
|
||||||
Assert.AreEqual("My Test Value", args.GetValue("test_value", string.Empty));
|
|
||||||
Assert.AreEqual("aaaaa", args.GetValue("aaaaa", string.Empty));
|
|
||||||
Assert.AreEqual("test_value \"My Test Value\" aaaaa \"aaaaa\"", args.ToString());
|
|
||||||
|
|
||||||
args.RemoveValue("Aaaaa");
|
|
||||||
|
|
||||||
Assert.AreEqual(1, args.Count);
|
|
||||||
Assert.IsTrue(args.HasValue("test_value"));
|
|
||||||
Assert.IsFalse(args.HasValue("aaaaa"));
|
|
||||||
Assert.AreEqual("test_value \"My Test Value\"", args.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void TestFlagAndValueMix(){
|
|
||||||
CommandLineArgs args = new CommandLineArgs();
|
|
||||||
|
|
||||||
args.AddFlag("my_test_flag_1");
|
|
||||||
args.AddFlag("my_test_flag_2");
|
|
||||||
args.AddFlag("aAaAa");
|
|
||||||
|
|
||||||
args.SetValue("test_value", "My Test Value");
|
|
||||||
args.SetValue("aAaAa", "aaaaa");
|
|
||||||
|
|
||||||
Assert.AreEqual(5, args.Count);
|
|
||||||
Assert.IsTrue(args.HasFlag("aaaaa"));
|
|
||||||
Assert.IsTrue(args.HasValue("aaaaa"));
|
|
||||||
Assert.AreEqual("my_test_flag_1 my_test_flag_2 aaaaa test_value \"My Test Value\" aaaaa \"aaaaa\"", args.ToString());
|
|
||||||
|
|
||||||
var dict = new Dictionary<string, string>();
|
|
||||||
args.ToDictionary(dict); // loses 'aaaaa' flag
|
|
||||||
|
|
||||||
Assert.AreEqual(4, dict.Count);
|
|
||||||
Assert.AreEqual("1", dict["my_test_flag_1"]);
|
|
||||||
Assert.AreEqual("1", dict["my_test_flag_2"]);
|
|
||||||
Assert.AreEqual("My Test Value", dict["test_value"]);
|
|
||||||
Assert.AreEqual("aaaaa", dict["aaaaa"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void TestClone(){
|
|
||||||
CommandLineArgs args = new CommandLineArgs();
|
|
||||||
|
|
||||||
args.AddFlag("my_test_flag_1");
|
|
||||||
args.AddFlag("my_test_flag_2");
|
|
||||||
args.AddFlag("aAaAa");
|
|
||||||
|
|
||||||
args.SetValue("test_value", "My Test Value");
|
|
||||||
args.SetValue("aAaAa", "aaaaa");
|
|
||||||
|
|
||||||
CommandLineArgs clone = args.Clone();
|
|
||||||
args.RemoveFlag("aaaaa");
|
|
||||||
args.RemoveValue("aaaaa");
|
|
||||||
clone.RemoveFlag("my_test_flag_1");
|
|
||||||
clone.RemoveFlag("my_test_flag_2");
|
|
||||||
clone.RemoveValue("test_value");
|
|
||||||
|
|
||||||
Assert.AreEqual(3, args.Count);
|
|
||||||
Assert.AreEqual(2, clone.Count);
|
|
||||||
|
|
||||||
Assert.AreEqual("my_test_flag_1 my_test_flag_2 test_value \"My Test Value\"", args.ToString());
|
|
||||||
Assert.AreEqual("aaaaa aaaaa \"aaaaa\"", clone.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void TestEmptyStringArray(){
|
|
||||||
CommandLineArgs args;
|
|
||||||
|
|
||||||
args = CommandLineArgs.FromStringArray('-', new string[0]);
|
|
||||||
Assert.AreEqual(0, args.Count);
|
|
||||||
|
|
||||||
args = CommandLineArgs.FromStringArray('-', new string[]{ "", "+fail", "@nope" });
|
|
||||||
Assert.AreEqual(0, args.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void TestValidStringArray(){
|
|
||||||
CommandLineArgs args;
|
|
||||||
|
|
||||||
args = CommandLineArgs.FromStringArray('-', new string[]{ "-flag1", "-flag2", "-FLAG3" });
|
|
||||||
Assert.AreEqual(3, args.Count);
|
|
||||||
Assert.IsTrue(args.HasFlag("-flag1"));
|
|
||||||
Assert.IsTrue(args.HasFlag("-flag2"));
|
|
||||||
Assert.IsTrue(args.HasFlag("-flag3"));
|
|
||||||
|
|
||||||
args = CommandLineArgs.FromStringArray('-', new string[]{ "-flag", "-value", "Here is some text!" });
|
|
||||||
Assert.AreEqual(2, args.Count);
|
|
||||||
Assert.IsTrue(args.HasFlag("-flag"));
|
|
||||||
Assert.IsTrue(args.HasValue("-value"));
|
|
||||||
Assert.AreEqual("Here is some text!", args.GetValue("-value", string.Empty));
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void TestCefEmptyString(){
|
|
||||||
Assert.AreEqual(0, CommandLineArgs.ReadCefArguments("").Count);
|
|
||||||
Assert.AreEqual(0, CommandLineArgs.ReadCefArguments(" ").Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void TestCefValidString(){
|
|
||||||
CommandLineArgs args = CommandLineArgs.ReadCefArguments("--aaa --bbb --first-value=123 --SECOND-VALUE=\"a b c d e\"\r\n--ccc");
|
|
||||||
// cef has no flags, flag arguments have a value of 1
|
|
||||||
// the processing removes all dashes in front of each key
|
|
||||||
|
|
||||||
Assert.AreEqual(5, args.Count);
|
|
||||||
Assert.IsTrue(args.HasValue("aaa"));
|
|
||||||
Assert.IsTrue(args.HasValue("bbb"));
|
|
||||||
Assert.IsTrue(args.HasValue("ccc"));
|
|
||||||
Assert.IsTrue(args.HasValue("first-value"));
|
|
||||||
Assert.IsTrue(args.HasValue("second-value"));
|
|
||||||
Assert.AreEqual("1", args.GetValue("aaa", string.Empty));
|
|
||||||
Assert.AreEqual("1", args.GetValue("bbb", string.Empty));
|
|
||||||
Assert.AreEqual("1", args.GetValue("ccc", string.Empty));
|
|
||||||
Assert.AreEqual("123", args.GetValue("first-value", string.Empty));
|
|
||||||
Assert.AreEqual("a b c d e", args.GetValue("second-value", string.Empty));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|