diff --git a/Configuration/UserConfig.cs b/Configuration/UserConfig.cs index c608ee60..c26efc6d 100644 --- a/Configuration/UserConfig.cs +++ b/Configuration/UserConfig.cs @@ -50,6 +50,7 @@ static UserConfig(){ public bool IgnoreTrackingUrlWarning { get; set; } = false; public bool EnableSmoothScrolling { get; set; } = true; public string BrowserPath { get; set; } = null; + public string SearchEngineUrl { get; set; } = null; private int _zoomLevel = 100; private bool _muteNotifications; diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs index 0e07c6d5..e0b1c273 100644 --- a/Core/FormBrowser.cs +++ b/Core/FormBrowser.cs @@ -301,6 +301,10 @@ public void ReloadToTweetDeck(){ AnalyticsFile.BrowserReloads.Trigger(); } + public void AddSearchColumn(string query){ + browser.AddSearchColumn(query); + } + public void TriggerTweetScreenshot(){ browser.TriggerTweetScreenshot(); } diff --git a/Core/Handling/ContextMenuBase.cs b/Core/Handling/ContextMenuBase.cs index f6414717..0ccfb5f7 100644 --- a/Core/Handling/ContextMenuBase.cs +++ b/Core/Handling/ContextMenuBase.cs @@ -11,6 +11,7 @@ using TweetDuck.Core.Notification; using TweetDuck.Core.Other; using TweetDuck.Core.Other.Analytics; +using TweetDuck.Resources; namespace TweetDuck.Core.Handling{ abstract class ContextMenuBase : IContextMenuHandler{ @@ -26,6 +27,7 @@ abstract class ContextMenuBase : IContextMenuHandler{ private const CefMenuCommand MenuCopyMediaUrl = (CefMenuCommand)26505; private const CefMenuCommand MenuSaveMedia = (CefMenuCommand)26506; private const CefMenuCommand MenuSaveTweetImages = (CefMenuCommand)26507; + private const CefMenuCommand MenuSearchInBrowser = (CefMenuCommand)26508; private const CefMenuCommand MenuOpenDevTools = (CefMenuCommand)26599; protected ContextInfo.LinkInfo LastLink { get; private set; } @@ -52,6 +54,11 @@ public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser bro LastChirp = TweetDeckBridge.ContextInfo.Chirp; } + if (parameters.TypeFlags.HasFlag(ContextMenuType.Selection) && !parameters.TypeFlags.HasFlag(ContextMenuType.Editable)){ + model.AddItem(MenuSearchInBrowser, "Search in browser"); + model.AddSeparator(); + } + bool hasTweetImage = LastLink.IsImage; bool hasTweetVideo = LastLink.IsVideo; @@ -165,6 +172,12 @@ void ViewImage(string path){ control.InvokeAsyncSafe(analytics.AnalyticsFile.DownloadedImages.Trigger); TwitterUtils.DownloadImages(LastChirp.Images, LastChirp.Authors.LastOrDefault(), ImageQuality); break; + + case MenuSearchInBrowser: + string query = parameters.SelectionText; + control.InvokeAsyncSafe(() => BrowserUtils.OpenExternalSearch(query)); + DeselectAll(frame); + break; case MenuOpenDevTools: browserControl.ShowDevTools(); @@ -182,6 +195,10 @@ public virtual bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, return false; } + protected void DeselectAll(IFrame frame){ + ScriptLoader.ExecuteScript(frame, "window.getSelection().removeAllRanges()", "gen:deselect"); + } + protected void OpenBrowser(Control control, string url){ control.InvokeAsyncSafe(() => BrowserUtils.OpenExternalBrowser(url)); } diff --git a/Core/Handling/ContextMenuBrowser.cs b/Core/Handling/ContextMenuBrowser.cs index 126ccccc..5b1e2691 100644 --- a/Core/Handling/ContextMenuBrowser.cs +++ b/Core/Handling/ContextMenuBrowser.cs @@ -1,6 +1,7 @@ using CefSharp; using System.Windows.Forms; using TweetDuck.Core.Controls; +using TweetDuck.Core.Utils; namespace TweetDuck.Core.Handling{ sealed class ContextMenuBrowser : ContextMenuBase{ @@ -16,6 +17,7 @@ sealed class ContextMenuBrowser : ContextMenuBase{ private const CefMenuCommand MenuCopyQuotedTweetUrl = (CefMenuCommand)26613; private const CefMenuCommand MenuScreenshotTweet = (CefMenuCommand)26614; private const CefMenuCommand MenuInputApplyROT13 = (CefMenuCommand)26615; + private const CefMenuCommand MenuSearchInColumn = (CefMenuCommand)26616; private const string TitleReloadBrowser = "Reload browser"; private const string TitleMuteNotifications = "Mute notifications"; @@ -37,12 +39,18 @@ public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser br RemoveSeparatorIfLast(model); if (parameters.TypeFlags.HasFlag(ContextMenuType.Selection)){ - if (parameters.TypeFlags.HasFlag(ContextMenuType.Editable)){ + bool isEditing = parameters.TypeFlags.HasFlag(ContextMenuType.Editable); + + if (isEditing){ model.AddSeparator(); model.AddItem(MenuInputApplyROT13, "Apply ROT13"); } model.AddSeparator(); + + if (!isEditing && TwitterUtils.IsTweetDeckWebsite(frame)){ + model.AddItem(MenuSearchInColumn, "Search in a column"); + } } base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model); @@ -135,6 +143,12 @@ public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser b case MenuInputApplyROT13: form.InvokeAsyncSafe(form.ApplyROT13); return true; + + case MenuSearchInColumn: + string query = parameters.SelectionText; + form.InvokeAsyncSafe(() => form.AddSearchColumn(query)); + DeselectAll(frame); + break; } return false; diff --git a/Core/Other/Settings/Dialogs/DialogSettingsSearchEngine.Designer.cs b/Core/Other/Settings/Dialogs/DialogSettingsSearchEngine.Designer.cs new file mode 100644 index 00000000..aff499c8 --- /dev/null +++ b/Core/Other/Settings/Dialogs/DialogSettingsSearchEngine.Designer.cs @@ -0,0 +1,103 @@ +namespace TweetDuck.Core.Other.Settings.Dialogs { + partial class DialogSettingsSearchEngine { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() { + this.textBoxUrl = new System.Windows.Forms.TextBox(); + this.btnCancel = new System.Windows.Forms.Button(); + this.btnApply = new System.Windows.Forms.Button(); + this.labelInfo = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // textBoxUrl + // + this.textBoxUrl.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.textBoxUrl.Location = new System.Drawing.Point(12, 28); + this.textBoxUrl.Name = "textBoxUrl"; + this.textBoxUrl.Size = new System.Drawing.Size(310, 20); + this.textBoxUrl.TabIndex = 1; + // + // btnCancel + // + this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnCancel.Location = new System.Drawing.Point(204, 56); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.btnCancel.Size = new System.Drawing.Size(56, 23); + this.btnCancel.TabIndex = 3; + this.btnCancel.Text = "Cancel"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // btnApply + // + this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnApply.Location = new System.Drawing.Point(266, 56); + this.btnApply.Name = "btnApply"; + this.btnApply.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.btnApply.Size = new System.Drawing.Size(56, 23); + this.btnApply.TabIndex = 2; + this.btnApply.Text = "Apply"; + this.btnApply.UseVisualStyleBackColor = true; + this.btnApply.Click += new System.EventHandler(this.btnApply_Click); + // + // labelInfo + // + this.labelInfo.AutoSize = true; + this.labelInfo.Location = new System.Drawing.Point(12, 9); + this.labelInfo.Margin = new System.Windows.Forms.Padding(3, 0, 3, 3); + this.labelInfo.Name = "labelInfo"; + this.labelInfo.Size = new System.Drawing.Size(264, 13); + this.labelInfo.TabIndex = 0; + this.labelInfo.Text = "The search query will be added at the end of the URL."; + // + // DialogSettingsSearchEngine + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(334, 91); + this.Controls.Add(this.labelInfo); + this.Controls.Add(this.btnApply); + this.Controls.Add(this.btnCancel); + this.Controls.Add(this.textBoxUrl); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "DialogSettingsSearchEngine"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBoxUrl; + private System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.Button btnApply; + private System.Windows.Forms.Label labelInfo; + } +} \ No newline at end of file diff --git a/Core/Other/Settings/Dialogs/DialogSettingsSearchEngine.cs b/Core/Other/Settings/Dialogs/DialogSettingsSearchEngine.cs new file mode 100644 index 00000000..765a8816 --- /dev/null +++ b/Core/Other/Settings/Dialogs/DialogSettingsSearchEngine.cs @@ -0,0 +1,27 @@ +using System; +using System.Windows.Forms; + +namespace TweetDuck.Core.Other.Settings.Dialogs{ + sealed partial class DialogSettingsSearchEngine : Form{ + public string Url => textBoxUrl.Text; + + public DialogSettingsSearchEngine(){ + InitializeComponent(); + + Text = Program.BrandName+" Options - Custom Search Engine"; + + textBoxUrl.Text = Program.UserConfig.SearchEngineUrl ?? ""; + textBoxUrl.Select(textBoxUrl.Text.Length, 0); + } + + private void btnApply_Click(object sender, EventArgs e){ + DialogResult = DialogResult.OK; + Close(); + } + + private void btnCancel_Click(object sender, EventArgs e){ + DialogResult = DialogResult.Cancel; + Close(); + } + } +} diff --git a/Core/Other/Settings/TabSettingsGeneral.Designer.cs b/Core/Other/Settings/TabSettingsGeneral.Designer.cs index 76b87f91..7aa603d9 100644 --- a/Core/Other/Settings/TabSettingsGeneral.Designer.cs +++ b/Core/Other/Settings/TabSettingsGeneral.Designer.cs @@ -44,6 +44,8 @@ private void InitializeComponent() { this.checkSmoothScrolling = new System.Windows.Forms.CheckBox(); this.labelBrowserPath = new System.Windows.Forms.Label(); this.comboBoxBrowserPath = new System.Windows.Forms.ComboBox(); + this.labelSearchEngine = new System.Windows.Forms.Label(); + this.comboBoxSearchEngine = new System.Windows.Forms.ComboBox(); ((System.ComponentModel.ISupportInitialize)(this.trackBarZoom)).BeginInit(); this.panelZoom.SuspendLayout(); this.flowPanel.SuspendLayout(); @@ -63,21 +65,21 @@ private void InitializeComponent() { // checkUpdateNotifications // this.checkUpdateNotifications.AutoSize = true; - this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 363); + this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 415); this.checkUpdateNotifications.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3); this.checkUpdateNotifications.Name = "checkUpdateNotifications"; this.checkUpdateNotifications.Size = new System.Drawing.Size(165, 17); - this.checkUpdateNotifications.TabIndex = 14; + this.checkUpdateNotifications.TabIndex = 15; this.checkUpdateNotifications.Text = "Check Updates Automatically"; this.checkUpdateNotifications.UseVisualStyleBackColor = true; // // btnCheckUpdates // - this.btnCheckUpdates.Location = new System.Drawing.Point(5, 386); + this.btnCheckUpdates.Location = new System.Drawing.Point(5, 438); this.btnCheckUpdates.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3); this.btnCheckUpdates.Name = "btnCheckUpdates"; this.btnCheckUpdates.Size = new System.Drawing.Size(144, 23); - this.btnCheckUpdates.TabIndex = 15; + this.btnCheckUpdates.TabIndex = 16; this.btnCheckUpdates.Text = "Check Updates Now"; this.btnCheckUpdates.UseVisualStyleBackColor = true; // @@ -99,7 +101,7 @@ private void InitializeComponent() { this.checkBestImageQuality.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3); this.checkBestImageQuality.Name = "checkBestImageQuality"; this.checkBestImageQuality.Size = new System.Drawing.Size(114, 17); - this.checkBestImageQuality.TabIndex = 5; + this.checkBestImageQuality.TabIndex = 4; this.checkBestImageQuality.Text = "Best Image Quality"; this.checkBestImageQuality.UseVisualStyleBackColor = true; // @@ -110,7 +112,7 @@ private void InitializeComponent() { this.checkOpenSearchInFirstColumn.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3); this.checkOpenSearchInFirstColumn.Name = "checkOpenSearchInFirstColumn"; this.checkOpenSearchInFirstColumn.Size = new System.Drawing.Size(219, 17); - this.checkOpenSearchInFirstColumn.TabIndex = 3; + this.checkOpenSearchInFirstColumn.TabIndex = 2; this.checkOpenSearchInFirstColumn.Text = "Add Search Columns Before First Column"; this.checkOpenSearchInFirstColumn.UseVisualStyleBackColor = true; // @@ -132,11 +134,11 @@ private void InitializeComponent() { // labelZoom // this.labelZoom.AutoSize = true; - this.labelZoom.Location = new System.Drawing.Point(3, 268); + this.labelZoom.Location = new System.Drawing.Point(3, 320); this.labelZoom.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0); this.labelZoom.Name = "labelZoom"; this.labelZoom.Size = new System.Drawing.Size(34, 13); - this.labelZoom.TabIndex = 11; + this.labelZoom.TabIndex = 12; this.labelZoom.Text = "Zoom"; // // zoomUpdateTimer @@ -160,11 +162,11 @@ private void InitializeComponent() { this.panelZoom.Anchor = System.Windows.Forms.AnchorStyles.Top; this.panelZoom.Controls.Add(this.trackBarZoom); this.panelZoom.Controls.Add(this.labelZoomValue); - this.panelZoom.Location = new System.Drawing.Point(0, 281); + this.panelZoom.Location = new System.Drawing.Point(0, 333); this.panelZoom.Margin = new System.Windows.Forms.Padding(0); this.panelZoom.Name = "panelZoom"; this.panelZoom.Size = new System.Drawing.Size(322, 36); - this.panelZoom.TabIndex = 12; + this.panelZoom.TabIndex = 13; // // checkAnimatedAvatars // @@ -173,7 +175,7 @@ private void InitializeComponent() { this.checkAnimatedAvatars.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3); this.checkAnimatedAvatars.Name = "checkAnimatedAvatars"; this.checkAnimatedAvatars.Size = new System.Drawing.Size(145, 17); - this.checkAnimatedAvatars.TabIndex = 6; + this.checkAnimatedAvatars.TabIndex = 5; this.checkAnimatedAvatars.Text = "Enable Animated Avatars"; this.checkAnimatedAvatars.UseVisualStyleBackColor = true; // @@ -181,11 +183,11 @@ private void InitializeComponent() { // this.labelUpdates.AutoSize = true; this.labelUpdates.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); - this.labelUpdates.Location = new System.Drawing.Point(0, 337); + this.labelUpdates.Location = new System.Drawing.Point(0, 389); this.labelUpdates.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0); this.labelUpdates.Name = "labelUpdates"; this.labelUpdates.Size = new System.Drawing.Size(70, 20); - this.labelUpdates.TabIndex = 13; + this.labelUpdates.TabIndex = 14; this.labelUpdates.Text = "Updates"; // // flowPanel @@ -203,6 +205,8 @@ private void InitializeComponent() { this.flowPanel.Controls.Add(this.checkSmoothScrolling); this.flowPanel.Controls.Add(this.labelBrowserPath); this.flowPanel.Controls.Add(this.comboBoxBrowserPath); + this.flowPanel.Controls.Add(this.labelSearchEngine); + this.flowPanel.Controls.Add(this.comboBoxSearchEngine); this.flowPanel.Controls.Add(this.labelZoom); this.flowPanel.Controls.Add(this.panelZoom); this.flowPanel.Controls.Add(this.labelUpdates); @@ -211,7 +215,7 @@ private void InitializeComponent() { this.flowPanel.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; this.flowPanel.Location = new System.Drawing.Point(9, 9); this.flowPanel.Name = "flowPanel"; - this.flowPanel.Size = new System.Drawing.Size(322, 415); + this.flowPanel.Size = new System.Drawing.Size(322, 466); this.flowPanel.TabIndex = 0; this.flowPanel.WrapContents = false; // @@ -222,7 +226,7 @@ private void InitializeComponent() { this.checkKeepLikeFollowDialogsOpen.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3); this.checkKeepLikeFollowDialogsOpen.Name = "checkKeepLikeFollowDialogsOpen"; this.checkKeepLikeFollowDialogsOpen.Size = new System.Drawing.Size(176, 17); - this.checkKeepLikeFollowDialogsOpen.TabIndex = 4; + this.checkKeepLikeFollowDialogsOpen.TabIndex = 3; this.checkKeepLikeFollowDialogsOpen.Text = "Keep Like/Follow Dialogs Open"; this.checkKeepLikeFollowDialogsOpen.UseVisualStyleBackColor = true; // @@ -234,7 +238,7 @@ private void InitializeComponent() { this.labelBrowserSettings.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0); this.labelBrowserSettings.Name = "labelBrowserSettings"; this.labelBrowserSettings.Size = new System.Drawing.Size(130, 20); - this.labelBrowserSettings.TabIndex = 7; + this.labelBrowserSettings.TabIndex = 6; this.labelBrowserSettings.Text = "Browser Settings"; // // checkSmoothScrolling @@ -244,7 +248,7 @@ private void InitializeComponent() { this.checkSmoothScrolling.Margin = new System.Windows.Forms.Padding(6, 6, 3, 3); this.checkSmoothScrolling.Name = "checkSmoothScrolling"; this.checkSmoothScrolling.Size = new System.Drawing.Size(105, 17); - this.checkSmoothScrolling.TabIndex = 8; + this.checkSmoothScrolling.TabIndex = 7; this.checkSmoothScrolling.Text = "Smooth Scrolling"; this.checkSmoothScrolling.UseVisualStyleBackColor = true; // @@ -255,7 +259,7 @@ private void InitializeComponent() { this.labelBrowserPath.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0); this.labelBrowserPath.Name = "labelBrowserPath"; this.labelBrowserPath.Size = new System.Drawing.Size(95, 13); - this.labelBrowserPath.TabIndex = 9; + this.labelBrowserPath.TabIndex = 8; this.labelBrowserPath.Text = "Open Links With..."; // // comboBoxBrowserPath @@ -266,7 +270,27 @@ private void InitializeComponent() { this.comboBoxBrowserPath.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3); this.comboBoxBrowserPath.Name = "comboBoxBrowserPath"; this.comboBoxBrowserPath.Size = new System.Drawing.Size(173, 21); - this.comboBoxBrowserPath.TabIndex = 10; + this.comboBoxBrowserPath.TabIndex = 9; + // + // labelSearchEngine + // + this.labelSearchEngine.AutoSize = true; + this.labelSearchEngine.Location = new System.Drawing.Point(3, 268); + this.labelSearchEngine.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0); + this.labelSearchEngine.Name = "labelSearchEngine"; + this.labelSearchEngine.Size = new System.Drawing.Size(77, 13); + this.labelSearchEngine.TabIndex = 10; + this.labelSearchEngine.Text = "Search Engine"; + // + // comboBoxSearchEngine + // + this.comboBoxSearchEngine.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxSearchEngine.FormattingEnabled = true; + this.comboBoxSearchEngine.Location = new System.Drawing.Point(5, 284); + this.comboBoxSearchEngine.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3); + this.comboBoxSearchEngine.Name = "comboBoxSearchEngine"; + this.comboBoxSearchEngine.Size = new System.Drawing.Size(173, 21); + this.comboBoxSearchEngine.TabIndex = 11; // // TabSettingsGeneral // @@ -274,7 +298,7 @@ private void InitializeComponent() { this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.flowPanel); this.Name = "TabSettingsGeneral"; - this.Size = new System.Drawing.Size(340, 433); + this.Size = new System.Drawing.Size(340, 484); ((System.ComponentModel.ISupportInitialize)(this.trackBarZoom)).EndInit(); this.panelZoom.ResumeLayout(false); this.flowPanel.ResumeLayout(false); @@ -305,5 +329,7 @@ private void InitializeComponent() { private System.Windows.Forms.ComboBox comboBoxBrowserPath; private System.Windows.Forms.Label labelBrowserSettings; private System.Windows.Forms.CheckBox checkSmoothScrolling; + private System.Windows.Forms.Label labelSearchEngine; + private System.Windows.Forms.ComboBox comboBoxSearchEngine; } } diff --git a/Core/Other/Settings/TabSettingsGeneral.cs b/Core/Other/Settings/TabSettingsGeneral.cs index 7024e23c..aeb9281a 100644 --- a/Core/Other/Settings/TabSettingsGeneral.cs +++ b/Core/Other/Settings/TabSettingsGeneral.cs @@ -4,6 +4,7 @@ using System.Windows.Forms; using TweetDuck.Core.Controls; using TweetDuck.Core.Handling.General; +using TweetDuck.Core.Other.Settings.Dialogs; using TweetDuck.Core.Utils; using TweetDuck.Updates; @@ -17,6 +18,9 @@ sealed partial class TabSettingsGeneral : BaseTabSettings{ private readonly int browserListIndexDefault; private readonly int browserListIndexCustom; + private readonly int searchEngineIndexDefault; + private readonly int searchEngineIndexCustom; + public TabSettingsGeneral(Action reloadColumns, UpdateHandler updates){ InitializeComponent(); @@ -56,6 +60,14 @@ public TabSettingsGeneral(Action reloadColumns, UpdateHandler updates){ browserListIndexCustom = comboBoxBrowserPath.Items.Add("(custom program...)"); UpdateBrowserPathSelection(); + comboBoxSearchEngine.Items.Add(new SearchEngine("DuckDuckGo", "https://duckduckgo.com/?q=")); + comboBoxSearchEngine.Items.Add(new SearchEngine("Google", "https://www.google.com/search?q=")); + comboBoxSearchEngine.Items.Add(new SearchEngine("Bing", "https://www.bing.com/search?q=")); + comboBoxSearchEngine.Items.Add(new SearchEngine("Yahoo", "https://search.yahoo.com/search?p=")); + searchEngineIndexDefault = comboBoxSearchEngine.Items.Add("(no engine set)"); + searchEngineIndexCustom = comboBoxSearchEngine.Items.Add("(custom url...)"); + UpdateSearchEngineSelection(); + trackBarZoom.SetValueSafe(Config.ZoomLevel); labelZoomValue.Text = trackBarZoom.Value+"%"; @@ -71,6 +83,7 @@ public override void OnReady(){ checkSmoothScrolling.CheckedChanged += checkSmoothScrolling_CheckedChanged; comboBoxBrowserPath.SelectedIndexChanged += comboBoxBrowserPath_SelectedIndexChanged; + comboBoxSearchEngine.SelectedIndexChanged += comboBoxSearchEngine_SelectedIndexChanged; trackBarZoom.ValueChanged += trackBarZoom_ValueChanged; checkUpdateNotifications.CheckedChanged += checkUpdateNotifications_CheckedChanged; @@ -146,6 +159,39 @@ private void comboBoxBrowserPath_SelectedIndexChanged(object sender, EventArgs e } } + private void comboBoxSearchEngine_SelectedIndexChanged(object sender, EventArgs e){ + if (comboBoxSearchEngine.SelectedIndex == searchEngineIndexCustom){ + using(DialogSettingsSearchEngine dialog = new DialogSettingsSearchEngine()){ + if (dialog.ShowDialog() == DialogResult.OK){ + Config.SearchEngineUrl = dialog.Url.Trim(); + } + } + + comboBoxSearchEngine.SelectedIndexChanged -= comboBoxSearchEngine_SelectedIndexChanged; + UpdateSearchEngineSelection(); + comboBoxSearchEngine.SelectedIndexChanged += comboBoxSearchEngine_SelectedIndexChanged; + } + else{ + Config.SearchEngineUrl = (comboBoxSearchEngine.SelectedItem as SearchEngine)?.Url; // default search engine item is a string and casts to null + } + } + + private void UpdateSearchEngineSelection(){ + if (string.IsNullOrEmpty(Config.SearchEngineUrl)){ + comboBoxSearchEngine.SelectedIndex = searchEngineIndexDefault; + } + else{ + SearchEngine engineInfo = comboBoxSearchEngine.Items.OfType<SearchEngine>().FirstOrDefault(engine => engine.Url == Config.SearchEngineUrl); + + if (engineInfo == null){ + comboBoxSearchEngine.SelectedIndex = searchEngineIndexCustom; + } + else{ + comboBoxSearchEngine.SelectedItem = engineInfo; + } + } + } + private void trackBarZoom_ValueChanged(object sender, EventArgs e){ if (trackBarZoom.AlignValueToTick()){ zoomUpdateTimer.Stop(); @@ -186,5 +232,19 @@ private void zoomUpdateTimer_Tick(object sender, EventArgs e){ Config.ZoomLevel = trackBarZoom.Value; zoomUpdateTimer.Stop(); } + + private sealed class SearchEngine{ + private string Name { get; } + public string Url { get; } + + public SearchEngine(string name, string url){ + Name = name; + Url = url; + } + + public override int GetHashCode() => Name.GetHashCode(); + public override bool Equals(object obj) => obj is SearchEngine other && Name == other.Name; + public override string ToString() => Name; + } } } diff --git a/Core/TweetDeckBrowser.cs b/Core/TweetDeckBrowser.cs index 26c42b54..20170168 100644 --- a/Core/TweetDeckBrowser.cs +++ b/Core/TweetDeckBrowser.cs @@ -227,6 +227,10 @@ public void ShowTweetDetail(string columnId, string chirpId, string fallbackUrl) browser.ExecuteScriptAsync("TDGF_showTweetDetail", columnId, chirpId, fallbackUrl); } + public void AddSearchColumn(string query){ + browser.ExecuteScriptAsync("TDGF_performSearch", query); + } + public void TriggerTweetScreenshot(){ browser.ExecuteScriptAsync("TDGF_triggerScreenshot()"); } diff --git a/Core/Utils/BrowserUtils.cs b/Core/Utils/BrowserUtils.cs index 17b95fb1..a352aaf2 100644 --- a/Core/Utils/BrowserUtils.cs +++ b/Core/Utils/BrowserUtils.cs @@ -127,6 +127,33 @@ public static void OpenExternalBrowser(string url){ } } + public static void OpenExternalSearch(string query){ + if (string.IsNullOrWhiteSpace(query))return; + + string searchUrl = Program.UserConfig.SearchEngineUrl; + + if (string.IsNullOrEmpty(searchUrl)){ + if (FormMessage.Question("Search Options", "You have not configured a default search engine yet, would you like to do it now?", FormMessage.Yes, FormMessage.No)){ + bool wereSettingsOpen = FormManager.TryFind<FormSettings>() != null; + + FormManager.TryFind<FormBrowser>()?.OpenSettings(); + if (wereSettingsOpen)return; + + FormSettings settings = FormManager.TryFind<FormSettings>(); + if (settings == null)return; + + settings.FormClosed += (sender, args) => { + if (args.CloseReason == CloseReason.UserClosing && Program.UserConfig.SearchEngineUrl != searchUrl){ + OpenExternalSearch(query); + } + }; + } + } + else{ + OpenExternalBrowser(searchUrl+Uri.EscapeUriString(query)); + } + } + public static string GetFileNameFromUrl(string url){ string file = Path.GetFileName(new Uri(url).AbsolutePath); return string.IsNullOrEmpty(file) ? null : file; diff --git a/Resources/Scripts/code.js b/Resources/Scripts/code.js index bfbe685b..9b809acc 100644 --- a/Resources/Scripts/code.js +++ b/Resources/Scripts/code.js @@ -1144,11 +1144,24 @@ } } - $(".js-app-search-input").val(""); - $(".js-perform-search").blur(); + if (!("tweetduck" in data)){ + $(".js-app-search-input").val(""); + $(".js-perform-search").blur(); + } } }); + // + // Block: Setup global function to add a search column with the specified query. + // + onAppReady.push(function(){ + let context = $._data(document, "events")["uiSearchInputSubmit"][0].handler.context; + + window.TDGF_performSearch = function(query){ + context.performSearch({ query, tweetduck: true }); + }; + }); + // // Block: Reorder search results to move accounts above hashtags. // diff --git a/TweetDuck.csproj b/TweetDuck.csproj index 82637d7b..6dda928c 100644 --- a/TweetDuck.csproj +++ b/TweetDuck.csproj @@ -170,6 +170,12 @@ <Compile Include="Core\Other\Settings\Dialogs\DialogSettingsAnalytics.Designer.cs"> <DependentUpon>DialogSettingsAnalytics.cs</DependentUpon> </Compile> + <Compile Include="Core\Other\Settings\Dialogs\DialogSettingsSearchEngine.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Core\Other\Settings\Dialogs\DialogSettingsSearchEngine.Designer.cs"> + <DependentUpon>DialogSettingsSearchEngine.cs</DependentUpon> + </Compile> <Compile Include="Core\Other\Settings\Dialogs\DialogSettingsCSS.cs"> <SubType>Form</SubType> </Compile>