Separate sticky note logic

This commit is contained in:
Idrees Hassan
2025-10-26 14:04:40 -04:00
parent 45ed91a531
commit ef764153b9
5 changed files with 881 additions and 473 deletions

View File

@@ -12,6 +12,7 @@ import {
import Frame from './frame.js';
import Layer from './layer.js';
import Anim from './anim.js';
import { StickyNote, createNewStickyNote, drawStickyNotes } from './stickyNotes.js';
// @ts-ignore
const SHARED_CONFIG = {
@@ -50,12 +51,7 @@ const DEFAULT_SETTINGS = {
*/
/**
* @typedef {Object} SavedStickyNote
* @property {string} id
* @property {string} site
* @property {string} content
* @property {number} top
* @property {number} left
* @typedef {import('./stickyNotes.js').SavedStickyNote} SavedStickyNote
*/
/**
@@ -306,27 +302,10 @@ Promise.all([
}
}
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;
}
}
const menuItems = [
new MenuItem(`Pet ${birdBirb()}`, pet),
new MenuItem("Field Guide", insertFieldGuide),
new MenuItem("Sticky Note", newStickyNote),
new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)),
new MenuItem(`Hide ${birdBirb()}`, hideBirb),
new DebugMenuItem("Freeze/Unfreeze", () => {
frozen = !frozen;
@@ -582,7 +561,7 @@ Promise.all([
pet();
});
drawStickyNotes();
drawStickyNotes(stickyNotes, save, deleteStickyNote);
let lastUrl = (window.location.href ?? "").split("?")[0];
setInterval(() => {
@@ -590,7 +569,7 @@ Promise.all([
if (currentUrl !== lastUrl) {
log("URL changed, updating sticky notes");
lastUrl = currentUrl;
drawStickyNotes();
drawStickyNotes(stickyNotes, save, deleteStickyNote);
}
}, URL_CHECK_INTERVAL);
@@ -677,81 +656,6 @@ Promise.all([
setY(birdY);
}
function newStickyNote() {
const id = Date.now().toString();
const site = window.location.href;
const stickyNote = new StickyNote(id, site, "");
const element = renderStickyNote(stickyNote);
element.style.left = `${window.innerWidth / 2 - element.offsetWidth / 2}px`;
element.style.top = `${window.scrollY + window.innerHeight / 2 - element.offsetHeight / 2}px`;
stickyNote.top = parseInt(element.style.top, 10);
stickyNote.left = parseInt(element.style.left, 10);
stickyNotes.push(stickyNote);
save();
}
/**
* @param {StickyNote} stickyNote
* @returns {HTMLElement}
*/
function renderStickyNote(stickyNote) {
let html = `
<div class="birb-window-header">
<div class="birb-window-title">Sticky Note</div>
<div class="birb-window-close">x</div>
</div>
<div class="birb-window-content">
<textarea class="birb-sticky-note-input" style="width: 150px;" placeholder="Write your notes here and they'll stick to the page!">${stickyNote.content}</textarea>
</div>`
const noteElement = makeElement("birb-window");
noteElement.classList.add("birb-sticky-note");
noteElement.innerHTML = html;
noteElement.style.top = `${stickyNote.top}px`;
noteElement.style.left = `${stickyNote.left}px`;
document.body.appendChild(noteElement);
makeDraggable(noteElement.querySelector(".birb-window-header"), true, (top, left) => {
stickyNote.top = top;
stickyNote.left = left;
save();
});
const closeButton = noteElement.querySelector(".birb-window-close");
if (closeButton) {
makeClosable(() => {
if (confirm("Are you sure you want to delete this sticky note?")) {
deleteStickyNote(stickyNote);
noteElement.remove();
}
}, closeButton);
}
const textarea = noteElement.querySelector(".birb-sticky-note-input");
if (textarea && textarea instanceof HTMLTextAreaElement) {
let saveTimeout;
// Save after debounce
textarea.addEventListener("input", () => {
stickyNote.content = textarea.value;
if (saveTimeout) {
clearTimeout(saveTimeout);
}
saveTimeout = setTimeout(() => {
save();
}, 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} stickyNote
*/
@@ -760,47 +664,6 @@ Promise.all([
save();
}
/**
* @param {StickyNote} stickyNote
* @returns {boolean} Whether the given sticky note is applicable to the current site/page
*/
function isStickyNoteApplicable(stickyNote) {
const stickyNoteUrl = stickyNote.site;
const currentUrl = window.location.href;
const stickyNoteWebsite = stickyNoteUrl.split("?")[0];
const currentWebsite = currentUrl.split("?")[0];
debug("Comparing " + stickyNoteUrl + " with " + currentUrl);
if (stickyNoteWebsite !== currentWebsite) {
return false;
}
const stickyNoteParams = parseUrlParams(stickyNoteUrl);
const currentParams = parseUrlParams(currentUrl);
debug("Comparing params: ", stickyNoteParams, currentParams);
if (window.location.hostname === "www.youtube.com") {
if (currentParams.v !== undefined && currentParams.v !== stickyNoteParams.v) {
return false;
}
}
return true;
}
function drawStickyNotes() {
// Remove all existing sticky notes
const existingNotes = document.querySelectorAll(".birb-sticky-note");
existingNotes.forEach(note => note.remove());
// Render all sticky notes
for (let stickyNote of stickyNotes) {
if (isStickyNoteApplicable(stickyNote)) {
renderStickyNote(stickyNote);
}
}
}
/**
* Create an HTML element with the specified parameters
* @param {string} className
@@ -1540,21 +1403,6 @@ Promise.all([
return { x, y };
}
/**
* Parse URL parameters into a key-value map
* @param {string} url
* @returns {Record<string, string>}
*/
function parseUrlParams(url) {
const queryString = url.split("?")[1];
if (!queryString) return {};
return queryString.split("&").reduce((params, param) => {
const [key, value] = param.split("=");
return { ...params, [key]: value };
}, {});
}
// Run the birb
init();
draw();