From 9a3d8629e5ec18e18d3ccdf914d131181ab050b5 Mon Sep 17 00:00:00 2001 From: Gnkalk Date: Wed, 19 Feb 2025 20:14:23 +0330 Subject: [PATCH] Add share button for search results with URL copying - Implement share button in results page with clipboard functionality - Add new 'share' SVG icon to icons template - Create JavaScript event handler for copying search URL - Update CSS for share button styling in LTR and RTL layouts - Add tooltip for copied URL feedback --- searx/static/themes/smart/css/ltr-style.css | 30 ++++++++++++++-- searx/static/themes/smart/css/rtl-style.css | 36 ++++++++++++++++--- searx/static/themes/smart/js/app.js | 18 +++++++++- .../static/themes/smart/scripts/svg2jinja.js | 1 + .../themes/smart/src/scss/_tooltip.scss | 8 +++-- .../themes/smart/src/scss/preferences.scss | 2 +- searx/static/themes/smart/src/scss/style.scss | 27 ++++++++++++-- searx/static/themes/smart/src/ts/app.ts | 19 +++++++++- searx/templates/smart/icons.html | 1 + searx/templates/smart/results.html | 27 ++++++++++++-- 10 files changed, 152 insertions(+), 17 deletions(-) diff --git a/searx/static/themes/smart/css/ltr-style.css b/searx/static/themes/smart/css/ltr-style.css index 3de9e34da..db9abb5a6 100644 --- a/searx/static/themes/smart/css/ltr-style.css +++ b/searx/static/themes/smart/css/ltr-style.css @@ -380,6 +380,10 @@ img, video { transform: translate(calc(-50% - 1rem), 40%); } +[tooltip].center-tooltip:before { + transform: translate(-50%, 40%); +} + [tooltip]:hover:after, [tooltip]:hover:before { opacity: 1; transition: opacity .25s ease-in-out .5s; @@ -1093,7 +1097,7 @@ main:has(.not-found) .button { padding: 0 1rem; transition: grid-template-columns .3s ease-in-out; display: grid; - overflow: auto; + overflow: hidden auto; } @media (width >= 90rem) { @@ -1104,11 +1108,17 @@ main:has(.not-found) .button { #results .result-count { color: var(--secondary-text-color); - text-align: end; grid-area: amount; font-size: .8rem; } +#results .result-count-container { + justify-content: end; + align-items: center; + gap: .5rem; + display: flex; +} + #results footer { grid-area: footer; } @@ -1193,6 +1203,22 @@ main:has(.not-found) .button { grid-template-columns: 2fr 0fr 1fr; } +#results .share_btn { + background-color: #0000; + border: none; + border-radius: 9999px; + padding: .25rem; +} + +#results .share_btn:hover { + background-color: var(--background-color); +} + +#results .share_btn svg { + width: 1rem; + height: 1rem; +} + .links { grid-area: links; justify-content: end; diff --git a/searx/static/themes/smart/css/rtl-style.css b/searx/static/themes/smart/css/rtl-style.css index 06442a363..3aee6b3a3 100644 --- a/searx/static/themes/smart/css/rtl-style.css +++ b/searx/static/themes/smart/css/rtl-style.css @@ -307,7 +307,7 @@ img, video { transition: opacity .25s ease-in-out; position: absolute; bottom: 100%; - right: 50%; + left: 50%; transform: translate(-50%, -20%); } @@ -322,10 +322,14 @@ img, video { transition: opacity .25s ease-in-out; position: absolute; bottom: 100%; - right: 50%; + left: 50%; transform: translate(calc(-50% - 1rem), 40%); } +[tooltip].center-tooltip:before { + transform: translate(-50%, 40%); +} + [tooltip]:hover:after, [tooltip]:hover:before { opacity: 1; transition: opacity .25s ease-in-out .5s; @@ -869,7 +873,7 @@ fieldset .container .name { } fieldset .container .name:not(#pref_safesearch)[tooltip]:after { - right: 100%; + left: 100%; } fieldset .container .name svg { @@ -1039,7 +1043,7 @@ main:has(.not-found) .button { padding: 0 1rem; transition: grid-template-columns .3s ease-in-out; display: grid; - overflow: auto; + overflow: hidden auto; } @media (width >= 90rem) { @@ -1050,11 +1054,17 @@ main:has(.not-found) .button { #results .result-count { color: var(--secondary-text-color); - text-align: end; grid-area: amount; font-size: .8rem; } +#results .result-count-container { + justify-content: end; + align-items: center; + gap: .5rem; + display: flex; +} + #results footer { grid-area: footer; } @@ -1139,6 +1149,22 @@ main:has(.not-found) .button { grid-template-columns: 2fr 0fr 1fr; } +#results .share_btn { + background-color: #0000; + border: none; + border-radius: 9999px; + padding: .25rem; +} + +#results .share_btn:hover { + background-color: var(--background-color); +} + +#results .share_btn svg { + width: 1rem; + height: 1rem; +} + .links { grid-area: links; justify-content: end; diff --git a/searx/static/themes/smart/js/app.js b/searx/static/themes/smart/js/app.js index bead2c270..8eff7c931 100644 --- a/searx/static/themes/smart/js/app.js +++ b/searx/static/themes/smart/js/app.js @@ -599,7 +599,7 @@ function $$(selector) { } (0, _images.checkImagePage)(); function afterPageLoad() { - // check for preferences page + // preferences page if ($("#preferences")) { // check for preferences hash const hashInput = $("#preferences-hash"); @@ -621,6 +621,22 @@ function afterPageLoad() { pasteInput.value = hash; }); } + // search page + if ($("#results")) { + const shareBtn = $("#share-url-btn"); + if (!shareBtn) return; + shareBtn.addEventListener("click", function() { + const searchUrl = shareBtn.getAttribute("data-search-url"); + if (!searchUrl) return; + (0, _utils.copyToClipboard)(searchUrl); + const copiedText = shareBtn.getAttribute("data-gitee-copied"); + if (!copiedText) return; + shareBtn.setAttribute("tooltip", copiedText); + setTimeout(()=>{ + shareBtn.removeAttribute("tooltip"); + }, 2000); + }); + } } if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", afterPageLoad); else afterPageLoad(); diff --git a/searx/static/themes/smart/scripts/svg2jinja.js b/searx/static/themes/smart/scripts/svg2jinja.js index bc506864d..492d5991b 100644 --- a/searx/static/themes/smart/scripts/svg2jinja.js +++ b/searx/static/themes/smart/scripts/svg2jinja.js @@ -11,6 +11,7 @@ const svgList = { plugin: "node_modules/remixicon/icons/Development/puzzle-2-fill.svg", info: "node_modules/remixicon/icons/System/information-2-fill.svg", database: "node_modules/remixicon/icons/Device/database-2-fill.svg", + share: "node_modules/remixicon/icons/System/share-fill.svg", }; const ejs = require("ejs"), diff --git a/searx/static/themes/smart/src/scss/_tooltip.scss b/searx/static/themes/smart/src/scss/_tooltip.scss index b4066317a..f24502b76 100644 --- a/searx/static/themes/smart/src/scss/_tooltip.scss +++ b/searx/static/themes/smart/src/scss/_tooltip.scss @@ -8,7 +8,7 @@ content: attr(tooltip); position: absolute; bottom: 100%; - @include mixin.left(50%); + left: 50%; transform: translate(-50%, -20%); background: var(--tooltip-background-color); color: var(--filled-text-color); @@ -24,7 +24,7 @@ content: " "; position: absolute; bottom: 100%; - @include mixin.left(50%); + left: 50%; transform: translate(calc(-50% - 1rem), 40%); white-space: nowrap; z-index: 1; @@ -35,6 +35,10 @@ border-color: var(--tooltip-background-color) transparent transparent transparent; } +*[tooltip].center-tooltip::before { + transform: translate(-50%, 40%); +} + *[tooltip]:hover::after { opacity: 1; diff --git a/searx/static/themes/smart/src/scss/preferences.scss b/searx/static/themes/smart/src/scss/preferences.scss index b83907f46..63885488f 100644 --- a/searx/static/themes/smart/src/scss/preferences.scss +++ b/searx/static/themes/smart/src/scss/preferences.scss @@ -174,7 +174,7 @@ fieldset { align-items: center; &:not(#pref_safesearch)[tooltip]::after { - @include mixin.left(100%); + left: 100%; } svg { diff --git a/searx/static/themes/smart/src/scss/style.scss b/searx/static/themes/smart/src/scss/style.scss index c4342cb09..c1c53c346 100644 --- a/searx/static/themes/smart/src/scss/style.scss +++ b/searx/static/themes/smart/src/scss/style.scss @@ -197,7 +197,8 @@ main:has(.not-found) { margin: 0 auto; padding: 0 1rem; max-width: 1800px; - overflow: auto; + overflow-x: hidden; + overflow-y: auto; transition: grid-template-columns 300ms ease-in-out; @include mixin.screens($screen-xl) { @@ -208,7 +209,13 @@ main:has(.not-found) { grid-area: amount; font-size: .8rem; color: var(--secondary-text-color); - text-align: end; + + &-container { + display: flex; + align-items: center; + gap: .5rem; + justify-content: end; + } } footer { @@ -296,6 +303,22 @@ main:has(.not-found) { &.image-open { grid-template-columns: 2fr 0fr 1fr; } + + .share_btn { + background-color: transparent; + border: none; + @include mixin.rounded(full); + padding: .25rem; + + &:hover { + background-color: var(--background-color); + } + + svg { + width: 1rem; + height: 1rem; + } + } } .links { diff --git a/searx/static/themes/smart/src/ts/app.ts b/searx/static/themes/smart/src/ts/app.ts index 34e1c4454..d6cbe0375 100644 --- a/searx/static/themes/smart/src/ts/app.ts +++ b/searx/static/themes/smart/src/ts/app.ts @@ -12,7 +12,7 @@ export function $$(selector: string) { checkImagePage(); function afterPageLoad() { - // check for preferences page + // preferences page if ($("#preferences")) { // check for preferences hash const hashInput = $("#preferences-hash") as HTMLInputElement; @@ -40,6 +40,23 @@ function afterPageLoad() { pasteInput.value = hash; }); } + + // search page + if ($("#results")) { + const shareBtn = $("#share-url-btn") as HTMLButtonElement; + if (!shareBtn) return; + shareBtn.addEventListener("click", function () { + const searchUrl = shareBtn.getAttribute("data-search-url"); + if (!searchUrl) return; + copyToClipboard(searchUrl); + const copiedText = shareBtn.getAttribute("data-gitee-copied"); + if (!copiedText) return; + shareBtn.setAttribute("tooltip", copiedText); + setTimeout(() => { + shareBtn.removeAttribute("tooltip"); + }, 2000); + }); + } } if (document.readyState === "loading") { diff --git a/searx/templates/smart/icons.html b/searx/templates/smart/icons.html index fd443241e..db6a77959 100644 --- a/searx/templates/smart/icons.html +++ b/searx/templates/smart/icons.html @@ -12,6 +12,7 @@ 'plugin':'', 'info':'', 'database':'', + 'share':'', } -%} diff --git a/searx/templates/smart/results.html b/searx/templates/smart/results.html index 5ecffec2a..b74cbf280 100644 --- a/searx/templates/smart/results.html +++ b/searx/templates/smart/results.html @@ -58,9 +58,30 @@ block body %} {% include 'smart/madules/search_header.html' %} {% if infoboxes %} {% include 'smart/madules/infoboxs.html' %} {% endif %} {%- if number_of_results != '0' -%} -

- {{ _('Number of results') }}: {{ number_of_results }} -

+
+
+ {{ _('Number of results') }}: {{ number_of_results }} + +
+
{%- endif -%} {% if 'images.html' in results|map(attribute='template')|unique|list%}