Add clipboard utility functions for preferences page

- Create new utils.ts module with clipboard-related functions
- Implement copyToClipboard and getFromClipboard methods
- Add clipboard functionality to preferences page for hash copying and pasting
- Update app.ts and images.ts to use new clipboard utility functions
- Modify preferences.html template with new element IDs for clipboard interactions
This commit is contained in:
Gnkalk 2025-02-19 18:57:12 +03:30
parent 587ef09958
commit d0e9ba73f5
5 changed files with 147 additions and 16 deletions

View file

@ -590,6 +590,7 @@ parcelHelpers.defineInteropFlag(exports);
parcelHelpers.export(exports, "$", ()=>$); parcelHelpers.export(exports, "$", ()=>$);
parcelHelpers.export(exports, "$$", ()=>$$); parcelHelpers.export(exports, "$$", ()=>$$);
var _images = require("./images"); var _images = require("./images");
var _utils = require("./utils");
function $(selector) { function $(selector) {
return document.querySelector(selector); return document.querySelector(selector);
} }
@ -597,13 +598,39 @@ function $$(selector) {
return document.querySelectorAll(selector); return document.querySelectorAll(selector);
} }
(0, _images.checkImagePage)(); (0, _images.checkImagePage)();
document.addEventListener("DOMContentLoaded", function() {}); function afterPageLoad() {
// check for preferences page
if ($("#preferences")) {
// check for preferences hash
const hashInput = $("#preferences-hash");
if (!hashInput) return;
const copyBtn = $("#copy-preferences-hash");
if (!copyBtn) return;
copyBtn.addEventListener("click", function() {
(0, _utils.copyToClipboard)(hashInput.value);
copyBtn.innerText = copyBtn.getAttribute("data-copied-text");
setTimeout(()=>{
copyBtn.innerText = copyBtn.getAttribute("data-copy-text");
}, 2000);
});
const pasteBtn = $("#paste-preferences-hash");
const pasteInput = $("#paste-preferences-hash-input");
if (!pasteBtn || !pasteInput) return;
pasteBtn.addEventListener("click", async function() {
const hash = await (0, _utils.getFromClipboard)();
pasteInput.value = hash;
});
}
}
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", afterPageLoad);
else afterPageLoad();
},{"./images":"jxVSe","@parcel/transformer-js/src/esmodule-helpers.js":"j7FRh"}],"jxVSe":[function(require,module,exports,__globalThis) { },{"./images":"jxVSe","@parcel/transformer-js/src/esmodule-helpers.js":"j7FRh","./utils":"hKc06"}],"jxVSe":[function(require,module,exports,__globalThis) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports); parcelHelpers.defineInteropFlag(exports);
parcelHelpers.export(exports, "checkImagePage", ()=>checkImagePage); parcelHelpers.export(exports, "checkImagePage", ()=>checkImagePage);
var _app = require("./app"); var _app = require("./app");
var _utils = require("./utils");
function handleImageDetails(image, { imageSrc, imageTitle, imageContent, imageSource, imageFilesize, imageDownload, formatSpan, filesizeSpan, engineSpan }) { function handleImageDetails(image, { imageSrc, imageTitle, imageContent, imageSource, imageFilesize, imageDownload, formatSpan, filesizeSpan, engineSpan }) {
const resultsContainer = (0, _app.$)("#results"); const resultsContainer = (0, _app.$)("#results");
resultsContainer.classList.add("image-open"); resultsContainer.classList.add("image-open");
@ -683,11 +710,9 @@ function setupImages(resultsContainer) {
canvas.getContext("2d").drawImage(imageSrc, 0, 0, imageSrc.width, imageSrc.height); canvas.getContext("2d").drawImage(imageSrc, 0, 0, imageSrc.width, imageSrc.height);
canvas.toBlob((blob)=>{ canvas.toBlob((blob)=>{
if (!blob) return; if (!blob) return;
navigator.clipboard.write([ (0, _utils.copyToClipboard)(new ClipboardItem({
new ClipboardItem({
"image/*": blob "image/*": blob
}) }));
]);
}); });
canvas.remove(); canvas.remove();
}); });
@ -712,7 +737,7 @@ function checkImagePage() {
if (resultsContainer.classList.contains("image-page")) setupImages(resultsContainer); if (resultsContainer.classList.contains("image-page")) setupImages(resultsContainer);
} }
},{"@parcel/transformer-js/src/esmodule-helpers.js":"j7FRh","./app":"3uyIQ"}],"j7FRh":[function(require,module,exports,__globalThis) { },{"./app":"3uyIQ","@parcel/transformer-js/src/esmodule-helpers.js":"j7FRh","./utils":"hKc06"}],"j7FRh":[function(require,module,exports,__globalThis) {
exports.interopDefault = function(a) { exports.interopDefault = function(a) {
return a && a.__esModule ? a : { return a && a.__esModule ? a : {
default: a default: a
@ -742,5 +767,38 @@ exports.export = function(dest, destName, get) {
}); });
}; };
},{}]},["1Y09f","3uyIQ"], "3uyIQ", "parcelRequire94c2") },{}],"hKc06":[function(require,module,exports,__globalThis) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
parcelHelpers.export(exports, "copyToClipboard", ()=>copyToClipboard);
parcelHelpers.export(exports, "getFromClipboard", ()=>getFromClipboard);
function copyToClipboard(item) {
if (navigator.clipboard) {
if (item instanceof ClipboardItem) navigator.clipboard.write([
item
]);
else navigator.clipboard.writeText(item);
return;
}
if (typeof item !== "string") return;
const textarea = document.createElement("textarea");
textarea.value = item;
document.body.appendChild(textarea);
textarea.select();
document.execCommand("copy");
document.body.removeChild(textarea);
}
async function getFromClipboard() {
if (navigator.clipboard) try {
const text = await navigator.clipboard.readText();
return text;
} catch (e) {
console.error(e);
return "";
}
alert("Clipboard not supported");
return "";
}
},{"@parcel/transformer-js/src/esmodule-helpers.js":"j7FRh"}]},["1Y09f","3uyIQ"], "3uyIQ", "parcelRequire94c2")

View file

@ -1,4 +1,5 @@
import { checkImagePage } from "./images"; import { checkImagePage } from "./images";
import { copyToClipboard, getFromClipboard } from "./utils";
export function $(selector: string) { export function $(selector: string) {
return document.querySelector(selector); return document.querySelector(selector);
@ -10,4 +11,39 @@ export function $$(selector: string) {
checkImagePage(); checkImagePage();
document.addEventListener("DOMContentLoaded", function () {}); function afterPageLoad() {
// check for preferences page
if ($("#preferences")) {
// check for preferences hash
const hashInput = $("#preferences-hash") as HTMLInputElement;
if (!hashInput) return;
const copyBtn = $("#copy-preferences-hash") as HTMLButtonElement;
if (!copyBtn) return;
copyBtn.addEventListener("click", function () {
copyToClipboard(hashInput.value);
copyBtn.innerText = copyBtn.getAttribute(
"data-copied-text"
) as string;
setTimeout(() => {
copyBtn.innerText = copyBtn.getAttribute(
"data-copy-text"
) as string;
}, 2000);
});
const pasteBtn = $("#paste-preferences-hash") as HTMLButtonElement;
const pasteInput = $(
"#paste-preferences-hash-input"
) as HTMLInputElement;
if (!pasteBtn || !pasteInput) return;
pasteBtn.addEventListener("click", async function () {
const hash = await getFromClipboard();
pasteInput.value = hash;
});
}
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", afterPageLoad);
} else {
afterPageLoad();
}

View file

@ -1,4 +1,5 @@
import { $, $$ } from "./app"; import { $, $$ } from "./app";
import { copyToClipboard } from "./utils";
interface ImageDetails { interface ImageDetails {
imageSrc: HTMLImageElement; imageSrc: HTMLImageElement;
@ -143,7 +144,7 @@ function setupImages(resultsContainer: HTMLElement) {
); );
canvas.toBlob((blob) => { canvas.toBlob((blob) => {
if (!blob) return; if (!blob) return;
navigator.clipboard.write([new ClipboardItem({ "image/*": blob })]); copyToClipboard(new ClipboardItem({ "image/*": blob }));
}); });
void canvas.remove(); void canvas.remove();
}); });

View file

@ -0,0 +1,33 @@
export function copyToClipboard(item: ClipboardItem | string) {
if (navigator.clipboard) {
if (item instanceof ClipboardItem) {
navigator.clipboard.write([item]);
} else {
navigator.clipboard.writeText(item);
}
return;
}
if (typeof item !== "string") return;
const textarea = document.createElement("textarea");
textarea.value = item;
document.body.appendChild(textarea);
textarea.select();
document.execCommand("copy");
document.body.removeChild(textarea);
}
export async function getFromClipboard(): Promise<string> {
if (navigator.clipboard) {
try {
const text = await navigator.clipboard.readText();
return text;
} catch (e) {
console.error(e);
return "";
}
}
alert("Clipboard not supported");
return "";
}

View file

@ -76,14 +76,17 @@
<div class="sidebyside"> <div class="sidebyside">
<input <input
type="text" type="text"
id="preferences-hash"
readonly readonly
value="{{- preferences_url_params|e }}" value="{{- preferences_url_params|e }}"
/> />
<button <button
id="copy-hash" id="copy-preferences-hash"
class="btn primary" class="btn primary"
type="button"
data-hash="{{- preferences_url_params|e -}}" data-hash="{{- preferences_url_params|e -}}"
data-copied-text="{{- _('Copied') -}}" data-copied-text="{{- _('Copied') -}}!"
data-copy-text="{{- _('Copy') -}}"
> >
{{- _('Copy') -}} {{- _('Copy') -}}
</button> </button>
@ -104,14 +107,14 @@
<div class="sidebyside"> <div class="sidebyside">
<input <input
type="text" type="text"
id="pref-hash-input" id="paste-preferences-hash-input"
name="preferences" name="preferences"
placeholder="{{- _('Preferences hash') -}}" placeholder="{{- _('Preferences hash') -}}"
/> />
<button <button
id="paste-hash" id="paste-preferences-hash"
class="btn secondary" class="btn secondary"
data-copied-text="{{- _('Copied') -}}" type="button"
> >
{{- _('Paste') -}} {{- _('Paste') -}}
</button> </button>