From 3fe52e549282d91dd0a991ce5b4bb7a410278104 Mon Sep 17 00:00:00 2001 From: Idrees Hassan Date: Mon, 3 Nov 2025 21:21:29 -0500 Subject: [PATCH 01/10] Use constants for paths --- browser-manifest.json | 2 +- build.js | 54 ++++++++++++++++++++++------------- dist/birb.js | 2 +- dist/extension.zip | Bin 147747 -> 147747 bytes dist/extension/birb.js | 2 +- dist/extension/manifest.json | 2 +- dist/userscript/birb.user.js | 4 +-- 7 files changed, 40 insertions(+), 26 deletions(-) diff --git a/browser-manifest.json b/browser-manifest.json index 43bf50d..89baa28 100644 --- a/browser-manifest.json +++ b/browser-manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.3.10", + "version": "2025.11.3.21", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/build.js b/build.js index 3ff16b1..518379c 100644 --- a/build.js +++ b/build.js @@ -4,20 +4,34 @@ import { rollup } from 'rollup'; import { readFileSync, writeFileSync, mkdirSync, unlinkSync, cpSync, createWriteStream } from 'fs'; import archiver from 'archiver'; +// Path constants +const SRC_DIR = "./src"; +const SPRITES_DIR = "./sprites"; +const IMAGES_DIR = "./images"; +const FONTS_DIR = "./fonts"; +const DIST_DIR = "./dist"; + +const BROWSER_MANIFEST = "./browser-manifest.json"; +const STYLESHEET_PATH = SRC_DIR + "/stylesheet.css"; +const APPLICATION_ENTRY = SRC_DIR + "/application.js"; +const BUNDLED_OUTPUT = DIST_DIR + "/birb.bundled.js"; +const BIRB_OUTPUT = DIST_DIR + "/birb.js"; +const USERSCRIPT_DIR = DIST_DIR + "/userscript"; +const EXTENSION_DIR = DIST_DIR + "/extension"; +const EXTENSION_ZIP = DIST_DIR + "/extension.zip"; + const spriteSheets = [ { key: "__SPRITE_SHEET__", - path: "./sprites/birb.png" + path: SPRITES_DIR + "/birb.png" }, { key: "__FEATHER_SPRITE_SHEET__", - path: "./sprites/feather.png" + path: SPRITES_DIR + "/feather.png" } ]; -const STYLESHEET_PATH = "./src/stylesheet.css"; const STYLESHEET_KEY = "___STYLESHEET___"; -const BROWSER_MANIFEST = "./browser-manifest.json"; const now = new Date(); const versionDate = `${now.getFullYear()}.${now.getMonth() + 1}.${now.getDate()}`; @@ -70,20 +84,20 @@ const userScriptHeader = // Bundle with rollup const bundle = await rollup({ - input: 'src/application.js', + input: APPLICATION_ENTRY, }); await bundle.write({ - file: 'dist/birb.bundled.js', + file: BUNDLED_OUTPUT, format: 'iife', }); await bundle.close(); -let birbJs = readFileSync('dist/birb.bundled.js', 'utf8'); +let birbJs = readFileSync(BUNDLED_OUTPUT, 'utf8'); // Delete bundled file -unlinkSync('./dist/birb.bundled.js'); +unlinkSync(BUNDLED_OUTPUT); // Replace version placeholder birbJs = birbJs.replaceAll('__VERSION__', version); @@ -99,33 +113,33 @@ const stylesheetContent = readFileSync(STYLESHEET_PATH, 'utf8'); birbJs = birbJs.replace(STYLESHEET_KEY, stylesheetContent); // Build standard javascript file -writeFileSync('./dist/birb.js', birbJs); +writeFileSync(BIRB_OUTPUT, birbJs); // Build user script -mkdirSync('./dist/userscript', { recursive: true }); +mkdirSync(USERSCRIPT_DIR, { recursive: true }); const userScript = userScriptHeader + birbJs; -writeFileSync('./dist/userscript/birb.user.js', userScript); +writeFileSync(USERSCRIPT_DIR + '/birb.user.js', userScript); // Build browser extension -mkdirSync('./dist/extension', { recursive: true }); +mkdirSync(EXTENSION_DIR, { recursive: true }); // Copy birb.js -writeFileSync('./dist/extension/birb.js', birbJs); +writeFileSync(EXTENSION_DIR + '/birb.js', birbJs); // Copy manifest.json const manifestContent = readFileSync(BROWSER_MANIFEST, 'utf8'); -writeFileSync('./dist/extension/manifest.json', manifestContent); +writeFileSync(EXTENSION_DIR + '/manifest.json', manifestContent); // Copy icons folder -mkdirSync('./dist/extension/images/icons', { recursive: true }); -cpSync('./images/icons/transparent', './dist/extension/images/icons/transparent', { recursive: true }); +mkdirSync(EXTENSION_DIR + '/images/icons', { recursive: true }); +cpSync(IMAGES_DIR + '/icons/transparent', EXTENSION_DIR + '/images/icons/transparent', { recursive: true }); // Copy fonts folder -mkdirSync('./dist/extension/fonts', { recursive: true }); -cpSync('./fonts', './dist/extension/fonts', { recursive: true }); +mkdirSync(EXTENSION_DIR + '/fonts', { recursive: true }); +cpSync(FONTS_DIR, EXTENSION_DIR + '/fonts', { recursive: true }); // Compress extension folder into zip -const output = createWriteStream('./dist/extension.zip'); +const output = createWriteStream(EXTENSION_ZIP); const archive = archiver('zip'); output.on('close', () => { @@ -137,7 +151,7 @@ archive.on('error', (err) => { }); archive.pipe(output); -archive.directory('./dist/extension/', false); +archive.directory(EXTENSION_DIR + '/', false); archive.finalize(); console.log(`Build complete: ${version}`); \ No newline at end of file diff --git a/dist/birb.js b/dist/birb.js index a54a94c..8238205 100644 --- a/dist/birb.js +++ b/dist/birb.js @@ -1867,7 +1867,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.10", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.10"); }, false), + new MenuItem("2025.11.3.21", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.21"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension.zip b/dist/extension.zip index 52d5f521104a6d5c046fa5f1410560139c0ecc02..bee307181bcf21ee5410cf81b609546e24e58393 100644 GIT binary patch delta 8423 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 K#TRj)$o~M(nS?$7 delta 8423 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 L(~CVZpz!|y>Vs{W diff --git a/dist/extension/birb.js b/dist/extension/birb.js index a54a94c..8238205 100644 --- a/dist/extension/birb.js +++ b/dist/extension/birb.js @@ -1867,7 +1867,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.10", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.10"); }, false), + new MenuItem("2025.11.3.21", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.21"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension/manifest.json b/dist/extension/manifest.json index 43bf50d..89baa28 100644 --- a/dist/extension/manifest.json +++ b/dist/extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.3.10", + "version": "2025.11.3.21", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/dist/userscript/birb.user.js b/dist/userscript/birb.user.js index c668e1d..40a1f10 100644 --- a/dist/userscript/birb.user.js +++ b/dist/userscript/birb.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Pocket Bird // @namespace https://idreesinc.com -// @version 2025.11.3.10 +// @version 2025.11.3.21 // @description It's a bird that hops around your web browser, the future is here // @author Idrees // @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js @@ -1881,7 +1881,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.10", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.10"); }, false), + new MenuItem("2025.11.3.21", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.21"); }, false), ]; const styleElement = document.createElement("style"); From e50c2c8a1f3b53c64b590e740c0efd7ee04eeadf Mon Sep 17 00:00:00 2001 From: Idrees Hassan Date: Mon, 3 Nov 2025 21:35:27 -0500 Subject: [PATCH 02/10] Add obsidian build --- .gitignore | 1 + browser-manifest.json | 2 +- build.js | 31 +- dist/birb.js | 2 +- dist/extension.zip | Bin 147747 -> 147747 bytes dist/extension/birb.js | 2 +- dist/extension/manifest.json | 2 +- dist/obsidian/main.js | 2659 ++++++++++++++++++++++++++++++++++ dist/obsidian/manifest.json | 10 + dist/userscript/birb.user.js | 4 +- obsidian-manifest.json | 10 + 11 files changed, 2712 insertions(+), 11 deletions(-) create mode 100644 dist/obsidian/main.js create mode 100644 dist/obsidian/manifest.json create mode 100644 obsidian-manifest.json diff --git a/.gitignore b/.gitignore index 43d5463..6be2695 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /node_modules .DS_Store /dist/birb.bundled.js +obsidian-test.sh diff --git a/browser-manifest.json b/browser-manifest.json index 89baa28..c9dad73 100644 --- a/browser-manifest.json +++ b/browser-manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.3.21", + "version": "2025.11.3.34", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/build.js b/build.js index 518379c..8fbfa16 100644 --- a/build.js +++ b/build.js @@ -12,13 +12,15 @@ const FONTS_DIR = "./fonts"; const DIST_DIR = "./dist"; const BROWSER_MANIFEST = "./browser-manifest.json"; +const OBSIDIAN_MANIFEST = "./obsidian-manifest.json"; +const USERSCRIPT_DIR = DIST_DIR + "/userscript"; +const EXTENSION_DIR = DIST_DIR + "/extension"; +const OBSIDIAN_DIR = DIST_DIR + "/obsidian"; + const STYLESHEET_PATH = SRC_DIR + "/stylesheet.css"; const APPLICATION_ENTRY = SRC_DIR + "/application.js"; const BUNDLED_OUTPUT = DIST_DIR + "/birb.bundled.js"; const BIRB_OUTPUT = DIST_DIR + "/birb.js"; -const USERSCRIPT_DIR = DIST_DIR + "/userscript"; -const EXTENSION_DIR = DIST_DIR + "/extension"; -const EXTENSION_ZIP = DIST_DIR + "/extension.zip"; const spriteSheets = [ { @@ -54,8 +56,9 @@ try { throw e; } -// Update manifest.json with new version const version = `${versionDate}.${buildNumber}`; + +// Update browser manifest with new version try { const manifest = JSON.parse(readFileSync(BROWSER_MANIFEST, 'utf8')); manifest.version = version; @@ -65,6 +68,14 @@ try { throw e; } +try { + const obsidianManifest = JSON.parse(readFileSync(OBSIDIAN_MANIFEST, 'utf8')); + obsidianManifest.version = version; + writeFileSync(OBSIDIAN_MANIFEST, JSON.stringify(obsidianManifest, null, 4), 'utf8'); +} catch (e) { + console.error("Could not update version in Obsidian manifest"); +} + const userScriptHeader = `// ==UserScript== // @name Pocket Bird @@ -139,7 +150,7 @@ mkdirSync(EXTENSION_DIR + '/fonts', { recursive: true }); cpSync(FONTS_DIR, EXTENSION_DIR + '/fonts', { recursive: true }); // Compress extension folder into zip -const output = createWriteStream(EXTENSION_ZIP); +const output = createWriteStream(DIST_DIR + "/extension.zip"); const archive = archiver('zip'); output.on('close', () => { @@ -154,4 +165,14 @@ archive.pipe(output); archive.directory(EXTENSION_DIR + '/', false); archive.finalize(); +// Build Obsidian plugin +mkdirSync(OBSIDIAN_DIR, { recursive: true }); + +// Copy birb.js to main.js +writeFileSync(OBSIDIAN_DIR + '/main.js', birbJs); + +// Copy manifest.json +const obsidianManifestContent = readFileSync(OBSIDIAN_MANIFEST, 'utf8'); +writeFileSync(OBSIDIAN_DIR + '/manifest.json', obsidianManifestContent); + console.log(`Build complete: ${version}`); \ No newline at end of file diff --git a/dist/birb.js b/dist/birb.js index 8238205..de3a838 100644 --- a/dist/birb.js +++ b/dist/birb.js @@ -1867,7 +1867,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.21", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.21"); }, false), + new MenuItem("2025.11.3.34", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.34"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension.zip b/dist/extension.zip index bee307181bcf21ee5410cf81b609546e24e58393..b2ae7684c633f944649dcab7321504746f5f0ac2 100644 GIT binary patch delta 8585 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 QfWber|7R^eivvXd2OZYhY5)KL diff --git a/dist/extension/birb.js b/dist/extension/birb.js index 8238205..de3a838 100644 --- a/dist/extension/birb.js +++ b/dist/extension/birb.js @@ -1867,7 +1867,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.21", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.21"); }, false), + new MenuItem("2025.11.3.34", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.34"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension/manifest.json b/dist/extension/manifest.json index 89baa28..c9dad73 100644 --- a/dist/extension/manifest.json +++ b/dist/extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.3.21", + "version": "2025.11.3.34", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/dist/obsidian/main.js b/dist/obsidian/main.js new file mode 100644 index 0000000..de3a838 --- /dev/null +++ b/dist/obsidian/main.js @@ -0,0 +1,2659 @@ +(function () { + 'use strict'; + + const Directions = { + LEFT: -1, + RIGHT: 1, + }; + + let debugMode = location.hostname === "127.0.0.1"; + + /** + * @returns {boolean} Whether debug mode is enabled + */ + function isDebug() { + return debugMode; + } + + /** + * @param {boolean} value + */ + function setDebug(value) { + debugMode = value; + } + + /** + * Create an HTML element with the specified parameters + * @param {string} className + * @param {string} [textContent] + * @param {string} [id] + * @returns {HTMLElement} + */ + function makeElement(className, textContent, id) { + const element = document.createElement("div"); + element.classList.add(className); + if (textContent) { + element.textContent = textContent; + } + if (id) { + element.id = id; + } + return element; + } + + /** + * @param {Document|Element} element + * @param {(e: Event) => void} action + */ + function onClick(element, action) { + element.addEventListener("click", (e) => action(e)); + element.addEventListener("touchend", (e) => { + if (e instanceof TouchEvent === false) { + return; + } else if (element instanceof HTMLElement === false) { + return; + } + const touch = e.changedTouches[0]; + const rect = element.getBoundingClientRect(); + if ( + touch.clientX >= rect.left && + touch.clientX <= rect.right && + touch.clientY >= rect.top && + touch.clientY <= rect.bottom + ) { + action(e); + } + }); + } + + /** + * @param {HTMLElement|null} element The element to detect drag events on + * @param {boolean} [parent] Whether to move the parent element when the child is dragged + * @param {(top: number, left: number) => void} [callback] Callback for when element is moved + */ + function makeDraggable(element, parent = true, callback = () => { }) { + if (!element) { + return; + } + + let isMouseDown = false; + let offsetX = 0; + let offsetY = 0; + let elementToMove = parent ? element.parentElement : element; + + if (!elementToMove) { + error("Birb: Parent element not found"); + return; + } + + element.addEventListener("mousedown", (e) => { + isMouseDown = true; + offsetX = e.clientX - elementToMove.offsetLeft; + offsetY = e.clientY - elementToMove.offsetTop; + }); + + element.addEventListener("touchstart", (e) => { + isMouseDown = true; + const touch = e.touches[0]; + offsetX = touch.clientX - elementToMove.offsetLeft; + offsetY = touch.clientY - elementToMove.offsetTop; + e.preventDefault(); + }); + + document.addEventListener("mouseup", (e) => { + if (isMouseDown) { + callback(elementToMove.offsetTop, elementToMove.offsetLeft); + e.preventDefault(); + } + isMouseDown = false; + }); + + document.addEventListener("touchend", (e) => { + if (isMouseDown) { + callback(elementToMove.offsetTop, elementToMove.offsetLeft); + e.preventDefault(); + } + isMouseDown = false; + }); + + document.addEventListener("mousemove", (e) => { + if (isMouseDown) { + elementToMove.style.left = `${Math.max(0, e.clientX - offsetX)}px`; + elementToMove.style.top = `${Math.max(0, e.clientY - offsetY)}px`; + } + }); + + document.addEventListener("touchmove", (e) => { + if (isMouseDown) { + const touch = e.touches[0]; + elementToMove.style.left = `${Math.max(0, touch.clientX - offsetX)}px`; + elementToMove.style.top = `${Math.max(0, touch.clientY - offsetY)}px`; + } + }); + } + + /** + * @param {() => void} func + * @param {Element} [closeButton] + */ + function makeClosable(func, closeButton) { + if (closeButton) { + onClick(closeButton, func); + } + document.addEventListener("keydown", (e) => { + if (closeButton && !document.body.contains(closeButton)) { + return; + } + if (e.key === "Escape") { + func(); + } + }); + } + + /** + * @returns {boolean} Whether the user is on a mobile device + */ + function isMobile() { + return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); + } + + function log() { + console.log("Birb: ", ...arguments); + } + + function debug() { + if (isDebug()) { + console.debug("Birb: ", ...arguments); + } + } + + function error() { + console.error("Birb: ", ...arguments); + } + + /** + * Get a layer from a sprite sheet array + * @param {string[][]} spriteSheet The sprite sheet pixel array + * @param {number} spriteIndex The sprite index + * @param {number} width The width of each sprite + * @returns {string[][]} + */ + function getLayer(spriteSheet, spriteIndex, width) { + // From an array of a horizontal sprite sheet, get the layer for a specific sprite + const layer = []; + for (let y = 0; y < width; y++) { + layer.push(spriteSheet[y].slice(spriteIndex * width, (spriteIndex + 1) * width)); + } + return layer; + } + + /** + * The height of the inner browser window + * Will be the same as getFixedWindowHeight() on most browsers + * On iOS, it will vary to be the height excluding the current address bar size (potentially greater than fixed height) + */ + function getWindowHeight() { + // Necessary because iOS 26 Safari is terrible and won't render + // fixed/sticky elements behind the address bar + return window.innerHeight; + } + + /** + * The fixed height of the inner browser window + * Will be the same as getWindowHeight() on most browsers + * On iOS, it will always be the height of the window when the address bar is fully expanded + * @returns The true height of the inner browser window + */ + function getFixedWindowHeight() { + return document.documentElement.clientHeight; + } + + /** Indicators for parts of the base bird sprite sheet */ + const Sprite = { + THEME_HIGHLIGHT: "theme-highlight", + TRANSPARENT: "transparent", + OUTLINE: "outline", + BORDER: "border", + FOOT: "foot", + BEAK: "beak", + EYE: "eye", + FACE: "face", + HOOD: "hood", + NOSE: "nose", + BELLY: "belly", + UNDERBELLY: "underbelly", + WING: "wing", + WING_EDGE: "wing-edge", + HEART: "heart", + HEART_BORDER: "heart-border", + HEART_SHINE: "heart-shine", + FEATHER_SPINE: "feather-spine", + }; + + /** @type {Record} */ + const SPRITE_SHEET_COLOR_MAP = { + "transparent": Sprite.TRANSPARENT, + "#ffffff": Sprite.BORDER, + "#000000": Sprite.OUTLINE, + "#010a19": Sprite.BEAK, + "#190301": Sprite.EYE, + "#af8e75": Sprite.FOOT, + "#639bff": Sprite.FACE, + "#99e550": Sprite.HOOD, + "#d95763": Sprite.NOSE, + "#f8b143": Sprite.BELLY, + "#ec8637": Sprite.UNDERBELLY, + "#578ae6": Sprite.WING, + "#326ed9": Sprite.WING_EDGE, + "#c82e2e": Sprite.HEART, + "#501a1a": Sprite.HEART_BORDER, + "#ff6b6b": Sprite.HEART_SHINE, + "#373737": Sprite.FEATHER_SPINE, + }; + + class BirdType { + /** + * @param {string} name + * @param {string} description + * @param {Record} colors + * @param {string[]} [tags] + */ + constructor(name, description, colors, tags = []) { + this.name = name; + this.description = description; + const defaultColors = { + [Sprite.TRANSPARENT]: "transparent", + [Sprite.OUTLINE]: "#000000", + [Sprite.BORDER]: "#ffffff", + [Sprite.BEAK]: "#000000", + [Sprite.EYE]: "#000000", + [Sprite.HEART]: "#c82e2e", + [Sprite.HEART_BORDER]: "#501a1a", + [Sprite.HEART_SHINE]: "#ff6b6b", + [Sprite.FEATHER_SPINE]: "#373737", + [Sprite.HOOD]: colors.face, + [Sprite.NOSE]: colors.face, + }; + /** @type {Record} */ + this.colors = { ...defaultColors, ...colors, [Sprite.THEME_HIGHLIGHT]: colors[Sprite.THEME_HIGHLIGHT] ?? colors.hood ?? colors.face }; + this.tags = tags; + } + } + + /** @type {Record} */ + const SPECIES = { + bluebird: new BirdType("Eastern Bluebird", + "Native to North American and very social, though can be timid around people.", { + [Sprite.FOOT]: "#af8e75", + [Sprite.FACE]: "#639bff", + [Sprite.BELLY]: "#f8b143", + [Sprite.UNDERBELLY]: "#ec8637", + [Sprite.WING]: "#578ae6", + [Sprite.WING_EDGE]: "#326ed9", + }), + shimaEnaga: new BirdType("Shima Enaga", + "Small, fluffy birds found in the snowy regions of Japan, these birds are highly sought after by ornithologists and nature photographers.", { + [Sprite.FOOT]: "#af8e75", + [Sprite.FACE]: "#ffffff", + [Sprite.BELLY]: "#ebe9e8", + [Sprite.UNDERBELLY]: "#ebd9d0", + [Sprite.WING]: "#f3d3c1", + [Sprite.WING_EDGE]: "#2d2d2dff", + [Sprite.THEME_HIGHLIGHT]: "#d7ac93", + }), + tuftedTitmouse: new BirdType("Tufted Titmouse", + "Native to the eastern United States, full of personality, and notably my wife's favorite bird.", { + [Sprite.FOOT]: "#af8e75", + [Sprite.FACE]: "#c7cad7", + [Sprite.BELLY]: "#e4e5eb", + [Sprite.UNDERBELLY]: "#d7cfcb", + [Sprite.WING]: "#b1b5c5", + [Sprite.WING_EDGE]: "#9d9fa9", + }, ["tuft"]), + europeanRobin: new BirdType("European Robin", + "Native to western Europe, this is the quintessential robin. Quite friendly, you'll often find them searching for worms.", { + [Sprite.FOOT]: "#af8e75", + [Sprite.FACE]: "#ffaf34", + [Sprite.HOOD]: "#aaa094", + [Sprite.BELLY]: "#ffaf34", + [Sprite.UNDERBELLY]: "#babec2", + [Sprite.WING]: "#aaa094", + [Sprite.WING_EDGE]: "#888580", + [Sprite.THEME_HIGHLIGHT]: "#ffaf34", + }), + redCardinal: new BirdType("Red Cardinal", + "Native to the eastern United States, this strikingly red bird is hard to miss.", { + [Sprite.BEAK]: "#d93619", + [Sprite.FOOT]: "#af8e75", + [Sprite.FACE]: "#31353d", + [Sprite.HOOD]: "#e83a1b", + [Sprite.BELLY]: "#e83a1b", + [Sprite.UNDERBELLY]: "#dc3719", + [Sprite.WING]: "#d23215", + [Sprite.WING_EDGE]: "#b1321c", + }, ["tuft"]), + americanGoldfinch: new BirdType("American Goldfinch", + "Coloured a brilliant yellow, this bird feeds almost entirely on the seeds of plants such as thistle, sunflowers, and coneflowers.", { + [Sprite.BEAK]: "#ffaf34", + [Sprite.FOOT]: "#af8e75", + [Sprite.FACE]: "#fff255", + [Sprite.NOSE]: "#383838", + [Sprite.HOOD]: "#383838", + [Sprite.BELLY]: "#fff255", + [Sprite.UNDERBELLY]: "#f5ea63", + [Sprite.WING]: "#e8e079", + [Sprite.WING_EDGE]: "#191919", + [Sprite.THEME_HIGHLIGHT]: "#ffcc00" + }), + barnSwallow: new BirdType("Barn Swallow", + "Agile birds that often roost in man-made structures, these birds are known to build nests near Ospreys for protection.", { + [Sprite.FOOT]: "#af8e75", + [Sprite.FACE]: "#db7c4d", + [Sprite.BELLY]: "#f7e1c9", + [Sprite.UNDERBELLY]: "#ebc9a3", + [Sprite.WING]: "#2252a9", + [Sprite.WING_EDGE]: "#1c448b", + [Sprite.HOOD]: "#2252a9", + }), + mistletoebird: new BirdType("Mistletoebird", + "Native to Australia, these birds eat mainly mistletoe and in turn spread the seeds far and wide.", { + [Sprite.FOOT]: "#6c6a7c", + [Sprite.FACE]: "#352e6d", + [Sprite.BELLY]: "#fd6833", + [Sprite.UNDERBELLY]: "#e6e1d8", + [Sprite.WING]: "#342b7c", + [Sprite.WING_EDGE]: "#282065", + }), + redAvadavat: new BirdType("Red Avadavat", + "Native to India and southeast Asia, these birds are also known as Strawberry Finches due to their speckled plumage.", { + [Sprite.BEAK]: "#f71919", + [Sprite.FOOT]: "#af7575", + [Sprite.FACE]: "#cb092b", + [Sprite.BELLY]: "#ae1724", + [Sprite.UNDERBELLY]: "#831b24", + [Sprite.WING]: "#7e3030", + [Sprite.WING_EDGE]: "#490f0f", + }), + scarletRobin: new BirdType("Scarlet Robin", + "Native to Australia, this striking robin can be found in Eucalyptus forests.", { + [Sprite.FOOT]: "#494949", + [Sprite.FACE]: "#3d3d3d", + [Sprite.BELLY]: "#fc5633", + [Sprite.UNDERBELLY]: "#dcdcdc", + [Sprite.WING]: "#2b2b2b", + [Sprite.WING_EDGE]: "#ebebeb", + [Sprite.THEME_HIGHLIGHT]: "#fc5633", + }), + americanRobin: new BirdType("American Robin", + "While not a true robin, this social North American bird is so named due to its orange coloring. It seems unbothered by nearby humans.", { + [Sprite.BEAK]: "#e89f30", + [Sprite.FOOT]: "#9f8075", + [Sprite.FACE]: "#2d2d2d", + [Sprite.BELLY]: "#eb7a3a", + [Sprite.UNDERBELLY]: "#eb7a3a", + [Sprite.WING]: "#444444", + [Sprite.WING_EDGE]: "#232323", + [Sprite.THEME_HIGHLIGHT]: "#eb7a3a", + }), + carolinaWren: new BirdType("Carolina Wren", + "Native to the eastern United States, these little birds are known for their curious and energetic nature.", { + [Sprite.FOOT]: "#af8e75", + [Sprite.FACE]: "#edc7a9", + [Sprite.NOSE]: "#f7eee5", + [Sprite.HOOD]: "#c58a5b", + [Sprite.BELLY]: "#e1b796", + [Sprite.UNDERBELLY]: "#c79e7c", + [Sprite.WING]: "#c58a5b", + [Sprite.WING_EDGE]: "#866348", + }), + }; + + class Layer { + /** + * @param {string[][]} pixels + * @param {string} [tag] + */ + constructor(pixels, tag = "default") { + this.pixels = pixels; + this.tag = tag; + } + } + + class Frame { + + /** @type {{ [tag: string]: string[][] }} */ + #pixelsByTag = {}; + + /** + * @param {Layer[]} layers + */ + constructor(layers) { + /** @type {Set} */ + let tags = new Set(); + for (let layer of layers) { + tags.add(layer.tag); + } + tags.add("default"); + for (let tag of tags) { + let maxHeight = layers.reduce((max, layer) => Math.max(max, layer.pixels.length), 0); + if (layers[0].tag !== "default") { + throw new Error("First layer must have the 'default' tag"); + } + this.pixels = layers[0].pixels.map(row => row.slice()); + // Pad from top with transparent pixels + while (this.pixels.length < maxHeight) { + this.pixels.unshift(new Array(this.pixels[0].length).fill(Sprite.TRANSPARENT)); + } + // Combine layers + for (let i = 1; i < layers.length; i++) { + if (layers[i].tag === "default" || layers[i].tag === tag) { + let layerPixels = layers[i].pixels; + let topMargin = maxHeight - layerPixels.length; + for (let y = 0; y < layerPixels.length; y++) { + for (let x = 0; x < layerPixels[y].length; x++) { + this.pixels[y + topMargin][x] = layerPixels[y][x] !== Sprite.TRANSPARENT ? layerPixels[y][x] : this.pixels[y + topMargin][x]; + } + } + } + } + this.#pixelsByTag[tag] = this.pixels.map(row => row.slice()); + } + } + + /** + * @param {string} [tag] + * @returns {string[][]} + */ + getPixels(tag = "default") { + return this.#pixelsByTag[tag] ?? this.#pixelsByTag["default"]; + } + + /** + * @param {CanvasRenderingContext2D} ctx + * @param {BirdType} [species] + * @param {number} direction + * @param {number} canvasPixelSize + */ + draw(ctx, direction, canvasPixelSize, species) { + // Clear the canvas before drawing the new frame + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + + const pixels = this.getPixels(species?.tags[0]); + for (let y = 0; y < pixels.length; y++) { + const row = pixels[y]; + for (let x = 0; x < pixels[y].length; x++) { + const cell = direction === Directions.LEFT ? row[x] : row[pixels[y].length - x - 1]; + ctx.fillStyle = species?.colors[cell] ?? cell; + ctx.fillRect(x * canvasPixelSize, y * canvasPixelSize, canvasPixelSize, canvasPixelSize); + } } } + } + + class Anim { + /** + * @param {Frame[]} frames + * @param {number[]} durations + * @param {boolean} loop + */ + constructor(frames, durations, loop = true) { + this.frames = frames; + this.durations = durations; + this.loop = loop; + this.lastFrameIndex = -1; + this.lastDirection = null; + this.lastTimeStart = null; + } + + getAnimationDuration() { + return this.durations.reduce((a, b) => a + b, 0); + } + + /** + * Get the current frame index based on elapsed time + * @param {number} time The elapsed time since animation start + * @returns {number} The index of the current frame + */ + getCurrentFrameIndex(time) { + let totalDuration = 0; + for (let i = 0; i < this.durations.length; i++) { + totalDuration += this.durations[i]; + if (time < totalDuration) { + return i; + } + } + return this.frames.length - 1; + } + + /** + * Clear the cached frame state + */ + #clearCache() { + this.lastFrameIndex = -1; + this.lastDirection = null; + } + + /** + * Check if the frame needs to be redrawn + * @param {number} frameIndex The current frame index + * @param {number} direction The current direction + * @returns {boolean} Whether the frame needs to be redrawn + */ + #shouldRedraw(frameIndex, direction) { + return frameIndex !== this.lastFrameIndex || direction !== this.lastDirection; + } + + /** + * @param {CanvasRenderingContext2D} ctx + * @param {number} direction + * @param {number} timeStart The start time of the animation in milliseconds + * @param {number} canvasPixelSize The size of a canvas pixel in pixels + * @param {BirdType} [species] The species to use for the animation + * @returns {boolean} Whether the animation is complete + */ + draw(ctx, direction, timeStart, canvasPixelSize, species) { + // Reset cache if animation was restarted + if (this.lastTimeStart !== timeStart) { + this.#clearCache(); + this.lastTimeStart = timeStart; + } + + let time = Date.now() - timeStart; + const duration = this.getAnimationDuration(); + + if (this.loop) { + time %= duration; + } + + const currentFrameIndex = this.getCurrentFrameIndex(time); + + if (this.#shouldRedraw(currentFrameIndex, direction)) { + this.frames[currentFrameIndex].draw(ctx, direction, canvasPixelSize, species); + this.lastFrameIndex = currentFrameIndex; + this.lastDirection = direction; + } + + // Return whether animation is complete (for non-looping animations) + return !this.loop && time >= duration; + } + } + + /** + * @typedef {keyof typeof Animations} AnimationType + */ + + const Animations = /** @type {const} */ ({ + STILL: "STILL", + BOB: "BOB", + FLYING: "FLYING", + HEART: "HEART" + }); + + class Birb { + animStart = Date.now(); + x = 0; + y = 0; + direction = Directions.RIGHT; + isAbsolutePositioned = false; + visible = true; + /** @type {AnimationType} */ + currentAnimation = Animations.STILL; + + /** + * @param {number} birbCssScale + * @param {number} canvasPixelSize + * @param {string[][]} spriteSheet The loaded sprite sheet pixel data + * @param {number} spriteWidth + * @param {number} spriteHeight + */ + constructor(birbCssScale, canvasPixelSize, spriteSheet, spriteWidth, spriteHeight) { + this.birbCssScale = birbCssScale; + this.canvasPixelSize = canvasPixelSize; + this.windowPixelSize = canvasPixelSize * birbCssScale; + this.spriteWidth = spriteWidth; + this.spriteHeight = spriteHeight; + + // Build layers from sprite sheet + this.layers = { + base: new Layer(getLayer(spriteSheet, 0, this.spriteWidth)), + down: new Layer(getLayer(spriteSheet, 1, this.spriteWidth)), + heartOne: new Layer(getLayer(spriteSheet, 2, this.spriteWidth)), + heartTwo: new Layer(getLayer(spriteSheet, 3, this.spriteWidth)), + heartThree: new Layer(getLayer(spriteSheet, 4, this.spriteWidth)), + tuftBase: new Layer(getLayer(spriteSheet, 5, this.spriteWidth), "tuft"), + tuftDown: new Layer(getLayer(spriteSheet, 6, this.spriteWidth), "tuft"), + wingsUp: new Layer(getLayer(spriteSheet, 7, this.spriteWidth)), + wingsDown: new Layer(getLayer(spriteSheet, 8, this.spriteWidth)), + happyEye: new Layer(getLayer(spriteSheet, 9, this.spriteWidth)), + }; + + // Build frames from layers + this.frames = { + base: new Frame([this.layers.base, this.layers.tuftBase]), + headDown: new Frame([this.layers.down, this.layers.tuftDown]), + wingsDown: new Frame([this.layers.base, this.layers.tuftBase, this.layers.wingsDown]), + wingsUp: new Frame([this.layers.down, this.layers.tuftDown, this.layers.wingsUp]), + heartOne: new Frame([this.layers.base, this.layers.tuftBase, this.layers.happyEye, this.layers.heartOne]), + heartTwo: new Frame([this.layers.base, this.layers.tuftBase, this.layers.happyEye, this.layers.heartTwo]), + heartThree: new Frame([this.layers.base, this.layers.tuftBase, this.layers.happyEye, this.layers.heartThree]), + heartFour: new Frame([this.layers.base, this.layers.tuftBase, this.layers.happyEye, this.layers.heartTwo]), + }; + + // Build animations from frames + this.animations = { + [Animations.STILL]: new Anim([this.frames.base], [1000]), + [Animations.BOB]: new Anim([ + this.frames.base, + this.frames.headDown + ], [ + 420, + 420 + ]), + [Animations.FLYING]: new Anim([ + this.frames.base, + this.frames.wingsUp, + this.frames.headDown, + this.frames.wingsDown, + ], [ + 30, + 80, + 30, + 60, + ]), + [Animations.HEART]: new Anim([ + this.frames.heartOne, + this.frames.heartTwo, + this.frames.heartThree, + this.frames.heartFour, + this.frames.heartThree, + this.frames.heartFour, + this.frames.heartThree, + this.frames.heartFour, + ], [ + 60, + 80, + 250, + 250, + 250, + 250, + 250, + 250, + ], false), + }; + + // Create canvas element + this.canvas = document.createElement("canvas"); + this.canvas.id = "birb"; + this.canvas.width = this.frames.base.getPixels()[0].length * canvasPixelSize; + this.canvas.height = spriteHeight * canvasPixelSize; + + this.ctx = this.canvas.getContext("2d"); + + // Append to document + document.body.appendChild(this.canvas); + } + + /** + * Draw the current animation frame + * @param {BirdType} species The species color data + * @returns {boolean} Whether the animation has completed (for non-looping animations) + */ + draw(species) { + const anim = this.animations[this.currentAnimation]; + return anim.draw(this.ctx, this.direction, this.animStart, this.canvasPixelSize, species); + } + + /** + * @returns {AnimationType} The current animation key + */ + getCurrentAnimation() { + return this.currentAnimation; + } + + /** + * Set the current animation by name and reset the animation timer + * @param {AnimationType} animationName + */ + setAnimation(animationName) { + this.currentAnimation = animationName; + this.animStart = Date.now(); + } + + /** + * Get the frames object + * @returns {Record} + */ + getFrames() { + return this.frames; + } + + /** + * Get the canvas element + * @returns {HTMLCanvasElement} + */ + getElement() { + return this.canvas; + } + + /** + * Get the canvas width in CSS pixels + * @returns {number} + */ + getElementWidth() { + return this.canvas.width * this.birbCssScale; + } + + /** + * Get the canvas height in CSS pixels + * @returns {number} + */ + getElementHeight() { + return this.canvas.height * this.birbCssScale; + } + + getElementTop() { + const rect = this.canvas.getBoundingClientRect(); + return rect.top; + } + + /** + * Set the X position + * @param {number} x + */ + setX(x) { + this.x = x; + let mod = this.getElementWidth() / -2 - (this.windowPixelSize * (this.direction === Directions.RIGHT ? 2 : -2)); + this.canvas.style.left = `${x + mod}px`; + } + + /** + * Set the Y position + * @param {number} y + */ + setY(y) { + this.y = y; + let bottom; + if (this.isAbsolutePositioned) { + // Position is absolute, convert from fixed + // Account for address bar shrinkage on iOS + bottom = y - window.scrollY - (getWindowHeight() - getFixedWindowHeight()); + } else { + // Position is fixed + bottom = y; + } + this.canvas.style.bottom = `${bottom}px`; + } + + /** + * Get the current X position + * @returns {number} + */ + getX() { + return this.x; + } + + /** + * Get the current Y position + * @returns {number} + */ + getY() { + return this.y; + } + + /** + * Set the direction the bird is facing + * @param {number} direction + */ + setDirection(direction) { + this.direction = direction; + } + + /** + * Set whether the element should be absolutely positioned + * @param {boolean} absolute + */ + setAbsolutePositioned(absolute) { + this.isAbsolutePositioned = absolute; + if (absolute) { + this.canvas.classList.add("birb-absolute"); + } else { + this.canvas.classList.remove("birb-absolute"); + } + // Update Y position to apply the new positioning mode + this.setY(this.y); + } + + /** + * Set visibility of the bird + * @param {boolean} visible + */ + setVisible(visible) { + this.visible = visible; + this.canvas.style.display = visible ? "" : "none"; + } + + /** + * Get visibility of the bird + * @returns {boolean} + */ + isVisible() { + return this.visible; + } + } + + const SAVE_KEY = "birbSaveData"; + + /** + * @typedef {import('./application.js').BirbSaveData} BirbSaveData + */ + + /** + * @abstract + */ + class Context { + + /** + * @abstract + * @returns {boolean} Whether this context is applicable + */ + isContextActive() { + throw new Error("Method not implemented"); + } + + /** + * @abstract + * @returns {Promise} + */ + async getSaveData() { + throw new Error("Method not implemented"); + } + + /** + * @abstract + * @param {BirbSaveData} saveData + */ + async putSaveData(saveData) { + throw new Error("Method not implemented"); + } + + /** + * @abstract + */ + resetSaveData() { + throw new Error("Method not implemented"); + } + } + + class LocalContext extends Context { + + /** + * @override + * @returns {boolean} + */ + isContextActive() { + return window.location.hostname === "127.0.0.1" + || window.location.hostname === "localhost" + || window.location.hostname.startsWith("192.168."); + } + + /** + * @override + * @returns {Promise} + */ + async getSaveData() { + log("Loading save data from localStorage"); + return JSON.parse(localStorage.getItem(SAVE_KEY) ?? "{}"); + } + + /** + * @override + * @param {BirbSaveData} saveData + */ + async putSaveData(saveData) { + log("Saving data to localStorage"); + localStorage.setItem(SAVE_KEY, JSON.stringify(saveData)); + } + + /** @override */ + resetSaveData() { + log("Resetting save data in localStorage"); + localStorage.removeItem(SAVE_KEY); + } + } + + class UserScriptContext extends Context { + + /** + * @override + * @returns {boolean} + */ + isContextActive() { + // @ts-expect-error + return typeof GM_getValue === "function"; + } + + /** + * @override + * @returns {Promise} + */ + async getSaveData() { + log("Loading save data from UserScript storage"); + /** @type {BirbSaveData|{}} */ + let saveData = {}; + // @ts-expect-error + saveData = GM_getValue(SAVE_KEY, {}) ?? {}; + return saveData; + } + + /** + * @override + * @param {BirbSaveData} saveData + */ + async putSaveData(saveData) { + log("Saving data to UserScript storage"); + // @ts-expect-error + GM_setValue(SAVE_KEY, saveData); + } + + /** @override */ + resetSaveData() { + log("Resetting save data in UserScript storage"); + // @ts-expect-error + GM_deleteValue(SAVE_KEY); + } + } + + class BrowserExtensionContext extends Context { + + /** + * @override + * @returns {boolean} + */ + isContextActive() { + // @ts-expect-error + return typeof chrome !== "undefined"; + } + + /** + * @override + * @returns {Promise} + */ + async getSaveData() { + log("Loading save data from browser extension storage"); + return new Promise((resolve) => { + // @ts-expect-error + chrome.storage.sync.get([SAVE_KEY], (result) => { + resolve(result[SAVE_KEY] ?? {}); + }); + }); + } + + /** + * @override + * @param {BirbSaveData} saveData + */ + async putSaveData(saveData) { + log("Saving data to browser extension storage"); + // @ts-expect-error + chrome.storage.sync.set({ [SAVE_KEY]: saveData }, function () { + // @ts-expect-error + if (chrome.runtime.lastError) { + // @ts-expect-error + console.error(chrome.runtime.lastError); + } else { + console.log("Settings saved successfully"); + } + }); + } + + /** @override */ + resetSaveData() { + log("Resetting save data in browser extension storage"); + // @ts-expect-error + chrome.storage.sync.clear(); + } + } + + const CONTEXTS = [ + new UserScriptContext(), + new BrowserExtensionContext(), + new LocalContext() + ]; + + function getContext() { + for (const context of CONTEXTS) { + if (context.isContextActive()) { + return context; + } + } + error("No applicable context found, defaulting to LocalContext"); + return CONTEXTS[0]; + } + + /** + * @typedef {Object} SavedStickyNote + * @property {string} id + * @property {string} site + * @property {string} content + * @property {number} top + * @property {number} left + */ + + 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; + } + } + + /** + * Parse URL parameters into a key-value map + * @param {string} url + * @returns {Record} + */ + 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 }; + }, {}); + } + + /** + * @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]; + + if (stickyNoteWebsite !== currentWebsite) { + return false; + } + + const stickyNoteParams = parseUrlParams(stickyNoteUrl); + const currentParams = parseUrlParams(currentUrl); + + if (window.location.hostname === "www.youtube.com") { + if (currentParams.v !== undefined && currentParams.v !== stickyNoteParams.v) { + return false; + } + } + return true; + } + + /** + * @param {StickyNote} stickyNote + * @param {() => void} onSave + * @param {() => void} onDelete + * @returns {HTMLElement} + */ + function renderStickyNote(stickyNote, onSave, onDelete) { + const noteElement = makeElement("birb-window"); + noteElement.classList.add("birb-sticky-note"); + + // 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`; + document.body.appendChild(noteElement); + + makeDraggable(header, true, (top, left) => { + stickyNote.top = top; + stickyNote.left = left; + onSave(); + }); + + if (closeButton) { + makeClosable(() => { + if (stickyNote.content.trim() === "" || confirm("Are you sure you want to delete this sticky note?")) { + onDelete(); + noteElement.remove(); + } + }, closeButton); + } + + 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 + */ + 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 + for (let stickyNote of stickyNotes) { + if (isStickyNoteApplicable(stickyNote)) { + renderStickyNote(stickyNote, onSave, () => onDelete(stickyNote)); + } + } + } + + /** + * @param {StickyNote[]} stickyNotes + * @param {() => void} onSave + * @param {(note: StickyNote) => void} onDelete + */ + function createNewStickyNote(stickyNotes, onSave, onDelete) { + const id = Date.now().toString(); + const site = window.location.href; + const stickyNote = new StickyNote(id, site, ""); + const element = renderStickyNote(stickyNote, onSave, () => onDelete(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); + onSave(); + } + + const MENU_ID = "birb-menu"; + const MENU_EXIT_ID = "birb-menu-exit"; + + class MenuItem { + /** + * @param {string} text + * @param {() => void} action + * @param {boolean} [removeMenu] + * @param {boolean} [isDebug] + */ + constructor(text, action, removeMenu = true, isDebug = false) { + this.text = text; + this.action = action; + this.removeMenu = removeMenu; + this.isDebug = isDebug; + } + } + + class DebugMenuItem extends MenuItem { + /** + * @param {string} text + * @param {() => void} action + */ + constructor(text, action, removeMenu = true) { + super(text, action, removeMenu, true); + } + } + + class Separator extends MenuItem { + constructor() { + super("", () => { }); + } + } + + /** + * @param {MenuItem} item + * @param {() => void} removeMenuCallback + * @returns {HTMLElement} + */ + function makeMenuItem(item, removeMenuCallback) { + if (item instanceof Separator) { + return makeElement("birb-window-separator"); + } + let menuItem = makeElement("birb-menu-item", item.text); + onClick(menuItem, () => { + if (item.removeMenu) { + removeMenuCallback(); + } + item.action(); + }); + return menuItem; + } + + /** + * Add the menu to the page if it doesn't already exist + * @param {MenuItem[]} menuItems + * @param {string} title + * @param {(menu: HTMLElement) => void} updateLocationCallback + */ + function insertMenu(menuItems, title, updateLocationCallback) { + if (document.querySelector("#" + MENU_ID)) { + return; + } + let menu = makeElement("birb-window", undefined, MENU_ID); + let header = makeElement("birb-window-header"); + const titleDiv = makeElement("birb-window-title", title); + header.appendChild(titleDiv); + let content = makeElement("birb-window-content"); + const removeCallback = () => removeMenu(); + for (const item of menuItems) { + if (!item.isDebug || isDebug()) { + content.appendChild(makeMenuItem(item, removeCallback)); + } + } + menu.appendChild(header); + menu.appendChild(content); + document.body.appendChild(menu); + makeDraggable(document.querySelector(".birb-window-header")); + + let menuExit = makeElement("birb-window-exit", undefined, MENU_EXIT_ID); + onClick(menuExit, removeCallback); + document.body.appendChild(menuExit); + makeClosable(removeCallback); + + updateLocationCallback(menu); + } + + /** + * Remove the menu from the page + */ + function removeMenu() { + const menu = document.querySelector("#" + MENU_ID); + if (menu) { + menu.remove(); + } + const exitMenu = document.querySelector("#" + MENU_EXIT_ID); + if (exitMenu) { + exitMenu.remove(); + } + } + + /** + * @returns {boolean} Whether the menu element is on the page + */ + function isMenuOpen() { + return document.querySelector("#" + MENU_ID) !== null; + } + + /** + * @param {MenuItem[]} menuItems + * @param {(menu: HTMLElement) => void} updateLocationCallback + */ + function switchMenuItems(menuItems, updateLocationCallback) { + const menu = document.querySelector("#" + MENU_ID); + if (!menu || !(menu instanceof HTMLElement)) { + return; + } + const content = menu.querySelector(".birb-window-content"); + if (!content) { + error("Birb: Content not found"); + return; + } + while (content.firstChild) { + content.removeChild(content.firstChild); + } + const removeCallback = () => removeMenu(); + for (const item of menuItems) { + if (!item.isDebug || isDebug()) { + content.appendChild(makeMenuItem(item, removeCallback)); + } + } + updateLocationCallback(menu); + } + + /** + * @typedef {import('./stickyNotes.js').SavedStickyNote} SavedStickyNote + */ + + /** + * @typedef {Object} BirbSaveData + * @property {string[]} unlockedSpecies + * @property {string} currentSpecies + * @property {Partial} settings + * @property {SavedStickyNote[]} [stickyNotes] + */ + + /** + * @typedef {typeof DEFAULT_SETTINGS} Settings + */ + const DEFAULT_SETTINGS = { + birbMode: false + }; + + // Rendering constants + const SPRITE_WIDTH = 32; + const SPRITE_HEIGHT = 32; + const FEATHER_SPRITE_WIDTH = 32; + const BIRB_CSS_SCALE = 1; + const UI_CSS_SCALE = isMobile() ? 0.9 : 1; + const CANVAS_PIXEL_SIZE = 1; + const WINDOW_PIXEL_SIZE = CANVAS_PIXEL_SIZE * BIRB_CSS_SCALE; + + // Build-time assets + const STYLESHEET = `:root { + --birb-border-size: 2px; + --birb-neg-border-size: calc(var(--birb-border-size) * -1); + --birb-double-border-size: calc(var(--birb-border-size) * 2); + --birb-neg-double-border-size: calc(var(--birb-neg-border-size) * 2); + --birb-highlight: #ffa3cb; + --birb-border-color: var(--birb-highlight); + --birb-background-color: #ffecda; + --birb-mix-color: color-mix(in srgb, var(--birb-highlight) 50%, var(--birb-background-color)); + --birb-scale: ${BIRB_CSS_SCALE}; + --birb-ui-scale: ${UI_CSS_SCALE}; +} + +#birb { + image-rendering: pixelated; + position: fixed; + bottom: 0; + transform: scale(var(--birb-scale)) !important; + transform-origin: bottom; + z-index: 2147483638 !important; + cursor: pointer; +} + +.birb-absolute { + position: absolute !important; +} + +.birb-decoration { + image-rendering: pixelated; + position: fixed; + bottom: 0; + transform: scale(var(--birb-scale)) !important; + transform-origin: bottom; + z-index: 2147483630 !important; +} + +.birb-window { + font-family: "Monocraft", monospace !important; + line-height: initial !important; + color: #000000 !important; + z-index: 2147483639 !important; + position: fixed; + background-color: var(--birb-background-color); + box-shadow: + var(--birb-border-size) 0 var(--birb-border-color), + var(--birb-neg-border-size) 0 var(--birb-border-color), + 0 var(--birb-neg-border-size) var(--birb-border-color), + 0 var(--birb-border-size) var(--birb-border-color), + var(--birb-double-border-size) 0 var(--birb-border-color), + var(--birb-neg-double-border-size) 0 var(--birb-border-color), + 0 var(--birb-neg-double-border-size) var(--birb-border-color), + 0 var(--birb-double-border-size) var(--birb-border-color), + 0 0 0 var(--birb-border-size) var(--birb-border-color), + 0 0 0 var(--birb-double-border-size) white, + var(--birb-double-border-size) 0 0 var(--birb-border-size) white, + var(--birb-neg-double-border-size) 0 0 var(--birb-border-size) white, + 0 var(--birb-neg-double-border-size) 0 var(--birb-border-size) white, + 0 var(--birb-double-border-size) 0 var(--birb-border-size) white; + box-sizing: border-box; + display: flex; + flex-direction: column; + transform: scale(var(--birb-ui-scale)) !important; + animation: pop-in 0.08s; + transition-timing-function: ease-in; +} + +#birb-menu { + transition-duration: 0.2s; + transition-timing-function: ease-out; + min-width: 140px; + z-index: 2147483639 !important; +} + +#birb-menu-exit { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 2147483637 !important; +} + +@keyframes pop-in { + 0% { + opacity: 1; + transform: scale(0.1); + } + + 100% { + opacity: 1; + transform: scale(var(--birb-ui-scale)); + } +} + +.birb-window-header { + box-sizing: border-box; + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + padding: 7px; + padding-top: 3px; + padding-bottom: 3px; + padding-left: 30px; + padding-right: 30px; + background-color: var(--birb-highlight); + box-shadow: + var(--birb-border-size) 0 var(--birb-highlight), + var(--birb-neg-border-size) 0 var(--birb-highlight), + 0 var(--birb-neg-border-size) var(--birb-highlight), + var(--birb-neg-border-size) var(--birb-border-size) var(--birb-border-color), + var(--birb-border-size) var(--birb-border-size) var(--birb-border-color); + color: var(--birb-border-color) !important; + font-size: 16px; +} + +.birb-window-title { + text-align: center; + flex-grow: 1; + user-select: none; + color: var(--birb-background-color); +} + +.birb-window-close { + position: absolute; + top: 1px; + right: 0; + color: var(--birb-background-color); + user-select: none; + cursor: pointer; + padding-left: 5px; + padding-right: 5px; +} + +.birb-window-close:hover { + transform: scale(1.1); +} + +.birb-window-content { + box-sizing: border-box; + background-color: var(--birb-background-color); + margin-top: var(--birb-border-size); + flex-grow: 1; + box-shadow: + var(--birb-border-size) 0 var(--birb-background-color), + var(--birb-neg-border-size) 0 var(--birb-background-color), + 0 var(--birb-border-size) var(--birb-background-color), + 0 var(--birb-neg-border-size) var(--birb-border-color), + 0 var(--birb-border-size) var(--birb-border-color); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding-top: calc(var(--birb-double-border-size)); + padding-bottom: var(--birb-border-size); +} + +.birb-pico-8-content { + background: #111111; + box-shadow: none; + display: flex; + justify-content: center; + overflow: hidden; + border: none; +} + +.birb-pico-8-content iframe { + width: 300px; + margin-left: -15px; + margin-right: -30px; + margin-top: -10px; + margin-bottom: -23px; + border: none; + aspect-ratio: 1; +} + +.birb-music-player-content { + background: var(--birb-background-color); + box-shadow: + var(--birb-border-size) 0 var(--birb-background-color), + var(--birb-neg-border-size) 0 var(--birb-background-color), + 0 var(--birb-border-size) var(--birb-background-color), + 0 var(--birb-neg-border-size) var(--birb-border-color), + 0 var(--birb-border-size) var(--birb-border-color); + display: flex; + justify-content: center; + overflow: hidden; + padding: 10px; +} + +.birb-menu-item { + width: calc(100% - var(--birb-double-border-size)); + font-size: 14px; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 10px; + padding-right: 10px; + box-sizing: border-box; + opacity: 0.7 !important; + user-select: none; + display: flex; + justify-content: space-between; + cursor: pointer; + color: black !important; +} + +.birb-menu-item:hover { + opacity: 1 !important; + background: var(--birb-highlight) !important; + color: white !important; + box-shadow: + var(--birb-border-size) 0 var(--birb-highlight), + var(--birb-neg-border-size) 0 var(--birb-highlight), + 0 var(--birb-neg-border-size) var(--birb-highlight), + 0 var(--birb-border-size) var(--birb-highlight); +} + +.birb-menu-item-arrow { + display: inline-block; +} + +.birb-window-separator { + width: 100%; + height: var(--birb-border-size); + background-color: var(--birb-border-color); + box-sizing: border-box; + margin-top: var(--birb-double-border-size); + margin-bottom: var(--birb-double-border-size); + opacity: 0.4; +} + +#birb-field-guide { + width: 322px !important; +} + +.birb-grid-content { + display: grid; + grid-template-rows: repeat(3, auto); + grid-auto-flow: column; + gap: 10px; + padding-top: 8px; + padding-bottom: 8px; + padding-left: 10px; + padding-right: 10px; + box-sizing: border-box; + justify-content: center; + align-items: center; +} + +.birb-grid-item { + width: 64px; + height: 64px; + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; +} + +.birb-grid-item:hover { + border-color: var(--birb-highlight); +} + +.birb-grid-item canvas { + image-rendering: pixelated; + transform: scale(2) !important; + padding-bottom: var(--birb-border-size); +} + +.birb-grid-item, .birb-field-guide-description, .birb-message-content { + border: var(--birb-border-size) solid rgb(255, 207, 144); + box-shadow: 0 0 0 var(--birb-border-size) white; + background: rgba(255, 221, 177, 0.5); +} + +.birb-grid-item-locked { + cursor: auto; + filter: grayscale(100%) sepia(30%); +} + +.birb-grid-item-locked canvas { + filter: contrast(90%); +} + +.birb-grid-item-selected { + border: var(--birb-border-size) solid var(--birb-highlight); + background: var(--birb-mix-color); +} + +.birb-field-guide-description { + max-width: calc(100% - 20px); + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; + padding: 8px; + padding-top: 4px; + padding-bottom: 4px; + margin-bottom: 10px; + font-size: 14px; + box-sizing: border-box; + color: rgb(124, 108, 75); +} + +#birb-feather { + cursor: pointer; +} + +.birb-message-content { + box-sizing: border-box; + margin: 2px; + width: 100%; + padding: 10px; + font-size: 14px; + color: rgb(124, 108, 75); +} + +.birb-sticky-note { + position: absolute; + box-sizing: border-box; +} + +.birb-sticky-note > .birb-window-content { + padding: 0; +} + +.birb-sticky-note-input { + width: 100%; + height: 100%; + padding: 10px !important; + resize: both !important; + min-width: 175px !important; + min-height: 135px !important; + box-sizing: border-box !important; + font-family: "Monocraft", monospace !important; + font-size: 14px !important; + color: black !important; + background-color: transparent !important; + border: none !important; +} + +.birb-sticky-note-input:focus { + outline: none; +}`; + const SPRITE_SHEET = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAgCAYAAABjE6FEAAAAAXNSR0IArs4c6QAABD5JREFUeJztnTFrFEEYht9JLAJidwju2YpdBAvzAyIWaXJXpRS0MBCwEBTJDwghhaAgGLTSyupMY2UqG9PYWQRb7yJyYJEIacxnkZ11bm5n9+7Y3Zm9ex8Imezd7Te7O9+zM7N7G4AQQgghhBBCCJkJlO8KkPAREXG9ppRiGyK1hY23BvgUkI7dbjYBAJ1ud6BcRR0IITOKxLSiSFpRNFTOkmNR8VtRJF8WF0U2NobKZccnpEzmfFeA5NNuNvG00UCn3R4qV8nB58942mgkZULqDgVYI3wJqNPtYrvfH1i23e8nQ2BCCCkFcwj8ZXEx+alqCJxWhypjE0ICQFKoOrZPAZl1oPwImTFE5Hzy3/hddXzfAvIhf0LK5ILvCtSNgxs3vMRVSikREZ+3nvB2F0JmFN3z0b0/9oKqx9cUBJleeEYfAzPp2BuqFr3v9W4XkcqPgS1dtoEZIe0CAM/AxAOy220JAG/zn3HsoNs/83R0cu8DNM+85g9yvqJVJBQwAYDdbksXvcx/KqWSOoTW+7Pzwkee1pHMiyDmzjQaH/QyETHfU0qDsIc+xnKIiITWEEl5PGh+8HqsfQp4FMxUWNvpJcvoPzdOAZriOVy7DzwCdm6/SV7f7bYH5mPKkFEIAiZE41vAGYhSKpHetHNlXsnRXynkWDhXIiIydzEaWHbveQ8f1+ew8uoMAHDy+wgA8P5JNHCWKUJGQwLGoIBvrbTxoPlBv7ewuITUDHGJ7/uPY3x9cd3LBaOyuDKvZOXVGT6uz6EICWYKELGA7r9O70JrASKWIAwZpQYb4yD4FjAJm7Wdnrx/Es36cc6VX6jD9VBwDoH1jbeu1035wZpzSGOSYfLZn96QgLX87Nj2cNy1TaPGJuFwurcsC6v7SpcBYGHVr/x8C3htp+d1Ys8VP+4I1SbPMisaCwune8vY+PUJAPDy8m0AwN3DdyMF+P7jGAAm6orr+Gk9UFvAGt0TTVkXQAnWlv/i26/8+KULuPp6mLgEZOZbySJy9j7rJMGRBWizsLqPmw8Pce3qpdTPWgdiIgH5FjAhmlDEpzndWxYzB+x8q0BA4sr/mRAgDAmmYYsPE/S+fAuYkJDpby3JxoUOMDjyqap9OwWIGkkwV4CI5/VsCZ18OwEANDYPXJ/9H2RC6fgWMCGh099aShr4nZ9vgfO2712C5oXJkPMut2JpEtLyS6OxeVDYhvsWMCEkF9GdEFuEWoIh599Ij8OKNwL9raXM9xUpP2RciTYFbNep6DoQQjJRX19cP084hwhDJleAWkJ5EixTPDo2UoRXVR0IIU4UzofeAyKcKsynYXSePU6eiqHLZT6gwPqid2r8sutACMnHfmJO6Pk41n+FU0qh8+xx8rdZRom9Lr3erPjs+RESBvGXEYAa5ONYj8Q3h6J2uQry4oe+swmZduqWg2Pfl+dcUQUb7js+IWS6+Ac8zd6eLzTjoQAAAABJRU5ErkJggg=="; + const FEATHER_SPRITE_SHEET = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAARhJREFUWIXtlbENwjAQRf8hSiZIRQ+9WQNRUFIAKzACBSsAA1Ag1mAABqCCBomG3hQQ9OMEx4ZDNH5SikSJ3/fZ5wCJRCKRSPwZ0RzMWmtLAhGvQyUAi9mXP/aFaGjJRQQiguHihMvcFMJUVUYlAMuHixPGy4en1WmVQqgHYHkuZjiEj6a2/LjtYzTY0eiZbgC37Mxh1UN3sn/dr6cCz/LHB/DJj9s+2oMdbtdz6TtfFwQHcMvOInfmQNjsgchNWLXmdfK6gyioAu/6uKrsm1kWLAciKuCuey5nYuXAh234bdmZ6INIUw4E/Ix49xtjCmXfzLL8nY/ktdgnAKwxxgIoXIyqmAOwvIqfiN0ALNd21HYBO9XXGMAdnZTYyHWzWjQAAAAASUVORK5CYII="; + + // Element IDs + const FIELD_GUIDE_ID = "birb-field-guide"; + const FEATHER_ID = "birb-feather"; + + const DEFAULT_BIRD = "bluebird"; + + // Birb movement + const HOP_SPEED = 0.07; + const FLY_SPEED = isMobile() ? 0.175 : 0.25; + const HOP_DISTANCE = 35; + + // Timing constants (in milliseconds) + const UPDATE_INTERVAL = 1000 / 60; // 60 FPS + const AFK_TIME = isDebug() ? 0 : 1000 * 5; + const PET_BOOST_DURATION = 1000 * 60 * 5; + const PET_MENU_COOLDOWN = 1000; + const URL_CHECK_INTERVAL = 500; + const HOP_DELAY = 500; + + // Random event chances per tick + const HOP_CHANCE = 1 / (60 * 2.5); // Every 2.5 seconds + const FOCUS_SWITCH_CHANCE = 1 / (60 * 20); // Every 20 seconds + const FEATHER_CHANCE = 1 / (60 * 60 * 60 * 2); // Every 2 hours + + // Feathers + const FEATHER_FALL_SPEED = 1; + const PET_FEATHER_BOOST = 2; + + // Focus element constraints + const MIN_FOCUS_ELEMENT_WIDTH = 100; + const MIN_FOCUS_ELEMENT_TOP = 80; + + /** @type {Partial} */ + let userSettings = {}; + + /** + * Load the sprite sheet and return the pixel-map template + * @param {string} dataUri + * @param {boolean} [templateColors] + * @returns {Promise} + */ + function loadSpriteSheetPixels(dataUri, templateColors = true) { + return new Promise((resolve, reject) => { + const img = new Image(); + img.src = dataUri; + img.onload = () => { + const canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + const ctx = canvas.getContext('2d'); + if (!ctx) { + reject(new Error('Failed to get canvas context')); + return; + } + ctx.drawImage(img, 0, 0); + const imageData = ctx.getImageData(0, 0, img.width, img.height); + const pixels = imageData.data; + const hexArray = []; + for (let y = 0; y < img.height; y++) { + const row = []; + for (let x = 0; x < img.width; x++) { + const index = (y * img.width + x) * 4; + const r = pixels[index]; + const g = pixels[index + 1]; + const b = pixels[index + 2]; + const a = pixels[index + 3]; + if (a === 0) { + row.push(Sprite.TRANSPARENT); + continue; + } + const hex = `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`; + if (!templateColors) { + row.push(hex); + continue; + } + if (SPRITE_SHEET_COLOR_MAP[hex] === undefined) { + error(`Unknown color: ${hex}`); + row.push(Sprite.TRANSPARENT); + } + row.push(SPRITE_SHEET_COLOR_MAP[hex]); + } + hexArray.push(row); + } + resolve(hexArray); + }; + img.onerror = (err) => { + reject(err); + }; + }); + } + + log("Loading sprite sheets..."); + + Promise.all([ + loadSpriteSheetPixels(SPRITE_SHEET), + loadSpriteSheetPixels(FEATHER_SPRITE_SHEET) + ]).then(([birbPixels, featherPixels]) => { + + const SPRITE_SHEET = birbPixels; + const FEATHER_SPRITE_SHEET = featherPixels; + + const featherLayers = { + feather: new Layer(getLayer(FEATHER_SPRITE_SHEET, 0, FEATHER_SPRITE_WIDTH)), + }; + + const featherFrames = { + feather: new Frame([featherLayers.feather]), + }; + + const FEATHER_ANIMATIONS = { + feather: new Anim([ + featherFrames.feather, + ], [ + 1000, + ]), + }; + + const menuItems = [ + new MenuItem(`Pet ${birdBirb()}`, pet), + new MenuItem("Field Guide", insertFieldGuide), + new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)), + new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), + new DebugMenuItem("Freeze/Unfreeze", () => { + frozen = !frozen; + }), + new DebugMenuItem("Reset Data", resetSaveData), + new DebugMenuItem("Unlock All", () => { + for (let type in SPECIES) { + unlockBird(type); + } + }), + new DebugMenuItem("Add Feather", () => { + activateFeather(); + }), + new DebugMenuItem("Disable Debug", () => { + setDebug(false); + }), + new Separator(), + new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), false), + ]; + + const settingsItems = [ + new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false), + new Separator(), + new MenuItem("Toggle Birb Mode", () => { + userSettings.birbMode = !userSettings.birbMode; + save(); + const message = makeElement("birb-message-content"); + message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`)); + if (userSettings.birbMode) { + message.appendChild(document.createElement("br")); + message.appendChild(document.createElement("br")); + message.appendChild(document.createTextNode("Welcome back to 2012")); + } + insertModal(`${birdBirb()} Mode`, message); + }), + new Separator(), + new MenuItem("2025.11.3.34", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.34"); }, false), + ]; + + const styleElement = document.createElement("style"); + + /** @type {Birb} */ + let birb; + + const States = { + IDLE: "idle", + HOP: "hop", + FLYING: "flying", + }; + + let frozen = false; + let stateStart = Date.now(); + let currentState = States.IDLE; + let ticks = 0; + // Bird's current position + let birdY = 0; + let birdX = 40; + // Bird's starting position (when flying) + let startX = 0; + let startY = 0; + // Bird's target position (when flying) + let targetX = 0; + let targetY = 0; + /** @type {HTMLElement|null} */ + let focusedElement = null; + let focusedBounds = { left: 0, right: 0, top: 0 }; + let lastActionTimestamp = Date.now(); + /** @type {number[]} */ + let petStack = []; + let currentSpecies = DEFAULT_BIRD; + let unlockedSpecies = [DEFAULT_BIRD]; + // let visible = true; + let lastPetTimestamp = 0; + /** @type {StickyNote[]} */ + let stickyNotes = []; + + async function load() { + /** @type {BirbSaveData|Object} */ + let saveData = await getContext().getSaveData(); + + debug("Loaded data: " + JSON.stringify(saveData)); + + if (!('settings' in saveData)) { + log("No user settings found in save data, starting fresh"); + } + + userSettings = saveData.settings ?? {}; + unlockedSpecies = saveData.unlockedSpecies ?? [DEFAULT_BIRD]; + currentSpecies = saveData.currentSpecies ?? DEFAULT_BIRD; + stickyNotes = []; + + if (saveData.stickyNotes) { + for (let note of saveData.stickyNotes) { + if (note.id) { + stickyNotes.push(new StickyNote(note.id, note.site, note.content, note.top, note.left)); + } + } + } + + log(stickyNotes.length + " sticky notes loaded"); + switchSpecies(currentSpecies); + } + + function save() { + /** @type {BirbSaveData} */ + const saveData = { + unlockedSpecies, + currentSpecies, + settings: userSettings + }; + + if (stickyNotes.length > 0) { + saveData.stickyNotes = stickyNotes.map(note => ({ + id: note.id, + site: note.site, + content: note.content, + top: note.top, + left: note.left + })); + } + + getContext().putSaveData(saveData); + } + + function resetSaveData() { + getContext().resetSaveData(); + load(); + } + + /** + * Get the user settings merged with default settings + * @returns {Settings} The merged settings + */ + function settings() { + return { ...DEFAULT_SETTINGS, ...userSettings }; + } + + /** + * Bird or birb, you decide + */ + function birdBirb() { + return settings().birbMode ? "Birb" : "Bird"; + } + + function init() { + log("Sprite sheets loaded successfully, initializing bird..."); + + if (window !== window.top) { + // Skip installation if within an iframe + log("In iframe, skipping Birb script initialization"); + return; + } + + // Preload font + const MONOCRAFT_SRC = "https://cdn.jsdelivr.net/gh/idreesinc/Monocraft@99b32ab40612ff2533a69d8f14bd8b3d9e604456/dist/Monocraft.otf"; + const fontLink = document.createElement("link"); + fontLink.rel = "stylesheet"; + fontLink.href = `url(${MONOCRAFT_SRC}) format('opentype')`; + document.head.appendChild(fontLink); + + // Add stylesheet font-face + const fontFace = ` + @font-face { + font-family: 'Monocraft'; + src: url(${MONOCRAFT_SRC}) format('opentype'); + font-weight: normal; + font-style: normal; + } + `; + + try { + const fontStyle = document.createElement("style"); + fontStyle.textContent = fontFace; + document.head.appendChild(fontStyle); + } catch (e) { + error("Failed to load font: " + e); + } + + load().then(onLoad); + } + + function onLoad() { + styleElement.textContent = STYLESHEET; + document.head.appendChild(styleElement); + + birb = new Birb(BIRB_CSS_SCALE, CANVAS_PIXEL_SIZE, SPRITE_SHEET, SPRITE_WIDTH, SPRITE_HEIGHT); + birb.setAnimation(Animations.BOB); + + window.addEventListener("scroll", () => { + lastActionTimestamp = Date.now(); + }); + + onClick(document, (e) => { + lastActionTimestamp = Date.now(); + if (e.target instanceof Node && document.querySelector("#" + MENU_EXIT_ID)?.contains(e.target)) { + removeMenu(); + } + }); + + const birbElement = birb.getElement(); + + onClick(birbElement, () => { + if (birb.getCurrentAnimation() === Animations.HEART && (Date.now() - lastPetTimestamp < PET_MENU_COOLDOWN)) { + // Currently being pet, don't open menu + return; + } + insertMenu(menuItems, `${birdBirb().toLowerCase()}OS`, updateMenuLocation); + }); + + birbElement.addEventListener("mouseover", () => { + lastActionTimestamp = Date.now(); + if (currentState === States.IDLE) { + petStack.push(Date.now()); + if (petStack.length > 10) { + petStack.shift(); + } + const pets = petStack.filter((time) => Date.now() - time < 1000).length; + if (pets >= 3) { + pet(); + // Clear the stack + petStack = []; + } + } + }); + + birbElement.addEventListener("touchmove", (e) => { + pet(); + }); + + drawStickyNotes(stickyNotes, save, deleteStickyNote); + + let lastUrl = (window.location.href ?? "").split("?")[0]; + setInterval(() => { + const currentUrl = (window.location.href ?? "").split("?")[0]; + if (currentUrl !== lastUrl) { + log("URL changed, updating sticky notes"); + lastUrl = currentUrl; + drawStickyNotes(stickyNotes, save, deleteStickyNote); + } + }, URL_CHECK_INTERVAL); + + setInterval(update, UPDATE_INTERVAL); + + focusOnElement(true); + } + + function update() { + ticks++; + + // Hide bird if the browser is fullscreen + if (document.fullscreenElement) { + birb.setVisible(false); + // Won't be restored on fullscreen exit + } + + if (currentState === States.IDLE && !frozen && !isMenuOpen()) { + if (Date.now() - stateStart > HOP_DELAY && Math.random() < HOP_CHANCE && birb.getCurrentAnimation() !== Animations.HEART) { + hop(); + } else if (Date.now() - lastActionTimestamp > AFK_TIME) { + // Idle for a while, do something + if (focusedElement === null) { + // Fly to an element + focusOnElement(); + lastActionTimestamp = Date.now(); + } else if (Math.random() < FOCUS_SWITCH_CHANCE) { + // Fly to another element if idle for a longer while + focusOnElement(); + lastActionTimestamp = Date.now(); + } + } + } else if (currentState === States.HOP) { + if (updateParabolicPath(HOP_SPEED)) { + setState(States.IDLE); + } + } + + // Double the chance of a feather if recently pet + const petMod = Date.now() - lastPetTimestamp < PET_BOOST_DURATION ? PET_FEATHER_BOOST : 1; + if (birb.isVisible() && Math.random() < FEATHER_CHANCE * petMod) { + lastPetTimestamp = 0; + activateFeather(); + } + updateFeather(); + } + + function draw() { + requestAnimationFrame(draw); + + if (!birb || !birb.isVisible()) { + return; + } + + updateFocusedElementBounds(); + + // Update the bird's position + if (currentState === States.IDLE) { + if (focusedElement && !isWithinHorizontalBounds()) { + flySomewhere(); + } + birdY = getFocusedY(); + } else if (currentState === States.FLYING) { + // Fly to target location (even if in the air) + if (updateParabolicPath(FLY_SPEED, 2)) { + setState(States.IDLE); + } + } + + const oldTargetY = targetY; + targetY = getFocusedY(); + // Adjust startY to account for scrolling + startY += targetY - oldTargetY; + if (targetY < 0 || targetY > getWindowHeight()) { + // Fly to another element or the ground if the focused element moves out of bounds + flySomewhere(); + } + + if (birb.draw(SPECIES[currentSpecies])) { + birb.setAnimation(Animations.STILL); + } + + // Clamp startY, birdY, targetY to a bit above the top of the window + const maxY = getWindowHeight() * 1.5; + startY = Math.min(startY, maxY); + birdY = Math.min(birdY, maxY); + targetY = Math.min(targetY, maxY); + + // Update HTML element position + birb.setX(birdX); + birb.setY(birdY); + } + + /** + * @param {StickyNote} stickyNote + */ + function deleteStickyNote(stickyNote) { + stickyNotes = stickyNotes.filter(note => note.id !== stickyNote.id); + save(); + } + + /** + * Create a window element with header and content + * @param {string} id + * @param {string} title + * @param {HTMLElement} contentElement + * @param {() => void} [onClose] + * @returns {HTMLElement} + */ + function createWindow(id, title, contentElement, onClose) { + const window = makeElement("birb-window", undefined, id); + + const header = makeElement("birb-window-header"); + const titleElement = makeElement("birb-window-title"); + titleElement.textContent = title; + const closeButton = makeElement("birb-window-close"); + closeButton.textContent = "x"; + + header.appendChild(titleElement); + header.appendChild(closeButton); + + const contentWrapper = makeElement("birb-window-content"); + contentWrapper.appendChild(contentElement); + + window.appendChild(header); + window.appendChild(contentWrapper); + + document.body.appendChild(window); + makeDraggable(header); + + makeClosable(() => { + window.remove(); + }, closeButton); + + return window; + } + + function activateFeather() { + if (document.querySelector("#" + FEATHER_ID)) { + return; + } + const speciesToUnlock = Object.keys(SPECIES).filter((species) => !unlockedSpecies.includes(species)); + if (speciesToUnlock.length === 0) { + // No more species to unlock + return; + } + const birdType = speciesToUnlock[Math.floor(Math.random() * speciesToUnlock.length)]; + insertFeather(birdType); + } + + /** + * @param {string} birdType + */ + function insertFeather(birdType) { + let type = SPECIES[birdType]; + const featherCanvas = document.createElement("canvas"); + featherCanvas.id = FEATHER_ID; + featherCanvas.classList.add("birb-decoration"); + featherCanvas.width = FEATHER_SPRITE_WIDTH * CANVAS_PIXEL_SIZE; + featherCanvas.height = FEATHER_SPRITE_WIDTH * CANVAS_PIXEL_SIZE; + const x = featherCanvas.width * 2 + Math.random() * (window.innerWidth - featherCanvas.width * 4); + featherCanvas.style.marginLeft = `${x}px`; + featherCanvas.style.top = `${-featherCanvas.height}px`; + const featherCtx = featherCanvas.getContext("2d"); + if (!featherCtx) { + return; + } + FEATHER_ANIMATIONS.feather.draw(featherCtx, Directions.LEFT, Date.now(), CANVAS_PIXEL_SIZE, type); + document.body.appendChild(featherCanvas); + onClick(featherCanvas, () => { + unlockBird(birdType); + removeFeather(); + if (document.querySelector("#" + FIELD_GUIDE_ID)) { + removeFieldGuide(); + insertFieldGuide(); + } + }); + } + + function removeFeather() { + const feather = document.querySelector("#" + FEATHER_ID); + if (feather) { + feather.remove(); + } + } + + /** + * @param {string} birdType + */ + function unlockBird(birdType) { + if (!unlockedSpecies.includes(birdType)) { + unlockedSpecies.push(birdType); + const message = makeElement("birb-message-content"); + message.appendChild(document.createTextNode("You've found a ")); + const bold = document.createElement("b"); + bold.textContent = SPECIES[birdType].name; + message.appendChild(bold); + message.appendChild(document.createTextNode(" feather! Use the Field Guide to switch your bird's species.")); + insertModal("New Bird Unlocked!", message); + } + save(); + } + + function updateFeather() { + const feather = document.querySelector("#birb-feather"); + if (!feather || !(feather instanceof HTMLElement)) { + return; + } + const y = parseInt(feather.style.top || "0") + FEATHER_FALL_SPEED; + feather.style.top = `${Math.min(y, getWindowHeight() - feather.offsetHeight)}px`; + if (y < getWindowHeight() - feather.offsetHeight) { + feather.style.left = `${Math.sin(3.14 * 2 * (ticks / 120)) * 25}px`; + } + } + + /** + * @param {HTMLElement} element + */ + function centerElement(element) { + element.style.left = `${window.innerWidth / 2 - element.offsetWidth / 2}px`; + element.style.top = `${getWindowHeight() / 2 - element.offsetHeight / 2}px`; + } + + /** + * @param {string} title + * @param {HTMLElement} content + */ + function insertModal(title, content) { + if (document.querySelector("#" + FIELD_GUIDE_ID)) { + return; + } + + const modal = createWindow("birb-modal", title, content); + + modal.style.width = "270px"; + centerElement(modal); + } + + /** + * @param {HTMLElement} menu + */ + function updateMenuLocation(menu) { + let x = birdX; + let y = birb.getElementTop() + birb.getElementHeight() / 2 + WINDOW_PIXEL_SIZE * 10; + const offset = 20; + if (x < window.innerWidth / 2) { + // Left side + x += offset; + } else { + // Right side + x -= (menu.offsetWidth + offset) * UI_CSS_SCALE; + } + if (y > getWindowHeight() / 2) { + // Top side + y -= (menu.offsetHeight + offset + 10) * UI_CSS_SCALE; + } else { + // Bottom side + y += offset; + } + menu.style.left = `${x}px`; + menu.style.top = `${y}px`; + } + function insertFieldGuide() { + if (document.querySelector("#" + FIELD_GUIDE_ID)) { + return; + } + + const contentContainer = document.createElement("div"); + const content = makeElement("birb-grid-content"); + const description = makeElement("birb-field-guide-description"); + contentContainer.appendChild(content); + contentContainer.appendChild(description); + + const fieldGuide = createWindow( + FIELD_GUIDE_ID, + "Field Guide", + contentContainer + ); + + const generateDescription = (/** @type {string} */ speciesId) => { + const type = SPECIES[speciesId]; + const unlocked = unlockedSpecies.includes(speciesId); + + const boldName = document.createElement("b"); + boldName.textContent = type.name; + + const spacer = document.createElement("div"); + spacer.style.height = "0.3em"; + + const descText = document.createTextNode(!unlocked ? "Not yet unlocked" : type.description); + + const fragment = document.createDocumentFragment(); + fragment.appendChild(boldName); + fragment.appendChild(spacer); + fragment.appendChild(descText); + + return fragment; + }; + + description.appendChild(generateDescription(currentSpecies)); + for (const [id, type] of Object.entries(SPECIES)) { + const unlocked = unlockedSpecies.includes(id); + const speciesElement = makeElement("birb-grid-item"); + if (id === currentSpecies) { + speciesElement.classList.add("birb-grid-item-selected"); + } + const speciesCanvas = document.createElement("canvas"); + speciesCanvas.width = SPRITE_WIDTH * CANVAS_PIXEL_SIZE; + speciesCanvas.height = SPRITE_HEIGHT * CANVAS_PIXEL_SIZE; + const speciesCtx = speciesCanvas.getContext("2d"); + if (!speciesCtx) { + return; + } + birb.getFrames().base.draw(speciesCtx, Directions.RIGHT, CANVAS_PIXEL_SIZE, type); + speciesElement.appendChild(speciesCanvas); + content.appendChild(speciesElement); + if (unlocked) { + onClick(speciesElement, () => { + switchSpecies(id); + document.querySelectorAll(".birb-grid-item").forEach((element) => { + element.classList.remove("birb-grid-item-selected"); + }); + speciesElement.classList.add("birb-grid-item-selected"); + }); + } else { + speciesElement.classList.add("birb-grid-item-locked"); + } + speciesElement.addEventListener("mouseover", () => { + description.textContent = ""; + description.appendChild(generateDescription(id)); + }); + speciesElement.addEventListener("mouseout", () => { + description.textContent = ""; + description.appendChild(generateDescription(currentSpecies)); + }); + } + centerElement(fieldGuide); + } + + function removeFieldGuide() { + const fieldGuide = document.querySelector("#" + FIELD_GUIDE_ID); + if (fieldGuide) { + fieldGuide.remove(); + } + } + + /** + * @param {string} type + */ + function switchSpecies(type) { + currentSpecies = type; + // Update CSS variable --birb-highlight to be wing color + document.documentElement.style.setProperty("--birb-highlight", SPECIES[type].colors[Sprite.THEME_HIGHLIGHT]); + save(); + } + + /** + * Update the birds location from the start to the target location on a parabolic path + * @param {number} speed The speed of the bird along the path + * @param {number} [intensity] The intensity of the parabolic path + * @returns {boolean} Whether the bird has reached the target location + */ + function updateParabolicPath(speed, intensity = 2.5) { + const dx = targetX - startX; + const dy = targetY - startY; + const distance = Math.sqrt(dx * dx + dy * dy); + const time = Date.now() - stateStart; + if (distance > Math.max(window.innerWidth, getWindowHeight()) / 2) { + speed *= 1.3; + } + const amount = Math.min(1, time / (distance / speed)); + const { x, y } = parabolicLerp(startX, startY, targetX, targetY, amount, intensity); + birdX = x; + birdY = y; + const complete = Math.abs(birdX - targetX) < 1 && Math.abs(birdY - targetY) < 1; + if (complete) { + birdX = targetX; + birdY = targetY; + } else { + birb.setDirection(targetX > birdX ? Directions.RIGHT : Directions.LEFT); + } + return complete; + } + + function getFocusedElementRandomX() { + return Math.random() * (focusedBounds.right - focusedBounds.left) + focusedBounds.left; + } + + function isWithinHorizontalBounds() { + return birdX >= focusedBounds.left && birdX <= focusedBounds.right; + } + + function getFocusedY() { + return getWindowHeight() - focusedBounds.top; + } + + /** + * Fly to either an element or the ground + */ + function flySomewhere() { + // On mobile, always prefer to focus on an element + // If not mobile, 50% chance to focus on ground + // if ((!isMobile() && coinFlip()) || !focusOnElement()) { + // focusOnGround(); + // } + if (!focusOnElement()) { + focusOnGround(); + } + } + + function focusOnGround() { + focusedElement = null; + updateFocusedElementBounds(); + flyTo(Math.random() * window.innerWidth, 0); + } + + /** + * Focus on an element within the viewport + * @param {boolean} [teleport] Whether to teleport to the element instead of flying + * @returns Whether an element to focus on was found + */ + function focusOnElement(teleport = false) { + if (frozen) { + return false; + } + const elements = document.querySelectorAll("img, video, .birb-sticky-note"); + const inWindow = Array.from(elements).filter((img) => { + const rect = img.getBoundingClientRect(); + return rect.left >= 0 && rect.top >= MIN_FOCUS_ELEMENT_TOP && rect.right <= window.innerWidth && rect.top <= getWindowHeight(); + }); + const visible = Array.from(inWindow).filter((img) => { + const style = window.getComputedStyle(img); + if (style.display === "none" || style.visibility === "hidden" || (style.opacity && parseFloat(style.opacity) < 0.25)) { + return false; + } + return true; + }); + /** @type {HTMLElement[]} */ + // @ts-expect-error + const largeElements = Array.from(visible).filter((img) => img instanceof HTMLElement && img !== focusedElement && img.offsetWidth >= MIN_FOCUS_ELEMENT_WIDTH); + // Ensure the bird doesn't land on fixed or sticky elements + const nonFixedElements = largeElements.filter((el) => { + const style = window.getComputedStyle(el); + return style.position !== "fixed" && style.position !== "sticky"; + }); + if (nonFixedElements.length === 0) { + return false; + } + const randomElement = nonFixedElements[Math.floor(Math.random() * nonFixedElements.length)]; + focusedElement = randomElement; + log("Focusing on element: ", focusedElement); + updateFocusedElementBounds(); + if (teleport) { + teleportTo(getFocusedElementRandomX(), getFocusedY()); + } else { + flyTo(getFocusedElementRandomX(), getFocusedY()); + } + return randomElement !== null; + } + + /** + * @param {number} x + * @param {number} y + */ + function teleportTo(x, y) { + birdX = x; + birdY = y; + setState(States.IDLE); + } + + function updateFocusedElementBounds() { + if (focusedElement === null) { + // Update ground location to bottom of window + focusedBounds = { left: 0, right: window.innerWidth, top: getWindowHeight() }; + return; + } + let { left, right, top } = focusedElement.getBoundingClientRect(); + if (focusedElement.classList.contains("birb-sticky-note")) { + top -= 4.5 * UI_CSS_SCALE; + if (focusedBounds.left !== left) { + // Sticky note has moved + const oldWidth = focusedBounds.right - focusedBounds.left; + const newWidth = right - left; + if (oldWidth === newWidth) { + // Move bird along with note + if (currentState === States.IDLE) { + birdX += left - focusedBounds.left; + } else if (currentState === States.HOP) { + startX += left - focusedBounds.left; + startY += top - focusedBounds.top; + targetX += left - focusedBounds.left; + targetY += top - focusedBounds.top; + } + } + } + } + focusedBounds = { left, right, top }; + } + + function hop() { + if (frozen) { + return; + } + if (currentState === States.IDLE) { + setState(States.HOP); + birb.setAnimation(Animations.FLYING); + if ((Math.random() < 0.5 && birdX - HOP_DISTANCE > focusedBounds.left) || birdX + HOP_DISTANCE > focusedBounds.right) { + targetX = birdX - HOP_DISTANCE; + } else { + targetX = birdX + HOP_DISTANCE; + } + targetY = getFocusedY(); + } + } + + function pet() { + if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) { + birb.setAnimation(Animations.HEART); + lastPetTimestamp = Date.now(); + } + } + + /** + * @param {number} x + * @param {number} y + */ + function flyTo(x, y) { + targetX = x; + targetY = y; + setState(States.FLYING); + birb.setAnimation(Animations.FLYING); + } + + /** + * @returns {boolean} Whether the bird should be absolutely positioned + */ + function isAbsolute() { + return focusedElement !== null && (currentState === States.IDLE || currentState === States.HOP); + } + + /** + * Set the current state and reset the state timer + * @param {string} state + */ + function setState(state) { + stateStart = Date.now(); + startX = birdX; + startY = birdY; + currentState = state; + if (state === States.IDLE) { + birb.setAnimation(Animations.BOB); + } + birb.setAbsolutePositioned(isAbsolute()); + birb.setY(birdY); + } + + // Helper functions + + /** + * @param {number} startX + * @param {number} startY + * @param {number} endX + * @param {number} endY + * @param {number} amount + * @param {number} [intensity] + * @returns {{x: number, y: number}} + */ + function parabolicLerp(startX, startY, endX, endY, amount, intensity = 1.2) { + const dx = endX - startX; + const dy = endY - startY; + const distance = Math.sqrt(dx * dx + dy * dy); + const angle = Math.atan2(dy, dx); + const midX = startX + Math.cos(angle) * distance / 2; + const midY = startY + Math.sin(angle) * distance / 2 + distance / 4 * intensity; + const t = amount; + const x = (1 - t) ** 2 * startX + 2 * (1 - t) * t * midX + t ** 2 * endX; + const y = (1 - t) ** 2 * startY + 2 * (1 - t) * t * midY + t ** 2 * endY; + return { x, y }; + } + + // Run the birb + init(); + draw(); + }).catch((e) => { + error("Error while loading sprite sheets: ", e); + }); + +})(); diff --git a/dist/obsidian/manifest.json b/dist/obsidian/manifest.json new file mode 100644 index 0000000..c0d5d22 --- /dev/null +++ b/dist/obsidian/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "pocket-bird", + "name": "Pocket Bird", + "version": "2025.11.3.34", + "minAppVersion": "0.15.0", + "description": "It's a pet bird in your Obsidian, what more could you want?", + "author": "Idrees Hassan", + "authorUrl": "https://idreesinc.com", + "isDesktopOnly": false +} \ No newline at end of file diff --git a/dist/userscript/birb.user.js b/dist/userscript/birb.user.js index 40a1f10..7304587 100644 --- a/dist/userscript/birb.user.js +++ b/dist/userscript/birb.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Pocket Bird // @namespace https://idreesinc.com -// @version 2025.11.3.21 +// @version 2025.11.3.34 // @description It's a bird that hops around your web browser, the future is here // @author Idrees // @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js @@ -1881,7 +1881,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.21", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.21"); }, false), + new MenuItem("2025.11.3.34", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.34"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/obsidian-manifest.json b/obsidian-manifest.json new file mode 100644 index 0000000..c0d5d22 --- /dev/null +++ b/obsidian-manifest.json @@ -0,0 +1,10 @@ +{ + "id": "pocket-bird", + "name": "Pocket Bird", + "version": "2025.11.3.34", + "minAppVersion": "0.15.0", + "description": "It's a pet bird in your Obsidian, what more could you want?", + "author": "Idrees Hassan", + "authorUrl": "https://idreesinc.com", + "isDesktopOnly": false +} \ No newline at end of file From 2826077d7ad847b6145c627f3de4de682266eea8 Mon Sep 17 00:00:00 2001 From: Idrees Hassan Date: Mon, 3 Nov 2025 21:51:56 -0500 Subject: [PATCH 03/10] Add obsidian context --- browser-manifest.json | 2 +- dist/birb.js | 39 +++++++++++++++++++++++++++++++-- dist/extension.zip | Bin 147747 -> 147808 bytes dist/extension/birb.js | 39 +++++++++++++++++++++++++++++++-- dist/extension/manifest.json | 2 +- dist/obsidian/main.js | 39 +++++++++++++++++++++++++++++++-- dist/obsidian/manifest.json | 2 +- dist/userscript/birb.user.js | 41 ++++++++++++++++++++++++++++++++--- obsidian-manifest.json | 2 +- src/context.js | 37 ++++++++++++++++++++++++++++++- 10 files changed, 189 insertions(+), 14 deletions(-) diff --git a/browser-manifest.json b/browser-manifest.json index c9dad73..ab08464 100644 --- a/browser-manifest.json +++ b/browser-manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.3.34", + "version": "2025.11.3.37", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/dist/birb.js b/dist/birb.js index de3a838..13a3c30 100644 --- a/dist/birb.js +++ b/dist/birb.js @@ -1012,8 +1012,43 @@ } } + class ObsidianContext extends Context { + + /** + * @override + * @returns {boolean} + */ + isContextActive() { + // @ts-expect-error + return typeof app !== "undefined" && typeof app.vault !== "undefined"; + } + + /** + * @override + * @returns {Promise} + */ + async getSaveData() { + log("Loading save data from Obsidian plugin storage unimplemented"); + return {}; + } + + /** + * @override + * @param {BirbSaveData} saveData + */ + async putSaveData(saveData) { + log("Saving data to Obsidian plugin storage unimplemented"); + } + + /** @override */ + resetSaveData() { + log("Resetting save data in Obsidian plugin storage unimplemented"); + } + } + const CONTEXTS = [ new UserScriptContext(), + new ObsidianContext(), new BrowserExtensionContext(), new LocalContext() ]; @@ -1025,7 +1060,7 @@ } } error("No applicable context found, defaulting to LocalContext"); - return CONTEXTS[0]; + return new LocalContext(); } /** @@ -1867,7 +1902,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.34", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.34"); }, false), + new MenuItem("2025.11.3.37", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.37"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension.zip b/dist/extension.zip index b2ae7684c633f944649dcab7321504746f5f0ac2..9fa6640143371baa9cbe4b220a76a5df6a8fae87 100644 GIT binary patch delta 26436 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 ADF6Tf delta 26366 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 B=HUPU diff --git a/dist/extension/birb.js b/dist/extension/birb.js index de3a838..13a3c30 100644 --- a/dist/extension/birb.js +++ b/dist/extension/birb.js @@ -1012,8 +1012,43 @@ } } + class ObsidianContext extends Context { + + /** + * @override + * @returns {boolean} + */ + isContextActive() { + // @ts-expect-error + return typeof app !== "undefined" && typeof app.vault !== "undefined"; + } + + /** + * @override + * @returns {Promise} + */ + async getSaveData() { + log("Loading save data from Obsidian plugin storage unimplemented"); + return {}; + } + + /** + * @override + * @param {BirbSaveData} saveData + */ + async putSaveData(saveData) { + log("Saving data to Obsidian plugin storage unimplemented"); + } + + /** @override */ + resetSaveData() { + log("Resetting save data in Obsidian plugin storage unimplemented"); + } + } + const CONTEXTS = [ new UserScriptContext(), + new ObsidianContext(), new BrowserExtensionContext(), new LocalContext() ]; @@ -1025,7 +1060,7 @@ } } error("No applicable context found, defaulting to LocalContext"); - return CONTEXTS[0]; + return new LocalContext(); } /** @@ -1867,7 +1902,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.34", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.34"); }, false), + new MenuItem("2025.11.3.37", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.37"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension/manifest.json b/dist/extension/manifest.json index c9dad73..ab08464 100644 --- a/dist/extension/manifest.json +++ b/dist/extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.3.34", + "version": "2025.11.3.37", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/dist/obsidian/main.js b/dist/obsidian/main.js index de3a838..13a3c30 100644 --- a/dist/obsidian/main.js +++ b/dist/obsidian/main.js @@ -1012,8 +1012,43 @@ } } + class ObsidianContext extends Context { + + /** + * @override + * @returns {boolean} + */ + isContextActive() { + // @ts-expect-error + return typeof app !== "undefined" && typeof app.vault !== "undefined"; + } + + /** + * @override + * @returns {Promise} + */ + async getSaveData() { + log("Loading save data from Obsidian plugin storage unimplemented"); + return {}; + } + + /** + * @override + * @param {BirbSaveData} saveData + */ + async putSaveData(saveData) { + log("Saving data to Obsidian plugin storage unimplemented"); + } + + /** @override */ + resetSaveData() { + log("Resetting save data in Obsidian plugin storage unimplemented"); + } + } + const CONTEXTS = [ new UserScriptContext(), + new ObsidianContext(), new BrowserExtensionContext(), new LocalContext() ]; @@ -1025,7 +1060,7 @@ } } error("No applicable context found, defaulting to LocalContext"); - return CONTEXTS[0]; + return new LocalContext(); } /** @@ -1867,7 +1902,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.34", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.34"); }, false), + new MenuItem("2025.11.3.37", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.37"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/obsidian/manifest.json b/dist/obsidian/manifest.json index c0d5d22..4220a9a 100644 --- a/dist/obsidian/manifest.json +++ b/dist/obsidian/manifest.json @@ -1,7 +1,7 @@ { "id": "pocket-bird", "name": "Pocket Bird", - "version": "2025.11.3.34", + "version": "2025.11.3.37", "minAppVersion": "0.15.0", "description": "It's a pet bird in your Obsidian, what more could you want?", "author": "Idrees Hassan", diff --git a/dist/userscript/birb.user.js b/dist/userscript/birb.user.js index 7304587..e64c82a 100644 --- a/dist/userscript/birb.user.js +++ b/dist/userscript/birb.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Pocket Bird // @namespace https://idreesinc.com -// @version 2025.11.3.34 +// @version 2025.11.3.37 // @description It's a bird that hops around your web browser, the future is here // @author Idrees // @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js @@ -1026,8 +1026,43 @@ } } + class ObsidianContext extends Context { + + /** + * @override + * @returns {boolean} + */ + isContextActive() { + // @ts-expect-error + return typeof app !== "undefined" && typeof app.vault !== "undefined"; + } + + /** + * @override + * @returns {Promise} + */ + async getSaveData() { + log("Loading save data from Obsidian plugin storage unimplemented"); + return {}; + } + + /** + * @override + * @param {BirbSaveData} saveData + */ + async putSaveData(saveData) { + log("Saving data to Obsidian plugin storage unimplemented"); + } + + /** @override */ + resetSaveData() { + log("Resetting save data in Obsidian plugin storage unimplemented"); + } + } + const CONTEXTS = [ new UserScriptContext(), + new ObsidianContext(), new BrowserExtensionContext(), new LocalContext() ]; @@ -1039,7 +1074,7 @@ } } error("No applicable context found, defaulting to LocalContext"); - return CONTEXTS[0]; + return new LocalContext(); } /** @@ -1881,7 +1916,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.34", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.34"); }, false), + new MenuItem("2025.11.3.37", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.37"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/obsidian-manifest.json b/obsidian-manifest.json index c0d5d22..4220a9a 100644 --- a/obsidian-manifest.json +++ b/obsidian-manifest.json @@ -1,7 +1,7 @@ { "id": "pocket-bird", "name": "Pocket Bird", - "version": "2025.11.3.34", + "version": "2025.11.3.37", "minAppVersion": "0.15.0", "description": "It's a pet bird in your Obsidian, what more could you want?", "author": "Idrees Hassan", diff --git a/src/context.js b/src/context.js index 25b8ecf..d3ada8e 100644 --- a/src/context.js +++ b/src/context.js @@ -174,8 +174,43 @@ class BrowserExtensionContext extends Context { } } +class ObsidianContext extends Context { + + /** + * @override + * @returns {boolean} + */ + isContextActive() { + // @ts-expect-error + return typeof app !== "undefined" && typeof app.vault !== "undefined"; + } + + /** + * @override + * @returns {Promise} + */ + async getSaveData() { + log("Loading save data from Obsidian plugin storage unimplemented"); + return {}; + } + + /** + * @override + * @param {BirbSaveData} saveData + */ + async putSaveData(saveData) { + log("Saving data to Obsidian plugin storage unimplemented"); + } + + /** @override */ + resetSaveData() { + log("Resetting save data in Obsidian plugin storage unimplemented"); + } +} + const CONTEXTS = [ new UserScriptContext(), + new ObsidianContext(), new BrowserExtensionContext(), new LocalContext() ]; @@ -187,5 +222,5 @@ export function getContext() { } } error("No applicable context found, defaulting to LocalContext"); - return CONTEXTS[0]; + return new LocalContext(); } \ No newline at end of file From ea0a14f08c58242e143dab097c8feac283782faf Mon Sep 17 00:00:00 2001 From: Idrees Hassan Date: Mon, 3 Nov 2025 22:05:25 -0500 Subject: [PATCH 04/10] Update build to use build cache --- .gitignore | 1 + browser-manifest.json | 2 +- build.js | 99 ++++++++++++++++------------------- dist/birb.js | 2 +- dist/extension.zip | Bin 147808 -> 147808 bytes dist/extension/birb.js | 2 +- dist/extension/manifest.json | 2 +- dist/obsidian/main.js | 2 +- dist/obsidian/manifest.json | 2 +- dist/userscript/birb.user.js | 4 +- obsidian-manifest.json | 2 +- package.json | 2 +- 12 files changed, 56 insertions(+), 64 deletions(-) diff --git a/.gitignore b/.gitignore index 6be2695..a3eebd7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .DS_Store /dist/birb.bundled.js obsidian-test.sh +build-cache.json diff --git a/browser-manifest.json b/browser-manifest.json index ab08464..c937aa8 100644 --- a/browser-manifest.json +++ b/browser-manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.3.37", + "version": "__VERSION__", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/build.js b/build.js index 8fbfa16..0d83103 100644 --- a/build.js +++ b/build.js @@ -5,6 +5,7 @@ import { readFileSync, writeFileSync, mkdirSync, unlinkSync, cpSync, createWrite import archiver from 'archiver'; // Path constants +const BUILD_CACHE_PATH = "./build-cache.json"; const SRC_DIR = "./src"; const SPRITES_DIR = "./sprites"; const IMAGES_DIR = "./images"; @@ -22,6 +23,9 @@ const APPLICATION_ENTRY = SRC_DIR + "/application.js"; const BUNDLED_OUTPUT = DIST_DIR + "/birb.bundled.js"; const BIRB_OUTPUT = DIST_DIR + "/birb.js"; +const VERSION_KEY = "__VERSION__"; +const STYLESHEET_KEY = "___STYLESHEET___"; + const spriteSheets = [ { key: "__SPRITE_SHEET__", @@ -33,65 +37,34 @@ const spriteSheets = [ } ]; -const STYLESHEET_KEY = "___STYLESHEET___"; +/** @type {Record} */ +let buildCache = {}; +try { + const cacheContent = readFileSync(BUILD_CACHE_PATH, 'utf8'); + buildCache = JSON.parse(cacheContent); +} catch (e) { + console.warn("No build cache found, starting fresh"); +} const now = new Date(); const versionDate = `${now.getFullYear()}.${now.getMonth() + 1}.${now.getDate()}`; -// Get current build number from the browser-manifest.json +// Get current build number from the build cache let buildNumber = 0; -try { - const manifest = JSON.parse(readFileSync(BROWSER_MANIFEST, 'utf8')); - if (manifest.version) { - if (manifest.version.startsWith(versionDate)) { - // Same day, increment build number - const parts = manifest.version.split('.'); - if (parts.length === 4) { - buildNumber = parseInt(parts[3], 10) + 1; - } - } + +if (buildCache.version && buildCache.version.startsWith(versionDate)) { + // Same day, increment build number + const parts = buildCache.version.split('.'); + if (parts.length === 4) { + buildNumber = parseInt(parts[3], 10) + 1; } -} catch (e) { - console.error("Could not read version from browser manifest"); - throw e; } const version = `${versionDate}.${buildNumber}`; -// Update browser manifest with new version -try { - const manifest = JSON.parse(readFileSync(BROWSER_MANIFEST, 'utf8')); - manifest.version = version; - writeFileSync(BROWSER_MANIFEST, JSON.stringify(manifest, null, 4), 'utf8'); -} catch (e) { - console.error("Could not update version in browser manifest"); - throw e; -} - -try { - const obsidianManifest = JSON.parse(readFileSync(OBSIDIAN_MANIFEST, 'utf8')); - obsidianManifest.version = version; - writeFileSync(OBSIDIAN_MANIFEST, JSON.stringify(obsidianManifest, null, 4), 'utf8'); -} catch (e) { - console.error("Could not update version in Obsidian manifest"); -} - -const userScriptHeader = -`// ==UserScript== -// @name Pocket Bird -// @namespace https://idreesinc.com -// @version ${version} -// @description It's a bird that hops around your web browser, the future is here -// @author Idrees -// @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js -// @updateURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js -// @match *://*/* -// @grant GM_setValue -// @grant GM_getValue -// @grant GM_deleteValue -// ==/UserScript== - -`; +// Update build cache +buildCache.version = version; +writeFileSync(BUILD_CACHE_PATH, JSON.stringify(buildCache), 'utf8'); // Bundle with rollup const bundle = await rollup({ @@ -111,7 +84,7 @@ let birbJs = readFileSync(BUNDLED_OUTPUT, 'utf8'); unlinkSync(BUNDLED_OUTPUT); // Replace version placeholder -birbJs = birbJs.replaceAll('__VERSION__', version); +birbJs = birbJs.replaceAll(VERSION_KEY, version); // Compile and insert sprite sheets for (const spriteSheet of spriteSheets) { @@ -127,6 +100,22 @@ birbJs = birbJs.replace(STYLESHEET_KEY, stylesheetContent); writeFileSync(BIRB_OUTPUT, birbJs); // Build user script +const userScriptHeader = + `// ==UserScript== +// @name Pocket Bird +// @namespace https://idreesinc.com +// @version ${version} +// @description It's a bird that hops around your web browser, the future is here +// @author Idrees +// @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js +// @updateURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js +// @match *://*/* +// @grant GM_setValue +// @grant GM_getValue +// @grant GM_deleteValue +// ==/UserScript== + +`; mkdirSync(USERSCRIPT_DIR, { recursive: true }); const userScript = userScriptHeader + birbJs; writeFileSync(USERSCRIPT_DIR + '/birb.user.js', userScript); @@ -138,8 +127,9 @@ mkdirSync(EXTENSION_DIR, { recursive: true }); writeFileSync(EXTENSION_DIR + '/birb.js', birbJs); // Copy manifest.json -const manifestContent = readFileSync(BROWSER_MANIFEST, 'utf8'); -writeFileSync(EXTENSION_DIR + '/manifest.json', manifestContent); +let browserManifest = readFileSync(BROWSER_MANIFEST, 'utf8'); +browserManifest = browserManifest.replace(VERSION_KEY, version); +writeFileSync(EXTENSION_DIR + '/manifest.json', browserManifest); // Copy icons folder mkdirSync(EXTENSION_DIR + '/images/icons', { recursive: true }); @@ -172,7 +162,8 @@ mkdirSync(OBSIDIAN_DIR, { recursive: true }); writeFileSync(OBSIDIAN_DIR + '/main.js', birbJs); // Copy manifest.json -const obsidianManifestContent = readFileSync(OBSIDIAN_MANIFEST, 'utf8'); -writeFileSync(OBSIDIAN_DIR + '/manifest.json', obsidianManifestContent); +let obsidianManifest = readFileSync(OBSIDIAN_MANIFEST, 'utf8'); +obsidianManifest = obsidianManifest.replace(/"version":\s*".*"/, `"version": "${version}"`); +writeFileSync(OBSIDIAN_DIR + '/manifest.json', obsidianManifest); console.log(`Build complete: ${version}`); \ No newline at end of file diff --git a/dist/birb.js b/dist/birb.js index 13a3c30..ce2a95a 100644 --- a/dist/birb.js +++ b/dist/birb.js @@ -1902,7 +1902,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.37", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.37"); }, false), + new MenuItem("2025.11.3.40", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.40"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension.zip b/dist/extension.zip index 9fa6640143371baa9cbe4b220a76a5df6a8fae87..c720120a4022942599b9236c6889766ced7babd5 100644 GIT binary patch delta 1189 zcmaFR#QC6!bHfr=rnwTEm$9ZfGwB`Q%;z~nM&e!m3$w@Z3=Fawj0^$Z%q(0CATU>A z^1f6hpyK97soNi=GS;~O+0&C&F`5GD?K4*~vax{}3pX$>1Q|K)G^6(R{B4ZsEKtsL zActeRy%iJdc7ffD%R$1^9d0mcPw%#3;@;+70?2rfR-NtpE-+Stlz@5DwQQKUw&!1AJP#7u4pi_QCTF-k>JFnE!b*8tp!pjf zFiwCe(4GzyV%uK)gz+w1XnXAo#&iTv@D1Z71W(`tV-tu6_U8W2jHxg`PX}^1wnzSC zya;oq_V)1qjQ--h+b~ndvj}g>-O0U|7PTd2}LH`8l+w?m8=ikHjyp=S3`1{o&C)JXVNym zF^Qh@<-;kn2Tz2K+`7JTiRdEk>6Poe`31HF&fMgizh}{l zAhXxxpeH}u=c7NT?TdVNW)t_MJ$mQ9RmIN9efj%%w%PspJs)y^1@8)Zyl(PTF85XL zTOPUb)wA&_&t8|mBCOuPw9_HxkJq)*DOxd~585;J=g!;F+ihR_*xy&jh-vw`!HDV`;-85mOHS#%1k&zgd3VTA}K8 zWmlYh?FqXC(UUTtth3jA+H~kl($~&c>T{)j+9%a74*#y#FP~i8wOh_-jLyaN zFXQSlHJGX$XU~`Oc;(y)h1;!f{ACUBX6I;cU3z-@c{3(&j=2&k(V#pyUCEqD7Zl-v z=1fMQ6wqqUWXK2-*kQrs3Znm8Fol5VP)nv@5WUKhDF{UWgVI4(OaUN%mo1ab^aEB* zCQwP4=|a{_W*|<39Z)6>%9&>kQT_o+JJ~?^Q=s%SC~aX2Hx_LC9VlPV4k8XT6zq&E iP+G$tB3=ch&p>H82Z(q9ls@FZ6bbe{I4qPMnQQ?EVb+lV delta 1189 zcmaFR#QC6!bHfr=CPvZC%UIK#nR1S7=JT8(BawCS^Nq*x3=Fawj0^$Z%q(0CAiyX( zd0(m$P;v94)a{Q_8S7kt?CD9X7)^on_L-{~+1Nmgg&P*H-_=fQkf+z5Su?fTjdvpJ1##ES}rvo`0+arH6 zUW7SQdwckQ#(xN{Kz*)or)>Yi&LofEIq)!fzfQj+3rG{Ta9Z^k?1L{}pGS{hlni&$r%dde)uNO+gPmzIKG& zIq|UWfx)JizuL0uS%W8Y964HlVpm^KYqs4F_Xi8l3U4p`xIg|!uyA+Jft8;NZY_-! z@3H>S%U4*o>|%w(YtIkgyS!R|N&Y*ri1%*$4F|;~K@NdkQZ4Ncmz|H-GS%c=5mL^I zUC)0%RenQP3g6GUreT$liD?^uIecyQ>-{6YasP$Y)gnq30lO}Fv4lEYNt3+U=lje% zpuenWYSc3CU61u_Pd@%}BhS8?nfYqaB9T+qOecK0){(jSSV?np`|_>d1UC0MoUUZfqzj7hKyxM| zPzq=@XEJ023GA?7as|=l|3T>>E2aPtzsr_MX8HjuCKITn z%yc1ZCNmJH!44>s2Ib7NhA964rJZab{3%fS8I-oLg&PYt{tlF{X9p1n8VYvC6)3G? f4-v0|(r2KwoC8F>07@TnV2T9$9vl|Rj!d=y)%mu+ diff --git a/dist/extension/birb.js b/dist/extension/birb.js index 13a3c30..ce2a95a 100644 --- a/dist/extension/birb.js +++ b/dist/extension/birb.js @@ -1902,7 +1902,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.37", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.37"); }, false), + new MenuItem("2025.11.3.40", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.40"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension/manifest.json b/dist/extension/manifest.json index ab08464..09eb809 100644 --- a/dist/extension/manifest.json +++ b/dist/extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.3.37", + "version": "2025.11.3.40", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/dist/obsidian/main.js b/dist/obsidian/main.js index 13a3c30..ce2a95a 100644 --- a/dist/obsidian/main.js +++ b/dist/obsidian/main.js @@ -1902,7 +1902,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.37", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.37"); }, false), + new MenuItem("2025.11.3.40", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.40"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/obsidian/manifest.json b/dist/obsidian/manifest.json index 4220a9a..34e3d99 100644 --- a/dist/obsidian/manifest.json +++ b/dist/obsidian/manifest.json @@ -1,7 +1,7 @@ { "id": "pocket-bird", "name": "Pocket Bird", - "version": "2025.11.3.37", + "version": "2025.11.3.40", "minAppVersion": "0.15.0", "description": "It's a pet bird in your Obsidian, what more could you want?", "author": "Idrees Hassan", diff --git a/dist/userscript/birb.user.js b/dist/userscript/birb.user.js index e64c82a..785482f 100644 --- a/dist/userscript/birb.user.js +++ b/dist/userscript/birb.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Pocket Bird // @namespace https://idreesinc.com -// @version 2025.11.3.37 +// @version 2025.11.3.40 // @description It's a bird that hops around your web browser, the future is here // @author Idrees // @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js @@ -1916,7 +1916,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.37", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.37"); }, false), + new MenuItem("2025.11.3.40", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.40"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/obsidian-manifest.json b/obsidian-manifest.json index 4220a9a..1f45808 100644 --- a/obsidian-manifest.json +++ b/obsidian-manifest.json @@ -1,7 +1,7 @@ { "id": "pocket-bird", "name": "Pocket Bird", - "version": "2025.11.3.37", + "version": "__VERSION__", "minAppVersion": "0.15.0", "description": "It's a pet bird in your Obsidian, what more could you want?", "author": "Idrees Hassan", diff --git a/package.json b/package.json index 7c2c0c9..cb76cb6 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "type": "module", "scripts": { "build": "node build.js", - "dev": "nodemon --watch src --watch stylesheet.css --watch build.js --exec \"npm run build\"" + "dev": "nodemon --watch src --watch package.json --watch stylesheet.css --watch build.js --watch obsidian-manifest.json --watch browser-manifest.json --exec \"npm run build\"" }, "devDependencies": { "archiver": "^7.0.1", From e99a61a4c676605c8c2037a26e451d53dfad17b8 Mon Sep 17 00:00:00 2001 From: Idrees Hassan Date: Thu, 13 Nov 2025 17:10:50 -0500 Subject: [PATCH 05/10] Create working obsidian plugin boilerplate --- build.js | 13 +++++++++++-- dist/birb.js | 2 +- dist/extension.zip | Bin 147808 -> 148744 bytes dist/extension/birb.js | 2 +- dist/extension/manifest.json | 2 +- dist/obsidian/main.js | 11 +++++++++-- dist/obsidian/manifest.json | 2 +- dist/userscript/birb.user.js | 4 ++-- 8 files changed, 26 insertions(+), 10 deletions(-) diff --git a/build.js b/build.js index 0d83103..fc437c6 100644 --- a/build.js +++ b/build.js @@ -158,8 +158,17 @@ archive.finalize(); // Build Obsidian plugin mkdirSync(OBSIDIAN_DIR, { recursive: true }); -// Copy birb.js to main.js -writeFileSync(OBSIDIAN_DIR + '/main.js', birbJs); +// Wrap birb.js with plugin boilerplate +const obsidianPlugin = ` +const { Plugin, Notice } = require('obsidian'); +module.exports = class MyPlugin extends Plugin { + onload() { + ${birbJs} + } +};` + +// Create main.js with plugin code +writeFileSync(OBSIDIAN_DIR + '/main.js', obsidianPlugin); // Copy manifest.json let obsidianManifest = readFileSync(OBSIDIAN_MANIFEST, 'utf8'); diff --git a/dist/birb.js b/dist/birb.js index ce2a95a..c85f4bf 100644 --- a/dist/birb.js +++ b/dist/birb.js @@ -1902,7 +1902,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.40", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.40"); }, false), + new MenuItem("2025.11.13.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.1"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension.zip b/dist/extension.zip index c720120a4022942599b9236c6889766ced7babd5..91cc8fd37f618e6fe07081dd91e32d19475ca90c 100644 GIT binary patch delta 10693 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 TgeNi0 { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.40"); }, false), + new MenuItem("2025.11.13.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.1"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension/manifest.json b/dist/extension/manifest.json index 09eb809..36d3602 100644 --- a/dist/extension/manifest.json +++ b/dist/extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.3.40", + "version": "2025.11.13.1", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/dist/obsidian/main.js b/dist/obsidian/main.js index ce2a95a..5e8eb3c 100644 --- a/dist/obsidian/main.js +++ b/dist/obsidian/main.js @@ -1,4 +1,8 @@ -(function () { + +const { Plugin, Notice } = require('obsidian'); +module.exports = class MyPlugin extends Plugin { + onload() { + (function () { 'use strict'; const Directions = { @@ -1902,7 +1906,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.40", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.40"); }, false), + new MenuItem("2025.11.13.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.1"); }, false), ]; const styleElement = document.createElement("style"); @@ -2692,3 +2696,6 @@ }); })(); + + } +}; diff --git a/dist/obsidian/manifest.json b/dist/obsidian/manifest.json index 34e3d99..ef306db 100644 --- a/dist/obsidian/manifest.json +++ b/dist/obsidian/manifest.json @@ -1,7 +1,7 @@ { "id": "pocket-bird", "name": "Pocket Bird", - "version": "2025.11.3.40", + "version": "2025.11.13.1", "minAppVersion": "0.15.0", "description": "It's a pet bird in your Obsidian, what more could you want?", "author": "Idrees Hassan", diff --git a/dist/userscript/birb.user.js b/dist/userscript/birb.user.js index 785482f..a17a07a 100644 --- a/dist/userscript/birb.user.js +++ b/dist/userscript/birb.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Pocket Bird // @namespace https://idreesinc.com -// @version 2025.11.3.40 +// @version 2025.11.13.1 // @description It's a bird that hops around your web browser, the future is here // @author Idrees // @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js @@ -1916,7 +1916,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.3.40", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.3.40"); }, false), + new MenuItem("2025.11.13.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.1"); }, false), ]; const styleElement = document.createElement("style"); From 40169dd4745bebf8321ec2b99016ae9af6a96c47 Mon Sep 17 00:00:00 2001 From: Idrees Hassan Date: Thu, 13 Nov 2025 17:20:04 -0500 Subject: [PATCH 06/10] Add obsidian plugin unloading --- build.js | 6 ++++++ dist/birb.js | 2 +- dist/extension.zip | Bin 148744 -> 148744 bytes dist/extension/birb.js | 2 +- dist/extension/manifest.json | 2 +- dist/obsidian/main.js | 10 ++++++++-- dist/obsidian/manifest.json | 2 +- dist/userscript/birb.user.js | 4 ++-- 8 files changed, 20 insertions(+), 8 deletions(-) diff --git a/build.js b/build.js index fc437c6..be51ab7 100644 --- a/build.js +++ b/build.js @@ -165,6 +165,12 @@ module.exports = class MyPlugin extends Plugin { onload() { ${birbJs} } + + onunload() { + // Remove the birb when the plugin is unloaded + document.getElementById('birb')?.remove(); + console.log('Pocket Bird unloaded!'); + } };` // Create main.js with plugin code diff --git a/dist/birb.js b/dist/birb.js index c85f4bf..7180c24 100644 --- a/dist/birb.js +++ b/dist/birb.js @@ -1902,7 +1902,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.1"); }, false), + new MenuItem("2025.11.13.2", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.2"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension.zip b/dist/extension.zip index 91cc8fd37f618e6fe07081dd91e32d19475ca90c..91981101c06868ec720553eb73a4066393754961 100644 GIT binary patch delta 4466 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 delta 4466 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 diff --git a/dist/extension/birb.js b/dist/extension/birb.js index c85f4bf..7180c24 100644 --- a/dist/extension/birb.js +++ b/dist/extension/birb.js @@ -1902,7 +1902,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.1"); }, false), + new MenuItem("2025.11.13.2", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.2"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension/manifest.json b/dist/extension/manifest.json index 36d3602..6afbae5 100644 --- a/dist/extension/manifest.json +++ b/dist/extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.13.1", + "version": "2025.11.13.2", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/dist/obsidian/main.js b/dist/obsidian/main.js index 5e8eb3c..c63c8bc 100644 --- a/dist/obsidian/main.js +++ b/dist/obsidian/main.js @@ -1906,7 +1906,7 @@ module.exports = class MyPlugin extends Plugin { insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.1"); }, false), + new MenuItem("2025.11.13.2", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.2"); }, false), ]; const styleElement = document.createElement("style"); @@ -2698,4 +2698,10 @@ module.exports = class MyPlugin extends Plugin { })(); } -}; + + onunload() { + // Remove the birb when the plugin is unloaded + document.getElementById('birb')?.remove(); + console.log('Pocket Bird unloaded!'); + } +}; \ No newline at end of file diff --git a/dist/obsidian/manifest.json b/dist/obsidian/manifest.json index ef306db..a55a7fa 100644 --- a/dist/obsidian/manifest.json +++ b/dist/obsidian/manifest.json @@ -1,7 +1,7 @@ { "id": "pocket-bird", "name": "Pocket Bird", - "version": "2025.11.13.1", + "version": "2025.11.13.2", "minAppVersion": "0.15.0", "description": "It's a pet bird in your Obsidian, what more could you want?", "author": "Idrees Hassan", diff --git a/dist/userscript/birb.user.js b/dist/userscript/birb.user.js index a17a07a..c05ddb3 100644 --- a/dist/userscript/birb.user.js +++ b/dist/userscript/birb.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Pocket Bird // @namespace https://idreesinc.com -// @version 2025.11.13.1 +// @version 2025.11.13.2 // @description It's a bird that hops around your web browser, the future is here // @author Idrees // @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js @@ -1916,7 +1916,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.1"); }, false), + new MenuItem("2025.11.13.2", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.2"); }, false), ]; const styleElement = document.createElement("style"); From d7dca478d68d78bf3059ee590c5beab94955cfa7 Mon Sep 17 00:00:00 2001 From: Idrees Hassan Date: Thu, 13 Nov 2025 17:46:03 -0500 Subject: [PATCH 07/10] Move sticky note path checking to context --- dist/birb.js | 106 ++++++++++++++++++---------------- dist/extension.zip | Bin 148744 -> 148897 bytes dist/extension/birb.js | 106 ++++++++++++++++++---------------- dist/extension/manifest.json | 2 +- dist/obsidian/main.js | 106 ++++++++++++++++++---------------- dist/obsidian/manifest.json | 2 +- dist/userscript/birb.user.js | 108 +++++++++++++++++++---------------- src/application.js | 10 ++-- src/context.js | 50 +++++++++++++++- src/stickyNotes.js | 46 ++------------- 10 files changed, 293 insertions(+), 243 deletions(-) diff --git a/dist/birb.js b/dist/birb.js index 7180c24..3436801 100644 --- a/dist/birb.js +++ b/dist/birb.js @@ -880,6 +880,40 @@ resetSaveData() { throw new Error("Method not implemented"); } + + /** + * @returns {string} The current path of the active page in this context + */ + getPath() { + // Default to website URL + return window.location.href; + } + + /** + * Checks if a path is applicable given the context + * @param {string} path Can be a site URL or another context-specific path + * @returns {boolean} Whether the path matches the current context state + */ + isPathApplicable(path) { + // Default to website URL matching + const currentUrl = window.location.href; + const stickyNoteWebsite = path.split("?")[0]; + const currentWebsite = currentUrl.split("?")[0]; + + if (stickyNoteWebsite !== currentWebsite) { + return false; + } + + const pathParams = parseUrlParams(path); + const currentParams = parseUrlParams(currentUrl); + + if (window.location.hostname === "www.youtube.com") { + if (currentParams.v !== undefined && currentParams.v !== pathParams.v) { + return false; + } + } + return true; + } } class LocalContext extends Context { @@ -1063,6 +1097,21 @@ return new LocalContext(); } + /** + * Parse URL parameters into a key-value map + * @param {string} url + * @returns {Record} + */ + 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 }; + }, {}); + } + /** * @typedef {Object} SavedStickyNote * @property {string} id @@ -1089,46 +1138,6 @@ } } - /** - * Parse URL parameters into a key-value map - * @param {string} url - * @returns {Record} - */ - 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 }; - }, {}); - } - - /** - * @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]; - - if (stickyNoteWebsite !== currentWebsite) { - return false; - } - - const stickyNoteParams = parseUrlParams(stickyNoteUrl); - const currentParams = parseUrlParams(currentUrl); - - if (window.location.hostname === "www.youtube.com") { - if (currentParams.v !== undefined && currentParams.v !== stickyNoteParams.v) { - return false; - } - } - return true; - } - /** * @param {StickyNote} stickyNote * @param {() => void} onSave @@ -1211,8 +1220,9 @@ const existingNotes = document.querySelectorAll(".birb-sticky-note"); existingNotes.forEach(note => note.remove()); // Render all sticky notes + const context = getContext(); for (let stickyNote of stickyNotes) { - if (isStickyNoteApplicable(stickyNote)) { + if (context.isPathApplicable(stickyNote.site)) { renderStickyNote(stickyNote, onSave, () => onDelete(stickyNote)); } } @@ -1225,7 +1235,7 @@ */ function createNewStickyNote(stickyNotes, onSave, onDelete) { const id = Date.now().toString(); - const site = window.location.href; + const site = getContext().getPath(); const stickyNote = new StickyNote(id, site, ""); const element = renderStickyNote(stickyNote, onSave, () => onDelete(stickyNote)); element.style.left = `${window.innerWidth / 2 - element.offsetWidth / 2}px`; @@ -1902,7 +1912,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.2", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.2"); }, false), + new MenuItem("2025.11.13.6", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.6"); }, false), ]; const styleElement = document.createElement("style"); @@ -2097,12 +2107,12 @@ drawStickyNotes(stickyNotes, save, deleteStickyNote); - let lastUrl = (window.location.href ?? "").split("?")[0]; + let lastPath = getContext().getPath().split("?")[0]; setInterval(() => { - const currentUrl = (window.location.href ?? "").split("?")[0]; - if (currentUrl !== lastUrl) { - log("URL changed, updating sticky notes"); - lastUrl = currentUrl; + const currentPath = getContext().getPath().split("?")[0]; + if (currentPath !== lastPath) { + log("Path changed, updating sticky notes"); + lastPath = currentPath; drawStickyNotes(stickyNotes, save, deleteStickyNote); } }, URL_CHECK_INTERVAL); diff --git a/dist/extension.zip b/dist/extension.zip index 91981101c06868ec720553eb73a4066393754961..9374412749c0713c2ca13da899dfb911f3f4b8e5 100644 GIT binary patch delta 26469 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 z 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 delta 26381 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%0A$z)rjrzd>G*0Mb)?X7F%Ud7 zKnz6iJAt3A+QDiF0KgDF0Ko9C1jHKu@`)b<>_0kLd;bTd69*AJf)X%~AomY{Kpz-L z@mTv0OzfsW5CGr@J81vqR2TYA999g>a##vx$uRI}Nd={q0D=FyYyS)_kc1`bGzLV1 zdjCh$BMqZxfBCCH|KA!{C13>h=|2S6_JaDq1TL6Q(9GOl!tebD{JRM`b<3nsH~=6C zcKkcvuS<`7?%%9}lRSrCFviXQV|`qGWKlu!V52;LQ~S|qBRpX=*Z)T)*m|s(I3uW9dIOE{~d^^FNxm z(tkqyZXM^(-ym$C!(jdQ>Toi$3wC0whphoN5&(eyUq4sx-9J{yP(7JHF&t!IF$O_U zDmhpgg))C)v_FF9h=0I~|9}{>Fwh3=4=6ADhiUc*)?xht)Bgk3J%aRje?Zs} diff --git a/dist/extension/birb.js b/dist/extension/birb.js index 7180c24..3436801 100644 --- a/dist/extension/birb.js +++ b/dist/extension/birb.js @@ -880,6 +880,40 @@ resetSaveData() { throw new Error("Method not implemented"); } + + /** + * @returns {string} The current path of the active page in this context + */ + getPath() { + // Default to website URL + return window.location.href; + } + + /** + * Checks if a path is applicable given the context + * @param {string} path Can be a site URL or another context-specific path + * @returns {boolean} Whether the path matches the current context state + */ + isPathApplicable(path) { + // Default to website URL matching + const currentUrl = window.location.href; + const stickyNoteWebsite = path.split("?")[0]; + const currentWebsite = currentUrl.split("?")[0]; + + if (stickyNoteWebsite !== currentWebsite) { + return false; + } + + const pathParams = parseUrlParams(path); + const currentParams = parseUrlParams(currentUrl); + + if (window.location.hostname === "www.youtube.com") { + if (currentParams.v !== undefined && currentParams.v !== pathParams.v) { + return false; + } + } + return true; + } } class LocalContext extends Context { @@ -1063,6 +1097,21 @@ return new LocalContext(); } + /** + * Parse URL parameters into a key-value map + * @param {string} url + * @returns {Record} + */ + 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 }; + }, {}); + } + /** * @typedef {Object} SavedStickyNote * @property {string} id @@ -1089,46 +1138,6 @@ } } - /** - * Parse URL parameters into a key-value map - * @param {string} url - * @returns {Record} - */ - 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 }; - }, {}); - } - - /** - * @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]; - - if (stickyNoteWebsite !== currentWebsite) { - return false; - } - - const stickyNoteParams = parseUrlParams(stickyNoteUrl); - const currentParams = parseUrlParams(currentUrl); - - if (window.location.hostname === "www.youtube.com") { - if (currentParams.v !== undefined && currentParams.v !== stickyNoteParams.v) { - return false; - } - } - return true; - } - /** * @param {StickyNote} stickyNote * @param {() => void} onSave @@ -1211,8 +1220,9 @@ const existingNotes = document.querySelectorAll(".birb-sticky-note"); existingNotes.forEach(note => note.remove()); // Render all sticky notes + const context = getContext(); for (let stickyNote of stickyNotes) { - if (isStickyNoteApplicable(stickyNote)) { + if (context.isPathApplicable(stickyNote.site)) { renderStickyNote(stickyNote, onSave, () => onDelete(stickyNote)); } } @@ -1225,7 +1235,7 @@ */ function createNewStickyNote(stickyNotes, onSave, onDelete) { const id = Date.now().toString(); - const site = window.location.href; + const site = getContext().getPath(); const stickyNote = new StickyNote(id, site, ""); const element = renderStickyNote(stickyNote, onSave, () => onDelete(stickyNote)); element.style.left = `${window.innerWidth / 2 - element.offsetWidth / 2}px`; @@ -1902,7 +1912,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.2", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.2"); }, false), + new MenuItem("2025.11.13.6", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.6"); }, false), ]; const styleElement = document.createElement("style"); @@ -2097,12 +2107,12 @@ drawStickyNotes(stickyNotes, save, deleteStickyNote); - let lastUrl = (window.location.href ?? "").split("?")[0]; + let lastPath = getContext().getPath().split("?")[0]; setInterval(() => { - const currentUrl = (window.location.href ?? "").split("?")[0]; - if (currentUrl !== lastUrl) { - log("URL changed, updating sticky notes"); - lastUrl = currentUrl; + const currentPath = getContext().getPath().split("?")[0]; + if (currentPath !== lastPath) { + log("Path changed, updating sticky notes"); + lastPath = currentPath; drawStickyNotes(stickyNotes, save, deleteStickyNote); } }, URL_CHECK_INTERVAL); diff --git a/dist/extension/manifest.json b/dist/extension/manifest.json index 6afbae5..cc12b0a 100644 --- a/dist/extension/manifest.json +++ b/dist/extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.13.2", + "version": "2025.11.13.6", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/dist/obsidian/main.js b/dist/obsidian/main.js index c63c8bc..91d0ecb 100644 --- a/dist/obsidian/main.js +++ b/dist/obsidian/main.js @@ -884,6 +884,40 @@ module.exports = class MyPlugin extends Plugin { resetSaveData() { throw new Error("Method not implemented"); } + + /** + * @returns {string} The current path of the active page in this context + */ + getPath() { + // Default to website URL + return window.location.href; + } + + /** + * Checks if a path is applicable given the context + * @param {string} path Can be a site URL or another context-specific path + * @returns {boolean} Whether the path matches the current context state + */ + isPathApplicable(path) { + // Default to website URL matching + const currentUrl = window.location.href; + const stickyNoteWebsite = path.split("?")[0]; + const currentWebsite = currentUrl.split("?")[0]; + + if (stickyNoteWebsite !== currentWebsite) { + return false; + } + + const pathParams = parseUrlParams(path); + const currentParams = parseUrlParams(currentUrl); + + if (window.location.hostname === "www.youtube.com") { + if (currentParams.v !== undefined && currentParams.v !== pathParams.v) { + return false; + } + } + return true; + } } class LocalContext extends Context { @@ -1067,6 +1101,21 @@ module.exports = class MyPlugin extends Plugin { return new LocalContext(); } + /** + * Parse URL parameters into a key-value map + * @param {string} url + * @returns {Record} + */ + 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 }; + }, {}); + } + /** * @typedef {Object} SavedStickyNote * @property {string} id @@ -1093,46 +1142,6 @@ module.exports = class MyPlugin extends Plugin { } } - /** - * Parse URL parameters into a key-value map - * @param {string} url - * @returns {Record} - */ - 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 }; - }, {}); - } - - /** - * @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]; - - if (stickyNoteWebsite !== currentWebsite) { - return false; - } - - const stickyNoteParams = parseUrlParams(stickyNoteUrl); - const currentParams = parseUrlParams(currentUrl); - - if (window.location.hostname === "www.youtube.com") { - if (currentParams.v !== undefined && currentParams.v !== stickyNoteParams.v) { - return false; - } - } - return true; - } - /** * @param {StickyNote} stickyNote * @param {() => void} onSave @@ -1215,8 +1224,9 @@ module.exports = class MyPlugin extends Plugin { const existingNotes = document.querySelectorAll(".birb-sticky-note"); existingNotes.forEach(note => note.remove()); // Render all sticky notes + const context = getContext(); for (let stickyNote of stickyNotes) { - if (isStickyNoteApplicable(stickyNote)) { + if (context.isPathApplicable(stickyNote.site)) { renderStickyNote(stickyNote, onSave, () => onDelete(stickyNote)); } } @@ -1229,7 +1239,7 @@ module.exports = class MyPlugin extends Plugin { */ function createNewStickyNote(stickyNotes, onSave, onDelete) { const id = Date.now().toString(); - const site = window.location.href; + const site = getContext().getPath(); const stickyNote = new StickyNote(id, site, ""); const element = renderStickyNote(stickyNote, onSave, () => onDelete(stickyNote)); element.style.left = `${window.innerWidth / 2 - element.offsetWidth / 2}px`; @@ -1906,7 +1916,7 @@ module.exports = class MyPlugin extends Plugin { insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.2", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.2"); }, false), + new MenuItem("2025.11.13.6", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.6"); }, false), ]; const styleElement = document.createElement("style"); @@ -2101,12 +2111,12 @@ module.exports = class MyPlugin extends Plugin { drawStickyNotes(stickyNotes, save, deleteStickyNote); - let lastUrl = (window.location.href ?? "").split("?")[0]; + let lastPath = getContext().getPath().split("?")[0]; setInterval(() => { - const currentUrl = (window.location.href ?? "").split("?")[0]; - if (currentUrl !== lastUrl) { - log("URL changed, updating sticky notes"); - lastUrl = currentUrl; + const currentPath = getContext().getPath().split("?")[0]; + if (currentPath !== lastPath) { + log("Path changed, updating sticky notes"); + lastPath = currentPath; drawStickyNotes(stickyNotes, save, deleteStickyNote); } }, URL_CHECK_INTERVAL); diff --git a/dist/obsidian/manifest.json b/dist/obsidian/manifest.json index a55a7fa..c2d4666 100644 --- a/dist/obsidian/manifest.json +++ b/dist/obsidian/manifest.json @@ -1,7 +1,7 @@ { "id": "pocket-bird", "name": "Pocket Bird", - "version": "2025.11.13.2", + "version": "2025.11.13.6", "minAppVersion": "0.15.0", "description": "It's a pet bird in your Obsidian, what more could you want?", "author": "Idrees Hassan", diff --git a/dist/userscript/birb.user.js b/dist/userscript/birb.user.js index c05ddb3..6201bbe 100644 --- a/dist/userscript/birb.user.js +++ b/dist/userscript/birb.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Pocket Bird // @namespace https://idreesinc.com -// @version 2025.11.13.2 +// @version 2025.11.13.6 // @description It's a bird that hops around your web browser, the future is here // @author Idrees // @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js @@ -894,6 +894,40 @@ resetSaveData() { throw new Error("Method not implemented"); } + + /** + * @returns {string} The current path of the active page in this context + */ + getPath() { + // Default to website URL + return window.location.href; + } + + /** + * Checks if a path is applicable given the context + * @param {string} path Can be a site URL or another context-specific path + * @returns {boolean} Whether the path matches the current context state + */ + isPathApplicable(path) { + // Default to website URL matching + const currentUrl = window.location.href; + const stickyNoteWebsite = path.split("?")[0]; + const currentWebsite = currentUrl.split("?")[0]; + + if (stickyNoteWebsite !== currentWebsite) { + return false; + } + + const pathParams = parseUrlParams(path); + const currentParams = parseUrlParams(currentUrl); + + if (window.location.hostname === "www.youtube.com") { + if (currentParams.v !== undefined && currentParams.v !== pathParams.v) { + return false; + } + } + return true; + } } class LocalContext extends Context { @@ -1077,6 +1111,21 @@ return new LocalContext(); } + /** + * Parse URL parameters into a key-value map + * @param {string} url + * @returns {Record} + */ + 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 }; + }, {}); + } + /** * @typedef {Object} SavedStickyNote * @property {string} id @@ -1103,46 +1152,6 @@ } } - /** - * Parse URL parameters into a key-value map - * @param {string} url - * @returns {Record} - */ - 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 }; - }, {}); - } - - /** - * @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]; - - if (stickyNoteWebsite !== currentWebsite) { - return false; - } - - const stickyNoteParams = parseUrlParams(stickyNoteUrl); - const currentParams = parseUrlParams(currentUrl); - - if (window.location.hostname === "www.youtube.com") { - if (currentParams.v !== undefined && currentParams.v !== stickyNoteParams.v) { - return false; - } - } - return true; - } - /** * @param {StickyNote} stickyNote * @param {() => void} onSave @@ -1225,8 +1234,9 @@ const existingNotes = document.querySelectorAll(".birb-sticky-note"); existingNotes.forEach(note => note.remove()); // Render all sticky notes + const context = getContext(); for (let stickyNote of stickyNotes) { - if (isStickyNoteApplicable(stickyNote)) { + if (context.isPathApplicable(stickyNote.site)) { renderStickyNote(stickyNote, onSave, () => onDelete(stickyNote)); } } @@ -1239,7 +1249,7 @@ */ function createNewStickyNote(stickyNotes, onSave, onDelete) { const id = Date.now().toString(); - const site = window.location.href; + const site = getContext().getPath(); const stickyNote = new StickyNote(id, site, ""); const element = renderStickyNote(stickyNote, onSave, () => onDelete(stickyNote)); element.style.left = `${window.innerWidth / 2 - element.offsetWidth / 2}px`; @@ -1916,7 +1926,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.2", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.2"); }, false), + new MenuItem("2025.11.13.6", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.6"); }, false), ]; const styleElement = document.createElement("style"); @@ -2111,12 +2121,12 @@ drawStickyNotes(stickyNotes, save, deleteStickyNote); - let lastUrl = (window.location.href ?? "").split("?")[0]; + let lastPath = getContext().getPath().split("?")[0]; setInterval(() => { - const currentUrl = (window.location.href ?? "").split("?")[0]; - if (currentUrl !== lastUrl) { - log("URL changed, updating sticky notes"); - lastUrl = currentUrl; + const currentPath = getContext().getPath().split("?")[0]; + if (currentPath !== lastPath) { + log("Path changed, updating sticky notes"); + lastPath = currentPath; drawStickyNotes(stickyNotes, save, deleteStickyNote); } }, URL_CHECK_INTERVAL); diff --git a/src/application.js b/src/application.js index 5ab3814..9ce19c4 100644 --- a/src/application.js +++ b/src/application.js @@ -426,12 +426,12 @@ Promise.all([ drawStickyNotes(stickyNotes, save, deleteStickyNote); - let lastUrl = (window.location.href ?? "").split("?")[0]; + let lastPath = getContext().getPath().split("?")[0]; setInterval(() => { - const currentUrl = (window.location.href ?? "").split("?")[0]; - if (currentUrl !== lastUrl) { - log("URL changed, updating sticky notes"); - lastUrl = currentUrl; + const currentPath = getContext().getPath().split("?")[0]; + if (currentPath !== lastPath) { + log("Path changed, updating sticky notes"); + lastPath = currentPath; drawStickyNotes(stickyNotes, save, deleteStickyNote); } }, URL_CHECK_INTERVAL); diff --git a/src/context.js b/src/context.js index d3ada8e..ddc8de3 100644 --- a/src/context.js +++ b/src/context.js @@ -1,4 +1,3 @@ - import { debug, log, error } from "./shared.js"; const SAVE_KEY = "birbSaveData"; @@ -42,6 +41,40 @@ export class Context { resetSaveData() { throw new Error("Method not implemented"); } + + /** + * @returns {string} The current path of the active page in this context + */ + getPath() { + // Default to website URL + return window.location.href; + } + + /** + * Checks if a path is applicable given the context + * @param {string} path Can be a site URL or another context-specific path + * @returns {boolean} Whether the path matches the current context state + */ + isPathApplicable(path) { + // Default to website URL matching + const currentUrl = window.location.href; + const stickyNoteWebsite = path.split("?")[0]; + const currentWebsite = currentUrl.split("?")[0]; + + if (stickyNoteWebsite !== currentWebsite) { + return false; + } + + const pathParams = parseUrlParams(path); + const currentParams = parseUrlParams(currentUrl); + + if (window.location.hostname === "www.youtube.com") { + if (currentParams.v !== undefined && currentParams.v !== pathParams.v) { + return false; + } + } + return true; + } } export class LocalContext extends Context { @@ -223,4 +256,19 @@ export function getContext() { } error("No applicable context found, defaulting to LocalContext"); return new LocalContext(); +} + +/** + * Parse URL parameters into a key-value map + * @param {string} url + * @returns {Record} + */ +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 }; + }, {}); } \ No newline at end of file diff --git a/src/stickyNotes.js b/src/stickyNotes.js index 29e7d8e..8e9c523 100644 --- a/src/stickyNotes.js +++ b/src/stickyNotes.js @@ -3,6 +3,7 @@ import { makeDraggable, makeClosable } from './shared.js'; +import { getContext } from './context.js'; /** * @typedef {Object} SavedStickyNote @@ -30,46 +31,6 @@ export class StickyNote { } } -/** - * Parse URL parameters into a key-value map - * @param {string} url - * @returns {Record} - */ -export 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 }; - }, {}); -} - -/** - * @param {StickyNote} stickyNote - * @returns {boolean} Whether the given sticky note is applicable to the current site/page - */ -export function isStickyNoteApplicable(stickyNote) { - const stickyNoteUrl = stickyNote.site; - const currentUrl = window.location.href; - const stickyNoteWebsite = stickyNoteUrl.split("?")[0]; - const currentWebsite = currentUrl.split("?")[0]; - - if (stickyNoteWebsite !== currentWebsite) { - return false; - } - - const stickyNoteParams = parseUrlParams(stickyNoteUrl); - const currentParams = parseUrlParams(currentUrl); - - if (window.location.hostname === "www.youtube.com") { - if (currentParams.v !== undefined && currentParams.v !== stickyNoteParams.v) { - return false; - } - } - return true; -} - /** * @param {StickyNote} stickyNote * @param {() => void} onSave @@ -152,8 +113,9 @@ export function drawStickyNotes(stickyNotes, onSave, onDelete) { const existingNotes = document.querySelectorAll(".birb-sticky-note"); existingNotes.forEach(note => note.remove()); // Render all sticky notes + const context = getContext(); for (let stickyNote of stickyNotes) { - if (isStickyNoteApplicable(stickyNote)) { + if (context.isPathApplicable(stickyNote.site)) { renderStickyNote(stickyNote, onSave, () => onDelete(stickyNote)); } } @@ -166,7 +128,7 @@ export function drawStickyNotes(stickyNotes, onSave, onDelete) { */ export function createNewStickyNote(stickyNotes, onSave, onDelete) { const id = Date.now().toString(); - const site = window.location.href; + const site = getContext().getPath(); const stickyNote = new StickyNote(id, site, ""); const element = renderStickyNote(stickyNote, onSave, () => onDelete(stickyNote)); element.style.left = `${window.innerWidth / 2 - element.offsetWidth / 2}px`; From d94e321b6619ed10915992bc046e56ec51c6d8f2 Mon Sep 17 00:00:00 2001 From: Idrees Hassan Date: Thu, 13 Nov 2025 18:00:06 -0500 Subject: [PATCH 08/10] Add sticky note setting to context --- dist/birb.js | 15 +++++++++++++-- dist/extension.zip | Bin 148897 -> 148965 bytes dist/extension/birb.js | 15 +++++++++++++-- dist/extension/manifest.json | 2 +- dist/obsidian/main.js | 15 +++++++++++++-- dist/obsidian/manifest.json | 2 +- dist/userscript/birb.user.js | 17 ++++++++++++++--- src/application.js | 4 +++- src/context.js | 9 +++++++++ 9 files changed, 67 insertions(+), 12 deletions(-) diff --git a/dist/birb.js b/dist/birb.js index 3436801..1c76315 100644 --- a/dist/birb.js +++ b/dist/birb.js @@ -914,6 +914,10 @@ } return true; } + + areStickyNotesEnabled() { + return true; + } } class LocalContext extends Context { @@ -1078,6 +1082,11 @@ resetSaveData() { log("Resetting save data in Obsidian plugin storage unimplemented"); } + + /** @override */ + areStickyNotesEnabled() { + return false; + } } const CONTEXTS = [ @@ -1875,7 +1884,9 @@ const menuItems = [ new MenuItem(`Pet ${birdBirb()}`, pet), new MenuItem("Field Guide", insertFieldGuide), - new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)), + ...(getContext().areStickyNotesEnabled() ? [ + new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)) + ] : []), new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), new DebugMenuItem("Freeze/Unfreeze", () => { frozen = !frozen; @@ -1912,7 +1923,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.6", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.6"); }, false), + new MenuItem("2025.11.13.8", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.8"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension.zip b/dist/extension.zip index 9374412749c0713c2ca13da899dfb911f3f4b8e5..e083bd7b06913b18f5ff553675ad045c7c2fdeba 100644 GIT binary patch delta 25402 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

&7?OgGe2wtH4Plnz6ufoI1 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 delta 25326 zcmV($K;ysViwU8N39zIE0;jc;rUf2mUD^tM$6WQLx<_gj{PF{6e+n4vRbGx4~le4St{P@9yD$5BmK? zP1@losE5_@%~7u&qJFzqtI!DPW^Xv^Ryz3h%P+xvHn*P6;GgU~HCp=Vr+>@^KLx)H z!qIrp9R`opUauWix=+DHGaNO;f%F-4sMFRk2)mVPJFHWqrGL!XS+s`RG_*`+PCARA z`4>QR2kTb`m5wviU8Ow^<6RDa!;$pKrHrLHcYgdi)^lMHRz_h^=>~h{qr)I<61N9)}xk>Kn`OE!UKt} zbZcR+5tOMO56LpwsI-R|i0i8C5Ypyo@=yzeTm{wb#Nnssd!ep`X&62bB}~_vmF`Vg zXF$T?b>W#Z~$OUi-q@STY#hBokQTKCy+%q_g$}fXoe+j6Q zbUSQ}g8%*Bgc?6V_AO?q)UV=sxJrTS~I>^D| zAKh`gZ5b{oLthxQk9tsMBf?94P`L?0;=N(e>v~*iHRm;$85KTR6^iDa-d)HlNXl%_ z_uv=)UTe16b<(hZGy+KDb)5nd-Ui)qry3641cX-emm>k!wMx5Pt<-Km1qJ;TGD)f!aa2B$J*gRpLI1T2F8MVUJC$+OaGq*7x#q(d{U zW2SL!;NgJqO7oqI<`3yqIa)N}3$$sea|rS~O$a}x$yJctq}=OM3z7o-XEw|%#!yp( z(aV62s}*j4AL)~5PQHFf1~Oq@ZnN*qZ7xjr2P~M|VWTo`tBTSo+eLB)oyPt6glR>K zC}lK@5db409$|pxH!~?F3UdaOyok;@L*j4XKl(26s&8)8H0<|^uj zY@ipC>E%=Wj&LP{&MWQ|?5-GHTKF#`_!Ij|M1$Mav#3a1ZDr9AgN^nM-Xd32<2bmk zwR^*GYm8;R%T~0z)1ZZ_fO1}^s1K}4QFY;QT8ySX&KX11y3WuXqw{q9Isf>Dq zG{KXQ$Ew#4jA6^*7# zsW-b*q6n?<7Ai3kq!-hPXE@A&%xtlDVdPYTc4Y!GGzPs6{uuTLEo@hZ&5+6lgUZBz z6A0OiUVpm&^rTfwT$3zQuW7&a5VjLK5QEV)-tX4K2R3W9af?29Bbo;HtvYthG>-hj zo+Yf*nmVd9vE1f>NhPkZV()NB6Hdv94E`JKg~53v0|-`^mVzBd3^8@<0c()EDItV6 zL*5c$>Lj$SF7~5AbAeTVdiRX}i&ncGRAoysBhC)6*v+8%d*1WACv zci;jty@cLZJCRR)s)`xNa`p$H#p?J@2AWQ#H$@NNJ$)F2!VgKA|E z3|rsAAl2`YE2M>8$0WF6H^cxf;D%`sJUXY>3EU9_^%3|17aWH*^iL2~!&(K3f?y4D zYeA{fs0>=9#o)Oaw6Ilyucsb=-1oY#M%Z$Kp9j(dkGnJ+VH-a&CK&(@n?McE#hF7y z6TxqqkuK;WC`a-a9$j#^23e51u2`K0YZ?c^5{Ij95H8 zyuycS2r}}Q^J9RprJu1k4F^%##s2XwDuX3%xGw$uxwyScUDC(JuzsWC7V~EWb~EG+ zA4cAzFQ4rUxnR+mr<9lW1S?WJgiPtYig}>@>~rZ<${TRT!h^hjIP7Z;_ETd$41OC; z`eE=0PZDtWvn(K37ufmw>yt~<)3g0@@pEafSS)`ooE)B)o+X^y0Da-KxqB1497G^V*>}FI*RF#tKW@b5)jY>dYDX26y!u8dtfEYtc z)|NM`jfPVKCXkYU&CPIiH4~K(J4i`=b9H@fIVvH>kdnqmHM`=JFfT|^Sld`zUXL0@ zydveR>l>ADEh;Dekdo!xT3C1HYdJ@XYa6*R7e)=48MMz#wvw&Hij&y5js<7iS6RI%punRkYpQc`B1_FKAyy7DaNG_c#DhL-n1$5+rays0ImDIyw zZP4nIt?5^o#gDaK8!E}KYpkB9;CfWK8GhoE+YcN8lau%lDFUA$lOqsQe-~;wC9#Y_ zbfe9UM@-)C7^blV^;b6w#jNt+-~TrApjF2Clcp62$jofYmh>N*hi-yq&&J4NOlubl z`^A#-VHJmav~I&?9o}2vP0bf8IBpqqgDou=^v@sT)RKJVz2LYvz%C@;32`h6Taqlj zyAVdTe+#k zaaf{~fQuA;r4Foc_%+(&Mg#UU@J_ZA;iM%84a08legb3p2I`NEf2)HE>_Wn3s0P*$ zScE-DmJ%TwIL7X@0a^uB?8ydQoTft0+~BkfHPLamg0tf==r?<#-p!!W$C^LP;% zilIw{`mh>qh8r?bQyNEowZ2);_*E?G8_V_OT6VfHLVd1I|6rZ=$P+UrnMn2ZN^NtQ z>j{xYW1y&BZjIQJe;FrKnM(sxEd4vY4(wx#Edp^43}e?+8sRK^NG>Yu&tL?@mon^i zEA7^3f^$s5dv63U*d*vou!n1euR!R^9d^rbDG=TNA_;2iwMt!ep+T}kf|YPJtorDQ zk)Xa_Yt&*@ED5UF>S}G(Z*T1kM(k#Nvr*X;#J&lx=LxU#f1g+m!ttQjM{vR!+*92+ zhKpJlaOo6+@8NwSZ6no)-LWyEjU*8Nb=<;P{%|OJ*kC~2r-S!n!enEBGtGJ%D4+Dk zub2|p>tbUI0-$Xt7{YqS;T`tKeAw0-bpAT?R~pMJK5ldon*XsMY3i>Rky&QVAJqQ>M{65z;iX(+NW4*XMpC_?Zp#WQg1 zs|_-XzNZC&h(zn&jGC|C1Q~&dLr@jF6#BtnHE zz~t^kbTX=p$m87eijs1FhSQlNp2FhMAlHQ|J?_G%*%+mW;CYJma62IsDF)LGY&cWX z#~21$nJ+>H3cU`THldP?p|g~3ft1;Q1uZ}&xX|A5$wqrfbg-hTB_!heGKNIKAAe}; zYo{2fxASB6;T}#Y9*6ij>Q7M590&ptqXD@`2xEeg{!4@`1m`)E$rvtwPuCBh%r7(-5X3PNApPp%|;0Bu(_+V=p>E+a~bkEW~XjAihG7` zcXhXOMJm#q)B&GX&td%(Or%J-r$t)>A{er1ka0XSU1GJvCsFYjYYNUnrF&Nyo^j+0 zw0VKsNVp1F>74n&7bUJEczv^(@=v^AOxhckJ3r6I* zmJs`65rAt8_bCjD<4)57-52mGQ|K4svqGbANp5l3jBOIFi<2BMEFu%p9VSH93ai5g zEovBS4nrV%1dVW5JEHhr{2zbgq0$^|<$aMz8PUVs0ggRJs>KX{uSC>S0RK%on(oC& zJ1awuv|t?WdBV;XYC8dk>v&kIA_jvQf>j%LZBobT4)ZUe9uwHzQCT@Ost#XyJ| z#uVA2AMt*nTORQLSp|hLN$Ryk!PDs6PF+qLuW8Ird{l@ZDvyL|YQxBXz}fl~g(pcL zr)tGM=qmXHaU=K+-N{oc1$U2IB+=Ol5w$rt*{_A@R20K)lC*oYxTg} zRAqaof+e78Od4Np?rJC|b`{vJ;KB@>pg1DI6ew=1PJZC9UFp-$5nyDL+rSK?Td0Ji zPTi^qF~qGoY*Z9_7_OL~b|9eR+N$ZI41FQvYS@?ulBG1zQ4m-oWT$9&MTsoXh&eU5 z0zUa(QnZ|Zl2w7_l&lJ$+Eyhv*2M@%bx~gnxjNRoU0`eAzbf5$MAB)a0B(C`p-y4Nkl>0j3wSZ3lLuMVe83V+ z8|g)VtPOI?QV=mMzQk`9z88_))~3_qTCan+5=TZ7%^r)Omsmh&I5ZhynvgOQh-kQb zc$smoLfVdkc4dcR*`sWUKt{J6(I^V8=LxWAjD+@1Yp%nRDq9rN$G-&IPzq_B$;UGujMYK0Tr@ovJ!^?0V}8 zsRfKS(=4RJ>!}8x(uoWZW9i85Wr${I(W%a3m94B};#NWxP2di~EDY*1PUJwL;9zw+ z<}u5r!@WU@M4{X3E|T#xWq&YF#g1U@&<_EQ}mnmB61_Zq`Qc!VTS0^gb6eK$wd{U9x-OAynlFz2u1!c zy9KvSw(vLp&42A2UP%bF{NQgKJ%~E|UmS|cWjz~CT4h6skRW=^<$0Q>SnK#9_CJ1D z0svG?m|>cea!`xbFki*hrST{{?G0Oh6l#h^*16Pq*BbKm1xSqE0Cpy95h43Ex>7Tz z++mB*nf*OXGcNdY@06iz)GU1Y)xvOyW0>{~^DD-+7<4LlHu*AAyN9FTSX{m+?0RKX z@%u60;7}6bH5YWz=(!5wi{lz`7o$6&L`6#jcvp^iG!jNCk)Bn`nbF-2fnN82Pa>&^ zZ461M7yA-bm0KC7v`?h1@^n?8H+c{TIcVkl6?N`T!q$;FF&~gF*y3|{aYDh$!ksf| zB{$COl(d2b)z8h5!7j%UhkSPn+FX7}W5p=8-HbE`xYrz{Mb{|r^*rOb4zja5;EM$( z-4{TS`%Wk2``-7bvi!YHnuG9v1+c8l?uKI6wqAtR)r3yoAY_|@;1s>|d;3KwUi*G$ zT(ya9Rlj7tBh~Avp$y1E=W!VPAfXGAiRmt=iRmJS#e_b8W`p7PYzXDn;2zue>RfGB{YJ6R9VSoIA&&U4!@*KMb#ZuEX2Pyuxd^nh1G@5)qs>xWJOcT zB6yb#xEtn&{j#QClF()@%|u8~#L!@b)iePd7BTSr%p&5>S%t)?v&zbUbHfO620L>W zak*84!aw~B-AXbpo>wFvnpaLNJ#(L!FwJDw&)6BwNW~@<^o-VjX_Dp?Y4cu^(ZNc+@FSqANM>m6@{h-**pg!*_;pBj=vgJ>o1x-_F)# z%bslM5r*gd;nR$Nz}bjcpK+pxFB+){|BLbW)W5f7mQz4>2KZ-O;=G_<4Jz#jLoqVq zJ3Da&t3#J6i;qFbKnHC6%WgpRZ>q?fSN&UXYd0Uh3&O|tZx$nYbiyluY&^-mr_eYc@idCfz`_}h79-5rktrcwfnCNXACEh#eoGowy8Z63d_YT% z+(N13J99062eRWPL|LH|(+%Y6_Q1Bj>Nq!%%A}Sj@q5EIJ<+5VjjuFM;=eZaK8Yv&e~;U&$i%VmBDQjT9dNHE@Rq%kD$K&O$3<+%A5}nIH6|Cl#@$3e>F^r zD)r!}5TT^G*$lgByH^HbGE}m{D}(64hmqo|=A?5twctV^S2Y$E$zDFkS zFi86wz)|DF1p=w-l*AS-0!e=yL1L=>w-H1-mp2^$%{g0^kRZ}0-m02CR=Jv87h`VgBw79Cii-kg&88Nrp(m1CH4}$q9BY*fWgHfY@zsqkeLuN zL}}VSYNDN4Oc~wb2oK=}sKO2qQ4?~9-{8;)72+nGFpbvm6b@zQ(1=NY)y|{Z(P;5D zL{YLfr^ldZ5Wgdxrr`jaS6Hk91(pCir36Y8whl=ghM1##5L`{eIjedEHI_O9=oGHJ zM=9>_@6$-HFdA2pt+&@PH(+>*+MSG+zT@~ON_mD$>^O5qTtZTXXgcXTGyiD>Q1}AJ zFj(<0hw*0Fp=Th1L%gJa(N<-QEPA*Ijf?K)@7M|eD*}lLdFA)E)rN_gxkFnA@TFj`}S~6>* z|G`?qSzZqjOF-rmX?6D6>FFI!p@f`T(1&W)DXI=iC&!fbeHf;Hc%E8`cF6mqu#+-I z!)ppskNL+TDsPw;gK=?$ug2hftJvIrX!9wvzVSN`+-Li;xg+V}7`12aj8fdHm(ucJfMg`O;c<%h0<-bS|zR4lisy);81bal} zKlwkUUa--O>lO|_mc<;U={tJgC0>W9_`K+d{Nu8J(BHI{8)Q<-7rNK0ssi~irW`ZI zLXqY6d9eRRiT@K28yNp%L-S9KDYhl=jteKp<>F>d%A8X@FH7MO$?(O;2t7j2_eF zN$U}RJF`}yJ*p_M`D5`n!;?vw@6B+W6bCmK#PvglJ+>L{EJQ~+tDjrQN`Z)L9G<7N zl_IYZxdCwOjI4?91a-;RO-KKW{O%%LBe*u{90wSm&v?+5?^f7iN7+)5T#LL>F{XIj z=YW0$FPJ4z`*n=OuO-e{0s5oRb%@A~R>JXr4^F+;H~{7JSDMB`|8i=WKK^(9wY}}g zb4D&R{%^F73l!Iw{~J7&fQ_TQfe&dC+guZ%pTOw}EOo7b#)=Iv*8p@@5dkV?h<1M9T71Y6J(r6mS7!1|3Z)Wg$Q?jPAQ`z%10*7vzB_cBi&GMEVOd4Lb`xo&eN`= zBIzCfjy~x)^dI{86ypm;VuWP)#p6tWAs!1DRQ5&8UYFQMX_!>J%{vjPV8zvW5D{Sb zGK#yscxoU5!*M^p!4WhKNB@<6UGasx*Sv2E#JaDY%88q}uS9~Jy13{M|6A;EPiDSI z)uaIs1`AL_^eFa{9|2)v<53Ix^O-RhrH1q*ZALAmPTFqWJ=cosfN$mn8OWP|WuTEh zoHwSP>xQdQHxB}U0F#D|69vjCG;CTXlshAF6%QNAdxrNNHlIa*Wz?Nu)zsI!^h)?@+WdZrNCg;zzq6yd;W> z4xc1CS%YtvV_nh-wYb)-D%w5jU@W(iAVO3Hq9q*Q@XbU`OgB(P;qBL}4BEzz+6o1iwZO(i4O|;x2 zP!>N0F{DewROnDO%Ca<1xqE==Mr+VX&F8@%;1}%T^v6Brvju;MV@6Ke1Y~9@9Mc#J z4d9Ay(*#vM$ux$5=`E()9G3aGe6k%)b2L29dmAHR&LhF3h|Bm6cql!^d?nh_D_9AYVR5+zL^EG#^r96v=+ zSRC?f^#L1PJJsZd^~vQgG7M0}u)jm83L!AcAPA z*t4us13K3k2@{2liGYnVFZ{mrfQu0~bwmeuomMxc9XoGCq12Io9et!#qN`wIL|O$M zMK3PeArB#(K!HCdi^+^ZIjSykOfK<;q<*3?T_{z*P+l)Yl~HW+??~Q>H~;VuSZZ;x ziin8Cachykf&cl*kTyuZf_=*b-^5ZyQ(;;e^JE&ip&5JcTs#adWSk1 zBIDA?JnO78LE)PqD@%^kMkhF<5tSyiLPADs7c$5GA^j+1KPn!df8O5)Tw*hW zQe(1NozmjvemPzRr=Tq|r_G-H2+j6!0v$Z2Uu`3!YSQAqJuvP>vLa4i~$ z#*t07jR16qX=P}-3?IwLjyBvE!VPmDzfXQwp0)QVS9vk z-O?34%a5qQ>pS`*st}E&zo-aGhpEC*AlqSed}DEnVL1%Met7(^Ao)*XNR6)H7!Dye zD3h>%DKV3SNUJc`Asf@;O@_Hmy(Qi_gjgr(|>ToSY|Fyo|X7?+Pse*!)&UQ`3lOhmcBI>r)baiB9)%Vp;7cxZ4Y$`ttI zWB85{wIt^T6)w`iz#IK1O+2g8UqD#uZOSx%w|GUjY+rNr2tNuW>?UA$aDv zkqCf%79yFcDX8FY*CNZ;<$(YK#oa7Z3?SZ!t@pwqy|G$p(^CTUmMF|0kD^D~FRj65 zKE4@eT*T}<@!B#1-Ug2A$uZ%^9Cl4EYf?pK!qgtZV%^7}DSV;?gvBPkNI}k%H$ifL z7ZF$3O|fU5rRIN}$5j&5#>SixG^%#6#D~h6#WSF~JtTi)d!r6$A1B-DXPW9C})$1{=oce z^f7ks`ZHxHkm!?{sRs;Lz8yJ7BYRGN9miQSRi zaG$_`3?Y2PgjDTY634jEQ*nHxu4zL(@N~OQUGGD5XY2U?f+im#<9MxUh8nu+Jej{_ zo`0Pseqi)M(fq(;x#oepA}Kk4ef=+^;@?JX5>LfY>jtKnuT5aL3&zcdm0VQD3bP}}=0zY}JCpw;>Nja#8c@4k z+{vFGmOqz@=w>+wddeVwTC!K9XWspy=$&7FL_DGK*8bVnXIw=8Tq@)bi)c-$a;4w% zeXjs|6|X|VKZ+>XAd}w2t+=ReA%FZKU;2Eye_1^IT-yKW_k_1bwofkn(&-jI1wJr} z6Hei_ID)4i&*g!j5k|^aheduD9bo_d7B91n2)pXKl{ecL$r=8CHpunq`m2_7!yA3k zT}x|~cFpzrI!#~0E3lZQrCS@r?uS6Re|6vcK8ZmJXt zlF)y!n)x5EC_W5-o1%(QcCfz<{`u%rpMpfRhVjBvC6_5t1sd%~k|rWN(qY_$i{j0L z2)&iu3h*!1(UrNE3XwxLLi!@tuitV~Yj*C_DFC80!42LSfH?s8K`v85Cehe7Sj20y zh;(}!NOvguhErW+{RY!zSJqcHme-ay06LC5 z0dsgaD#Wfqq@aZdgQ5HV8iu3g9e2NMno65~g$VzaVWwooVg4x&2Paf}4~xTQ1<4-X zLg~Aedjp(*Q?T}V9b{Y?a)p;8`J7f$I^p@2Ug=a@r{AeDy_TLbe6E#KHm%|Q28sC{;0>(0lbfneid&9%%I_Yz$3robs6L7J#*AymW8riSrP3qor$+H(!qmgS0XU zrm;Gub1&*qq98EV;yoo4hHbWjz#+i$Jw<0$PzHk!Q2f=$Xg{0;$y!OLJMznnl*#-L z1~RID82Jt9&*^d3J@jGR-w+h4IiM7Qz(VGKX#BYz6h1ORh>bZ-o=lpJGITOWmI{2PieLR`>n|Vc34V_N?W=_F#jXV|Pw9)TuF~ry1@3eVd$AheDhRhnxlL|3| zWYdyeBbvvVlRehN?{tQ;$c*H$5Gyzs^myT#HfLiT2`mobH>=T;z(`?|3{K3j!TunB zJ}Sp>`HI1qrRb75G|L>S>_#ueB+Pqypkxr^7P1kIMPcz(PZ)Ga{+I~&+a}!%W}KO5 zAEV~8tVgC=sW3@ zacNwyBnyo;X^3X4UgzaV&}%frEO1)9RufdZ z`YmTSQmV3WwQkwt!G6{<1|_VEtFY*uZgE=9BGNHEWf%g?!2q?OC06&Qdx=y`BOsVH}j

w2O^a*sd>s-i(nP$eH+Z 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 diff --git a/dist/extension/birb.js b/dist/extension/birb.js index 3436801..1c76315 100644 --- a/dist/extension/birb.js +++ b/dist/extension/birb.js @@ -914,6 +914,10 @@ } return true; } + + areStickyNotesEnabled() { + return true; + } } class LocalContext extends Context { @@ -1078,6 +1082,11 @@ resetSaveData() { log("Resetting save data in Obsidian plugin storage unimplemented"); } + + /** @override */ + areStickyNotesEnabled() { + return false; + } } const CONTEXTS = [ @@ -1875,7 +1884,9 @@ const menuItems = [ new MenuItem(`Pet ${birdBirb()}`, pet), new MenuItem("Field Guide", insertFieldGuide), - new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)), + ...(getContext().areStickyNotesEnabled() ? [ + new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)) + ] : []), new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), new DebugMenuItem("Freeze/Unfreeze", () => { frozen = !frozen; @@ -1912,7 +1923,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.6", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.6"); }, false), + new MenuItem("2025.11.13.8", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.8"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension/manifest.json b/dist/extension/manifest.json index cc12b0a..75df989 100644 --- a/dist/extension/manifest.json +++ b/dist/extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.13.6", + "version": "2025.11.13.8", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/dist/obsidian/main.js b/dist/obsidian/main.js index 91d0ecb..7740254 100644 --- a/dist/obsidian/main.js +++ b/dist/obsidian/main.js @@ -918,6 +918,10 @@ module.exports = class MyPlugin extends Plugin { } return true; } + + areStickyNotesEnabled() { + return true; + } } class LocalContext extends Context { @@ -1082,6 +1086,11 @@ module.exports = class MyPlugin extends Plugin { resetSaveData() { log("Resetting save data in Obsidian plugin storage unimplemented"); } + + /** @override */ + areStickyNotesEnabled() { + return false; + } } const CONTEXTS = [ @@ -1879,7 +1888,9 @@ module.exports = class MyPlugin extends Plugin { const menuItems = [ new MenuItem(`Pet ${birdBirb()}`, pet), new MenuItem("Field Guide", insertFieldGuide), - new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)), + ...(getContext().areStickyNotesEnabled() ? [ + new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)) + ] : []), new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), new DebugMenuItem("Freeze/Unfreeze", () => { frozen = !frozen; @@ -1916,7 +1927,7 @@ module.exports = class MyPlugin extends Plugin { insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.6", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.6"); }, false), + new MenuItem("2025.11.13.8", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.8"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/obsidian/manifest.json b/dist/obsidian/manifest.json index c2d4666..43489ee 100644 --- a/dist/obsidian/manifest.json +++ b/dist/obsidian/manifest.json @@ -1,7 +1,7 @@ { "id": "pocket-bird", "name": "Pocket Bird", - "version": "2025.11.13.6", + "version": "2025.11.13.8", "minAppVersion": "0.15.0", "description": "It's a pet bird in your Obsidian, what more could you want?", "author": "Idrees Hassan", diff --git a/dist/userscript/birb.user.js b/dist/userscript/birb.user.js index 6201bbe..9a5a6c0 100644 --- a/dist/userscript/birb.user.js +++ b/dist/userscript/birb.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Pocket Bird // @namespace https://idreesinc.com -// @version 2025.11.13.6 +// @version 2025.11.13.8 // @description It's a bird that hops around your web browser, the future is here // @author Idrees // @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js @@ -928,6 +928,10 @@ } return true; } + + areStickyNotesEnabled() { + return true; + } } class LocalContext extends Context { @@ -1092,6 +1096,11 @@ resetSaveData() { log("Resetting save data in Obsidian plugin storage unimplemented"); } + + /** @override */ + areStickyNotesEnabled() { + return false; + } } const CONTEXTS = [ @@ -1889,7 +1898,9 @@ const menuItems = [ new MenuItem(`Pet ${birdBirb()}`, pet), new MenuItem("Field Guide", insertFieldGuide), - new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)), + ...(getContext().areStickyNotesEnabled() ? [ + new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)) + ] : []), new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), new DebugMenuItem("Freeze/Unfreeze", () => { frozen = !frozen; @@ -1926,7 +1937,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.6", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.6"); }, false), + new MenuItem("2025.11.13.8", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.8"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/src/application.js b/src/application.js index 9ce19c4..bd52124 100644 --- a/src/application.js +++ b/src/application.js @@ -194,7 +194,9 @@ Promise.all([ const menuItems = [ new MenuItem(`Pet ${birdBirb()}`, pet), new MenuItem("Field Guide", insertFieldGuide), - new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)), + ...(getContext().areStickyNotesEnabled() ? [ + new MenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote)) + ] : []), new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), new DebugMenuItem("Freeze/Unfreeze", () => { frozen = !frozen; diff --git a/src/context.js b/src/context.js index ddc8de3..d3cd2ab 100644 --- a/src/context.js +++ b/src/context.js @@ -75,6 +75,10 @@ export class Context { } return true; } + + areStickyNotesEnabled() { + return true; + } } export class LocalContext extends Context { @@ -239,6 +243,11 @@ class ObsidianContext extends Context { resetSaveData() { log("Resetting save data in Obsidian plugin storage unimplemented"); } + + /** @override */ + areStickyNotesEnabled() { + return false; + } } const CONTEXTS = [ From c312500f19d5af8050099ec268ac127d26ecd235 Mon Sep 17 00:00:00 2001 From: Idrees Hassan Date: Thu, 13 Nov 2025 18:14:44 -0500 Subject: [PATCH 09/10] Expose obsidian plugin api and allow saving/loading --- build.js | 3 ++- dist/birb.js | 13 +++++++------ dist/extension.zip | Bin 148965 -> 148982 bytes dist/extension/birb.js | 13 +++++++------ dist/extension/manifest.json | 2 +- dist/obsidian/main.js | 16 +++++++++------- dist/obsidian/manifest.json | 2 +- dist/userscript/birb.user.js | 15 ++++++++------- src/context.js | 11 ++++++----- 9 files changed, 41 insertions(+), 34 deletions(-) diff --git a/build.js b/build.js index be51ab7..1e11733 100644 --- a/build.js +++ b/build.js @@ -161,8 +161,9 @@ mkdirSync(OBSIDIAN_DIR, { recursive: true }); // Wrap birb.js with plugin boilerplate const obsidianPlugin = ` const { Plugin, Notice } = require('obsidian'); -module.exports = class MyPlugin extends Plugin { +module.exports = class PocketBird extends Plugin { onload() { + const OBSIDIAN_PLUGIN = this; ${birbJs} } diff --git a/dist/birb.js b/dist/birb.js index 1c76315..d82e1f1 100644 --- a/dist/birb.js +++ b/dist/birb.js @@ -1066,21 +1066,22 @@ * @returns {Promise} */ async getSaveData() { - log("Loading save data from Obsidian plugin storage unimplemented"); - return {}; + // @ts-expect-error + return await OBSIDIAN_PLUGIN.loadData() ?? {}; } /** * @override - * @param {BirbSaveData} saveData + * @param {BirbSaveData|{}} saveData */ async putSaveData(saveData) { - log("Saving data to Obsidian plugin storage unimplemented"); + // @ts-expect-error + return await OBSIDIAN_PLUGIN.saveData(saveData); } /** @override */ resetSaveData() { - log("Resetting save data in Obsidian plugin storage unimplemented"); + this.putSaveData({}); } /** @override */ @@ -1923,7 +1924,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.8", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.8"); }, false), + new MenuItem("2025.11.13.16", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.16"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension.zip b/dist/extension.zip index e083bd7b06913b18f5ff553675ad045c7c2fdeba..fdc7731738f10a746a90114d6b69dd65d71a3431 100644 GIT binary patch delta 26853 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 apHTnwJ$NY0f4N#gdf-mTj$-g;iSR$N9Q`!_ delta 26837 zcmV(tKCwc3>^-k_h#O|rOrmn88u1+<^-P)+t>jtTp!Q;Q? zUW|ufFdPk9wb6_J{OezHwO)5P3btE=kZTQtH&koxu((rx9V}*F;rH48?jHVspx@u9 zNjn?`^{_g=IqKCz)Nl7{6&fMk>(b7*p{cA4xDfn#= zj>d!TFnFx?dhM{%{T5s_!%;IFNS{H6I&BSuuv@9N!#Xuu`q!MDMQgZCL(635q_YT` z{{TdHuzqDw={Q5(Rode)-sLcV97&&C%2=9n=f|I8Jr@RHWfTULZm?HAIt;>g*a^F% z;J!6#2AE7R?1!~hqZQTz1|b}UgQ3h{K_U`#Z@vY!c4as`2GSBsuSem-sL<<<(D}#Y z8m+n(Si}-UMFHqre6F3!ZK!1_JM^o-8Rk{cstXQ;HO$oB1od8ROtVaX*Ld=#oB4X{ zZvG|kGpAM4-0@*+I7(OQ^=KHb(`p1MXEYhfwscCsSk7P6Jti|p%?*6ERjZE5t-7hB zOrg-k2=|-fe_JQ>hfd?0p`nN6RQNh5-eJx!gEzkfcfD5qTTo#^i6gexEwo#;+mw#_ zN~_8I3}S!|?u~F0cEdq`YQ9E|=3fP=kVlZd@rQ@c>1LzexYi82^{C||ki*!4@Iay~ z-CEdd1ZAqnL$XXZD(xW#;<_q3gtR%DJk$aqS3z|eG`thdgE>#asgZd>1QZUF(!Cs)cqWP_Y4lB^2^|tHvx5$ zZikIg@W20?P~&H7&{kjd~p##Ng1k}})# zJ@|#c*P5+%oir?ejR4YkU8jJA*FksOsfL4B0io6W2OUJoAOcS$ zAjI?f)EXZ3u+nY!?z`xM`JT#Y>FPBa(D;}5obf+hxu0}@gmUkQ@cG8T_p8BYS^zGp z;(u+v(^|*eYG9Ne6w+`o=t1hYT7&BA;8dn;5Z3LDfJN}XC{ss1c~)ADRBB9zbZDk^ z%rveIJRA^SX})vO{2`qxM~eo0fi^954ncmW3E{^yxeAh-lzV+@K~jMK%!Zl87;0)T zdLGbmwZiRxBYhIh$=46bKqkz~ZT6kH&4uayfCY0qY*fZ=RZ%)+yGYKU)3_g>Fs*12 zrHp1V0$?P>BMh+oY9_@*Va|Y(7tuLqJkZoi$M>foXir>soId|=&w<5-RMYbap**bk zAC4yNP?noF!SDZmJgSVE=}zS#l>tEl;kp-_GT5)D}Lu@GBTt(fG z4fIShJ%5Vd5w1kgdBvTA-4&xt3;$&Ve_~&WXmGoF5*3N7tt=X1u+iSZTjYvr90%96 zc5fJNjj^nE*@|{|8njRqP|oWV^?_9>sxCZEi_z4_Ib#btC9eYNfkl%@_=J|Y4JS#u z+#d*kc1rMr?WEePPtqXbr~=c^gU3i>v_h%^KzCspL&;XHIILCr;k>C$psL+v_{~SM z-D+4%#O&c{?}OE7K=uXpoE6vr)mA%%QFGU-P3^o$XHc=fn_J3v>jRkDf82-FlhPlp z(`K(5;y;x-{?)7hvDJp@v4y2{^2dHrI{4#%q#q6{!BMN*T56?7;c%4dR_gM)Tt>al22$g>xZzFDaH=tH5fyUYmYAKXqS16I z^=5ZU6rmN~LM29m^kO>k42KzznJxA%jGRi)u1r9N#-P{1AH)8jh3)FF8B*C`P?>mt z0wJ5x>yOtTziHJH*Cfl-Yuax;gzbb5#9%ay_q+A*fz4WN+@cTOh^E1PtBxHrjU&IX zX9+8{rj9C2EVnseQi&_9*gG83gi|siga1l|&jJU2E-Wac zaFcX@JZ!qqUr#=!hu9s4`caVjlQhSMQ6?&17lQ0d_*NK&vUMc66}$-}U=4CNC4}&1 z$Xg;zorJd4#eOuX4tn<_z4xG4@1D_r(Q3DYs%$BS?IFTN9@&)>{QK`w_dnYH`_`BKb!E=P#$0sE!@4^U@5sQb1 zSNKp3K}P;^ehd({^fUIR;UFrz*gxJyWw68z*QLKd6}NY(OZvDN)^Bv&V*ZT4Zic+! z!^nH|<&&Ku7c4sSl=9M^U`2|DkSU#4F%Pt#eJY(wc>~T^c#s!=hkdQVerl|T!Ed8U zKMWq>NdgXkmIVas0y|%S`R3B}^lZOe{8ZX27R#RsCx<6zpN{gU(Avag9>HEK{nHLj z37PXhHu!(@wt`Gg$};@Fs7y(&h1pCcyBQS{Riz}mnOV+cqY}_p3M!3_aD6o@AjXiA zwdKufqv4c*38Z9yb2D6B%|s={4pLIzTwPyVj!K9zq@=M?&8|2l%nMQ!);89b*P})e zuSogo`bH&Oi^_>Vq+~g_7S^5lTF#N;+D0zSg;7Ih2JJJGtz;{)BIP5g(P*qy*Q)Uv z%t<=<`ZE5BD(tw-geuHC?7|MU2jfk0n2ulNW9l1rz53c^L-0y^?QIUR1qO6uXT zHfZ(9*7PgP;>TLA4VC2AHCE5J;CfWK8GhtaXh$(P2ICsE7_8k6yk^dL*sO40@a>}! z`1tyxnj52LYnYZ}8U`IJ58SHs(P@qb&R<+bbYES39tG}P#ba*nT2!Jd5+5P&aXlAR zRQ9JzKdNYd5OtyoB0F5JVihZgh|F#cF_~S+?8L>&XnxPGYT{a}!gEQrn60>yvYlVa zV=b;mtOw@vtC1X{R0x(PZS9wnG$xdTQGu{$YB?pbj6rmx&5cJ)-tHKtu>|#3Hw(qA z^5EBB%{*w8asH%f1p+cNo3bVShvuQ1pxLuAvKZ5U+Qq_tv7~%h#o->U+i+Qj_f~jQ z^Ti5|TL#@=OUniQ^T#-~Bwu+iIPMLw3(0pv9E-x1Bunougi$!`)nIBugqpqaO%qP( zE?Y&d4o;jZ1M<}d{jk@^z7bopN1}$o3#nr!xaw&ps4av>=0a7~ULh-3E>+d*l}0+2 ztEdWp_NtIF&?Q2BSPeJB4VkDZjibI= z->hf+Di-yP<@$0hJ6#x|K3AuIuugmAi5Zhjr22ZLwzgAK9RPOYQ*l? z7|})&i2pKf;VgeRls#-PpzhPbyD?#ZvN6D!X1xuRPkQ4QObP6Dv9SdK(6$o{VLjvU z4tr!iZ0ij=f1UX&jpY>|H@XPT|5&M1GMll&h%Al9bki7FsugUebAIoZEJ?llWZBr* zSlx&TR+3yekceCi!g`@HfD@t8j+5*RTyDyy2=;_TFzv_yy9L@I02o4chM;GE6Jych z(P<5*=|C2|NblzI8ccgn%AdD5EN7Qjmt~)3mlaE-aAUcWjj?`2q@>aqk?OVO^*CIX zNcG%uF8ieHRI{j2<7s`1$qp=0UPgC&?K+sZ){GOwuCum=l7x&(=y$BGa3R50)T-b_ zc!IrX?_R}-v`x?mLo79wHv5`?NRkF2NCVdf5pu|dq{P~2Jq(5jfFPF@QF7FVjXWH8 z8|V-!PIMd0+E71C=`l-1hu17Eo<~KjGr83mD%GBw|8aSP{_&Z^k~pa_B5_i`F%mac z!wNQa9_v{WhZ|vLJ;s;59A-D^AHR9B9M)=?%)GTB;H>MG?qM7B?&Fky-$GHKWlHn> z4IK}N^#Dg69nX{28}!JL2t%S%=`MCE2nmA}Vygr80Np@n&w{vxr2+E8sW_(ChAuSl z5dVhP@C0ts5Y8-i@(kcSWXJy$p`S;~dUd_F5|c=WBI{wc7Q7 zv}gN(3_b+)k-sdgh}%=-5KdIC0MGOjHu73+t+Fo4#Lk>tS7M{C=EAkvNUyJLEXOb! zNBUZrt;dASioxr1lBRix{LqzVtiwbT>CoMR}aT0NhNJ(hC zai?-Kjps;`AdAJH=383yAnLh`T)B&%$~3LpPzLJGRmRI*YKZfrK<+-9XIOKYooQ5<0^O2_XybSul&a zETBT^`+2*6MOlQgNyI9n3pgn+(Ob0Mih8Pz2Q37svErkcSDYQTYPyr3ElN+iO~QI@ zJ-$*}o2s!MhG9&P*+sIpx=~q;34uewY;}Ee&Bt$yg0=O{FloKur7Ed+pMo1}Ys)LL z7BOWUUo#(HvlD5CqgjsU`2;@ELoEK`WcRSNf&?OerWB$1>i07NAMB5lDkzm7>|5jl zX@h?|ZaQ&~@4yX?!xf73bNqIX?5BRMhb%x0Y1r-!fggO6BbT`!Wst2&nE`raJWPAo z87CB!z(?dV>$vAziqyC5fKduZdfuZRLy7*xJjfeP>o#g=lnZeyAJcPZZoTHEcM2*R@B*2m3(oke$9QdbDgy36> zXW-aZ8)O!JPYVJOiPpUtHDA68G6E5Yo=R_swI)b|ALuehjN;@C#!)|`p(rt_JFNi> z5^frFVERQMgww>5XJ-}{Y``{1m`(D7&v)4b8~h= zPS{F9Z6}6>n8CJsz(5Fgc`#@YC@G*tkc}b-9X=afPlAOA;*Zx4AIFy1tl%x41f@ULs1b5in)md~BM}WBu`4qELHyp)1L$|xS+qohY zX-?{ZPpjv!ehMa1B;3=YtpO1X*)+&Fo|!JO+To+9c#Jg#XQ9%)s|?RL@&($wKzEWJ zM!9X=U>YH`%RT+vf|G_$O))8sk_!3EGCCbKv0rsKZuBmV+uRi6v;`ybTuX?5{jmtZ zwT1f>2E}ow>45GFc$F#i3-MW@QMe?xxNOEYiPptQ4j2}ZiRca!B5Q@!VS^Sm3^s=$ z5IurMIIJB}d@ufwzwuCM4z}{XNTiJDVeSCO9wXIahF2o$DS*F{j;4Dt($30|BYAxm zaw|Jg;FyM-v4+)g!1Kb;wj)P>7^S0GawzA!HMrXVtVJych(^}~({wQqVumqAw&+K^ zU+9(x{C`$KVN8;GEm80^I=54o)5dEW^CKS>;)lv3VVc@7@*i-vK1Jb4(#NSsV3Ib?(|XT(e|VOA=wj|Y4UGFHJx$hLcby}spP#Z zOSj-=(*c%#)FqBVw3I4+7Fwx^0{Ow1;sV>0C}+BfinTlXkMj}!haKW|_$3gn`39Fg z{X$E0l+lGHzqH)ygg7@E(3Kri${G$FPPk-TY%45?4SXbtaCMV~(^@_7HdWc)sbC4H z8k5FXo4Xo{iCqP@E4VO!!zL(>NH7J8+p3cvIBZw?^m7Cl8Ra%G!{`<&;iyx$Dnbl# zYYrO~g&u}0=BFJ9=(x6Ox+p_m$haCd=7D4>4RjO))(F`t8eUN%3p8R*4X%JszLyj& zr({)NIVG#Yr?yoIj&(7@QC-y6f-X@O*)S=Xj%+6~7SO5N#2OiYN~@Ms=XH?(<x?0a}0^Ox`+o++as{hKAF2B<>@xFU*jBQRfHQv|1_wy3Hot}sDySM zK1W&*BUqhv(HFaas0y1;%u6v0!}PRZ`jxCUm?p7_dMZ5ML@*e(gC!%97*v!DA(F+B zg_^fh_!5aKofOcC(GY=t-Fi$1o6%xxfkdcNSTQ8HV$1?w%;@AnRy7~61k*-(5o?2- zvJ^y2i!bq;h3{D;x3%fCxYp|+uEdd%M6<^t=s6b984gWiyyjk6rA7mLwITvx0U zqsLH}`%hkMxPd5rBhYMj$LnEA+>*$40b(p2*}V+W3@tjea49#C=?v5PRBfE*>t!! zNRcRXd)-AcKFG|r)rN@Dw-&(;ARu?7~RS?)TW`;SYzvqA}uMd7dz(Q5to=~ z0mh&BPu>7A{1*MDy@=chFzGI$YM3FqG-1L_e{xZO1*u1jSt{=z9wI`K|I2Q{t&=VM zjeqlBJBL>i0xduI8%GbK4*wU2qH?B)e>fy z=A<0dqBYD{adl}t3Qv2(7KNH(k##P0-nE8&eE|}qH-Mc9TSUlyjjq(pDRu2kUw*YP9O4+JJ;VHpaV-X&3Z6~AjMVPoC^#0EFABR}8CCp#3^+KH zM0m{wT{L>Cg81UNM%=~dPAE~)(g5C-BOZ-}kxHazm2zfuw?m-U{gX&4VjDve>czf9 zRpnO3DeV(!t2|v5=uIBPK@M6ue?^_UldyGvWKPTnqzktA++Cbdu(ELHOj^l}Gdm@% zAVKwWb7Zi~al|3t-GVlkAJSMcifuO|%>nKu2WinY%6mP}c&dZ!><;*1!AbWSP~^VT zN%_9_{i!T}uao8=d~s3+uOunaKndIo6_Sre|v) zbuCLDw@H&k=$O(=+7R@kq5vFQk1&wX1S0lL8`3eG8{8AH-}$RrlRVODi-2j8(1}`j>76f=W0MoD6*m{Wf8o8%Ld#H z^TU2w(=SPAGnZx}q$gr%Fv4n@01k^7cz$LPap$Z;V$@k><$t(gggAqpIg7a5szKqO z{)KKO85hqhk`K)*CzhVMPfVC*vg>E;jAo=_lL~r9>oiGoinMvM0p}yjPHM|Z1}r<5 zvq+&*LN2x`hpCs*N$IrLeX2u$IS7f_ib?IFiH&IE;{r^6Q#oTw&F45J5>; z2t}S2g9Iutztfxx0}DLr6e!V^9QVph+4=9g2e;un!?=-i&*~m=7NT!wYqDiew)6n!xxRzg#X3(d+OiYGRr9-I|KYPE^%H^uLhNNgrOLJ8S$N+xPsN8 zOO?gPAY`BeHvVNdp!zpeVL;T!41!Y#8TqE^#tYnGT92m7kg{8XZv8t9VPTPJ*t*B) z$AXTYY`v6M#oZIeAqNqEy}FT<(dT6Efj`q-oq;SCL9hB52bl`LB}D8d>JF{MzmTKf zo;LF*sDSAs9O-x(#b#jP3`dI*=IqFn5U;>4W0Q}^9aX<24J+M#cUV54B}ZB#g@&_}PQ2&iqLvB)+vyCWB%_mE&K8OZMGQ0H)nP1sOztNwHh*^-WizJ?KE* zXb*w+$*hcmNC*p3Fe1uinj}WpE`z>0r*9JV9iGBb!&ydvcv)O)HQeB&JcMxQy2)3X2;sX$a5){XB1H<<7kCIn;9Rhs z#(no*yG{AJQed+SCV}PI#TkiXx<9$c~BugTb8Yb3%NODUNt*kgKFYm?!)}47)|#O;!yw6Q}ybDRcFC%MaV#IA#M%dE5Hh=E3FQgdcY*>U@8B;_~~u&3J@}-N{EHU;baA% zIjPJ?<_xOU=_7+c>P32qs6>f{a14|FJbdvojV(jfwEjjp3G83yNXi~*fthgChfFlK zz2wY)s34mls71^uI&z8XvPe%&KgtM9w~sL?iq_**KmbHSD+fb5NFLF6;7vy*S6Edoh@96@5L{M`s5oy!}JzjMximL(*J^c!zg%^s^?LB0!(TcRA+i1hB$ z>JF=vq}4Et#RcebiYA5@&{5lx2Zl5g(lp}WF$~Vn4$;5_d8t7VJq|Dk8`FYapzs`A zkEZ|(28s+7%c8*zAd`E&%EAnhRa0ha+!A{UUQrOnCBWd~5VlZ!LC8!98KN|8A2rc` z&Mc;k?r?;M@B&m}2Z*Q%xx;U8XoL!J6Hb^$Yj}zVc{_y^wO59ji8kq9R%i|C)KSg{ z6pc9xms(e{&mH4->xGhn@>L@-EwpTFl$!r_p8PkgivcuZQnmA_b~IYN4N;V=&FL{H z8pQ8Nr)fCA<`ovJK!GK|PAP#Bg{?z>5{Dt?C?5n@({RqJ9zl(z&Hy@vEALT?`}_Me z(kqO{Rb=b!b<7PIo}zXqqowaS{)tka;SxK}oDr9hR3Vy9`p(RM8UYl(z%dL~Jj`J{ zD^A>-DscuuqTvupR_NsmBWz~9($jmhPSLv&!6BaBXsh-{+CAKy#?5&1cWlXjfZ2ge zhHNT$`*6ecEDfZJT0`x@Uk?D>^zKmKI>G~^6P`Yu{f zL-X0qTsph9krulvw)o7N=zp>Ja9Y?y1Rs#SMauxY`SiGtrcgo>E+|m70~J*VrITaI z6F&@7JWs7eTk8E$*hv{H<0Zv^KF>dXd(Ldo9pxVTZ`UrK5SAO74|yy}kGnAHMBGnl zn3f*cuL7Q+DB)IPlCtZgXL$y{8G?vQDRHG^c+SY_Hu6!770Cr62`(|IJYRy<-y zog=MjiIcGz@%V?u1t2B~{*(3o@ zuz@Wa(Tyj-{}5kC7(?Wx%iT`=kjsX!4o+m z6twT*Zw6+P5CZ{B;fk_F4elrF&M){TS^7COys^G!X)UoBncdQV1Gr2PvYMt~dfqEr zLvRLMlDm`g&GWjDQaGpkVZCXdXHv4&V8Yu}^(9#_kvIX9Kw#v!MhUGs4YMwlYI^>? z%H?mQ2Veb=d)S_7dxA|R5~lp0QZLw<#&rwFE6ZYz()1lY2otYERD4==ME-HR=pS0k z4KgW53|$0PRe=P58dIJeW1+}$`!v}9pv3yb>bYNDO7Xu{Z-Zh@x|rP`8jZ3vq~Xv!2p^jC@t(e86Ehay7#L)Flr)1sp8$Ymacq;IgK3 z2w^-;<3U@#TZxSwpi4z^X!35y*z<8u2l^4bV3t7bmod`KmN-ua=#N6z4I}qx3CBM; z^7AFtkn0u@}y(<1I}Qy=^4)Gq;0(BN$mIB0oH%z=t%6ZLSH>kKptK zmbz9zW5ouTYXCZ{hyax`^4l;G^-^)GjyN2Q2{O(jH?a<(f1yYGLR`H*;*?Pl<%1gM zF-<*Dl5VIs7Fs#ZAzi@l^=a2pk@Sv#N1t>Y`VW2l7UK&=VuWOPj(#sdct7>?8P6%M{>IQp;j>xwU&%;r^9Al7|j zRnGau2PP8a)J1v$IPqdfiZb&>swNG9Fqn}V7)TMH{PYMD8&7G_pHGarC^e)fX)|ge zVbgZ&?x|K>2YfRx$UwF(1C8|IylnMUH(ZT>x_J-)1ei1or6@d4p<(+pq1+jXt9aN@ z-ZQ-Ku=y++ENT-EA=s5+-L7CJHjFU##4VkkQ59)s{u268tQVRJr5)-mwz@bx;?1XR zAjh8)nS>_U)lC1vuYq&XT8OOILe}{UPO=P-HQl0vZx|G(1c8zgctTl%c|=+g>1ddL z4sm|)I~1*qyFFH-_^B`mFNva}!zYPO*5KRaSeJA{Ev_}Iigu4W7|X3Bh!9nQ7!3zF zd^52c(+yOS_$}z8X<`XD6$k2cCgAuFk;-Hc(g-&@cFTZ5)MK;G(e!*5y zf80|RUGRr^cjSCeKxUT0;gGS=0IujZO^fA|Od}VV-eS7VVVRH1CmZ85N5k{HK{68N zJWWiBxQy?Bx1wQO3I~OG(RP+D9^LA(k>HQPT9m!omZ}p;rWj#S!mU6*TsE>u(n?a}N0E9xeydzy-zQ4q)_EfG~3D z#&x$W1t(oSMWL`%Nrj`QDu~gFJq9Z^pmUv(Fj3f;2oovu!tYBDxERq|M|51+X?0WD zvGXz&N*&qJr(q?g3pPfiRnSp?^vGZn9LZIWBC%tL(i0g;Mnk zWfMaz8%0F_j+CKzX%Nqkr4|>fh{ISMw-)&u_@5stY2zF>wfOHxAc~*{J>(By?b}O! z#goVao>Lpx84oPuS-Mje4Zo~safPccjv*+NlD8_8j2apTZwlGgo(&{_0voqvC_FrB zFmwzV*#60u3?%G~W0R16wvDqyB>3f%7#>y@A52~7YD$lJNphA=*?qw7qDN`+NT@cS zW>gECI7W@vLmDJ1A}v9RW=aMg{TEvnj+Bx(OoooEGlovOivh*rj3Adc6g^Uqy{afO zie}{We$tMhrr?L@FOw#J%HPMHLMHOjL4H&{O}4Prn$NNtg~nFDMty0RDQwa2o5lYx zGm+Rp$DzYX&tW8C5#B~1WJ>cnAUs&Mw?YxAqZ<^LTzuyQc=xJV&IfJD`BAbTQf8k6 z8`CxEz=0jvp8Oru(caRcR9JbjMsszgsI4Ug58F4VRaM#&W25+g-I4xvdovNV3+Ck9 zRmDmDiz*IKWCn=1i=wj8JJit-d7eh*F=?F%3SR|TS#q28x@s5GG!(m?V9mX^^QStcv)BZN#5}O&68k5cHlol`d%ke5WN^OxjZT93xXts}I^xzS)Gjm5y zOFPPEs9TDCioeZ&W#S=%YtcY7j%>1R+)-4eC6B&Jd3+O2W8;wl9^)0(ZqjGe8)hzM zrnbi4av6-LBD-#COZD&{wnuo^EnVTW{D=y?zN0^)3eiaVi;AFhm?|7fvK>~(Hx{QD zmSaimhsVDK$$t_1q8$1rc85-S9Htv zHCK=Dqd>xczA}O(3920KL!QSMuCRJo6Ozj~o z)_n|`!Y4{VSZvZe800*86(n~NafRI!d*)ec{>OQLTwqacY|I%!qiP3Be5jmRJOirR zllE7(H|l`)ak8y`qWOR6pkfR#vnBYBxDcK$E+=Rp^Xj#nHJc>=kg%hn4CW%*A>vYD zL$)$y4I>sM3)3=+ayE(R56r(tA7kgPKU0PRi9VT`dcc6?+mUlLvgg!soHbKriWWwb z<&`Oa2MRUgDg+De&EDM5F-^)gh%uKK{$e6oBBQ;dQi@p6pJEMO@Tb{JjRS@S5@S^i zb!XJ0MGG;a1u=0>)XdJS0M86h%O|?Poh)Z8kko;zZ_Z>ZMLs#gn?wp44_#ciT~1;X zK)8q-&e~kXq?e{i+{Hu^GlG8FO%#=r_LQD~39&~6)^mDy(M>~`#>&&?&-hR-Hh!~f zowc0YT!%bSW3nRv9N{suP}Ld|+$ZoKLkJ%+Ayxa9#4#@PR2-knYqC-gJl(ES*ZUCN z**gAj(BwnpIj=R%P(xRpC-axg^RKhS4~$+Ynjd&9*F11nBqgV>|7BGC+o(>(nL*?AnDa5X8~;SJ?#5;;_z)7Qk~*d^#|b8Nf^S;ZV8Q5tvKz1l5?k|ddb$rX`DT<&1bsCA0qZ@k6&vk7>@qYiMZl8ee% zVRq!$yah@4UPri+ z_gXe}APg;f)`3M%HEvJO)0wVH^7{D2{&sl}-7M!oPZ>l@_KNhlyk8W(F3eAVmnSsd z+CSU+gzN90N`?Gk5v?gfuk?Gq?-f9=;w?%n=Loe8GU-j+#f$0|^2hJP=6}4R_%LjWDn{AC{yO;gqfdQ*3KG#8#tToC zT&6@7XtW4;^jb1Hz`s~WSLQY>L=HI+>5E+Ye$A=0*||@r00{L2 zH+W|N<^bRaxxxvVL}S}v5pUcgT<&!s-J$3!PIZxM988y8Szp;$UR&M>ytdF{L&9{w zM=!k&coMQgn!Ca@n+RZk`_=6Q6PGr1q%)SZ^8crCknwO}p%>$yAaB5eSZq{~qIrT# zzDK=ouQtF#&)7S5@O#*&x4~Tm%;B}F5W5DEf)<`BhVJ)k7><_LoKWpOEDoC$q?mXOrSDem4RB7u+UI4Eab?IAUXJ8{b6QR5gr{42rBiL4 zey7ItT6)Uxsa8(ew1)eW)BN)tcrYhx*_Tfu+Up=`d}n?M7|SHmkyfAY4I68jG&Jnn z5vM+LU`VPL>&hctQXjMM^sIh7gw5{B0XZ2Sub<>uJ=up5wANQv`Z@??4+WY<07}0d z(%6rEW?84Nx^ z@mC+C{csW_YbBlT$S*TeCi6cS$f#muRirBw?3z`3+@#lI_ z_{cvYHs&;WGHEu-(8(N)_namU6GapSpx?-d@OG%`kpvj5!IK!vpL(3lKI3sT+;%jc zLhuwVUyIdnbRUMqZg@ENrpq4jA(#-ykYonT^%1MVJiN}7(?1s(^UK~RW4riYg)+-R zchef?37Lt1`Zc~x%{CDK!r~Pfn3S^6!S~ea{k>H+r8YVcydNC4(5Zkd0_8 z3X89L!k|O)$3(baH|csYXn-drDPBlBt`0x2C(=C43(Q5R z6(itZkix04|CBH$w)SLlrZ~ijOXGSipCOo$0D3KFjwyz;v;y|xig@OFpR9nV^mbe| z3-#iE{(=Ofg$Qmmuu;}CiEi1i->UT%H_Wm@3>%RHJM%364?R0vVWc`f^Vw4&S!lFL zLo{3UIxk0pUZWvqfz#r(nxN9vZ#g4NjdHfg=3-W)Q$MP3F6#Q@3c+I5Yi`iAn3Gk_ z2WqZDd09q_ywzppX2HZ$q^;T_Ws8EcgX@Za9nmq|xwwz>sgF>9P%n?w$Wv81tqx9D!(W(XX+5OnQa@sr9)_nyi_$Z|Wwlao-i#xXn1_HZlur754#dJu6}wr_mBMCMqtOUuzkXqS@%y;Ws9?PUx zc=qh0U2L?%c75??j0{80#FumM&U-9>WZCxy$%tHyZqZ8xfQ!p<8VlV&g69`WCtl;& zt{+xLDZHan8IO9j4s$K~V^NkpAV)U+Hx+DYW3tYgV#8A&X4?MO|3*{H)|ZKPiH{Eo z4sp=8CJM~(jsBUi$Xn!*Q3SO7Ng(Larx|W*MlgXDX&ILfJqC@0&k+mTfq7wn@9{g{ z{3&-$F6Nsts@u@cVOd|Crg8f!5NCkHt&8;#F}JNggEW3*I%y>iG884*K#zD!7k-F;*TD^*K$lYx(n&9Ih}v&eQp@=HRDYVg8r_)rbbUDexhEvC$UAdsoAS_`755*h*nQMCFV5kz6R1bQhuitzd z!PTzbX7zR8Ymx67CNb5k+G^U;nW^Y?p(d`&=I|_3HiLJM)|EF@FGFE}())ZsfMJR0 zv#CUW$N5H*cT9jb$F9DwEN1?B4i8afPeLrRDQES3S%jdD&T1T|#4L$+~cAqsk{9b#F;W`(Y5`X#PAcO85*U1~>Jo+?hB zzu(25K6HyQp5L1iZrUDyb;J|;l8>2LgCnSlu3&gxb)yH!TjiC^M*iyt-a0{Mlz+{^ z3r=>I-O19GEYK3sJQ^fn!Ug6jquuKkoft3myEp%#$4u5%UbWtDot)ig-tOM?^7!9z z>AYDyzrn9_`ZIr1$Y0?!@4a z8SE5`SIyDp!D0TORlol{&RzBETlu@M`N{r8D9%%v+DZfU~+X(+^^Igy0;&)*=lFCyScD_wfv#889r?6cfzmr z^>Vm=vbpf}X#IG9eRn1Q?%fUg+uAA=4sH+HCmU~XPxEKR%iYa>|E#q;d7Eus<(9YZ zZq9G_*Xz~KS6lgm?6|(RRXf9k_RA-49}Y{c(oX;Ec&B`F+c`elct1Kj*x9()$(-ko zd)2oeYPD{^__fp63G=JR$K&I>-Av}Z&|N-T`SO0FyS2K1vAL4#+}wURKm4+N^Zsgo z`TpR`@#*MlaM#$&wsOniM)zF~@D*-%YWJTvK3oU~ZC|Us#a{I;e7DiaE`;|RnKMGY5lw>FvdS{{BOM|J_w}WwO1p^ErReS-+@v2Mp%!-d^@|H5_L%%d2SdwX}Oux@sJL=x(mPyE(kvSU>)ps~u0W<;v;q z!FcC>Jg5x|Yj^9Ver@Y&cklgR>0zU=+#K~6>e;K|#{1KSmHlj~dV16vRtopyZn$xO zceQYOevm)io@{h7`TOJL?fT?sXW?}H^KL%hS?di33%j?Q=R3gTC{r%KzrB2y?_RX; zmRh;BrHzHR=ZE9d{#xhorugCHLv>O*m~4Jt9~>O*o^4&Uz77w+oObRvPHW-vmwvr` zdT~>4?ceOJV$RJ@d%M{G+O1zaTz%btT6oy_lG)0y3RXuhlLN>jg$Lg{&@T9^zvY7 zb1!#RSZmx|92It(na#~gsX18be%QRbX`JNNv$?`*@ABaG^k_WF9rTN%!%1m>?c^bR zzkSub8=_6|c4u?9UfdZMFM9jU)y>WQ&l@LikM9pR2bIgC&4=^;Y3{7nDqrnXkHh}j zcJJN0&j)9h+0EK%W@Dv!-`s{+ zpI^1}NBHn?x;t43yV;A*`*&Y%_OAAB#~(hoil5gixuwI;qpPpwt4!GXP`xQEuOB@$ zv**Xl!|qajuvRO4T{_&`TG~GNyg6LR^^WS*QT^*$dDPgsf45hEJGwjB?>0K`jz14? zYR%(|!^=*+@pkQI((2{MOKan|gJCCodvTbrwcd^k<8ZRty&7NUo4MtcYQ6JeZU1=x z{C=glwEwWO`7rui=v+3w9v*IVua<5{^_y<~?ft{U&3^B4fAXc1Ke@l#|I%n3XYz-~ z^;~xEYU^b4@^bfoC|~b>C|^zXF1}uTW@gBj&flM$y*Fr`_}Y?V@`X(b-^3Gm>+wu_1Oh4N>sBEzqBzZs*Iu1hSN!z0V&~FeyT>aP4$0^Pd3Gt!tTJ z=d@&M=Xc(ID(@fBSoVGkMV3-rDK+~kh+sP{mOpKsoRrF+w$IP<<^7Xm)A>)-YrHC7 zSSp;H93tv})YP=|L|(5?g}q|otqbUCMouirRAfXH5A*c21Amv$Tx3+iTR0)I&Eu9( zlWxxq16(@94J*2?Cm5ing+0Y!7Bf#VbUE6K69$lpVK52sCpOiLJJWFIq;QTH+>8Bk zVK1=!l5j2r9W+*g&-VsiW7+bsB$sZz|S9vRn_9b!{ z#mHm%(rGG>z|<(0kd7$n=I=w&G>f z&~(XvHD&Je(PrX&(DKUcHI{4Bv_LzbA;*?GZ=9KQjwTrX`r~wFIC|5(#1Dn@gV*}v zqK=9?ehQlmfSJ?9 z?hYk*ixnvDh2jpy-Q9~zDcTRc_uV_*f5}L4_MB_2Gqv?i?Jfk(1Em-ICFtN1F9CSzi`t zcd~FYr`WD z&RJGcI%AQ$NwZp+{i5h?tP$0P>5Qajivr6W;->K2_gYYeL~9VjV8+WAw)%Q!@D2+a zxe|DMgW%K2wX0q!g=VK=N{vNl&w4jHjF%eZ_Ve?02dQSM!}-;?xYI86hAQ%bw^tl! zec}xHUM~ROvPaDHT_jqMB=^M6Xm~)27i{wLgGA5Pye_=>pfxpgA38`U50=j+tH--?#kI9`D!)~?5r+(1mpif%Ts5n~ z5!*ClWg*RdPQ!X{-cIQi3XVF>3gV%EjP%G;N4QR6bjNI$MUkD!{=EcQwr8?{3}eIl6yJBrTC`lT95tl=ThCiaBT&y-S)AWo*|4 z5W=wHGmC-zg?v4^T!mN^4E+L&ZdiR=mQKcFGey@#&9;*{j#X4C5|jp&^BeeX+*8^aCIL?p0GkmhID(-y|;C8 z*7GoDO~5KzuIdsT5a+zlRLq@;p?AUMMx|g|K0`$w*zaub6!vris<1c)>v+P{mn{Sdxd6bhSVrheM;pu zt^|D;9__z+tT~>eZpgHl=8tWvD;{?SJ(BLsgW$@YIRyo`Bi`Hk%7{+TPWG5{W@TRm z^g|q0Y)NK8r=Fq*o181+B0lsb&wg>k#0VXznL=s3G|otqcjEdv+@^sw|^N5HpS3JBg|~Y zWnI0U5EVG;w9lZ^xcb&+g1BGA3EPBmw;JTDud3Rx@~s(wAnya&vTG}ged_K_?Vl;_ z8HtaHi1$64NzJxcKqp}vG~pzmDt%m{Ql&(>3HedikDv6o$Orw9<9OLTFy;O!`ZB7e z7A|C`+M5&wfsZ~&rQ0qd40$r*_Bx+{#HmMu9*5J2;iEU<`>fxqx+4}gRAW=Mzd22` zM3L48h{#xrHum}5AIeUcRQ6cAc}SpoQcAI$!#pyYm3XYh(cC3dK-JerAH0sdQ4vQF zCUyiQxfv+L{WFW*GFI#aVr+JIuVs2w(?3f1kOOKIoy zuo-g5mm*-~eMx`B>Q>H|LHhhD77qpeu9dr7Rwxgj6VHNqCEo#ANpFlC z#hMaFwK*o(nCLbUUQ8&1wk;-kpUEZ_2HX8uO+(gq%>A-K@C{qfYKpHNop(4apH-V`TvPe<0A&jn)vel)G!<>U!JYjy4aR=$`BrS6T+8z3Z;^<`Jy1{n+&8p-jV*(*z0iruPtrjuUQr*Q<9{EyZ0_(sS9nI#*z-+MfbL_$xR)k@>Go^}ThpV?2_UXqF>x+l%Q*g{YqbVeG5 z=guB{Rf|zj<vyWNm|9~pu0(W_(z^`6 zU-BXDv#VB%#Hnkm!6kt|4mLbcy{v!ul80%=UPjqQ|4ZK3v*sNnMBb`1k8$cG{H1?Q zBUdkIXSiNUim2$QTdb1gQubX%Z)EMzQLyf~#}c=$WtW-%0)C>f*cqJpZdJP(B@#V; zbxICNrURtLa!np``9h{9X)AH3`A4l3QlSA<0f^Y?APtiAT-~l{ca2pw2G2Ej;~nx1 zE_k9kS%~?HCIznM&*q;7E_P_kpWD^hs<{i2vAjv}`7a zlB=PTh^0&z)Dw^qppa^;z?TqPIV~US&t`_S-AMoCdQeBtU!?lpAs)O$%&S~rea~M&6N33P2e+to9^SI= zpk@V6>bkU1Zi437-QD3OD`Ho6KEt&VmU-TuhLPdnqa}>sVp;WX9?ml+(Ri?Up9CDb zpguYhQ!<@s)5^JjT9S*9VdWjK+Z-8_Je*GBt*MX*TfbOPJz7s#v$$BJ#zAW3&v_SA z?9#Hs;6n~SSfJ(Q5x2N}oDuKY2dh8i3PM93Uyw#Y8Omh6PhC1zJ4NmkkNh1c;zB%I zb>Fme;$y1*5M1;gMOJ2_cs$fN(S{RXSRN!Y$-4O!p1zUu8e&?EoB967>X1WG z#Ex+ph`DuT8~co?J1(izT_yXDd|~Vm6hugbDHi`=k(c z3sl_F0ayFYSji5A@v~IdOJrAr@u3OpJtzR|I& z%G~QvLG=Qzw%jo?4LX=Rm|jM*>DT0hIfn+I%LI&M7*;OaqQ^@|TA(+1&XE0vzTj#M zDTy$xn+*hzr*js6=;l8NY6P(~QZ`Q}DUfGGMM`n8MJgJ*qA0|sDO>D)$8G1JP89Hm7K?#=^>yN$^IvoKw3); zDg~KYIP_G~lADi*GrQDIiv2|2Nd;=TOs-;M=u_bv8!ttNGQat9B5r3N0zUBt(&zjp zIEoyW7}mL7Fk_-qyh(|nOj6VOxjj-(^N^#`BGciDgw(ZvW>kn;XHe_xY$`qo*U&?& zwoxLm*wCA}hyAuNy9gKLUNcM{IL1W zv5$$mY>s-oYok{m(I@hc8W@FMH&QX6mM9lwv6%?k)C)bOC1aWZ^Na@K%rfzue-EL5OJG!IIT{a`KEPtU>S~+BWc{94O#OlD)2Z%(Wv_?h^2|-=^gRpUyPgCa#W@@3W8&2}Q+A_wq zV*caiQF~)l+i=Q}cZ%U~x4|2{n$>W|J7n{|O@4`MK}yEh`yfPiZ^~eNbsL=RE=lJ= z8l@N?a+)fQKFa|RL750b^bTIPO<087`BB;y=m!C<898JfKk63;_ZDRw>8R$y>_cqK zD6y}2p{a$Cy&*ERgC_{#0bHpc297yL5_K&Os~ob@KS4w}r+Nrb{2aNj$V)l|Q#okX z-)yskC=MVJ#b>d|jy58$c<(yXtZ2U8sJI2J%GfQ~G>S)ph(^v!3ElN6C`!V=DCWzaOwq zv=o8JPaz80kKUCB#XzHHaabi*O>?`{euF7soC7rwpg7Sj@(A5Dh@+aW<;yn=2cM9n z8FMitNJDXMKgEhUv8CNz;nqg8pv}yGTi>n-xK0xf1q~n=e5m{k30DuJ_+G!8_Nj=- zbe0_7dk{8(F?|B*jfjVt0qwb1eQYgU-B+8(z6Mjdi(jC6t&L1I9qq)G0Nc`5kPjVW z@O4}>){=)8^}@S8kw!)$Z+b_Ypf2843JvH5AyU2tIJeA92PgP<#7ogu+``$9p?=SB}X`qPLSRS>hv8VN1LH z7TPW^2H~HK+Xaa7aK`Z3d6_>vx zzrZ@)R-TUQ>J=@8>uk=5D z_KynVHunZc)?Z%PA|(V+=tmUk0Gqx0zMhxoQ_?d@M^~fQ)fBqOVP*n?+*&D|yzC#8 z;M_qSNJA6!YM*XAgkq6mwX%H>WO=!qveG}s#$=!J->lC0a0NR)OPv`g`*~;f3Jh=# za2RKl?&o@%V(clF?0B4*s_1Q*iH)C$+^y8jaeYEyv=u}psVGUGorD4#2?uGAsnGo- zpLRN)vps6VJ`{g<^)abt8?8f4y{omCLg+V0Zrv5}BM$yqY0{yrP3dR2kYU!zEa;Ul z>GYCHkAe05dK>2B2GyA33vmz2UdR`*bT2X|G8q+>o4r}Of}MfKE-RV-REQqo!yVG~dny`0%tpb2EmkXMASpjH|%rY{7C% z{t+(8j($&xS1f0j`vHQg-cHWNGKjUrq$Lef>dlwP!oA(KsOYqLI7Eac>5(pk{;H(w z8Nbw3;Tp|$@6GG7npL;Fqhi}8|LzjdPm#Ew6TJX9{R4#%QCI+60yY^EnTpTZ<_6-h z1`;MmGyi^XjpDtbi8vV`(+o7rYV^Iib*7W{m zOUQm$U3^<9J&F>q%xpF$$JlDiA^JGGd+R;yK9kmGqolK2+{5)?w(40KHx|d6b5mKV zZa(++D%`ejwc5OyYjlY@A#=(R?hH+u&~p!j^9yctW}6s*TRKGTYMcA`Q!DvAdHU#) zO4Z-76|7b_=^Qp4Rk_LMM9kcvI_@@gO`Mbq?jX{)4GlgbR>tH(ot^#l6@{CnG!-B0 za`t=YWn60`c>;n~kvrz05EsJ-5tujdDBjq>qig29;iQ_4(NooA5Lm77xbA+VvBTz> zr-tuXspTh<>ou8#CMFWYm$2An(F%}J)lwnOR3<+ z!Pjv`TGeGb$+d&(JS*>B5}8g-ukm9?CBvjGmE&Bk$x9s_@`N%#21q@Xs+Fw0iF^*X zv=okm2vU;Ao0vgsDN;I=?c<672WXV@+e7N^QaM!e%F5{KEqr96o z9BxBe1$`UIfKRMcb%po`z*-Ky3>0g!qMGr3b6G5z!)tq^b6MBUy8McHn@;oaQ}@dc zB@(=0m>JVdLA|KiRR|!2#9u>!)VjFlvG&?)aLv#x^y9zFRWWAw0Q%5S^?tU z$QC`;#Z2%s*@HvGu7vMOGczf>;IOkJcI~ZlH$=CkogE} zy^K@s`z7>fWy%k>8N?TcH)oCqMAt7MI$|bfQMf6q(YCyzgSW5=Rta z-bUbT(apqz3SryZ$3i5aZ8y{R)q8_VFgC#k*M3%Fw=o-Jz{^K`o)C$|wLu-~7a@7V zowL(da~B7?VaD+zlu)I%lv$em=+2R`Is3!3JkFZm)y%Pi$i^IgyqACndv(ZRgR-Gh z1=AV9LKo|EHcjj#sZ!sdeg3oVVJ5F6k*jP@;P09@`R6_>!q^|>XV$JVvL`W1)?HK6 z^$3HLdRpJ^?+3@#X(g7r0kq{bo81+xta&bDs&g{C_N#f(|Mw4AI z;tlF$_YK{~4TJo4OMQnz?e*-REeU{c%4af5wdmd=$TpeROeCO$ME5}9+S-C_1T(kP zkIk5bp1HEy(a`Un;*~^m>2Zq(rh!z8WpN$|AA1Aey?3EuX&X|8;#)DZ9}!9e=;yRC zu#{1OO8L=L*e$K@l_vVH$BO)-H<1M|%_e_iSg^0|N)G8>-%=%wcE9m8H;a?=tmn_= zXQz;klU82kp58VN$XILghoZsAFM*|$nFNde@F|dn4vlrJ2=FZs5J*m-RSFzV$IS0> zZcS54NUG;k4;E3kPf1Ggh64mF9H|WpQT398SZZ;i?o2%r(yteo$n}uoPh?VN{97g2 z!d?9?fKk;h3Y1=s8t5nF5lh9w2W^s50i@6|?4rq@ibog1zV$Yoa^6>5R?y&L!Q;cN zUw};LH_3E?B{=b7j5`NO2P}^S-1yC2q^!8^u0HFi=%czaxR;8QL^f&$`m!Sg-lE?? z!k41rhg+x1JCwI(zqx8KqQoK_g0CF2{9l%Y>x$`yS@nx!9>TkL7~2C|L-AGWq8%z! zN3;3!4mAs5K8Y?$m;0&oKA!7j7JWsgM%s2-VkRqn2e; z@*`Eb^K_%VTSTNG6cHW#@Fx!V#S{Z?rBxb{?hAsE!JVz~Z2+04GE zJ>sO3#F1{zGs|5(*)XJ7K|Vi1U_Iq1(#hW!{5ZW{gBJZZ)@6+Otk^Fl5h2n_4#F9i zBV)~D#9A0r7X)KHW;Tew|J?nd!le(JDOfo{#v326p0`r=Gjd2i=0?KWmq-L6PIJ^y zuG%9E)0QbpClc8RX@_4XWt;x_SCm~qOj%}MNaDBydryw~*6Mc7_@}ns+H1LmX_WLY zJWO~bYRH4hWUXAr7sc+vhYB6Z)1Y7?#cAW>&2-}R{VsC3&c5J7ktl7ANB7qBt}GJH zOu=qIo2i=HW>|&tC^8A|a^9PI0%al!4fG{i1cuKs`GsCopB?p=f2rF8;k9!yS9}iN zymed=FR4Gf5R#qPPh~7D_I<|UBZ-sPktlnDF=T9HzM%U?!*Y|Ur&a=Q8wtXaU`p`e z+5nc6Z{}R)cp+AHf&H~QAqCJUquJ_tx~9H8=C?ZOT;$*M*MT@4=Y-kVPT!&1;@XSUZTSyl(%wYLgBa!@WCp*%1?_iCmJrEI)Mx#An~ z9C3V_Jdr-{h8?ub#t>j&7)_E06T06;QPANj3z0eZ^+C-JU(os(1GbwtHL?x#f2u#T+cr0I%Y z^cQ%qv@h0crAfYfvuqOyTV4}I!h9+G7Q?m6Dogt^|2R5|nK+vvzgQh1EyER0;i^yr z0YA=`l>S164C79QgOCFo!ly=%i1KIj3{1t_#7q}C9pYsyafDIOn6u0D6gh@jJW`Uz zq7oX_viMKgl;nuLgVDudxyZMy>ucVkcIlo;Yy!@Vk8_lr%~Mh0omh zZBzLsqH1gfY9(-b2NdXC(O=HVzNP@?4nxki3Njs4m>uyn`T($+Nq~SlE@CM z-)oN*TZ z3DrqtURWf0ocO@ksfxY1EfgQfUCxaZ`}ON%;trB)TH;OQ+2(!b$u!v-fh|4{XxkG^ z6d~Ua>Ml_DwVju3T5GsM9PM%;V7|SNDVygiIV|34u|m(Z(L@ol7_BDURbKpl>s<#N zCrMqM^}NhBpoV#Y&?p-y8*k0kk<`&6%9fU{cltv3M3<`ba8PQwRTq@Pz8P=53c(&@ zqcpNpmGb0S)1&0#d}Yr23?%2&etXt8%$`*xEcgPhY#t#!S`*60S1q%nC!F_|IVy7^ z$lbs9K)wd%(u4b+5{ay5{(Up(4r4#<=;)4OYlbC-Kw)aP9Qp?HXtiNH8=;FCjMu~I zGlex~-;gfa5 z9gT_h=xKzFV2W4Jr5+GEsxWPjzE!UI9?7rv7&fSnBDI*287rUgG{7{+*1bPo7CM`# zWaB6;qSKNGjhTs=?3&?E=}g7HXNy?zGde161B76(gHM}=U{ER1*P%#;cfw{a6v83D zGL%2;(EG7c?Sn{ZmChB?Fb6rByP*d5iZCGs9%U~4j{KBjJ5hmx;~VOUQfl+zqRhyU zQlS7H)J61eo>gX!eX(mVB1exSguYx!C#T@R5dQ-s{nKt+-Xxt)rzv>q2_ zJvNCZp^wn_^l#wjRjfld3&(6=qH@%OmNOEicxCn`f??1CLMM7_3?6AryRC<2WU+U` zMcxPaW$ewE@Rc<^xQ-%g@7&VyeT1gHC|KQ{2rv!iP4~wS5t8|R|1;TN_cyAVA}l@} z9!8l(hY18kA3XpHH}*VXyjgw!MBwF?w8LdmMQ=Y z%xH)GPc_T7NwNcR>Ofn|yl#MZkYbiUR;^$iH0}!JXp( zxTgJKK=~i@7eB_P7s&EY%vWb{hZqp1Np}|D@yF*s5MmS5B4GR(%5uX4I{)Nh3p_+5Rz`xMbD^z_A@csk6>IADw z0+GQ*9RSRxjd6hVe_G)W4%c-01eknN~(_87JEyXyF%4 zTD^?NCd0VrE+CkPL9>xKwxO0Lan?OQNjI0d0PI9BHHev80H)zP>@s=ZxH73@F;;$0 zHuU3i>(l&hUwpf_QQwveN4NK(>Y+y5gON4^Q7Oq}6e0gg0uc>Qz&c2+!qf>P=<6@< zMK1L(=OGEt=spLRy^aQt7G zuRWGPC2v$iD8*7stp#k7Ph3x2Btno9diF-@um7m3s!h;U=7@NlBPeSvXRp)k$h(&* z)_zV{_;@fYihxc;XJ~Io4J5OB`GsCgbA??ZEBH-;c^Z4w6`Z>x@9)qd@(z-6Rv{m2 zm;pb{wPf%8V@U=E z^#Y*5Ork)fSBgyHg@PRTLs5g@|Bb%-LxP9@pag$X4tP}buh1K>l+XCT6f)!guUX*Z zx%3-I2ne;87uA2&3<0bz2IM4vZT}3H8{vi*gX;e=s#*9u_)8|kebu-i_HxRvD}SLc z$qErnB>tCr2JsgrZ{r^Z2K#Z2=rUeg(4$8UE=-JIR+SO3RnmU4wM2CflnY`65cPVzv_+l zf&j;1|6&xRfH;3dz{uGl-M>GQ z1G9+(aUg-%z(2zm{E|igbcU|$7zhGi G;Qs@TfE5e? diff --git a/dist/extension/birb.js b/dist/extension/birb.js index 1c76315..d82e1f1 100644 --- a/dist/extension/birb.js +++ b/dist/extension/birb.js @@ -1066,21 +1066,22 @@ * @returns {Promise} */ async getSaveData() { - log("Loading save data from Obsidian plugin storage unimplemented"); - return {}; + // @ts-expect-error + return await OBSIDIAN_PLUGIN.loadData() ?? {}; } /** * @override - * @param {BirbSaveData} saveData + * @param {BirbSaveData|{}} saveData */ async putSaveData(saveData) { - log("Saving data to Obsidian plugin storage unimplemented"); + // @ts-expect-error + return await OBSIDIAN_PLUGIN.saveData(saveData); } /** @override */ resetSaveData() { - log("Resetting save data in Obsidian plugin storage unimplemented"); + this.putSaveData({}); } /** @override */ @@ -1923,7 +1924,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.8", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.8"); }, false), + new MenuItem("2025.11.13.16", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.16"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/extension/manifest.json b/dist/extension/manifest.json index 75df989..c8f1e33 100644 --- a/dist/extension/manifest.json +++ b/dist/extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.13.8", + "version": "2025.11.13.16", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/dist/obsidian/main.js b/dist/obsidian/main.js index 7740254..e545261 100644 --- a/dist/obsidian/main.js +++ b/dist/obsidian/main.js @@ -1,7 +1,8 @@ const { Plugin, Notice } = require('obsidian'); -module.exports = class MyPlugin extends Plugin { +module.exports = class PocketBird extends Plugin { onload() { + const OBSIDIAN_PLUGIN = this; (function () { 'use strict'; @@ -1070,21 +1071,22 @@ module.exports = class MyPlugin extends Plugin { * @returns {Promise} */ async getSaveData() { - log("Loading save data from Obsidian plugin storage unimplemented"); - return {}; + // @ts-expect-error + return await OBSIDIAN_PLUGIN.loadData() ?? {}; } /** * @override - * @param {BirbSaveData} saveData + * @param {BirbSaveData|{}} saveData */ async putSaveData(saveData) { - log("Saving data to Obsidian plugin storage unimplemented"); + // @ts-expect-error + return await OBSIDIAN_PLUGIN.saveData(saveData); } /** @override */ resetSaveData() { - log("Resetting save data in Obsidian plugin storage unimplemented"); + this.putSaveData({}); } /** @override */ @@ -1927,7 +1929,7 @@ module.exports = class MyPlugin extends Plugin { insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.8", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.8"); }, false), + new MenuItem("2025.11.13.16", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.16"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/dist/obsidian/manifest.json b/dist/obsidian/manifest.json index 43489ee..d692265 100644 --- a/dist/obsidian/manifest.json +++ b/dist/obsidian/manifest.json @@ -1,7 +1,7 @@ { "id": "pocket-bird", "name": "Pocket Bird", - "version": "2025.11.13.8", + "version": "2025.11.13.16", "minAppVersion": "0.15.0", "description": "It's a pet bird in your Obsidian, what more could you want?", "author": "Idrees Hassan", diff --git a/dist/userscript/birb.user.js b/dist/userscript/birb.user.js index 9a5a6c0..c6e381d 100644 --- a/dist/userscript/birb.user.js +++ b/dist/userscript/birb.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Pocket Bird // @namespace https://idreesinc.com -// @version 2025.11.13.8 +// @version 2025.11.13.16 // @description It's a bird that hops around your web browser, the future is here // @author Idrees // @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js @@ -1080,21 +1080,22 @@ * @returns {Promise} */ async getSaveData() { - log("Loading save data from Obsidian plugin storage unimplemented"); - return {}; + // @ts-expect-error + return await OBSIDIAN_PLUGIN.loadData() ?? {}; } /** * @override - * @param {BirbSaveData} saveData + * @param {BirbSaveData|{}} saveData */ async putSaveData(saveData) { - log("Saving data to Obsidian plugin storage unimplemented"); + // @ts-expect-error + return await OBSIDIAN_PLUGIN.saveData(saveData); } /** @override */ resetSaveData() { - log("Resetting save data in Obsidian plugin storage unimplemented"); + this.putSaveData({}); } /** @override */ @@ -1937,7 +1938,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.8", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.8"); }, false), + new MenuItem("2025.11.13.16", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.16"); }, false), ]; const styleElement = document.createElement("style"); diff --git a/src/context.js b/src/context.js index d3cd2ab..31640bb 100644 --- a/src/context.js +++ b/src/context.js @@ -227,21 +227,22 @@ class ObsidianContext extends Context { * @returns {Promise} */ async getSaveData() { - log("Loading save data from Obsidian plugin storage unimplemented"); - return {}; + // @ts-expect-error + return await OBSIDIAN_PLUGIN.loadData() ?? {}; } /** * @override - * @param {BirbSaveData} saveData + * @param {BirbSaveData|{}} saveData */ async putSaveData(saveData) { - log("Saving data to Obsidian plugin storage unimplemented"); + // @ts-expect-error + return await OBSIDIAN_PLUGIN.saveData(saveData); } /** @override */ resetSaveData() { - log("Resetting save data in Obsidian plugin storage unimplemented"); + this.putSaveData({}); } /** @override */ From 71bb8204e2c520612a567c12d4eeebb74e5ff18b Mon Sep 17 00:00:00 2001 From: Idrees Hassan Date: Thu, 13 Nov 2025 18:41:37 -0500 Subject: [PATCH 10/10] Add focusing on obsidian elements --- build.js | 2 ++ dist/birb.js | 32 +++++++++++++++++++++++++++++--- dist/extension.zip | Bin 148982 -> 149183 bytes dist/extension/birb.js | 32 +++++++++++++++++++++++++++++--- dist/extension/manifest.json | 2 +- dist/obsidian/main.js | 34 +++++++++++++++++++++++++++++++--- dist/obsidian/manifest.json | 2 +- dist/userscript/birb.user.js | 34 ++++++++++++++++++++++++++++++---- src/application.js | 4 ++-- src/context.js | 26 ++++++++++++++++++++++++++ 10 files changed, 151 insertions(+), 17 deletions(-) diff --git a/build.js b/build.js index 1e11733..027105a 100644 --- a/build.js +++ b/build.js @@ -163,8 +163,10 @@ const obsidianPlugin = ` const { Plugin, Notice } = require('obsidian'); module.exports = class PocketBird extends Plugin { onload() { + console.log("Loading Pocket Bird version ${version}..."); const OBSIDIAN_PLUGIN = this; ${birbJs} + console.log("Pocket Bird loaded!"); } onunload() { diff --git a/dist/birb.js b/dist/birb.js index d82e1f1..5bded46 100644 --- a/dist/birb.js +++ b/dist/birb.js @@ -881,6 +881,17 @@ throw new Error("Method not implemented"); } + /** + * @returns {string[]} A list of CSS selectors for focusable elements + */ + getFocusableElements() { + return ["img", "video", ".birb-sticky-note"]; + } + + getFocusElementTopMargin() { + return 80; + } + /** * @returns {string} The current path of the active page in this context */ @@ -1084,6 +1095,21 @@ this.putSaveData({}); } + /** @override */ + getFocusElementTopMargin() { + return 10; + } + + /** @override */ + getFocusableElements() { + const elements = [ + ".workspace-leaf", + ".cm-callout", + ".HyperMD-codeblock-begin" + ]; + return super.getFocusableElements().concat(elements); + } + /** @override */ areStickyNotesEnabled() { return false; @@ -1795,7 +1821,6 @@ // Focus element constraints const MIN_FOCUS_ELEMENT_WIDTH = 100; - const MIN_FOCUS_ELEMENT_TOP = 80; /** @type {Partial} */ let userSettings = {}; @@ -1924,7 +1949,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.16", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.16"); }, false), + new MenuItem("2025.11.13.27", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.27"); }, false), ]; const styleElement = document.createElement("style"); @@ -2551,7 +2576,8 @@ if (frozen) { return false; } - const elements = document.querySelectorAll("img, video, .birb-sticky-note"); + const MIN_FOCUS_ELEMENT_TOP = getContext().getFocusElementTopMargin(); + const elements = document.querySelectorAll(getContext().getFocusableElements().join(", ")); const inWindow = Array.from(elements).filter((img) => { const rect = img.getBoundingClientRect(); return rect.left >= 0 && rect.top >= MIN_FOCUS_ELEMENT_TOP && rect.right <= window.innerWidth && rect.top <= getWindowHeight(); diff --git a/dist/extension.zip b/dist/extension.zip index fdc7731738f10a746a90114d6b69dd65d71a3431..416407c8359f1d3f0ea0b261d5f6a6a36f8e50eb 100644 GIT binary patch delta 26861 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 */ let userSettings = {}; @@ -1924,7 +1949,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.16", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.16"); }, false), + new MenuItem("2025.11.13.27", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.27"); }, false), ]; const styleElement = document.createElement("style"); @@ -2551,7 +2576,8 @@ if (frozen) { return false; } - const elements = document.querySelectorAll("img, video, .birb-sticky-note"); + const MIN_FOCUS_ELEMENT_TOP = getContext().getFocusElementTopMargin(); + const elements = document.querySelectorAll(getContext().getFocusableElements().join(", ")); const inWindow = Array.from(elements).filter((img) => { const rect = img.getBoundingClientRect(); return rect.left >= 0 && rect.top >= MIN_FOCUS_ELEMENT_TOP && rect.right <= window.innerWidth && rect.top <= getWindowHeight(); diff --git a/dist/extension/manifest.json b/dist/extension/manifest.json index c8f1e33..dfa33f3 100644 --- a/dist/extension/manifest.json +++ b/dist/extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Pocket Bird", "description": "It's a pet bird in your browser, what more could you want?", - "version": "2025.11.13.16", + "version": "2025.11.13.27", "homepage_url": "https://idreesinc.com", "icons": { "48": "images/icons/transparent/48x48x1.png", diff --git a/dist/obsidian/main.js b/dist/obsidian/main.js index e545261..4386c5f 100644 --- a/dist/obsidian/main.js +++ b/dist/obsidian/main.js @@ -2,6 +2,7 @@ const { Plugin, Notice } = require('obsidian'); module.exports = class PocketBird extends Plugin { onload() { + console.log("Loading Pocket Bird version 2025.11.13.27..."); const OBSIDIAN_PLUGIN = this; (function () { 'use strict'; @@ -886,6 +887,17 @@ module.exports = class PocketBird extends Plugin { throw new Error("Method not implemented"); } + /** + * @returns {string[]} A list of CSS selectors for focusable elements + */ + getFocusableElements() { + return ["img", "video", ".birb-sticky-note"]; + } + + getFocusElementTopMargin() { + return 80; + } + /** * @returns {string} The current path of the active page in this context */ @@ -1089,6 +1101,21 @@ module.exports = class PocketBird extends Plugin { this.putSaveData({}); } + /** @override */ + getFocusElementTopMargin() { + return 10; + } + + /** @override */ + getFocusableElements() { + const elements = [ + ".workspace-leaf", + ".cm-callout", + ".HyperMD-codeblock-begin" + ]; + return super.getFocusableElements().concat(elements); + } + /** @override */ areStickyNotesEnabled() { return false; @@ -1800,7 +1827,6 @@ module.exports = class PocketBird extends Plugin { // Focus element constraints const MIN_FOCUS_ELEMENT_WIDTH = 100; - const MIN_FOCUS_ELEMENT_TOP = 80; /** @type {Partial} */ let userSettings = {}; @@ -1929,7 +1955,7 @@ module.exports = class PocketBird extends Plugin { insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.16", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.16"); }, false), + new MenuItem("2025.11.13.27", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.27"); }, false), ]; const styleElement = document.createElement("style"); @@ -2556,7 +2582,8 @@ module.exports = class PocketBird extends Plugin { if (frozen) { return false; } - const elements = document.querySelectorAll("img, video, .birb-sticky-note"); + const MIN_FOCUS_ELEMENT_TOP = getContext().getFocusElementTopMargin(); + const elements = document.querySelectorAll(getContext().getFocusableElements().join(", ")); const inWindow = Array.from(elements).filter((img) => { const rect = img.getBoundingClientRect(); return rect.left >= 0 && rect.top >= MIN_FOCUS_ELEMENT_TOP && rect.right <= window.innerWidth && rect.top <= getWindowHeight(); @@ -2720,6 +2747,7 @@ module.exports = class PocketBird extends Plugin { })(); + console.log("Pocket Bird loaded!"); } onunload() { diff --git a/dist/obsidian/manifest.json b/dist/obsidian/manifest.json index d692265..7591d6d 100644 --- a/dist/obsidian/manifest.json +++ b/dist/obsidian/manifest.json @@ -1,7 +1,7 @@ { "id": "pocket-bird", "name": "Pocket Bird", - "version": "2025.11.13.16", + "version": "2025.11.13.27", "minAppVersion": "0.15.0", "description": "It's a pet bird in your Obsidian, what more could you want?", "author": "Idrees Hassan", diff --git a/dist/userscript/birb.user.js b/dist/userscript/birb.user.js index c6e381d..364d825 100644 --- a/dist/userscript/birb.user.js +++ b/dist/userscript/birb.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Pocket Bird // @namespace https://idreesinc.com -// @version 2025.11.13.16 +// @version 2025.11.13.27 // @description It's a bird that hops around your web browser, the future is here // @author Idrees // @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js @@ -895,6 +895,17 @@ throw new Error("Method not implemented"); } + /** + * @returns {string[]} A list of CSS selectors for focusable elements + */ + getFocusableElements() { + return ["img", "video", ".birb-sticky-note"]; + } + + getFocusElementTopMargin() { + return 80; + } + /** * @returns {string} The current path of the active page in this context */ @@ -1098,6 +1109,21 @@ this.putSaveData({}); } + /** @override */ + getFocusElementTopMargin() { + return 10; + } + + /** @override */ + getFocusableElements() { + const elements = [ + ".workspace-leaf", + ".cm-callout", + ".HyperMD-codeblock-begin" + ]; + return super.getFocusableElements().concat(elements); + } + /** @override */ areStickyNotesEnabled() { return false; @@ -1809,7 +1835,6 @@ // Focus element constraints const MIN_FOCUS_ELEMENT_WIDTH = 100; - const MIN_FOCUS_ELEMENT_TOP = 80; /** @type {Partial} */ let userSettings = {}; @@ -1938,7 +1963,7 @@ insertModal(`${birdBirb()} Mode`, message); }), new Separator(), - new MenuItem("2025.11.13.16", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.16"); }, false), + new MenuItem("2025.11.13.27", () => { alert("Thank you for using Pocket Bird! You are on version: 2025.11.13.27"); }, false), ]; const styleElement = document.createElement("style"); @@ -2565,7 +2590,8 @@ if (frozen) { return false; } - const elements = document.querySelectorAll("img, video, .birb-sticky-note"); + const MIN_FOCUS_ELEMENT_TOP = getContext().getFocusElementTopMargin(); + const elements = document.querySelectorAll(getContext().getFocusableElements().join(", ")); const inWindow = Array.from(elements).filter((img) => { const rect = img.getBoundingClientRect(); return rect.left >= 0 && rect.top >= MIN_FOCUS_ELEMENT_TOP && rect.right <= window.innerWidth && rect.top <= getWindowHeight(); diff --git a/src/application.js b/src/application.js index bd52124..8489f65 100644 --- a/src/application.js +++ b/src/application.js @@ -104,7 +104,6 @@ const PET_FEATHER_BOOST = 2; // Focus element constraints const MIN_FOCUS_ELEMENT_WIDTH = 100; -const MIN_FOCUS_ELEMENT_TOP = 80; /** @type {Partial} */ let userSettings = {}; @@ -864,7 +863,8 @@ Promise.all([ if (frozen) { return false; } - const elements = document.querySelectorAll("img, video, .birb-sticky-note"); + const MIN_FOCUS_ELEMENT_TOP = getContext().getFocusElementTopMargin(); + const elements = document.querySelectorAll(getContext().getFocusableElements().join(", ")); const inWindow = Array.from(elements).filter((img) => { const rect = img.getBoundingClientRect(); return rect.left >= 0 && rect.top >= MIN_FOCUS_ELEMENT_TOP && rect.right <= window.innerWidth && rect.top <= getWindowHeight(); diff --git a/src/context.js b/src/context.js index 31640bb..7e21dbc 100644 --- a/src/context.js +++ b/src/context.js @@ -42,6 +42,17 @@ export class Context { throw new Error("Method not implemented"); } + /** + * @returns {string[]} A list of CSS selectors for focusable elements + */ + getFocusableElements() { + return ["img", "video", ".birb-sticky-note"]; + } + + getFocusElementTopMargin() { + return 80; + } + /** * @returns {string} The current path of the active page in this context */ @@ -245,6 +256,21 @@ class ObsidianContext extends Context { this.putSaveData({}); } + /** @override */ + getFocusElementTopMargin() { + return 10; + } + + /** @override */ + getFocusableElements() { + const elements = [ + ".workspace-leaf", + ".cm-callout", + ".HyperMD-codeblock-begin" + ]; + return super.getFocusableElements().concat(elements); + } + /** @override */ areStickyNotesEnabled() { return false;