Update colors and add icons

This commit is contained in:
Idrees Hassan
2026-04-03 19:06:28 -07:00
parent 2f3d7958ea
commit 85ade65a57
12 changed files with 652 additions and 142 deletions

BIN
dist/extension.zip vendored

Binary file not shown.

131
dist/extension/birb.js vendored
View File

@@ -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";

View File

@@ -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",

133
dist/obsidian/main.js vendored
View File

@@ -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";

View File

@@ -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",

View File

@@ -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";

131
dist/web/birb.embed.js vendored
View File

@@ -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";

131
dist/web/birb.js vendored
View File

@@ -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";

View File

@@ -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";

View File

@@ -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);

View File

@@ -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"
}

View File

@@ -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 {