diff --git a/dist/extension.zip b/dist/extension.zip index cd5a50a..840aaa7 100644 Binary files a/dist/extension.zip and b/dist/extension.zip differ diff --git a/dist/extension/birb.js b/dist/extension/birb.js index 0f6b1bc..3b77b68 100644 --- a/dist/extension/birb.js +++ b/dist/extension/birb.js @@ -622,8 +622,8 @@ "url": "https://en.wikipedia.org/wiki/Cuban_tody", "colors": { "beak": "#f16f54", - "face": "#5fdf44", - "chin": "#f12d3e", + "face": "#5ad63e", + "chin": "#e8273b", "collar": "#f12d3e", "belly": "#f6f5e4", "collar-scruff": "#a3ebff", @@ -644,11 +644,14 @@ "colors": { "face": "#9c3af2", "wing": "#8f37ed", - "wing-edge": "#7029b8", + "wing-edge": "#5b20c2", "belly": "#ffffff", "underbelly": "#f2f2f2", "foot": "#736a66", - "collar": "#aa60e6" + "collar": "#b760e6", + "nose": "#7a2ec7", + "cheek": "#7a2ec7", + "nose-tip": "#7a2ec7" }, "rarity": "uncommon" } @@ -1945,11 +1948,13 @@ /** * @param {string|(() => string)} text * @param {() => void} action + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, removeMenu = true) { + constructor(text, action, icon, removeMenu = true) { this.text = text; this.action = action; + this.icon = icon; this.removeMenu = removeMenu; } } @@ -1959,10 +1964,11 @@ * @param {string} text * @param {() => void} action * @param {() => boolean} condition + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, condition, removeMenu = true) { - super(text, action, removeMenu); + constructor(text, action, condition, icon, removeMenu = true) { + super(text, action, icon, removeMenu); this.condition = condition; } } @@ -1973,7 +1979,7 @@ * @param {() => void} action */ constructor(text, action, removeMenu = true) { - super(text, action, () => isDebug(), removeMenu); + super(text, action, () => isDebug(), undefined, removeMenu); } } @@ -1988,11 +1994,29 @@ * @param {() => void} removeMenuCallback * @returns {HTMLElement} */ - function makeMenuItem(item, removeMenuCallback) { + function createMenuItem(item, removeMenuCallback) { if (item instanceof Separator) { return makeElement("birb-window-separator"); } let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text); + if (item.icon) { + const iconCanvas = document.createElement("canvas"); + iconCanvas.width = 7; + iconCanvas.height = 6; + iconCanvas.classList.add("birb-menu-item-icon"); + const ctx = iconCanvas.getContext("2d"); + if (ctx) { + for (let row = 0; row < item.icon.length; row++) { + for (let col = 0; col < item.icon[row].length; col++) { + if (item.icon[row][col]) { + ctx.fillStyle = "black"; + ctx.fillRect(col, row, 1, 1); + } + } + } + } + menuItem.prepend(iconCanvas); + } onClick(menuItem, () => { if (item.removeMenu) { removeMenuCallback(); @@ -2020,7 +2044,7 @@ const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } menu.appendChild(header); @@ -2077,7 +2101,7 @@ const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } updateLocationCallback(menu); @@ -2328,15 +2352,17 @@ font-size: 14px; padding-top: 4px; padding-bottom: 4px; - padding-left: 10px; + padding-left: 2px; padding-right: 10px; box-sizing: border-box; opacity: 0.7 !important; user-select: none; display: flex; - justify-content: space-between; + justify-content: left; + align-items: center; cursor: pointer; color: black !important; + transition: background 0.1s, color 0.1s; } .birb-menu-item:hover { @@ -2348,6 +2374,21 @@ 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); + transition: none; +} + +.birb-menu-item-icon { + width: calc(7 * var(--birb-border-size)); + height: calc(6 * var(--birb-border-size)); + padding-right: calc(5 * var(--birb-border-size)); + flex-shrink: 0; + image-rendering: pixelated; + color: var(--birb-highlight); + opacity: 0.9; +} + +.birb-menu-item:hover > .birb-menu-item-icon { + filter: invert(1); } .birb-menu-item-arrow { @@ -2398,10 +2439,12 @@ justify-content: center; align-items: center; cursor: pointer; + transition: border-color 0.1s; } .birb-grid-item:hover { border-color: var(--birb-highlight); + transition: none; } .birb-grid-item canvas { @@ -2608,12 +2651,47 @@ }; const menuItems = [ - new MenuItem(`Pet ${birdBirb()}`, pet), - new MenuItem("Field Guide", insertFieldGuide), - new MenuItem("Wardrobe", insertWardrobe), - new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled()), - new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), - new DebugMenuItem("Freeze/Unfreeze", () => { + new MenuItem(`Pet ${birdBirb()}`, pet, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + ]), + new MenuItem("Field Guide", insertFieldGuide, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 1, 0, 1, 1, 1], + ]), + new MenuItem("Wardrobe", insertWardrobe, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 0, 0, 0, 1, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 1, 1, 1, 1, 0], + ]), + new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled(), [ + [0, 0, 1, 1, 1, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [1, 0, 0, 1, 0, 1, 0], + [1, 0, 1, 0, 0, 1, 0], + [1, 0, 0, 0, 0, 1, 0], + [1, 1, 1, 1, 1, 1, 0], + ]), + new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false), [ + [0, 1, 0, 1, 0, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 1, 1, 0, 0], + ]), + new DebugMenuItem("Freeze", () => { frozen = !frozen; }), new DebugMenuItem("Reset Data", resetSaveData), @@ -2632,11 +2710,18 @@ setDebug(false); }), new Separator(), - new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), false), + new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), [ + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 1, 1, 0, 1], + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + [1, 0, 1, 1, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + ], false), ]; const settingsItems = [ - new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false), + new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), undefined, false), new Separator(), new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => { userSettings.soundEnabled = !settings().soundEnabled; @@ -2656,7 +2741,7 @@ }), new Separator(), new MenuItem(() => `Source Code ${isPetBoostActive() ? " ❤" : ""}`, () => { window.open("https://github.com/IdreesInc/Pocket-Bird"); }), - new MenuItem("2026.3.30", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.3.30"); }, false), + new MenuItem("Build 2026.4.3", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.4.3"); }, undefined, false), ]; /** @type {Birb} */ @@ -3236,7 +3321,7 @@ latinName.textContent = type.latinName; latinName.href = type.url; latinName.target = "_blank"; - + const spacerTwo = document.createElement("div"); spacerTwo.style.height = "0.4em"; diff --git a/dist/extension/manifest.json b/dist/extension/manifest.json index 247dbb8..d79f6e0 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": "2026.3.30", + "version": "2026.4.3", "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 82a25f0..74ea4c1 100644 --- a/dist/obsidian/main.js +++ b/dist/obsidian/main.js @@ -1,7 +1,7 @@ const { Plugin, Notice } = require('obsidian'); module.exports = class PocketBird extends Plugin { onload() { - console.log("Loading Pocket Bird version 2026.3.30..."); + console.log("Loading Pocket Bird version 2026.4.3..."); const OBSIDIAN_PLUGIN = this; (function () { 'use strict'; @@ -627,8 +627,8 @@ module.exports = class PocketBird extends Plugin { "url": "https://en.wikipedia.org/wiki/Cuban_tody", "colors": { "beak": "#f16f54", - "face": "#5fdf44", - "chin": "#f12d3e", + "face": "#5ad63e", + "chin": "#e8273b", "collar": "#f12d3e", "belly": "#f6f5e4", "collar-scruff": "#a3ebff", @@ -649,11 +649,14 @@ module.exports = class PocketBird extends Plugin { "colors": { "face": "#9c3af2", "wing": "#8f37ed", - "wing-edge": "#7029b8", + "wing-edge": "#5b20c2", "belly": "#ffffff", "underbelly": "#f2f2f2", "foot": "#736a66", - "collar": "#aa60e6" + "collar": "#b760e6", + "nose": "#7a2ec7", + "cheek": "#7a2ec7", + "nose-tip": "#7a2ec7" }, "rarity": "uncommon" } @@ -1978,11 +1981,13 @@ module.exports = class PocketBird extends Plugin { /** * @param {string|(() => string)} text * @param {() => void} action + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, removeMenu = true) { + constructor(text, action, icon, removeMenu = true) { this.text = text; this.action = action; + this.icon = icon; this.removeMenu = removeMenu; } } @@ -1992,10 +1997,11 @@ module.exports = class PocketBird extends Plugin { * @param {string} text * @param {() => void} action * @param {() => boolean} condition + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, condition, removeMenu = true) { - super(text, action, removeMenu); + constructor(text, action, condition, icon, removeMenu = true) { + super(text, action, icon, removeMenu); this.condition = condition; } } @@ -2006,7 +2012,7 @@ module.exports = class PocketBird extends Plugin { * @param {() => void} action */ constructor(text, action, removeMenu = true) { - super(text, action, () => isDebug(), removeMenu); + super(text, action, () => isDebug(), undefined, removeMenu); } } @@ -2021,11 +2027,29 @@ module.exports = class PocketBird extends Plugin { * @param {() => void} removeMenuCallback * @returns {HTMLElement} */ - function makeMenuItem(item, removeMenuCallback) { + function createMenuItem(item, removeMenuCallback) { if (item instanceof Separator) { return makeElement("birb-window-separator"); } let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text); + if (item.icon) { + const iconCanvas = document.createElement("canvas"); + iconCanvas.width = 7; + iconCanvas.height = 6; + iconCanvas.classList.add("birb-menu-item-icon"); + const ctx = iconCanvas.getContext("2d"); + if (ctx) { + for (let row = 0; row < item.icon.length; row++) { + for (let col = 0; col < item.icon[row].length; col++) { + if (item.icon[row][col]) { + ctx.fillStyle = "black"; + ctx.fillRect(col, row, 1, 1); + } + } + } + } + menuItem.prepend(iconCanvas); + } onClick(menuItem, () => { if (item.removeMenu) { removeMenuCallback(); @@ -2053,7 +2077,7 @@ module.exports = class PocketBird extends Plugin { const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } menu.appendChild(header); @@ -2110,7 +2134,7 @@ module.exports = class PocketBird extends Plugin { const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } updateLocationCallback(menu); @@ -2361,15 +2385,17 @@ module.exports = class PocketBird extends Plugin { font-size: 14px; padding-top: 4px; padding-bottom: 4px; - padding-left: 10px; + padding-left: 2px; padding-right: 10px; box-sizing: border-box; opacity: 0.7 !important; user-select: none; display: flex; - justify-content: space-between; + justify-content: left; + align-items: center; cursor: pointer; color: black !important; + transition: background 0.1s, color 0.1s; } .birb-menu-item:hover { @@ -2381,6 +2407,21 @@ module.exports = class PocketBird extends Plugin { 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); + transition: none; +} + +.birb-menu-item-icon { + width: calc(7 * var(--birb-border-size)); + height: calc(6 * var(--birb-border-size)); + padding-right: calc(5 * var(--birb-border-size)); + flex-shrink: 0; + image-rendering: pixelated; + color: var(--birb-highlight); + opacity: 0.9; +} + +.birb-menu-item:hover > .birb-menu-item-icon { + filter: invert(1); } .birb-menu-item-arrow { @@ -2431,10 +2472,12 @@ module.exports = class PocketBird extends Plugin { justify-content: center; align-items: center; cursor: pointer; + transition: border-color 0.1s; } .birb-grid-item:hover { border-color: var(--birb-highlight); + transition: none; } .birb-grid-item canvas { @@ -2641,12 +2684,47 @@ module.exports = class PocketBird extends Plugin { }; const menuItems = [ - new MenuItem(`Pet ${birdBirb()}`, pet), - new MenuItem("Field Guide", insertFieldGuide), - new MenuItem("Wardrobe", insertWardrobe), - new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled()), - new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), - new DebugMenuItem("Freeze/Unfreeze", () => { + new MenuItem(`Pet ${birdBirb()}`, pet, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + ]), + new MenuItem("Field Guide", insertFieldGuide, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 1, 0, 1, 1, 1], + ]), + new MenuItem("Wardrobe", insertWardrobe, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 0, 0, 0, 1, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 1, 1, 1, 1, 0], + ]), + new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled(), [ + [0, 0, 1, 1, 1, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [1, 0, 0, 1, 0, 1, 0], + [1, 0, 1, 0, 0, 1, 0], + [1, 0, 0, 0, 0, 1, 0], + [1, 1, 1, 1, 1, 1, 0], + ]), + new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false), [ + [0, 1, 0, 1, 0, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 1, 1, 0, 0], + ]), + new DebugMenuItem("Freeze", () => { frozen = !frozen; }), new DebugMenuItem("Reset Data", resetSaveData), @@ -2665,11 +2743,18 @@ module.exports = class PocketBird extends Plugin { setDebug(false); }), new Separator(), - new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), false), + new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), [ + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 1, 1, 0, 1], + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + [1, 0, 1, 1, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + ], false), ]; const settingsItems = [ - new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false), + new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), undefined, false), new Separator(), new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => { userSettings.soundEnabled = !settings().soundEnabled; @@ -2689,7 +2774,7 @@ module.exports = class PocketBird extends Plugin { }), new Separator(), new MenuItem(() => `Source Code ${isPetBoostActive() ? " ❤" : ""}`, () => { window.open("https://github.com/IdreesInc/Pocket-Bird"); }), - new MenuItem("2026.3.30", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.3.30"); }, false), + new MenuItem("Build 2026.4.3", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.4.3"); }, undefined, false), ]; /** @type {Birb} */ @@ -3269,7 +3354,7 @@ module.exports = class PocketBird extends Plugin { latinName.textContent = type.latinName; latinName.href = type.url; latinName.target = "_blank"; - + const spacerTwo = document.createElement("div"); spacerTwo.style.height = "0.4em"; diff --git a/dist/obsidian/manifest.json b/dist/obsidian/manifest.json index 23df7f5..38c0638 100644 --- a/dist/obsidian/manifest.json +++ b/dist/obsidian/manifest.json @@ -1,7 +1,7 @@ { "id": "pocket-bird", "name": "Pocket Bird", - "version": "2026.3.30", + "version": "2026.4.3", "minAppVersion": "0.15.0", "description": "Add a pet bird to fly around your notes and keep you company!", "author": "Idrees Hassan", diff --git a/dist/userscript/birb.user.js b/dist/userscript/birb.user.js index e33d655..9cba60e 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 2026.3.30 +// @version 2026.4.3 // @description It's a pet bird in your browser, what more could you want? // @author Idrees // @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js @@ -636,8 +636,8 @@ "url": "https://en.wikipedia.org/wiki/Cuban_tody", "colors": { "beak": "#f16f54", - "face": "#5fdf44", - "chin": "#f12d3e", + "face": "#5ad63e", + "chin": "#e8273b", "collar": "#f12d3e", "belly": "#f6f5e4", "collar-scruff": "#a3ebff", @@ -658,11 +658,14 @@ "colors": { "face": "#9c3af2", "wing": "#8f37ed", - "wing-edge": "#7029b8", + "wing-edge": "#5b20c2", "belly": "#ffffff", "underbelly": "#f2f2f2", "foot": "#736a66", - "collar": "#aa60e6" + "collar": "#b760e6", + "nose": "#7a2ec7", + "cheek": "#7a2ec7", + "nose-tip": "#7a2ec7" }, "rarity": "uncommon" } @@ -1940,11 +1943,13 @@ /** * @param {string|(() => string)} text * @param {() => void} action + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, removeMenu = true) { + constructor(text, action, icon, removeMenu = true) { this.text = text; this.action = action; + this.icon = icon; this.removeMenu = removeMenu; } } @@ -1954,10 +1959,11 @@ * @param {string} text * @param {() => void} action * @param {() => boolean} condition + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, condition, removeMenu = true) { - super(text, action, removeMenu); + constructor(text, action, condition, icon, removeMenu = true) { + super(text, action, icon, removeMenu); this.condition = condition; } } @@ -1968,7 +1974,7 @@ * @param {() => void} action */ constructor(text, action, removeMenu = true) { - super(text, action, () => isDebug(), removeMenu); + super(text, action, () => isDebug(), undefined, removeMenu); } } @@ -1983,11 +1989,29 @@ * @param {() => void} removeMenuCallback * @returns {HTMLElement} */ - function makeMenuItem(item, removeMenuCallback) { + function createMenuItem(item, removeMenuCallback) { if (item instanceof Separator) { return makeElement("birb-window-separator"); } let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text); + if (item.icon) { + const iconCanvas = document.createElement("canvas"); + iconCanvas.width = 7; + iconCanvas.height = 6; + iconCanvas.classList.add("birb-menu-item-icon"); + const ctx = iconCanvas.getContext("2d"); + if (ctx) { + for (let row = 0; row < item.icon.length; row++) { + for (let col = 0; col < item.icon[row].length; col++) { + if (item.icon[row][col]) { + ctx.fillStyle = "black"; + ctx.fillRect(col, row, 1, 1); + } + } + } + } + menuItem.prepend(iconCanvas); + } onClick(menuItem, () => { if (item.removeMenu) { removeMenuCallback(); @@ -2015,7 +2039,7 @@ const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } menu.appendChild(header); @@ -2072,7 +2096,7 @@ const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } updateLocationCallback(menu); @@ -2323,15 +2347,17 @@ font-size: 14px; padding-top: 4px; padding-bottom: 4px; - padding-left: 10px; + padding-left: 2px; padding-right: 10px; box-sizing: border-box; opacity: 0.7 !important; user-select: none; display: flex; - justify-content: space-between; + justify-content: left; + align-items: center; cursor: pointer; color: black !important; + transition: background 0.1s, color 0.1s; } .birb-menu-item:hover { @@ -2343,6 +2369,21 @@ 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); + transition: none; +} + +.birb-menu-item-icon { + width: calc(7 * var(--birb-border-size)); + height: calc(6 * var(--birb-border-size)); + padding-right: calc(5 * var(--birb-border-size)); + flex-shrink: 0; + image-rendering: pixelated; + color: var(--birb-highlight); + opacity: 0.9; +} + +.birb-menu-item:hover > .birb-menu-item-icon { + filter: invert(1); } .birb-menu-item-arrow { @@ -2393,10 +2434,12 @@ justify-content: center; align-items: center; cursor: pointer; + transition: border-color 0.1s; } .birb-grid-item:hover { border-color: var(--birb-highlight); + transition: none; } .birb-grid-item canvas { @@ -2603,12 +2646,47 @@ }; const menuItems = [ - new MenuItem(`Pet ${birdBirb()}`, pet), - new MenuItem("Field Guide", insertFieldGuide), - new MenuItem("Wardrobe", insertWardrobe), - new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled()), - new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), - new DebugMenuItem("Freeze/Unfreeze", () => { + new MenuItem(`Pet ${birdBirb()}`, pet, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + ]), + new MenuItem("Field Guide", insertFieldGuide, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 1, 0, 1, 1, 1], + ]), + new MenuItem("Wardrobe", insertWardrobe, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 0, 0, 0, 1, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 1, 1, 1, 1, 0], + ]), + new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled(), [ + [0, 0, 1, 1, 1, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [1, 0, 0, 1, 0, 1, 0], + [1, 0, 1, 0, 0, 1, 0], + [1, 0, 0, 0, 0, 1, 0], + [1, 1, 1, 1, 1, 1, 0], + ]), + new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false), [ + [0, 1, 0, 1, 0, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 1, 1, 0, 0], + ]), + new DebugMenuItem("Freeze", () => { frozen = !frozen; }), new DebugMenuItem("Reset Data", resetSaveData), @@ -2627,11 +2705,18 @@ setDebug(false); }), new Separator(), - new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), false), + new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), [ + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 1, 1, 0, 1], + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + [1, 0, 1, 1, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + ], false), ]; const settingsItems = [ - new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false), + new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), undefined, false), new Separator(), new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => { userSettings.soundEnabled = !settings().soundEnabled; @@ -2651,7 +2736,7 @@ }), new Separator(), new MenuItem(() => `Source Code ${isPetBoostActive() ? " ❤" : ""}`, () => { window.open("https://github.com/IdreesInc/Pocket-Bird"); }), - new MenuItem("2026.3.30", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.3.30"); }, false), + new MenuItem("Build 2026.4.3", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.4.3"); }, undefined, false), ]; /** @type {Birb} */ @@ -3231,7 +3316,7 @@ latinName.textContent = type.latinName; latinName.href = type.url; latinName.target = "_blank"; - + const spacerTwo = document.createElement("div"); spacerTwo.style.height = "0.4em"; diff --git a/dist/web/birb.embed.js b/dist/web/birb.embed.js index 978f444..829a758 100644 --- a/dist/web/birb.embed.js +++ b/dist/web/birb.embed.js @@ -622,8 +622,8 @@ "url": "https://en.wikipedia.org/wiki/Cuban_tody", "colors": { "beak": "#f16f54", - "face": "#5fdf44", - "chin": "#f12d3e", + "face": "#5ad63e", + "chin": "#e8273b", "collar": "#f12d3e", "belly": "#f6f5e4", "collar-scruff": "#a3ebff", @@ -644,11 +644,14 @@ "colors": { "face": "#9c3af2", "wing": "#8f37ed", - "wing-edge": "#7029b8", + "wing-edge": "#5b20c2", "belly": "#ffffff", "underbelly": "#f2f2f2", "foot": "#736a66", - "collar": "#aa60e6" + "collar": "#b760e6", + "nose": "#7a2ec7", + "cheek": "#7a2ec7", + "nose-tip": "#7a2ec7" }, "rarity": "uncommon" } @@ -1920,11 +1923,13 @@ /** * @param {string|(() => string)} text * @param {() => void} action + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, removeMenu = true) { + constructor(text, action, icon, removeMenu = true) { this.text = text; this.action = action; + this.icon = icon; this.removeMenu = removeMenu; } } @@ -1934,10 +1939,11 @@ * @param {string} text * @param {() => void} action * @param {() => boolean} condition + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, condition, removeMenu = true) { - super(text, action, removeMenu); + constructor(text, action, condition, icon, removeMenu = true) { + super(text, action, icon, removeMenu); this.condition = condition; } } @@ -1948,7 +1954,7 @@ * @param {() => void} action */ constructor(text, action, removeMenu = true) { - super(text, action, () => isDebug(), removeMenu); + super(text, action, () => isDebug(), undefined, removeMenu); } } @@ -1963,11 +1969,29 @@ * @param {() => void} removeMenuCallback * @returns {HTMLElement} */ - function makeMenuItem(item, removeMenuCallback) { + function createMenuItem(item, removeMenuCallback) { if (item instanceof Separator) { return makeElement("birb-window-separator"); } let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text); + if (item.icon) { + const iconCanvas = document.createElement("canvas"); + iconCanvas.width = 7; + iconCanvas.height = 6; + iconCanvas.classList.add("birb-menu-item-icon"); + const ctx = iconCanvas.getContext("2d"); + if (ctx) { + for (let row = 0; row < item.icon.length; row++) { + for (let col = 0; col < item.icon[row].length; col++) { + if (item.icon[row][col]) { + ctx.fillStyle = "black"; + ctx.fillRect(col, row, 1, 1); + } + } + } + } + menuItem.prepend(iconCanvas); + } onClick(menuItem, () => { if (item.removeMenu) { removeMenuCallback(); @@ -1995,7 +2019,7 @@ const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } menu.appendChild(header); @@ -2052,7 +2076,7 @@ const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } updateLocationCallback(menu); @@ -2303,15 +2327,17 @@ font-size: 14px; padding-top: 4px; padding-bottom: 4px; - padding-left: 10px; + padding-left: 2px; padding-right: 10px; box-sizing: border-box; opacity: 0.7 !important; user-select: none; display: flex; - justify-content: space-between; + justify-content: left; + align-items: center; cursor: pointer; color: black !important; + transition: background 0.1s, color 0.1s; } .birb-menu-item:hover { @@ -2323,6 +2349,21 @@ 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); + transition: none; +} + +.birb-menu-item-icon { + width: calc(7 * var(--birb-border-size)); + height: calc(6 * var(--birb-border-size)); + padding-right: calc(5 * var(--birb-border-size)); + flex-shrink: 0; + image-rendering: pixelated; + color: var(--birb-highlight); + opacity: 0.9; +} + +.birb-menu-item:hover > .birb-menu-item-icon { + filter: invert(1); } .birb-menu-item-arrow { @@ -2373,10 +2414,12 @@ justify-content: center; align-items: center; cursor: pointer; + transition: border-color 0.1s; } .birb-grid-item:hover { border-color: var(--birb-highlight); + transition: none; } .birb-grid-item canvas { @@ -2583,12 +2626,47 @@ }; const menuItems = [ - new MenuItem(`Pet ${birdBirb()}`, pet), - new MenuItem("Field Guide", insertFieldGuide), - new MenuItem("Wardrobe", insertWardrobe), - new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled()), - new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), - new DebugMenuItem("Freeze/Unfreeze", () => { + new MenuItem(`Pet ${birdBirb()}`, pet, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + ]), + new MenuItem("Field Guide", insertFieldGuide, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 1, 0, 1, 1, 1], + ]), + new MenuItem("Wardrobe", insertWardrobe, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 0, 0, 0, 1, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 1, 1, 1, 1, 0], + ]), + new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled(), [ + [0, 0, 1, 1, 1, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [1, 0, 0, 1, 0, 1, 0], + [1, 0, 1, 0, 0, 1, 0], + [1, 0, 0, 0, 0, 1, 0], + [1, 1, 1, 1, 1, 1, 0], + ]), + new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false), [ + [0, 1, 0, 1, 0, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 1, 1, 0, 0], + ]), + new DebugMenuItem("Freeze", () => { frozen = !frozen; }), new DebugMenuItem("Reset Data", resetSaveData), @@ -2607,11 +2685,18 @@ setDebug(false); }), new Separator(), - new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), false), + new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), [ + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 1, 1, 0, 1], + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + [1, 0, 1, 1, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + ], false), ]; const settingsItems = [ - new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false), + new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), undefined, false), new Separator(), new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => { userSettings.soundEnabled = !settings().soundEnabled; @@ -2631,7 +2716,7 @@ }), new Separator(), new MenuItem(() => `Source Code ${isPetBoostActive() ? " ❤" : ""}`, () => { window.open("https://github.com/IdreesInc/Pocket-Bird"); }), - new MenuItem("2026.3.30", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.3.30"); }, false), + new MenuItem("Build 2026.4.3", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.4.3"); }, undefined, false), ]; /** @type {Birb} */ @@ -3211,7 +3296,7 @@ latinName.textContent = type.latinName; latinName.href = type.url; latinName.target = "_blank"; - + const spacerTwo = document.createElement("div"); spacerTwo.style.height = "0.4em"; diff --git a/dist/web/birb.js b/dist/web/birb.js index 978f444..829a758 100644 --- a/dist/web/birb.js +++ b/dist/web/birb.js @@ -622,8 +622,8 @@ "url": "https://en.wikipedia.org/wiki/Cuban_tody", "colors": { "beak": "#f16f54", - "face": "#5fdf44", - "chin": "#f12d3e", + "face": "#5ad63e", + "chin": "#e8273b", "collar": "#f12d3e", "belly": "#f6f5e4", "collar-scruff": "#a3ebff", @@ -644,11 +644,14 @@ "colors": { "face": "#9c3af2", "wing": "#8f37ed", - "wing-edge": "#7029b8", + "wing-edge": "#5b20c2", "belly": "#ffffff", "underbelly": "#f2f2f2", "foot": "#736a66", - "collar": "#aa60e6" + "collar": "#b760e6", + "nose": "#7a2ec7", + "cheek": "#7a2ec7", + "nose-tip": "#7a2ec7" }, "rarity": "uncommon" } @@ -1920,11 +1923,13 @@ /** * @param {string|(() => string)} text * @param {() => void} action + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, removeMenu = true) { + constructor(text, action, icon, removeMenu = true) { this.text = text; this.action = action; + this.icon = icon; this.removeMenu = removeMenu; } } @@ -1934,10 +1939,11 @@ * @param {string} text * @param {() => void} action * @param {() => boolean} condition + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, condition, removeMenu = true) { - super(text, action, removeMenu); + constructor(text, action, condition, icon, removeMenu = true) { + super(text, action, icon, removeMenu); this.condition = condition; } } @@ -1948,7 +1954,7 @@ * @param {() => void} action */ constructor(text, action, removeMenu = true) { - super(text, action, () => isDebug(), removeMenu); + super(text, action, () => isDebug(), undefined, removeMenu); } } @@ -1963,11 +1969,29 @@ * @param {() => void} removeMenuCallback * @returns {HTMLElement} */ - function makeMenuItem(item, removeMenuCallback) { + function createMenuItem(item, removeMenuCallback) { if (item instanceof Separator) { return makeElement("birb-window-separator"); } let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text); + if (item.icon) { + const iconCanvas = document.createElement("canvas"); + iconCanvas.width = 7; + iconCanvas.height = 6; + iconCanvas.classList.add("birb-menu-item-icon"); + const ctx = iconCanvas.getContext("2d"); + if (ctx) { + for (let row = 0; row < item.icon.length; row++) { + for (let col = 0; col < item.icon[row].length; col++) { + if (item.icon[row][col]) { + ctx.fillStyle = "black"; + ctx.fillRect(col, row, 1, 1); + } + } + } + } + menuItem.prepend(iconCanvas); + } onClick(menuItem, () => { if (item.removeMenu) { removeMenuCallback(); @@ -1995,7 +2019,7 @@ const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } menu.appendChild(header); @@ -2052,7 +2076,7 @@ const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } updateLocationCallback(menu); @@ -2303,15 +2327,17 @@ font-size: 14px; padding-top: 4px; padding-bottom: 4px; - padding-left: 10px; + padding-left: 2px; padding-right: 10px; box-sizing: border-box; opacity: 0.7 !important; user-select: none; display: flex; - justify-content: space-between; + justify-content: left; + align-items: center; cursor: pointer; color: black !important; + transition: background 0.1s, color 0.1s; } .birb-menu-item:hover { @@ -2323,6 +2349,21 @@ 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); + transition: none; +} + +.birb-menu-item-icon { + width: calc(7 * var(--birb-border-size)); + height: calc(6 * var(--birb-border-size)); + padding-right: calc(5 * var(--birb-border-size)); + flex-shrink: 0; + image-rendering: pixelated; + color: var(--birb-highlight); + opacity: 0.9; +} + +.birb-menu-item:hover > .birb-menu-item-icon { + filter: invert(1); } .birb-menu-item-arrow { @@ -2373,10 +2414,12 @@ justify-content: center; align-items: center; cursor: pointer; + transition: border-color 0.1s; } .birb-grid-item:hover { border-color: var(--birb-highlight); + transition: none; } .birb-grid-item canvas { @@ -2583,12 +2626,47 @@ }; const menuItems = [ - new MenuItem(`Pet ${birdBirb()}`, pet), - new MenuItem("Field Guide", insertFieldGuide), - new MenuItem("Wardrobe", insertWardrobe), - new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled()), - new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), - new DebugMenuItem("Freeze/Unfreeze", () => { + new MenuItem(`Pet ${birdBirb()}`, pet, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + ]), + new MenuItem("Field Guide", insertFieldGuide, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 1, 0, 1, 1, 1], + ]), + new MenuItem("Wardrobe", insertWardrobe, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 0, 0, 0, 1, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 1, 1, 1, 1, 0], + ]), + new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled(), [ + [0, 0, 1, 1, 1, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [1, 0, 0, 1, 0, 1, 0], + [1, 0, 1, 0, 0, 1, 0], + [1, 0, 0, 0, 0, 1, 0], + [1, 1, 1, 1, 1, 1, 0], + ]), + new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false), [ + [0, 1, 0, 1, 0, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 1, 1, 0, 0], + ]), + new DebugMenuItem("Freeze", () => { frozen = !frozen; }), new DebugMenuItem("Reset Data", resetSaveData), @@ -2607,11 +2685,18 @@ setDebug(false); }), new Separator(), - new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), false), + new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), [ + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 1, 1, 0, 1], + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + [1, 0, 1, 1, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + ], false), ]; const settingsItems = [ - new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false), + new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), undefined, false), new Separator(), new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => { userSettings.soundEnabled = !settings().soundEnabled; @@ -2631,7 +2716,7 @@ }), new Separator(), new MenuItem(() => `Source Code ${isPetBoostActive() ? " ❤" : ""}`, () => { window.open("https://github.com/IdreesInc/Pocket-Bird"); }), - new MenuItem("2026.3.30", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.3.30"); }, false), + new MenuItem("Build 2026.4.3", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.4.3"); }, undefined, false), ]; /** @type {Birb} */ @@ -3211,7 +3296,7 @@ latinName.textContent = type.latinName; latinName.href = type.url; latinName.target = "_blank"; - + const spacerTwo = document.createElement("div"); spacerTwo.style.height = "0.4em"; diff --git a/src/application.js b/src/application.js index ed63e93..e1123aa 100644 --- a/src/application.js +++ b/src/application.js @@ -169,12 +169,47 @@ function startApplication(birbPixels, featherPixels, hatsPixels) { }; const menuItems = [ - new MenuItem(`Pet ${birdBirb()}`, pet), - new MenuItem("Field Guide", insertFieldGuide), - new MenuItem("Wardrobe", insertWardrobe), - new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled()), - new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false)), - new DebugMenuItem("Freeze/Unfreeze", () => { + new MenuItem(`Pet ${birdBirb()}`, pet, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + ]), + new MenuItem("Field Guide", insertFieldGuide, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 1, 0, 1, 1, 1], + ]), + new MenuItem("Wardrobe", insertWardrobe, [ + [0, 1, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 1, 0, 0, 0, 1, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [0, 1, 1, 1, 1, 1, 0], + ]), + new ConditionalMenuItem("Sticky Note", () => createNewStickyNote(stickyNotes, save, deleteStickyNote), () => getContext().areStickyNotesEnabled(), [ + [0, 0, 1, 1, 1, 1, 0], + [0, 1, 0, 0, 0, 1, 0], + [1, 0, 0, 1, 0, 1, 0], + [1, 0, 1, 0, 0, 1, 0], + [1, 0, 0, 0, 0, 1, 0], + [1, 1, 1, 1, 1, 1, 0], + ]), + new MenuItem(`Hide ${birdBirb()}`, () => birb.setVisible(false), [ + [0, 1, 0, 1, 0, 1, 0], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 0, 1, 0], + [0, 0, 1, 1, 1, 0, 0], + ]), + new DebugMenuItem("Freeze", () => { frozen = !frozen; }), new DebugMenuItem("Reset Data", resetSaveData), @@ -193,11 +228,18 @@ function startApplication(birbPixels, featherPixels, hatsPixels) { setDebug(false); }), new Separator(), - new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), false), + new MenuItem("Settings", () => switchMenuItems(settingsItems, updateMenuLocation), [ + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 1, 1, 0, 1], + [0, 0, 0, 0, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + [1, 0, 1, 1, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 0], + ], false), ]; const settingsItems = [ - new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false), + new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), undefined, false), new Separator(), new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => { userSettings.soundEnabled = !settings().soundEnabled; @@ -217,7 +259,7 @@ function startApplication(birbPixels, featherPixels, hatsPixels) { }), new Separator(), new MenuItem(() => `Source Code ${isPetBoostActive() ? " ❤" : ""}`, () => { window.open("https://github.com/IdreesInc/Pocket-Bird"); }), - new MenuItem("__VERSION__", () => { alert("Thank you for using Pocket Bird! You are on version: __VERSION__") }, false), + new MenuItem("Build __VERSION__", () => { alert("Thank you for using Pocket Bird! You are on version: __VERSION__") }, undefined, false), ]; /** @type {Birb} */ @@ -801,7 +843,7 @@ function startApplication(birbPixels, featherPixels, hatsPixels) { latinName.textContent = type.latinName; latinName.href = type.url; latinName.target = "_blank"; - + const spacerTwo = document.createElement("div"); spacerTwo.style.height = "0.4em"; diff --git a/src/menu.js b/src/menu.js index 09b7878..fc41098 100644 --- a/src/menu.js +++ b/src/menu.js @@ -14,11 +14,13 @@ export class MenuItem { /** * @param {string|(() => string)} text * @param {() => void} action + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, removeMenu = true) { + constructor(text, action, icon, removeMenu = true) { this.text = text; this.action = action; + this.icon = icon; this.removeMenu = removeMenu; } } @@ -28,10 +30,11 @@ export class ConditionalMenuItem extends MenuItem { * @param {string} text * @param {() => void} action * @param {() => boolean} condition + * @param {number[][]} [icon] * @param {boolean} [removeMenu] */ - constructor(text, action, condition, removeMenu = true) { - super(text, action, removeMenu); + constructor(text, action, condition, icon, removeMenu = true) { + super(text, action, icon, removeMenu); this.condition = condition; } } @@ -42,7 +45,7 @@ export class DebugMenuItem extends ConditionalMenuItem { * @param {() => void} action */ constructor(text, action, removeMenu = true) { - super(text, action, () => isDebug(), removeMenu); + super(text, action, () => isDebug(), undefined, removeMenu); } } @@ -57,11 +60,29 @@ export class Separator extends MenuItem { * @param {() => void} removeMenuCallback * @returns {HTMLElement} */ -function makeMenuItem(item, removeMenuCallback) { +function createMenuItem(item, removeMenuCallback) { if (item instanceof Separator) { return makeElement("birb-window-separator"); } let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text); + if (item.icon) { + const iconCanvas = document.createElement("canvas"); + iconCanvas.width = 7; + iconCanvas.height = 6; + iconCanvas.classList.add("birb-menu-item-icon"); + const ctx = iconCanvas.getContext("2d"); + if (ctx) { + for (let row = 0; row < item.icon.length; row++) { + for (let col = 0; col < item.icon[row].length; col++) { + if (item.icon[row][col]) { + ctx.fillStyle = "black"; + ctx.fillRect(col, row, 1, 1); + } + } + } + } + menuItem.prepend(iconCanvas); + } onClick(menuItem, () => { if (item.removeMenu) { removeMenuCallback(); @@ -89,7 +110,7 @@ export function insertMenu(menuItems, title, updateLocationCallback) { const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } menu.appendChild(header); @@ -146,7 +167,7 @@ export function switchMenuItems(menuItems, updateLocationCallback) { const removeCallback = () => removeMenu(); for (const item of menuItems) { if (!(item instanceof ConditionalMenuItem) || item.condition()) { - content.appendChild(makeMenuItem(item, removeCallback)); + content.appendChild(createMenuItem(item, removeCallback)); } } updateLocationCallback(menu); diff --git a/src/species.js b/src/species.js index d92a7e9..885e45c 100644 --- a/src/species.js +++ b/src/species.js @@ -394,8 +394,8 @@ export default { "url": "https://en.wikipedia.org/wiki/Cuban_tody", "colors": { "beak": "#f16f54", - "face": "#5fdf44", - "chin": "#f12d3e", + "face": "#5ad63e", + "chin": "#e8273b", "collar": "#f12d3e", "belly": "#f6f5e4", "collar-scruff": "#a3ebff", @@ -416,11 +416,14 @@ export default { "colors": { "face": "#9c3af2", "wing": "#8f37ed", - "wing-edge": "#7029b8", + "wing-edge": "#5b20c2", "belly": "#ffffff", "underbelly": "#f2f2f2", "foot": "#736a66", - "collar": "#aa60e6" + "collar": "#b760e6", + "nose": "#7a2ec7", + "cheek": "#7a2ec7", + "nose-tip": "#7a2ec7" }, "rarity": "uncommon" } diff --git a/src/stylesheet.css b/src/stylesheet.css index 37a7ab6..15dad68 100644 --- a/src/stylesheet.css +++ b/src/stylesheet.css @@ -211,15 +211,17 @@ font-size: 14px; padding-top: 4px; padding-bottom: 4px; - padding-left: 10px; + padding-left: 2px; padding-right: 10px; box-sizing: border-box; opacity: 0.7 !important; user-select: none; display: flex; - justify-content: space-between; + justify-content: left; + align-items: center; cursor: pointer; color: black !important; + transition: background 0.1s, color 0.1s; } .birb-menu-item:hover { @@ -231,6 +233,21 @@ 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); + transition: none; +} + +.birb-menu-item-icon { + width: calc(7 * var(--birb-border-size)); + height: calc(6 * var(--birb-border-size)); + padding-right: calc(5 * var(--birb-border-size)); + flex-shrink: 0; + image-rendering: pixelated; + color: var(--birb-highlight); + opacity: 0.9; +} + +.birb-menu-item:hover > .birb-menu-item-icon { + filter: invert(1); } .birb-menu-item-arrow { @@ -281,10 +298,12 @@ justify-content: center; align-items: center; cursor: pointer; + transition: border-color 0.1s; } .birb-grid-item:hover { border-color: var(--birb-highlight); + transition: none; } .birb-grid-item canvas {