From 5f2aeb78bffab698f5dfad8aed6fe9aba002ee31 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 14 Sep 2024 23:03:06 +0100 Subject: [PATCH 1/3] Changed to improve favicon detection --- BookmarkManager.csproj | 2 +- EditBookmarkForm.cs | 3 +- Services/WebProvider.cs | 216 ++++++++++++++++++++++++++++++++-------- UpdateIconsForm.cs | 2 +- build-installer.iss | 2 +- 5 files changed, 177 insertions(+), 48 deletions(-) diff --git a/BookmarkManager.csproj b/BookmarkManager.csproj index 5cefae5..f7a4438 100644 --- a/BookmarkManager.csproj +++ b/BookmarkManager.csproj @@ -14,7 +14,7 @@ Ray Lam 1.0.0.0 1.0.0.0 - 0.6.1.0249 + 0.6.2.092 bukkubuddy True 8.0 diff --git a/EditBookmarkForm.cs b/EditBookmarkForm.cs index 08d53f3..19b1e89 100644 --- a/EditBookmarkForm.cs +++ b/EditBookmarkForm.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Drawing; using System.Threading.Tasks; using System.Windows.Forms; +using System.Xml; using BookmarkManager.Services; using bzit.bomg.Models; using RyzStudio.Windows.Forms; @@ -414,7 +415,7 @@ namespace FizzyLauncher { try { - pictureBox1.Image = await _webProvider.RetrieveImage(document); + pictureBox1.Image = await _webProvider.RetrieveImage(url, document); if (pictureBox1.Image != null) { if (pictureBox1.Image.Width > 16) diff --git a/Services/WebProvider.cs b/Services/WebProvider.cs index c592dd3..602364d 100644 --- a/Services/WebProvider.cs +++ b/Services/WebProvider.cs @@ -1,6 +1,9 @@ using System; +using System.Collections.Generic; using System.Drawing; +using System.Linq; using System.Net; +using System.Security.Policy; using System.Threading.Tasks; using HtmlAgilityPack; using RyzStudio.Net; @@ -148,7 +151,7 @@ namespace BookmarkManager.Services return result; } - public async Task RetrieveImage(HtmlAgilityPack.HtmlDocument document) + public async Task RetrieveImage(string url, HtmlAgilityPack.HtmlDocument document) { var iconUrl = this.ParseFavicon(document); if (string.IsNullOrWhiteSpace(iconUrl)) @@ -156,6 +159,18 @@ namespace BookmarkManager.Services return null; } + try + { + var baseUri = new Uri(url); + var absoluteUri = new Uri(baseUri, iconUrl); + + iconUrl = absoluteUri.AbsoluteUri; + } + catch + { + return null; + } + return await this.RetrieveImage(iconUrl); } @@ -169,25 +184,25 @@ namespace BookmarkManager.Services return result; } - result = ParseTagValue_Attr(document, "//meta[@property='og:title']", "content", string.Empty)?.Trim(); + result = FindNodeAttrValue(document, "//meta[@property='og:title']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; } - result = ParseTagValue_Attr(document, "//meta[@name='twitter:title']", "content", string.Empty)?.Trim(); + result = FindNodeAttrValue(document, "//meta[@name='twitter:title']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; } - result = ParseTagValue_Attr(document, "//meta[@property='og:site_name']", "content", string.Empty)?.Trim(); + result = FindNodeAttrValue(document, "//meta[@property='og:site_name']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; } - result = ParseTagValue_Attr(document, "//meta[@itemprop='name']", "content", string.Empty)?.Trim(); + result = FindNodeAttrValue(document, "//meta[@itemprop='name']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; @@ -200,31 +215,31 @@ namespace BookmarkManager.Services { string result = null; - result = ParseTagValue_Attr(document, "//meta[@name='description']", "content", string.Empty)?.Trim(); + result = FindNodeAttrValue(document, "//meta[@name='description']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; } - result = ParseTagValue_Attr(document, "//meta[@property='og:description']", "content", string.Empty)?.Trim(); + result = FindNodeAttrValue(document, "//meta[@property='og:description']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; } - result = ParseTagValue_Attr(document, "//meta[@name='twitter:description']", "content", string.Empty)?.Trim(); + result = FindNodeAttrValue(document, "//meta[@name='twitter:description']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; } - result = ParseTagValue_Attr(document, "//meta[@property='og:description']", "content", string.Empty)?.Trim(); + result = FindNodeAttrValue(document, "//meta[@property='og:description']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; } - result = ParseTagValue_Attr(document, "//meta[@itemprop='description']", "content", string.Empty)?.Trim(); + result = FindNodeAttrValue(document, "//meta[@itemprop='description']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; @@ -237,49 +252,85 @@ namespace BookmarkManager.Services { string result = null; - result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'shortcut icon']", "href", string.Empty)?.Trim(); + //var tt1 = FindNode_AtrributeContains(document, "//link[contains(@rel, 'icon')]", "href", string.Empty); + //var tt1 = FindNode_AtrributeContains(document, "link", "rel", "icon"); + + // Find link-rel contains "icon" + var linkNodes = FindNode(document, "link", "rel"); + foreach (var item in linkNodes) + { + var relValue = item.Attributes["rel"].Value?.Trim() ?? string.Empty; + if (!ContainsWord(relValue, "icon")) + { + continue; + } + + var hrefValue = item.Attributes["href"].Value?.Trim() ?? string.Empty; + if (string.IsNullOrWhiteSpace(hrefValue)) + { + continue; + } + + return System.Web.HttpUtility.HtmlDecode(hrefValue); + } + + // Find link-rel contains apple-icon + var appleIconPatterns = new List() { "apple-touch-icon", "apple-touch-icon-precomposed" }; + + foreach (var item in linkNodes) + { + var relValue = item.Attributes["rel"].Value?.Trim() ?? string.Empty; + if (!appleIconPatterns.Contains(relValue?.ToLower() ?? string.Empty)) + { + continue; + } + + var hrefValue = item.Attributes["href"].Value?.Trim() ?? string.Empty; + if (string.IsNullOrWhiteSpace(hrefValue)) + { + continue; + } + + return System.Web.HttpUtility.HtmlDecode(hrefValue); + } + + //result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'shortcut icon']", "href", string.Empty)?.Trim(); + //if (!string.IsNullOrWhiteSpace(result)) + //{ + // return result; + //} + + //result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'icon']", "href", string.Empty)?.Trim(); + //if (!string.IsNullOrWhiteSpace(result)) + //{ + // return result; + //} + + //result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'apple-touch-icon']", "href", string.Empty)?.Trim(); + //if (!string.IsNullOrWhiteSpace(result)) + //{ + // return result; + //} + + //result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'apple-touch-icon-precomposed']", "href", string.Empty)?.Trim(); + //if (!string.IsNullOrWhiteSpace(result)) + //{ + // return result; + //} + + result = FindNodeAttrValue(document, "//meta[@property='og:image']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; } - result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'icon']", "href", string.Empty)?.Trim(); + result = FindNodeAttrValue(document, "//meta[@name='twitter:image']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; } - result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'apple-touch-icon']", "href", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'apple-touch-icon-precomposed']", "href", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - result = ParseTagValue_Attr(document, "//meta[translate(@property, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'og:image']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - result = ParseTagValue_Attr(document, "//meta[translate(@name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'twitter:image']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - result = ParseTagValue_Attr(document, "//meta[translate(@property, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'og:image']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - result = ParseTagValue_Attr(document, "//meta[translate(@itemprop, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'image']", "content", string.Empty)?.Trim(); + result = FindNodeAttrValue(document, "//meta[@itemprop='image']", "content", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; @@ -320,7 +371,7 @@ namespace BookmarkManager.Services return defaultValue; } - private string ParseTagValue_Attr(HtmlAgilityPack.HtmlDocument document, string xPath, string attr, string defaultValue = "") + private string FindNodeAttrValue(HtmlAgilityPack.HtmlDocument document, string xPath, string attr, string defaultValue = "") { var hnc = document.DocumentNode.SelectNodes(xPath); if (hnc == null) @@ -351,5 +402,82 @@ namespace BookmarkManager.Services return defaultValue; } + //private List FindNode_AtrributeContains(HtmlAgilityPack.HtmlDocument document, string nodeName, string attrName, string findValue) + //{ + // var response = new List(); + + // var xPath = $"//{nodeName}[@{attrName}]"; + // var hnc = document.DocumentNode.SelectNodes(xPath); + // if (hnc == null) + // { + // return response; + // } + + // if (hnc.Count <= 0) + // { + // return response; + // } + + // foreach (HtmlNode item in hnc) + // { + // if (!item.Attributes.Contains(attrName)) + // { + // continue; + // } + + // if (!ContainsWord(item.Attributes[attrName].Value ?? string.Empty, findValue)) + // { + // continue; + // } + + // response.Add(item); + // } + + // return response; + //} + + private List FindNode(HtmlAgilityPack.HtmlDocument document, string nodeName, string attrName) + { + var xPath = (string.IsNullOrWhiteSpace(attrName) ? $"//{nodeName}" : $"//{nodeName}[@{attrName}]"); + var hnc = document.DocumentNode.SelectNodes(xPath); + if (hnc == null) + { + return new List(); + } + + if (hnc.Count <= 0) + { + return new List(); + } + + return hnc.ToList(); + } + + private bool ContainsWord(string haystack, string needle) + { + haystack = haystack?.Trim() ?? string.Empty; + + if (!haystack.Contains(" ")) + { + return haystack.Equals(needle, StringComparison.CurrentCultureIgnoreCase); + } + + foreach (var item in haystack.Split(" ")) + { + if (string.IsNullOrWhiteSpace(item)) + { + continue; + } + + if (item.Equals(needle, StringComparison.CurrentCultureIgnoreCase)) + { + return true; + } + } + + return false; + } + + } } \ No newline at end of file diff --git a/UpdateIconsForm.cs b/UpdateIconsForm.cs index 91477cc..db85498 100644 --- a/UpdateIconsForm.cs +++ b/UpdateIconsForm.cs @@ -360,7 +360,7 @@ namespace FizzyLauncher try { - var image = await _webProvider.RetrieveImage(document); + var image = await _webProvider.RetrieveImage(item.Value.Address, document); if (image != null) { if (image.Width > 16) diff --git a/build-installer.iss b/build-installer.iss index ce48110..341125e 100644 --- a/build-installer.iss +++ b/build-installer.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "BukkuBuddy Bookmark Manager" -#define MyAppVersion "0.6.0.716" +#define MyAppVersion "0.6.2.092" #define MyAppPublisher "Hi, I'm Ray" #define MyAppURL "https://www.hiimray.co.uk/software-bookmark-manager" #define MyAppExeName "bukkubuddy.exe" -- 2.45.2 From b4f236266a79c667d143e57e10736d508d68e347 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 15 Sep 2024 12:48:31 +0100 Subject: [PATCH 2/3] Refactored WebProvider for clarity --- EditBookmarkForm.cs | 2 +- Services/WebProvider.cs | 260 ++++++++++++++++------------------------ 2 files changed, 103 insertions(+), 159 deletions(-) diff --git a/EditBookmarkForm.cs b/EditBookmarkForm.cs index 19b1e89..9cc8365 100644 --- a/EditBookmarkForm.cs +++ b/EditBookmarkForm.cs @@ -408,7 +408,7 @@ namespace FizzyLauncher if (updateDescription) { - textBox3.Text = _webProvider.ParseMetaDescription(document); + textBox3.Text = _webProvider.ParseDescription(document); } if (updateIcon) diff --git a/Services/WebProvider.cs b/Services/WebProvider.cs index 602364d..710c0dc 100644 --- a/Services/WebProvider.cs +++ b/Services/WebProvider.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Net; -using System.Security.Policy; using System.Threading.Tasks; using HtmlAgilityPack; using RyzStudio.Net; @@ -178,168 +177,102 @@ namespace BookmarkManager.Services { string result = null; - result = ParseTagValue(document, "//title", string.Empty)?.Trim(); + // Find basic title + result = FindNodeValue(document, "//title", string.Empty)?.Trim(); if (!string.IsNullOrWhiteSpace(result)) { return result; } - result = FindNodeAttrValue(document, "//meta[@property='og:title']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) + // Find title from extended meta + var patternList = new List() { - return result; - } + "//meta[@property='og:title']", + "//meta[@property='og:site_name']", + "//meta[@name='twitter:title']", + "//meta[@itemprop='name']" + }; - result = FindNodeAttrValue(document, "//meta[@name='twitter:title']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) + foreach (var item in patternList) { - return result; - } + result = FindNodeAttrValue(document, item, "content", string.Empty)?.Trim(); + if (string.IsNullOrWhiteSpace(result)) + { + continue; + } - result = FindNodeAttrValue(document, "//meta[@property='og:site_name']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - result = FindNodeAttrValue(document, "//meta[@itemprop='name']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { return result; } return string.Empty; } - public string ParseMetaDescription(HtmlAgilityPack.HtmlDocument document) + public string ParseDescription(HtmlAgilityPack.HtmlDocument document) { - string result = null; - - result = FindNodeAttrValue(document, "//meta[@name='description']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) + var patternList = new List() { + "//meta[@name='description']", + "//meta[@property='og:description']", + "//meta[@name='twitter:description']", + "//meta[@itemprop='description']", + }; + + foreach (var item in patternList) + { + var result = FindNodeAttrValue(document, item, "content", string.Empty)?.Trim(); + if (string.IsNullOrWhiteSpace(result)) + { + continue; + } + return result; } - result = FindNodeAttrValue(document, "//meta[@property='og:description']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - result = FindNodeAttrValue(document, "//meta[@name='twitter:description']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - result = FindNodeAttrValue(document, "//meta[@property='og:description']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - result = FindNodeAttrValue(document, "//meta[@itemprop='description']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - return result; + return string.Empty; } public string ParseFavicon(HtmlAgilityPack.HtmlDocument document) { string result = null; - //var tt1 = FindNode_AtrributeContains(document, "//link[contains(@rel, 'icon')]", "href", string.Empty); - //var tt1 = FindNode_AtrributeContains(document, "link", "rel", "icon"); - - // Find link-rel contains "icon" - var linkNodes = FindNode(document, "link", "rel"); - foreach (var item in linkNodes) + // Find link-rel that contains word + result = FindNodeAttrValue_ContainsWord(document, "link", "rel", "href", "icon"); + if (!string.IsNullOrWhiteSpace(result)) { - var relValue = item.Attributes["rel"].Value?.Trim() ?? string.Empty; - if (!ContainsWord(relValue, "icon")) - { - continue; - } - - var hrefValue = item.Attributes["href"].Value?.Trim() ?? string.Empty; - if (string.IsNullOrWhiteSpace(hrefValue)) - { - continue; - } - - return System.Web.HttpUtility.HtmlDecode(hrefValue); + return result; } // Find link-rel contains apple-icon - var appleIconPatterns = new List() { "apple-touch-icon", "apple-touch-icon-precomposed" }; - - foreach (var item in linkNodes) + var matchPatterns = new List() { "apple-touch-icon", "apple-touch-icon-precomposed" }; + result = FindNodeAttrValue_Equals(document, "link", "rel", "href", matchPatterns); + if (!string.IsNullOrWhiteSpace(result)) { - var relValue = item.Attributes["rel"].Value?.Trim() ?? string.Empty; - if (!appleIconPatterns.Contains(relValue?.ToLower() ?? string.Empty)) + return result; + } + + // Find favicon from extended meta + var patternList = new List() + { + "//meta[@property='og:image']", + "//meta[@name='twitter:image']", + "//meta[@itemprop='image']" + }; + + foreach (var item in patternList) + { + result = FindNodeAttrValue(document, item, "content", string.Empty)?.Trim(); + if (string.IsNullOrWhiteSpace(result)) { continue; } - var hrefValue = item.Attributes["href"].Value?.Trim() ?? string.Empty; - if (string.IsNullOrWhiteSpace(hrefValue)) - { - continue; - } - - return System.Web.HttpUtility.HtmlDecode(hrefValue); - } - - //result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'shortcut icon']", "href", string.Empty)?.Trim(); - //if (!string.IsNullOrWhiteSpace(result)) - //{ - // return result; - //} - - //result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'icon']", "href", string.Empty)?.Trim(); - //if (!string.IsNullOrWhiteSpace(result)) - //{ - // return result; - //} - - //result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'apple-touch-icon']", "href", string.Empty)?.Trim(); - //if (!string.IsNullOrWhiteSpace(result)) - //{ - // return result; - //} - - //result = ParseTagValue_Attr(document, "//link[translate(@rel, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'apple-touch-icon-precomposed']", "href", string.Empty)?.Trim(); - //if (!string.IsNullOrWhiteSpace(result)) - //{ - // return result; - //} - - result = FindNodeAttrValue(document, "//meta[@property='og:image']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { return result; } - result = FindNodeAttrValue(document, "//meta[@name='twitter:image']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - result = FindNodeAttrValue(document, "//meta[@itemprop='image']", "content", string.Empty)?.Trim(); - if (!string.IsNullOrWhiteSpace(result)) - { - return result; - } - - return "/favicon.ico"; + return string.Empty; } - private string ParseTagValue(HtmlAgilityPack.HtmlDocument document, string xPath, string defaultValue = "") + private string FindNodeValue(HtmlAgilityPack.HtmlDocument document, string xPath, string defaultValue = "") { var hnc = document.DocumentNode.SelectNodes(xPath); if (hnc == null) @@ -402,40 +335,6 @@ namespace BookmarkManager.Services return defaultValue; } - //private List FindNode_AtrributeContains(HtmlAgilityPack.HtmlDocument document, string nodeName, string attrName, string findValue) - //{ - // var response = new List(); - - // var xPath = $"//{nodeName}[@{attrName}]"; - // var hnc = document.DocumentNode.SelectNodes(xPath); - // if (hnc == null) - // { - // return response; - // } - - // if (hnc.Count <= 0) - // { - // return response; - // } - - // foreach (HtmlNode item in hnc) - // { - // if (!item.Attributes.Contains(attrName)) - // { - // continue; - // } - - // if (!ContainsWord(item.Attributes[attrName].Value ?? string.Empty, findValue)) - // { - // continue; - // } - - // response.Add(item); - // } - - // return response; - //} - private List FindNode(HtmlAgilityPack.HtmlDocument document, string nodeName, string attrName) { var xPath = (string.IsNullOrWhiteSpace(attrName) ? $"//{nodeName}" : $"//{nodeName}[@{attrName}]"); @@ -453,6 +352,52 @@ namespace BookmarkManager.Services return hnc.ToList(); } + private string FindNodeAttrValue_ContainsWord(HtmlAgilityPack.HtmlDocument document, string nodeName, string attrName, string returnAttrName, string matchEqualList, string defaultValue = "") + { + var linkNodes = FindNode(document, nodeName, attrName); + foreach (var item in linkNodes) + { + var relValue = item.Attributes[attrName].Value?.Trim() ?? string.Empty; + if (!ContainsWord(relValue, matchEqualList)) + { + continue; + } + + var hrefValue = item.Attributes[returnAttrName].Value?.Trim() ?? string.Empty; + if (string.IsNullOrWhiteSpace(hrefValue)) + { + continue; + } + + return System.Web.HttpUtility.HtmlDecode(hrefValue); + } + + return defaultValue; + } + + private string FindNodeAttrValue_Equals(HtmlAgilityPack.HtmlDocument document, string nodeName, string attrName, string returnAttrName, List matchValueList, string defaultValue = "") + { + var linkNodes = FindNode(document, nodeName, attrName); + foreach (var item in linkNodes) + { + var relValue = item.Attributes[attrName].Value?.Trim() ?? string.Empty; + if (!matchValueList.Contains(relValue?.ToLower() ?? string.Empty)) + { + continue; + } + + var hrefValue = item.Attributes[returnAttrName].Value?.Trim() ?? string.Empty; + if (string.IsNullOrWhiteSpace(hrefValue)) + { + continue; + } + + return System.Web.HttpUtility.HtmlDecode(hrefValue); + } + + return defaultValue; + } + private bool ContainsWord(string haystack, string needle) { haystack = haystack?.Trim() ?? string.Empty; @@ -478,6 +423,5 @@ namespace BookmarkManager.Services return false; } - } } \ No newline at end of file -- 2.45.2 From f769de084e2f2cad279e4983164aa9e65cdf23e5 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 15 Sep 2024 15:50:53 +0100 Subject: [PATCH 3/3] Added function to add page in batch --- AddBatchPageForm.cs | 312 +++++++++++++++++++++++++++++++++++++++++ AddBatchPageForm.resx | 120 ++++++++++++++++ BookmarkManager.csproj | 3 + MainForm.Designer.cs | 82 ++++++----- MainForm.cs | 40 ++++++ MainForm.resx | 4 +- 6 files changed, 527 insertions(+), 34 deletions(-) create mode 100644 AddBatchPageForm.cs create mode 100644 AddBatchPageForm.resx diff --git a/AddBatchPageForm.cs b/AddBatchPageForm.cs new file mode 100644 index 0000000..84d7ac9 --- /dev/null +++ b/AddBatchPageForm.cs @@ -0,0 +1,312 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Threading.Tasks; +using System.Windows.Forms; +using BookmarkManager.Services; +using bzit.bomg.Models; +using RyzStudio.Windows.Forms; +using RyzStudio.Windows.ThemedForms; + +namespace FizzyLauncher +{ + public class AddBatchPageForm : Form + { + private System.Windows.Forms.Label label1; + + + private readonly WebProvider _webProvider; + private string _rootPath; + private bool _isBusy = false; + private THorizontalSeparator tHorizontalSeparator3; + private ThButton button3; + private ThProgressBar progressBar2; + private RyzStudio.Windows.ThemedForms.Composite.DialogFooter dialogFooter1; + private ThToolbarMemoBox memoBox1; + private List _result = new List(); + private bool _requestCancel = false; + + + public AddBatchPageForm(string rootPath) + { + InitializeComponent(); + + UISetup.Dialog(this); + + _result = new List(); + + _webProvider = new WebProvider(); + _webProvider.IgnoreSSL = true; + + _rootPath = rootPath; + } + + private void InitializeComponent() + { + label1 = new Label(); + tHorizontalSeparator3 = new THorizontalSeparator(); + button3 = new ThButton(); + progressBar2 = new ThProgressBar(); + dialogFooter1 = new RyzStudio.Windows.ThemedForms.Composite.DialogFooter(); + memoBox1 = new ThToolbarMemoBox(); + SuspendLayout(); + // + // label1 + // + label1.AutoSize = true; + label1.BackColor = System.Drawing.Color.Transparent; + label1.ForeColor = System.Drawing.SystemColors.ControlText; + label1.Location = new System.Drawing.Point(10, 20); + label1.Margin = new Padding(0); + label1.Name = "label1"; + label1.Padding = new Padding(0, 8, 0, 0); + label1.Size = new System.Drawing.Size(185, 23); + label1.TabIndex = 153; + label1.Text = "Add pages (one URL on each line)"; + label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // tHorizontalSeparator3 + // + tHorizontalSeparator3.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + tHorizontalSeparator3.AutoScrollMargin = new System.Drawing.Size(0, 0); + tHorizontalSeparator3.AutoScrollMinSize = new System.Drawing.Size(0, 0); + tHorizontalSeparator3.BackColor = System.Drawing.Color.Transparent; + tHorizontalSeparator3.Location = new System.Drawing.Point(10, 321); + tHorizontalSeparator3.Margin = new Padding(0, 10, 0, 0); + tHorizontalSeparator3.MaximumSize = new System.Drawing.Size(4920, 2); + tHorizontalSeparator3.MinimumSize = new System.Drawing.Size(0, 22); + tHorizontalSeparator3.Name = "tHorizontalSeparator3"; + tHorizontalSeparator3.Size = new System.Drawing.Size(424, 22); + tHorizontalSeparator3.TabIndex = 207; + tHorizontalSeparator3.TabStop = false; + // + // button3 + // + button3.ActiveImage = null; + button3.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; + button3.BackColor = System.Drawing.Color.Transparent; + button3.EnableMenuOnClick = false; + button3.EnableReactiveVisual = true; + button3.HoverImage = null; + button3.IdleImage = null; + button3.LabelText = "&Add Pages"; + button3.Location = new System.Drawing.Point(306, 393); + button3.Name = "button3"; + button3.Size = new System.Drawing.Size(128, 32); + button3.TabIndex = 209; + button3.TabStop = false; + button3.MouseClick += button3_MouseClick; + // + // progressBar2 + // + progressBar2.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + progressBar2.BackColor = System.Drawing.Color.Transparent; + progressBar2.BarColour = System.Drawing.Color.FromArgb(79, 193, 203); + progressBar2.BarTextColour = System.Drawing.Color.Black; + progressBar2.EnableReactiveVisual = false; + progressBar2.Font = new System.Drawing.Font("Segoe UI", 9F); + progressBar2.Location = new System.Drawing.Point(10, 353); + progressBar2.Maximum = 100; + progressBar2.Minimum = 0; + progressBar2.Name = "progressBar2"; + progressBar2.ProgressText = "50/100"; + progressBar2.ShowProgressText = true; + progressBar2.Size = new System.Drawing.Size(424, 20); + progressBar2.TabIndex = 210; + progressBar2.TabStop = false; + progressBar2.Value = 50; + // + // dialogFooter1 + // + dialogFooter1.BackColor = System.Drawing.Color.FromArgb(240, 240, 240); + dialogFooter1.Button1Text = "&Close"; + dialogFooter1.Dialog = this; + dialogFooter1.Dock = DockStyle.Bottom; + dialogFooter1.IsBusy = false; + dialogFooter1.Location = new System.Drawing.Point(0, 437); + dialogFooter1.Name = "dialogFooter1"; + dialogFooter1.Size = new System.Drawing.Size(444, 84); + // + // memoBox1 + // + memoBox1.AllowDrop = true; + memoBox1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + memoBox1.BackColor = System.Drawing.Color.Transparent; + memoBox1.ClearedValue = ""; + memoBox1.EnableReactiveVisual = true; + memoBox1.Font = new System.Drawing.Font("Segoe UI", 9F); + memoBox1.Location = new System.Drawing.Point(10, 53); + memoBox1.Name = "memoBox1"; + memoBox1.ReadOnly = false; + memoBox1.ScrollBars = ScrollBars.Vertical; + memoBox1.Size = new System.Drawing.Size(424, 258); + memoBox1.TabIndex = 211; + memoBox1.TabStop = false; + memoBox1.WordWrap = false; + // + // AddBatchPageForm + // + AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + BackColor = System.Drawing.Color.White; + ClientSize = new System.Drawing.Size(444, 521); + Controls.Add(memoBox1); + Controls.Add(dialogFooter1); + Controls.Add(progressBar2); + Controls.Add(button3); + Controls.Add(tHorizontalSeparator3); + Controls.Add(label1); + KeyPreview = true; + MinimumSize = new System.Drawing.Size(460, 560); + Name = "AddBatchPageForm"; + Text = "Add Pages (Batch)"; + ResumeLayout(false); + PerformLayout(); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + memoBox1.Text = string.Empty; + + progressBar2.Minimum = 0; + progressBar2.Value = 0; + progressBar2.Maximum = memoBox1.Lines?.Length ?? 0; + + memoBox1.Focus(); + } + + protected override void OnClosing(CancelEventArgs e) + { + base.OnClosing(e); + + if (this.IsBusy) + { + e.Cancel = true; + } + } + + + public List Result + { + get => _result; + private set => _result = value; + } + + + protected bool IsBusy + { + get => _isBusy; + set + { + _isBusy = value; + + UIControl.SetEnable(memoBox1, !this.IsBusy); + UIControl.Invoke(button3, (x) => + { + button3.LabelText = (this.IsBusy ? "&Stop" : "&Add Pages"); + }); + + dialogFooter1.IsBusy = _isBusy; + } + } + + private async void button3_MouseClick(object sender, MouseEventArgs e) + { + await Task.Run(async () => + { + if (this.IsBusy) + { + _requestCancel = true; + return; + } + + this.IsBusy = true; + + this.Result = new List(); + + progressBar2.Minimum = 0; + progressBar2.Value = 0; + progressBar2.Maximum = memoBox1.Lines?.Length ?? 0; + + foreach (var item in memoBox1.Lines ?? new string[0]) + { + progressBar2.Value++; + + if (string.IsNullOrWhiteSpace(item)) + { + continue; + } + + var newModel = new BookmarkModel(); + newModel.Address = item; + newModel.Path = _rootPath; + + if (_requestCancel) + { + break; + } + + newModel = await UpdateBookmark(newModel, true, true); + if (newModel == null) + { + continue; + } + + if (_requestCancel) + { + break; + } + + this.Result.Add(newModel); + } + + //_requestCancel = false; + + this.IsBusy = false; + + if (!_requestCancel) + { + this.DialogResult = DialogResult.OK; + + UIControl.Close(this); + } + + _requestCancel = false; + }); + } + + private async Task UpdateBookmark(BookmarkModel model, bool updateTitle, bool updateDescription) + { + if (string.IsNullOrWhiteSpace(model.Address)) + { + return null; + } + + if (!model.Address.StartsWith("http://", StringComparison.CurrentCultureIgnoreCase) && !model.Address.StartsWith("https://", StringComparison.CurrentCultureIgnoreCase)) + { + model.Address = "http://" + model.Address; + } + + var document = await _webProvider.RetrieveHtmlDocument(model.Address); + if (document == null) + { + return null; + } + + if (updateTitle) + { + model.Title = _webProvider.ParseTitle(document); + } + + if (updateDescription) + { + model.Description = _webProvider.ParseDescription(document); + } + + return model; + } + + } +} \ No newline at end of file diff --git a/AddBatchPageForm.resx b/AddBatchPageForm.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/AddBatchPageForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/BookmarkManager.csproj b/BookmarkManager.csproj index f7a4438..7f050a1 100644 --- a/BookmarkManager.csproj +++ b/BookmarkManager.csproj @@ -106,6 +106,9 @@ True AppResource.resx + + Form + diff --git a/MainForm.Designer.cs b/MainForm.Designer.cs index e98c264..11c53e5 100644 --- a/MainForm.Designer.cs +++ b/MainForm.Designer.cs @@ -71,6 +71,7 @@ namespace FizzyLauncher sortToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); folderContextMenu = new System.Windows.Forms.ContextMenuStrip(components); addPageToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem(); addFolderToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator(); openAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -90,6 +91,7 @@ namespace FizzyLauncher moveUpToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); moveDownToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); treeView1 = new RyzStudio.Windows.Forms.BookmarkTreeView(); + toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem(); menuStrip1.SuspendLayout(); rootContextMenu.SuspendLayout(); folderContextMenu.SuspendLayout(); @@ -193,7 +195,7 @@ namespace FizzyLauncher findToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; findToolStripMenuItem.Name = "findToolStripMenuItem"; findToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F; - findToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + findToolStripMenuItem.Size = new System.Drawing.Size(137, 22); findToolStripMenuItem.Text = "&Find"; findToolStripMenuItem.Click += findToolStripMenuItem_Click; // @@ -207,26 +209,26 @@ namespace FizzyLauncher // expandAllToolStripMenuItem // expandAllToolStripMenuItem.Name = "expandAllToolStripMenuItem"; - expandAllToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + expandAllToolStripMenuItem.Size = new System.Drawing.Size(152, 22); expandAllToolStripMenuItem.Text = "&Expand All"; expandAllToolStripMenuItem.Click += expandAllToolStripMenuItem_Click; // // collapseAllToolStripMenuItem // collapseAllToolStripMenuItem.Name = "collapseAllToolStripMenuItem"; - collapseAllToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + collapseAllToolStripMenuItem.Size = new System.Drawing.Size(152, 22); collapseAllToolStripMenuItem.Text = "&Collapse All"; collapseAllToolStripMenuItem.Click += collapseAllToolStripMenuItem_Click; // // toolStripSeparator1 // toolStripSeparator1.Name = "toolStripSeparator1"; - toolStripSeparator1.Size = new System.Drawing.Size(177, 6); + toolStripSeparator1.Size = new System.Drawing.Size(149, 6); // // alwaysOnTopToolStripMenuItem // alwaysOnTopToolStripMenuItem.Name = "alwaysOnTopToolStripMenuItem"; - alwaysOnTopToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + alwaysOnTopToolStripMenuItem.Size = new System.Drawing.Size(152, 22); alwaysOnTopToolStripMenuItem.Text = "Always On &Top"; alwaysOnTopToolStripMenuItem.Click += alwaysOnTopToolStripMenuItem_Click; // @@ -240,21 +242,21 @@ namespace FizzyLauncher // toolStripMenuItem9 // toolStripMenuItem9.Name = "toolStripMenuItem9"; - toolStripMenuItem9.Size = new System.Drawing.Size(180, 22); + toolStripMenuItem9.Size = new System.Drawing.Size(168, 22); toolStripMenuItem9.Text = "Update &Icons"; toolStripMenuItem9.Click += toolStripMenuItem9_Click; // // toolStripSeparator2 // toolStripSeparator2.Name = "toolStripSeparator2"; - toolStripSeparator2.Size = new System.Drawing.Size(177, 6); + toolStripSeparator2.Size = new System.Drawing.Size(165, 6); // // optionsToolStripMenuItem // optionsToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; optionsToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F12; - optionsToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + optionsToolStripMenuItem.Size = new System.Drawing.Size(168, 22); optionsToolStripMenuItem.Text = "&Options"; optionsToolStripMenuItem.Click += optionsToolStripMenuItem_Click; // @@ -270,19 +272,19 @@ namespace FizzyLauncher viewHelpToolStripMenuItem1.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; viewHelpToolStripMenuItem1.Name = "viewHelpToolStripMenuItem1"; viewHelpToolStripMenuItem1.ShortcutKeys = System.Windows.Forms.Keys.F1; - viewHelpToolStripMenuItem1.Size = new System.Drawing.Size(180, 22); + viewHelpToolStripMenuItem1.Size = new System.Drawing.Size(146, 22); viewHelpToolStripMenuItem1.Text = "&View Help"; viewHelpToolStripMenuItem1.Click += viewHelpToolStripMenuItem1_Click; // // toolStripMenuItem16 // toolStripMenuItem16.Name = "toolStripMenuItem16"; - toolStripMenuItem16.Size = new System.Drawing.Size(177, 6); + toolStripMenuItem16.Size = new System.Drawing.Size(143, 6); // // aboutToolStripMenuItem1 // aboutToolStripMenuItem1.Name = "aboutToolStripMenuItem1"; - aboutToolStripMenuItem1.Size = new System.Drawing.Size(180, 22); + aboutToolStripMenuItem1.Size = new System.Drawing.Size(146, 22); aboutToolStripMenuItem1.Text = "&About"; aboutToolStripMenuItem1.Click += aboutToolStripMenuItem1_Click; // @@ -294,85 +296,92 @@ namespace FizzyLauncher // // rootContextMenu // - rootContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { addPageToolStripMenuItem, addFolderToolStripMenuItem, toolStripMenuItem2, editToolStripMenuItem, toolStripMenuItem3, sortToolStripMenuItem }); + rootContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { addPageToolStripMenuItem, toolStripMenuItem11, addFolderToolStripMenuItem, toolStripMenuItem2, editToolStripMenuItem, toolStripMenuItem3, sortToolStripMenuItem }); rootContextMenu.Name = "rootContextMenu"; - rootContextMenu.Size = new System.Drawing.Size(133, 104); + rootContextMenu.Size = new System.Drawing.Size(181, 148); // // addPageToolStripMenuItem // addPageToolStripMenuItem.Name = "addPageToolStripMenuItem"; - addPageToolStripMenuItem.Size = new System.Drawing.Size(132, 22); + addPageToolStripMenuItem.Size = new System.Drawing.Size(180, 22); addPageToolStripMenuItem.Text = "Add &Page"; addPageToolStripMenuItem.Click += addPageToolStripMenuItem_Click; // // addFolderToolStripMenuItem // addFolderToolStripMenuItem.Name = "addFolderToolStripMenuItem"; - addFolderToolStripMenuItem.Size = new System.Drawing.Size(132, 22); + addFolderToolStripMenuItem.Size = new System.Drawing.Size(180, 22); addFolderToolStripMenuItem.Text = "Add &Folder"; addFolderToolStripMenuItem.Click += addFolderToolStripMenuItem_Click; // // toolStripMenuItem2 // toolStripMenuItem2.Name = "toolStripMenuItem2"; - toolStripMenuItem2.Size = new System.Drawing.Size(129, 6); + toolStripMenuItem2.Size = new System.Drawing.Size(177, 6); // // editToolStripMenuItem // editToolStripMenuItem.Name = "editToolStripMenuItem"; - editToolStripMenuItem.Size = new System.Drawing.Size(132, 22); + editToolStripMenuItem.Size = new System.Drawing.Size(180, 22); editToolStripMenuItem.Text = "&Edit"; editToolStripMenuItem.Click += editToolStripMenuItem_Click; // // toolStripMenuItem3 // toolStripMenuItem3.Name = "toolStripMenuItem3"; - toolStripMenuItem3.Size = new System.Drawing.Size(129, 6); + toolStripMenuItem3.Size = new System.Drawing.Size(177, 6); // // sortToolStripMenuItem // sortToolStripMenuItem.Name = "sortToolStripMenuItem"; - sortToolStripMenuItem.Size = new System.Drawing.Size(132, 22); + sortToolStripMenuItem.Size = new System.Drawing.Size(180, 22); sortToolStripMenuItem.Text = "&Sort"; sortToolStripMenuItem.Click += sortToolStripMenuItem_Click; // // folderContextMenu // - folderContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { addPageToolStripMenuItem1, addFolderToolStripMenuItem1, toolStripMenuItem4, openAllToolStripMenuItem, editToolStripMenuItem1, deleteToolStripMenuItem, toolStripMenuItem5, sortToolStripMenuItem1, toolStripMenuItem6, moveUpToolStripMenuItem, moveDownToolStripMenuItem }); + folderContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { addPageToolStripMenuItem1, toolStripMenuItem10, addFolderToolStripMenuItem1, toolStripMenuItem4, openAllToolStripMenuItem, editToolStripMenuItem1, deleteToolStripMenuItem, toolStripMenuItem5, sortToolStripMenuItem1, toolStripMenuItem6, moveUpToolStripMenuItem, moveDownToolStripMenuItem }); folderContextMenu.Name = "folderContextMenu"; - folderContextMenu.Size = new System.Drawing.Size(139, 198); + folderContextMenu.Size = new System.Drawing.Size(167, 220); // // addPageToolStripMenuItem1 // addPageToolStripMenuItem1.Name = "addPageToolStripMenuItem1"; - addPageToolStripMenuItem1.Size = new System.Drawing.Size(138, 22); + addPageToolStripMenuItem1.Size = new System.Drawing.Size(166, 22); addPageToolStripMenuItem1.Text = "Add &Page"; addPageToolStripMenuItem1.Click += addPageToolStripMenuItem1_Click; // + // toolStripMenuItem10 + // + toolStripMenuItem10.Name = "toolStripMenuItem10"; + toolStripMenuItem10.Size = new System.Drawing.Size(166, 22); + toolStripMenuItem10.Text = "Add Page (&Batch)"; + toolStripMenuItem10.Click += toolStripMenuItem10_Click; + // // addFolderToolStripMenuItem1 // addFolderToolStripMenuItem1.Name = "addFolderToolStripMenuItem1"; - addFolderToolStripMenuItem1.Size = new System.Drawing.Size(138, 22); + addFolderToolStripMenuItem1.Size = new System.Drawing.Size(166, 22); addFolderToolStripMenuItem1.Text = "Add &Folder"; addFolderToolStripMenuItem1.Click += addFolderToolStripMenuItem1_Click; // // toolStripMenuItem4 // toolStripMenuItem4.Name = "toolStripMenuItem4"; - toolStripMenuItem4.Size = new System.Drawing.Size(135, 6); + toolStripMenuItem4.Size = new System.Drawing.Size(163, 6); // // openAllToolStripMenuItem // openAllToolStripMenuItem.Image = BookmarkManager.AppResource.bookmark; openAllToolStripMenuItem.Name = "openAllToolStripMenuItem"; - openAllToolStripMenuItem.Size = new System.Drawing.Size(138, 22); + openAllToolStripMenuItem.Size = new System.Drawing.Size(166, 22); openAllToolStripMenuItem.Text = "&Open All"; openAllToolStripMenuItem.Click += openAllToolStripMenuItem_Click; // // editToolStripMenuItem1 // editToolStripMenuItem1.Name = "editToolStripMenuItem1"; - editToolStripMenuItem1.Size = new System.Drawing.Size(138, 22); + editToolStripMenuItem1.Size = new System.Drawing.Size(166, 22); editToolStripMenuItem1.Text = "&Edit"; editToolStripMenuItem1.Click += editToolStripMenuItem1_Click; // @@ -380,32 +389,32 @@ namespace FizzyLauncher // deleteToolStripMenuItem.Image = BookmarkManager.AppResource.trash; deleteToolStripMenuItem.Name = "deleteToolStripMenuItem"; - deleteToolStripMenuItem.Size = new System.Drawing.Size(138, 22); + deleteToolStripMenuItem.Size = new System.Drawing.Size(166, 22); deleteToolStripMenuItem.Text = "&Delete"; deleteToolStripMenuItem.Click += deleteToolStripMenuItem_Click; // // toolStripMenuItem5 // toolStripMenuItem5.Name = "toolStripMenuItem5"; - toolStripMenuItem5.Size = new System.Drawing.Size(135, 6); + toolStripMenuItem5.Size = new System.Drawing.Size(163, 6); // // sortToolStripMenuItem1 // sortToolStripMenuItem1.Name = "sortToolStripMenuItem1"; - sortToolStripMenuItem1.Size = new System.Drawing.Size(138, 22); + sortToolStripMenuItem1.Size = new System.Drawing.Size(166, 22); sortToolStripMenuItem1.Text = "&Sort"; sortToolStripMenuItem1.Click += sortToolStripMenuItem1_Click; // // toolStripMenuItem6 // toolStripMenuItem6.Name = "toolStripMenuItem6"; - toolStripMenuItem6.Size = new System.Drawing.Size(135, 6); + toolStripMenuItem6.Size = new System.Drawing.Size(163, 6); // // moveUpToolStripMenuItem // moveUpToolStripMenuItem.Image = BookmarkManager.AppResource.arrow_up_circle; moveUpToolStripMenuItem.Name = "moveUpToolStripMenuItem"; - moveUpToolStripMenuItem.Size = new System.Drawing.Size(138, 22); + moveUpToolStripMenuItem.Size = new System.Drawing.Size(166, 22); moveUpToolStripMenuItem.Text = "Move &Up"; moveUpToolStripMenuItem.Click += moveUpToolStripMenuItem_Click; // @@ -413,7 +422,7 @@ namespace FizzyLauncher // moveDownToolStripMenuItem.Image = BookmarkManager.AppResource.arrow_down_circle; moveDownToolStripMenuItem.Name = "moveDownToolStripMenuItem"; - moveDownToolStripMenuItem.Size = new System.Drawing.Size(138, 22); + moveDownToolStripMenuItem.Size = new System.Drawing.Size(166, 22); moveDownToolStripMenuItem.Text = "Move &Down"; moveDownToolStripMenuItem.Click += moveDownToolStripMenuItem_Click; // @@ -482,6 +491,13 @@ namespace FizzyLauncher treeView1.Size = new System.Drawing.Size(300, 556); treeView1.TabIndex = 5; // + // toolStripMenuItem11 + // + toolStripMenuItem11.Name = "toolStripMenuItem11"; + toolStripMenuItem11.Size = new System.Drawing.Size(180, 22); + toolStripMenuItem11.Text = "Add Page (&Batch)"; + toolStripMenuItem11.Click += toolStripMenuItem11_Click; + // // MainForm // AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); @@ -563,6 +579,8 @@ namespace FizzyLauncher private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem9; private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; private RyzStudio.Windows.Forms.BookmarkTreeView treeView1; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem10; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem11; } } diff --git a/MainForm.cs b/MainForm.cs index 305fc89..a07d333 100644 --- a/MainForm.cs +++ b/MainForm.cs @@ -394,6 +394,36 @@ namespace FizzyLauncher } } + /// + /// Add page (batch) + /// + /// + /// + private void toolStripMenuItem11_Click(object sender, EventArgs e) + { + if (this.IsBusy) + { + return; + } + + var nodeType = treeView1.GetNodeType(); + if ((nodeType != NodeType.Root) && (nodeType != NodeType.Folder)) + { + return; + } + + var nodePath = treeView1.GetNodePath(); + + var form = new AddBatchPageForm(nodePath); + if (form.ShowDialog() == DialogResult.OK) + { + foreach (var item in form.Result) + { + treeView1.AddNode(item); + } + } + } + /// /// Add folder /// @@ -457,6 +487,16 @@ namespace FizzyLauncher addPageToolStripMenuItem_Click(sender, e); } + /// + /// Add page (batch) + /// + /// + /// + private void toolStripMenuItem10_Click(object sender, EventArgs e) + { + toolStripMenuItem11_Click(this, e); + } + /// /// Add folder /// diff --git a/MainForm.resx b/MainForm.resx index 845d051..ca4a045 100644 --- a/MainForm.resx +++ b/MainForm.resx @@ -1,7 +1,7 @@