mirror of
https://github.com/NohamR/Pocket-Bird.git
synced 2026-05-25 19:59:38 +00:00
161 lines
4.7 KiB
JavaScript
161 lines
4.7 KiB
JavaScript
import {
|
|
getContext,
|
|
makeElement,
|
|
makeDraggable,
|
|
makeClosable
|
|
} from './shared.js';
|
|
|
|
/**
|
|
* @typedef {Object} SavedStickyNote
|
|
* @property {string} id
|
|
* @property {string} site
|
|
* @property {string} content
|
|
* @property {number} top
|
|
* @property {number} left
|
|
*/
|
|
|
|
export class StickyNote {
|
|
/**
|
|
* @param {string} id
|
|
* @param {string} [site]
|
|
* @param {string} [content]
|
|
* @param {number} [top]
|
|
* @param {number} [left]
|
|
*/
|
|
constructor(id, site = "", content = "", top = 0, left = 0) {
|
|
this.id = id;
|
|
this.site = site;
|
|
this.content = content;
|
|
this.top = top;
|
|
this.left = left;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {StickyNote} stickyNote
|
|
* @param {HTMLElement} page
|
|
* @param {() => void} onSave
|
|
* @param {() => void} onDelete
|
|
* @returns {HTMLElement}
|
|
*/
|
|
export function renderStickyNote(stickyNote, page, onSave, onDelete) {
|
|
const noteElement = makeElement("birb-window");
|
|
noteElement.classList.add("birb-sticky-note");
|
|
const color = getColor(stickyNote.id);
|
|
noteElement.style.setProperty("--birb-highlight", color);
|
|
noteElement.style.setProperty("--birb-border-color", color);
|
|
|
|
// Create header
|
|
const header = makeElement("birb-window-header");
|
|
const titleDiv = makeElement("birb-window-title", "Sticky Note");
|
|
const closeButton = makeElement("birb-window-close", "x");
|
|
header.appendChild(titleDiv);
|
|
header.appendChild(closeButton);
|
|
|
|
// Create content
|
|
const content = makeElement("birb-window-content");
|
|
const textarea = document.createElement("textarea");
|
|
textarea.className = "birb-sticky-note-input";
|
|
textarea.style.width = "150px";
|
|
textarea.placeholder = "Write your notes here and they'll stick to the page!";
|
|
textarea.value = stickyNote.content;
|
|
content.appendChild(textarea);
|
|
|
|
noteElement.appendChild(header);
|
|
noteElement.appendChild(content);
|
|
|
|
noteElement.style.top = `${stickyNote.top}px`;
|
|
noteElement.style.left = `${stickyNote.left}px`;
|
|
page.appendChild(noteElement);
|
|
|
|
makeDraggable(header, true, (top, left) => {
|
|
stickyNote.top = top;
|
|
stickyNote.left = left;
|
|
onSave();
|
|
}, page);
|
|
|
|
if (closeButton) {
|
|
makeClosable(() => {
|
|
if (stickyNote.content.trim() === "" || confirm("Are you sure you want to delete this sticky note?")) {
|
|
onDelete();
|
|
noteElement.remove();
|
|
}
|
|
}, closeButton, false);
|
|
}
|
|
|
|
if (textarea && textarea instanceof HTMLTextAreaElement) {
|
|
let saveTimeout;
|
|
// Save after debounce
|
|
textarea.addEventListener("input", () => {
|
|
stickyNote.content = textarea.value;
|
|
if (saveTimeout) {
|
|
clearTimeout(saveTimeout);
|
|
}
|
|
saveTimeout = setTimeout(() => {
|
|
onSave();
|
|
}, 250);
|
|
});
|
|
}
|
|
|
|
// On window resize
|
|
window.addEventListener("resize", () => {
|
|
const modTop = `${stickyNote.top - Math.min(window.innerHeight - noteElement.offsetHeight, stickyNote.top)}px`;
|
|
const modLeft = `${stickyNote.left - Math.min(window.innerWidth - noteElement.offsetWidth, stickyNote.left)}px`;
|
|
noteElement.style.transform = `scale(var(--birb-ui-scale)) translate(-${modLeft}, -${modTop})`;
|
|
});
|
|
|
|
return noteElement;
|
|
}
|
|
|
|
/**
|
|
* @param {StickyNote[]} stickyNotes
|
|
* @param {() => void} onSave
|
|
* @param {(note: StickyNote) => void} onDelete
|
|
*/
|
|
export function drawStickyNotes(stickyNotes, onSave, onDelete) {
|
|
// Remove all existing sticky notes
|
|
const existingNotes = document.querySelectorAll(".birb-sticky-note");
|
|
existingNotes.forEach(note => note.remove());
|
|
// Render all sticky notes
|
|
const pageElement = getContext().getActivePage();
|
|
const context = getContext();
|
|
for (let stickyNote of stickyNotes) {
|
|
if (context.isPathApplicable(stickyNote.site)) {
|
|
renderStickyNote(stickyNote, pageElement, onSave, () => onDelete(stickyNote));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {StickyNote[]} stickyNotes
|
|
* @param {() => void} onSave
|
|
* @param {(note: StickyNote) => void} onDelete
|
|
*/
|
|
export function createNewStickyNote(stickyNotes, onSave, onDelete) {
|
|
if (getContext().areStickyNotesEnabled() === false) {
|
|
return;
|
|
}
|
|
const id = Date.now().toString();
|
|
const site = getContext().getPath();
|
|
const stickyNote = new StickyNote(id, site, "");
|
|
const page = getContext().getActivePage();
|
|
const element = renderStickyNote(stickyNote, page, onSave, () => onDelete(stickyNote));
|
|
element.style.left = `${page.clientWidth / 2 - element.offsetWidth / 2}px`;
|
|
element.style.top = `${page.scrollTop + page.clientHeight / 2 - element.offsetHeight / 2}px`;
|
|
stickyNote.top = parseInt(element.style.top, 10);
|
|
stickyNote.left = parseInt(element.style.left, 10);
|
|
stickyNotes.push(stickyNote);
|
|
onSave();
|
|
}
|
|
|
|
/**
|
|
* Get a color based on the mod of the sticky note ID
|
|
* @param {string} id
|
|
* @returns {string} A color hex code
|
|
*/
|
|
function getColor(id) {
|
|
const colors = ["#ff8baa", "#79bcff", "#d18bff", "#6de192", "#ffd17c", "#ffb37c", "#ff7c7c"];
|
|
const index = parseInt(id, 10) % colors.length;
|
|
return colors[index];
|
|
}
|