/**
* Asynchronous, clipboard, and timer utilities for TinAI.
*/
/**
* Creates a debounced function that delays invoking func until after wait milliseconds.
* Provides a .cancel() method to abort any scheduled execution.
* @param {Function} func - Function to debounce.
* @param {number} [wait=250] - Milliseconds to delay.
* @returns {Function & { cancel: Function }} Debounced wrapper function with cancel method.
*/
export function debounce(func, wait = 250) {
let timeout = null;
const executedFunction = function(...args) {
const later = () => {
timeout = null;
func.apply(this, args);
};
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
timeout = setTimeout(later, wait);
};
executedFunction.cancel = function() {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
};
return executedFunction;
}
/**
* Copies plain text to the clipboard with modern clipboard API and fallback.
* @param {string} text - String to copy.
* @param {HTMLElement|null} [feedbackButton=null] - Optional button to show visual feedback on.
* @returns {Promise<boolean>} Whether copy succeeded.
*/
export async function copyToClipboard(text, feedbackButton = null) {
const applyFeedback = () => {
if (!feedbackButton) return;
const originalText = feedbackButton.textContent;
feedbackButton.textContent = 'Copied!';
feedbackButton.disabled = true;
setTimeout(() => {
feedbackButton.textContent = originalText;
feedbackButton.disabled = false;
}, 1500);
};
if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
try {
await navigator.clipboard.writeText(text || '');
applyFeedback();
return true;
} catch (err) {
console.warn('navigator.clipboard.writeText failed, falling back to legacy execCommand:', err);
}
}
try {
const textarea = document.createElement('textarea');
textarea.value = text || '';
textarea.setAttribute('readonly', '');
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
textarea.style.top = '0';
document.body.appendChild(textarea);
textarea.select();
const successful = document['execCommand']('copy');
document.body.removeChild(textarea);
if (successful) {
applyFeedback();
}
return !!successful;
} catch (err) {
console.error('All clipboard copy methods failed:', err);
return false;
}
}
async-utils.js
×
Type: Web, text/plain
2.32 Kilobytes
Last Modified 2026-09-04 18:10:48
⬇ Download File
Type: Web, text/plain
2.32 Kilobytes
Last Modified 2026-09-04 18:10:48
⬇ Download File