125 lines
3.5 KiB
JavaScript
125 lines
3.5 KiB
JavaScript
import { firstLineRange, currentLine, advance, copyText, adjustCopiedLine, trimTrailing } from './queue.mjs';
|
|
import { serializePrefs, parsePrefs } from './prefs.mjs';
|
|
|
|
const pasteField = document.getElementById('pasteField');
|
|
const queueSwitch = document.getElementById('queueSwitch');
|
|
const advanceBtn = document.getElementById('advanceBtn');
|
|
const focusSwitch = document.getElementById('focusSwitch');
|
|
const newlineSwitch = document.getElementById('newlineSwitch');
|
|
|
|
const savedPrefs = parsePrefs(localStorage.getItem('queued-paste-prefs'));
|
|
newlineSwitch.checked = savedPrefs.newLines;
|
|
focusSwitch.checked = savedPrefs.advanceFocus;
|
|
|
|
function savePrefs() {
|
|
localStorage.setItem('queued-paste-prefs', serializePrefs({
|
|
newLines: newlineSwitch.checked,
|
|
advanceFocus: focusSwitch.checked,
|
|
}));
|
|
}
|
|
|
|
// Focus-based advancing is a heuristic: a paste outside this page cannot be
|
|
// observed, so a window blur followed by a refocus is treated as one paste.
|
|
// blurredSinceAdvance gates that, and armedAt suppresses the focus events
|
|
// fired by clipboard permission prompts right after arming.
|
|
let blurredSinceAdvance = false;
|
|
let armedAt = 0;
|
|
|
|
async function copyCurrentLine() {
|
|
await navigator.clipboard.writeText(copyText(pasteField.value, newlineSwitch.checked));
|
|
}
|
|
|
|
function selectCurrentLine() {
|
|
const { start, end } = firstLineRange(pasteField.value);
|
|
pasteField.setSelectionRange(start, end);
|
|
}
|
|
|
|
function setQueueing(on) {
|
|
queueSwitch.checked = on;
|
|
pasteField.readOnly = on;
|
|
pasteField.classList.toggle('paste-active', on);
|
|
advanceBtn.disabled = !on;
|
|
if (!on) {
|
|
pasteField.setSelectionRange(pasteField.value.length, pasteField.value.length);
|
|
}
|
|
}
|
|
|
|
async function startQueueing() {
|
|
pasteField.value = trimTrailing(pasteField.value);
|
|
if (pasteField.value === '') {
|
|
// Nothing to queue.
|
|
setQueueing(false);
|
|
return;
|
|
}
|
|
try {
|
|
await copyCurrentLine();
|
|
} catch (err) {
|
|
alert('Could not access the clipboard: ' + err.message);
|
|
setQueueing(false);
|
|
return;
|
|
}
|
|
setQueueing(true);
|
|
selectCurrentLine();
|
|
blurredSinceAdvance = false;
|
|
armedAt = Date.now();
|
|
}
|
|
|
|
async function advanceQueue() {
|
|
pasteField.value = advance(pasteField.value);
|
|
if (pasteField.value === '') {
|
|
setQueueing(false);
|
|
return;
|
|
}
|
|
try {
|
|
await copyCurrentLine();
|
|
} catch (err) {
|
|
alert('Could not copy the next line: ' + err.message);
|
|
setQueueing(false);
|
|
return;
|
|
}
|
|
selectCurrentLine();
|
|
}
|
|
|
|
queueSwitch.addEventListener('change', () => {
|
|
if (queueSwitch.checked) {
|
|
startQueueing();
|
|
} else {
|
|
setQueueing(false);
|
|
}
|
|
});
|
|
|
|
advanceBtn.addEventListener('click', () => {
|
|
advanceQueue();
|
|
});
|
|
|
|
focusSwitch.addEventListener('change', () => {
|
|
blurredSinceAdvance = false;
|
|
armedAt = Date.now();
|
|
savePrefs();
|
|
});
|
|
|
|
newlineSwitch.addEventListener('change', async () => {
|
|
savePrefs();
|
|
if (!queueSwitch.checked) return;
|
|
try {
|
|
const clipboardText = await navigator.clipboard.readText();
|
|
const adjusted = adjustCopiedLine(clipboardText, currentLine(pasteField.value), newlineSwitch.checked);
|
|
if (adjusted !== null) {
|
|
await navigator.clipboard.writeText(adjusted);
|
|
}
|
|
} catch (err) {
|
|
alert('Could not update the clipboard: ' + err.message);
|
|
}
|
|
});
|
|
|
|
window.addEventListener('blur', () => {
|
|
blurredSinceAdvance = true;
|
|
});
|
|
|
|
window.addEventListener('focus', () => {
|
|
if (!queueSwitch.checked || !focusSwitch.checked) return;
|
|
if (!blurredSinceAdvance) return;
|
|
if (Date.now() - armedAt < 1000) return;
|
|
blurredSinceAdvance = false;
|
|
advanceQueue();
|
|
});
|