mirror of
https://github.com/NohamR/Pocket-Bird.git
synced 2026-05-25 12:17:22 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47b418324c | ||
|
|
e5956426d5 | ||
|
|
0cc06a8856 | ||
|
|
dd4184f642 | ||
|
|
5a82ba858f |
BIN
dist/extension.zip
vendored
BIN
dist/extension.zip
vendored
Binary file not shown.
73
dist/extension/birb.js
vendored
73
dist/extension/birb.js
vendored
@@ -857,6 +857,50 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
class Birdsong {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {AudioContext}
|
||||||
|
*/
|
||||||
|
audioContext;
|
||||||
|
|
||||||
|
chirp() {
|
||||||
|
if (!this.audioContext) {
|
||||||
|
this.audioContext = new AudioContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
const TIMES = [0, 0.06, 0.10, 0.15];
|
||||||
|
const FREQUENCIES = [2200,
|
||||||
|
3500 + Math.random() * 600,
|
||||||
|
2100 + Math.random() * 200,
|
||||||
|
1600 + Math.random() * 400];
|
||||||
|
const VOLUMES = [0.0001, 0.3, 0.3, 0.0001];
|
||||||
|
|
||||||
|
const oscillator = this.audioContext.createOscillator();
|
||||||
|
oscillator.type = "sine";
|
||||||
|
const gain = this.audioContext.createGain();
|
||||||
|
oscillator.connect(gain);
|
||||||
|
gain.connect(this.audioContext.destination);
|
||||||
|
|
||||||
|
const now = this.audioContext.currentTime;
|
||||||
|
for (let i = 0; i < TIMES.length; i++) {
|
||||||
|
const time = TIMES[i] + now;
|
||||||
|
if (i === 0) {
|
||||||
|
oscillator.frequency.setValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.setValueAtTime(VOLUMES[i], time);
|
||||||
|
} else {
|
||||||
|
oscillator.frequency.exponentialRampToValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.exponentialRampToValueAtTime(VOLUMES[i], time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oscillator.start(now);
|
||||||
|
oscillator.stop(now + TIMES[TIMES.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const SAVE_KEY = "birbSaveData";
|
const SAVE_KEY = "birbSaveData";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1165,7 +1209,7 @@
|
|||||||
|
|
||||||
class MenuItem {
|
class MenuItem {
|
||||||
/**
|
/**
|
||||||
* @param {string} text
|
* @param {string|(() => string)} text
|
||||||
* @param {() => void} action
|
* @param {() => void} action
|
||||||
* @param {boolean} [removeMenu]
|
* @param {boolean} [removeMenu]
|
||||||
*/
|
*/
|
||||||
@@ -1214,7 +1258,7 @@
|
|||||||
if (item instanceof Separator) {
|
if (item instanceof Separator) {
|
||||||
return makeElement("birb-window-separator");
|
return makeElement("birb-window-separator");
|
||||||
}
|
}
|
||||||
let menuItem = makeElement("birb-menu-item", item.text);
|
let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text);
|
||||||
onClick(menuItem, () => {
|
onClick(menuItem, () => {
|
||||||
if (item.removeMenu) {
|
if (item.removeMenu) {
|
||||||
removeMenuCallback();
|
removeMenuCallback();
|
||||||
@@ -1321,7 +1365,8 @@
|
|||||||
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
||||||
*/
|
*/
|
||||||
const DEFAULT_SETTINGS = {
|
const DEFAULT_SETTINGS = {
|
||||||
birbMode: false
|
birbMode: false,
|
||||||
|
soundEnabled: true
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rendering constants
|
// Rendering constants
|
||||||
@@ -1534,6 +1579,7 @@
|
|||||||
|
|
||||||
.birb-menu-item {
|
.birb-menu-item {
|
||||||
width: calc(100% - var(--birb-double-border-size));
|
width: calc(100% - var(--birb-double-border-size));
|
||||||
|
white-space: nowrap;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
@@ -1806,12 +1852,16 @@
|
|||||||
const settingsItems = [
|
const settingsItems = [
|
||||||
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
new MenuItem("Toggle Birb Mode", () => {
|
new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => {
|
||||||
userSettings.birbMode = !userSettings.birbMode;
|
userSettings.soundEnabled = !settings().soundEnabled;
|
||||||
|
save();
|
||||||
|
}),
|
||||||
|
new MenuItem(() => `Toggle ${birdBirb(true)} Mode`, () => {
|
||||||
|
userSettings.birbMode = !settings().birbMode;
|
||||||
save();
|
save();
|
||||||
const message = makeElement("birb-message-content");
|
const message = makeElement("birb-message-content");
|
||||||
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
||||||
if (userSettings.birbMode) {
|
if (settings().birbMode) {
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
||||||
@@ -1819,7 +1869,7 @@
|
|||||||
insertModal(`${birdBirb()} Mode`, message);
|
insertModal(`${birdBirb()} Mode`, message);
|
||||||
}),
|
}),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
new MenuItem("2026.1.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.1.1"); }, false),
|
new MenuItem("2026.1.4", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.1.4"); }, false),
|
||||||
];
|
];
|
||||||
|
|
||||||
const styleElement = document.createElement("style");
|
const styleElement = document.createElement("style");
|
||||||
@@ -1833,6 +1883,8 @@
|
|||||||
FLYING: "flying",
|
FLYING: "flying",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const birdsong = new Birdsong();
|
||||||
|
|
||||||
let frozen = false;
|
let frozen = false;
|
||||||
let stateStart = Date.now();
|
let stateStart = Date.now();
|
||||||
let currentState = States.IDLE;
|
let currentState = States.IDLE;
|
||||||
@@ -1923,8 +1975,8 @@
|
|||||||
/**
|
/**
|
||||||
* Bird or birb, you decide
|
* Bird or birb, you decide
|
||||||
*/
|
*/
|
||||||
function birdBirb() {
|
function birdBirb(invert = false) {
|
||||||
return settings().birbMode ? "Birb" : "Bird";
|
return settings().birbMode !== invert ? "Birb" : "Bird";
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
@@ -2513,6 +2565,9 @@
|
|||||||
|
|
||||||
function pet() {
|
function pet() {
|
||||||
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
||||||
|
if (settings().soundEnabled) {
|
||||||
|
birdsong.chirp();
|
||||||
|
}
|
||||||
birb.setAnimation(Animations.HEART);
|
birb.setAnimation(Animations.HEART);
|
||||||
lastPetTimestamp = Date.now();
|
lastPetTimestamp = Date.now();
|
||||||
}
|
}
|
||||||
|
|||||||
2
dist/extension/manifest.json
vendored
2
dist/extension/manifest.json
vendored
@@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "Pocket Bird",
|
"name": "Pocket Bird",
|
||||||
"description": "It's a pet bird in your browser, what more could you want?",
|
"description": "It's a pet bird in your browser, what more could you want?",
|
||||||
"version": "2026.1.1",
|
"version": "2026.1.4",
|
||||||
"homepage_url": "https://idreesinc.com",
|
"homepage_url": "https://idreesinc.com",
|
||||||
"icons": {
|
"icons": {
|
||||||
"48": "images/icons/transparent/48x48x1.png",
|
"48": "images/icons/transparent/48x48x1.png",
|
||||||
|
|||||||
75
dist/obsidian/main.js
vendored
75
dist/obsidian/main.js
vendored
@@ -1,7 +1,7 @@
|
|||||||
const { Plugin, Notice } = require('obsidian');
|
const { Plugin, Notice } = require('obsidian');
|
||||||
module.exports = class PocketBird extends Plugin {
|
module.exports = class PocketBird extends Plugin {
|
||||||
onload() {
|
onload() {
|
||||||
console.log("Loading Pocket Bird version 2026.1.1...");
|
console.log("Loading Pocket Bird version 2026.1.4...");
|
||||||
const OBSIDIAN_PLUGIN = this;
|
const OBSIDIAN_PLUGIN = this;
|
||||||
(function () {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
@@ -862,6 +862,50 @@ module.exports = class PocketBird extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
class Birdsong {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {AudioContext}
|
||||||
|
*/
|
||||||
|
audioContext;
|
||||||
|
|
||||||
|
chirp() {
|
||||||
|
if (!this.audioContext) {
|
||||||
|
this.audioContext = new AudioContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
const TIMES = [0, 0.06, 0.10, 0.15];
|
||||||
|
const FREQUENCIES = [2200,
|
||||||
|
3500 + Math.random() * 600,
|
||||||
|
2100 + Math.random() * 200,
|
||||||
|
1600 + Math.random() * 400];
|
||||||
|
const VOLUMES = [0.0001, 0.3, 0.3, 0.0001];
|
||||||
|
|
||||||
|
const oscillator = this.audioContext.createOscillator();
|
||||||
|
oscillator.type = "sine";
|
||||||
|
const gain = this.audioContext.createGain();
|
||||||
|
oscillator.connect(gain);
|
||||||
|
gain.connect(this.audioContext.destination);
|
||||||
|
|
||||||
|
const now = this.audioContext.currentTime;
|
||||||
|
for (let i = 0; i < TIMES.length; i++) {
|
||||||
|
const time = TIMES[i] + now;
|
||||||
|
if (i === 0) {
|
||||||
|
oscillator.frequency.setValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.setValueAtTime(VOLUMES[i], time);
|
||||||
|
} else {
|
||||||
|
oscillator.frequency.exponentialRampToValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.exponentialRampToValueAtTime(VOLUMES[i], time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oscillator.start(now);
|
||||||
|
oscillator.stop(now + TIMES[TIMES.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const ROOT_PATH = "";
|
const ROOT_PATH = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1208,7 +1252,7 @@ module.exports = class PocketBird extends Plugin {
|
|||||||
|
|
||||||
class MenuItem {
|
class MenuItem {
|
||||||
/**
|
/**
|
||||||
* @param {string} text
|
* @param {string|(() => string)} text
|
||||||
* @param {() => void} action
|
* @param {() => void} action
|
||||||
* @param {boolean} [removeMenu]
|
* @param {boolean} [removeMenu]
|
||||||
*/
|
*/
|
||||||
@@ -1257,7 +1301,7 @@ module.exports = class PocketBird extends Plugin {
|
|||||||
if (item instanceof Separator) {
|
if (item instanceof Separator) {
|
||||||
return makeElement("birb-window-separator");
|
return makeElement("birb-window-separator");
|
||||||
}
|
}
|
||||||
let menuItem = makeElement("birb-menu-item", item.text);
|
let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text);
|
||||||
onClick(menuItem, () => {
|
onClick(menuItem, () => {
|
||||||
if (item.removeMenu) {
|
if (item.removeMenu) {
|
||||||
removeMenuCallback();
|
removeMenuCallback();
|
||||||
@@ -1364,7 +1408,8 @@ module.exports = class PocketBird extends Plugin {
|
|||||||
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
||||||
*/
|
*/
|
||||||
const DEFAULT_SETTINGS = {
|
const DEFAULT_SETTINGS = {
|
||||||
birbMode: false
|
birbMode: false,
|
||||||
|
soundEnabled: true
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rendering constants
|
// Rendering constants
|
||||||
@@ -1577,6 +1622,7 @@ module.exports = class PocketBird extends Plugin {
|
|||||||
|
|
||||||
.birb-menu-item {
|
.birb-menu-item {
|
||||||
width: calc(100% - var(--birb-double-border-size));
|
width: calc(100% - var(--birb-double-border-size));
|
||||||
|
white-space: nowrap;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
@@ -1849,12 +1895,16 @@ module.exports = class PocketBird extends Plugin {
|
|||||||
const settingsItems = [
|
const settingsItems = [
|
||||||
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
new MenuItem("Toggle Birb Mode", () => {
|
new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => {
|
||||||
userSettings.birbMode = !userSettings.birbMode;
|
userSettings.soundEnabled = !settings().soundEnabled;
|
||||||
|
save();
|
||||||
|
}),
|
||||||
|
new MenuItem(() => `Toggle ${birdBirb(true)} Mode`, () => {
|
||||||
|
userSettings.birbMode = !settings().birbMode;
|
||||||
save();
|
save();
|
||||||
const message = makeElement("birb-message-content");
|
const message = makeElement("birb-message-content");
|
||||||
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
||||||
if (userSettings.birbMode) {
|
if (settings().birbMode) {
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
||||||
@@ -1862,7 +1912,7 @@ module.exports = class PocketBird extends Plugin {
|
|||||||
insertModal(`${birdBirb()} Mode`, message);
|
insertModal(`${birdBirb()} Mode`, message);
|
||||||
}),
|
}),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
new MenuItem("2026.1.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.1.1"); }, false),
|
new MenuItem("2026.1.4", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.1.4"); }, false),
|
||||||
];
|
];
|
||||||
|
|
||||||
const styleElement = document.createElement("style");
|
const styleElement = document.createElement("style");
|
||||||
@@ -1876,6 +1926,8 @@ module.exports = class PocketBird extends Plugin {
|
|||||||
FLYING: "flying",
|
FLYING: "flying",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const birdsong = new Birdsong();
|
||||||
|
|
||||||
let frozen = false;
|
let frozen = false;
|
||||||
let stateStart = Date.now();
|
let stateStart = Date.now();
|
||||||
let currentState = States.IDLE;
|
let currentState = States.IDLE;
|
||||||
@@ -1966,8 +2018,8 @@ module.exports = class PocketBird extends Plugin {
|
|||||||
/**
|
/**
|
||||||
* Bird or birb, you decide
|
* Bird or birb, you decide
|
||||||
*/
|
*/
|
||||||
function birdBirb() {
|
function birdBirb(invert = false) {
|
||||||
return settings().birbMode ? "Birb" : "Bird";
|
return settings().birbMode !== invert ? "Birb" : "Bird";
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
@@ -2556,6 +2608,9 @@ module.exports = class PocketBird extends Plugin {
|
|||||||
|
|
||||||
function pet() {
|
function pet() {
|
||||||
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
||||||
|
if (settings().soundEnabled) {
|
||||||
|
birdsong.chirp();
|
||||||
|
}
|
||||||
birb.setAnimation(Animations.HEART);
|
birb.setAnimation(Animations.HEART);
|
||||||
lastPetTimestamp = Date.now();
|
lastPetTimestamp = Date.now();
|
||||||
}
|
}
|
||||||
|
|||||||
2
dist/obsidian/manifest.json
vendored
2
dist/obsidian/manifest.json
vendored
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "pocket-bird",
|
"id": "pocket-bird",
|
||||||
"name": "Pocket Bird",
|
"name": "Pocket Bird",
|
||||||
"version": "2026.1.1",
|
"version": "2026.1.4",
|
||||||
"minAppVersion": "0.15.0",
|
"minAppVersion": "0.15.0",
|
||||||
"description": "Add a pet bird to fly around your notes and keep you company!",
|
"description": "Add a pet bird to fly around your notes and keep you company!",
|
||||||
"author": "Idrees Hassan",
|
"author": "Idrees Hassan",
|
||||||
|
|||||||
75
dist/userscript/birb.user.js
vendored
75
dist/userscript/birb.user.js
vendored
@@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Pocket Bird
|
// @name Pocket Bird
|
||||||
// @namespace https://idreesinc.com
|
// @namespace https://idreesinc.com
|
||||||
// @version 2026.1.1
|
// @version 2026.1.4
|
||||||
// @description It's a pet bird in your browser, what more could you want?
|
// @description It's a pet bird in your browser, what more could you want?
|
||||||
// @author Idrees
|
// @author Idrees
|
||||||
// @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js
|
// @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/userscript/birb.user.js
|
||||||
@@ -871,6 +871,50 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
class Birdsong {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {AudioContext}
|
||||||
|
*/
|
||||||
|
audioContext;
|
||||||
|
|
||||||
|
chirp() {
|
||||||
|
if (!this.audioContext) {
|
||||||
|
this.audioContext = new AudioContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
const TIMES = [0, 0.06, 0.10, 0.15];
|
||||||
|
const FREQUENCIES = [2200,
|
||||||
|
3500 + Math.random() * 600,
|
||||||
|
2100 + Math.random() * 200,
|
||||||
|
1600 + Math.random() * 400];
|
||||||
|
const VOLUMES = [0.0001, 0.3, 0.3, 0.0001];
|
||||||
|
|
||||||
|
const oscillator = this.audioContext.createOscillator();
|
||||||
|
oscillator.type = "sine";
|
||||||
|
const gain = this.audioContext.createGain();
|
||||||
|
oscillator.connect(gain);
|
||||||
|
gain.connect(this.audioContext.destination);
|
||||||
|
|
||||||
|
const now = this.audioContext.currentTime;
|
||||||
|
for (let i = 0; i < TIMES.length; i++) {
|
||||||
|
const time = TIMES[i] + now;
|
||||||
|
if (i === 0) {
|
||||||
|
oscillator.frequency.setValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.setValueAtTime(VOLUMES[i], time);
|
||||||
|
} else {
|
||||||
|
oscillator.frequency.exponentialRampToValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.exponentialRampToValueAtTime(VOLUMES[i], time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oscillator.start(now);
|
||||||
|
oscillator.stop(now + TIMES[TIMES.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const SAVE_KEY = "birbSaveData";
|
const SAVE_KEY = "birbSaveData";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1170,7 +1214,7 @@
|
|||||||
|
|
||||||
class MenuItem {
|
class MenuItem {
|
||||||
/**
|
/**
|
||||||
* @param {string} text
|
* @param {string|(() => string)} text
|
||||||
* @param {() => void} action
|
* @param {() => void} action
|
||||||
* @param {boolean} [removeMenu]
|
* @param {boolean} [removeMenu]
|
||||||
*/
|
*/
|
||||||
@@ -1219,7 +1263,7 @@
|
|||||||
if (item instanceof Separator) {
|
if (item instanceof Separator) {
|
||||||
return makeElement("birb-window-separator");
|
return makeElement("birb-window-separator");
|
||||||
}
|
}
|
||||||
let menuItem = makeElement("birb-menu-item", item.text);
|
let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text);
|
||||||
onClick(menuItem, () => {
|
onClick(menuItem, () => {
|
||||||
if (item.removeMenu) {
|
if (item.removeMenu) {
|
||||||
removeMenuCallback();
|
removeMenuCallback();
|
||||||
@@ -1326,7 +1370,8 @@
|
|||||||
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
||||||
*/
|
*/
|
||||||
const DEFAULT_SETTINGS = {
|
const DEFAULT_SETTINGS = {
|
||||||
birbMode: false
|
birbMode: false,
|
||||||
|
soundEnabled: true
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rendering constants
|
// Rendering constants
|
||||||
@@ -1539,6 +1584,7 @@
|
|||||||
|
|
||||||
.birb-menu-item {
|
.birb-menu-item {
|
||||||
width: calc(100% - var(--birb-double-border-size));
|
width: calc(100% - var(--birb-double-border-size));
|
||||||
|
white-space: nowrap;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
@@ -1811,12 +1857,16 @@
|
|||||||
const settingsItems = [
|
const settingsItems = [
|
||||||
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
new MenuItem("Toggle Birb Mode", () => {
|
new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => {
|
||||||
userSettings.birbMode = !userSettings.birbMode;
|
userSettings.soundEnabled = !settings().soundEnabled;
|
||||||
|
save();
|
||||||
|
}),
|
||||||
|
new MenuItem(() => `Toggle ${birdBirb(true)} Mode`, () => {
|
||||||
|
userSettings.birbMode = !settings().birbMode;
|
||||||
save();
|
save();
|
||||||
const message = makeElement("birb-message-content");
|
const message = makeElement("birb-message-content");
|
||||||
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
||||||
if (userSettings.birbMode) {
|
if (settings().birbMode) {
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
||||||
@@ -1824,7 +1874,7 @@
|
|||||||
insertModal(`${birdBirb()} Mode`, message);
|
insertModal(`${birdBirb()} Mode`, message);
|
||||||
}),
|
}),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
new MenuItem("2026.1.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.1.1"); }, false),
|
new MenuItem("2026.1.4", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.1.4"); }, false),
|
||||||
];
|
];
|
||||||
|
|
||||||
const styleElement = document.createElement("style");
|
const styleElement = document.createElement("style");
|
||||||
@@ -1838,6 +1888,8 @@
|
|||||||
FLYING: "flying",
|
FLYING: "flying",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const birdsong = new Birdsong();
|
||||||
|
|
||||||
let frozen = false;
|
let frozen = false;
|
||||||
let stateStart = Date.now();
|
let stateStart = Date.now();
|
||||||
let currentState = States.IDLE;
|
let currentState = States.IDLE;
|
||||||
@@ -1928,8 +1980,8 @@
|
|||||||
/**
|
/**
|
||||||
* Bird or birb, you decide
|
* Bird or birb, you decide
|
||||||
*/
|
*/
|
||||||
function birdBirb() {
|
function birdBirb(invert = false) {
|
||||||
return settings().birbMode ? "Birb" : "Bird";
|
return settings().birbMode !== invert ? "Birb" : "Bird";
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
@@ -2518,6 +2570,9 @@
|
|||||||
|
|
||||||
function pet() {
|
function pet() {
|
||||||
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
||||||
|
if (settings().soundEnabled) {
|
||||||
|
birdsong.chirp();
|
||||||
|
}
|
||||||
birb.setAnimation(Animations.HEART);
|
birb.setAnimation(Animations.HEART);
|
||||||
lastPetTimestamp = Date.now();
|
lastPetTimestamp = Date.now();
|
||||||
}
|
}
|
||||||
|
|||||||
73
dist/web/birb.embed.js
vendored
73
dist/web/birb.embed.js
vendored
@@ -857,6 +857,50 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
class Birdsong {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {AudioContext}
|
||||||
|
*/
|
||||||
|
audioContext;
|
||||||
|
|
||||||
|
chirp() {
|
||||||
|
if (!this.audioContext) {
|
||||||
|
this.audioContext = new AudioContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
const TIMES = [0, 0.06, 0.10, 0.15];
|
||||||
|
const FREQUENCIES = [2200,
|
||||||
|
3500 + Math.random() * 600,
|
||||||
|
2100 + Math.random() * 200,
|
||||||
|
1600 + Math.random() * 400];
|
||||||
|
const VOLUMES = [0.0001, 0.3, 0.3, 0.0001];
|
||||||
|
|
||||||
|
const oscillator = this.audioContext.createOscillator();
|
||||||
|
oscillator.type = "sine";
|
||||||
|
const gain = this.audioContext.createGain();
|
||||||
|
oscillator.connect(gain);
|
||||||
|
gain.connect(this.audioContext.destination);
|
||||||
|
|
||||||
|
const now = this.audioContext.currentTime;
|
||||||
|
for (let i = 0; i < TIMES.length; i++) {
|
||||||
|
const time = TIMES[i] + now;
|
||||||
|
if (i === 0) {
|
||||||
|
oscillator.frequency.setValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.setValueAtTime(VOLUMES[i], time);
|
||||||
|
} else {
|
||||||
|
oscillator.frequency.exponentialRampToValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.exponentialRampToValueAtTime(VOLUMES[i], time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oscillator.start(now);
|
||||||
|
oscillator.stop(now + TIMES[TIMES.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const SAVE_KEY = "birbSaveData";
|
const SAVE_KEY = "birbSaveData";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1150,7 +1194,7 @@
|
|||||||
|
|
||||||
class MenuItem {
|
class MenuItem {
|
||||||
/**
|
/**
|
||||||
* @param {string} text
|
* @param {string|(() => string)} text
|
||||||
* @param {() => void} action
|
* @param {() => void} action
|
||||||
* @param {boolean} [removeMenu]
|
* @param {boolean} [removeMenu]
|
||||||
*/
|
*/
|
||||||
@@ -1199,7 +1243,7 @@
|
|||||||
if (item instanceof Separator) {
|
if (item instanceof Separator) {
|
||||||
return makeElement("birb-window-separator");
|
return makeElement("birb-window-separator");
|
||||||
}
|
}
|
||||||
let menuItem = makeElement("birb-menu-item", item.text);
|
let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text);
|
||||||
onClick(menuItem, () => {
|
onClick(menuItem, () => {
|
||||||
if (item.removeMenu) {
|
if (item.removeMenu) {
|
||||||
removeMenuCallback();
|
removeMenuCallback();
|
||||||
@@ -1306,7 +1350,8 @@
|
|||||||
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
||||||
*/
|
*/
|
||||||
const DEFAULT_SETTINGS = {
|
const DEFAULT_SETTINGS = {
|
||||||
birbMode: false
|
birbMode: false,
|
||||||
|
soundEnabled: true
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rendering constants
|
// Rendering constants
|
||||||
@@ -1519,6 +1564,7 @@
|
|||||||
|
|
||||||
.birb-menu-item {
|
.birb-menu-item {
|
||||||
width: calc(100% - var(--birb-double-border-size));
|
width: calc(100% - var(--birb-double-border-size));
|
||||||
|
white-space: nowrap;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
@@ -1791,12 +1837,16 @@
|
|||||||
const settingsItems = [
|
const settingsItems = [
|
||||||
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
new MenuItem("Toggle Birb Mode", () => {
|
new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => {
|
||||||
userSettings.birbMode = !userSettings.birbMode;
|
userSettings.soundEnabled = !settings().soundEnabled;
|
||||||
|
save();
|
||||||
|
}),
|
||||||
|
new MenuItem(() => `Toggle ${birdBirb(true)} Mode`, () => {
|
||||||
|
userSettings.birbMode = !settings().birbMode;
|
||||||
save();
|
save();
|
||||||
const message = makeElement("birb-message-content");
|
const message = makeElement("birb-message-content");
|
||||||
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
||||||
if (userSettings.birbMode) {
|
if (settings().birbMode) {
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
||||||
@@ -1804,7 +1854,7 @@
|
|||||||
insertModal(`${birdBirb()} Mode`, message);
|
insertModal(`${birdBirb()} Mode`, message);
|
||||||
}),
|
}),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
new MenuItem("2026.1.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.1.1"); }, false),
|
new MenuItem("2026.1.4", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.1.4"); }, false),
|
||||||
];
|
];
|
||||||
|
|
||||||
const styleElement = document.createElement("style");
|
const styleElement = document.createElement("style");
|
||||||
@@ -1818,6 +1868,8 @@
|
|||||||
FLYING: "flying",
|
FLYING: "flying",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const birdsong = new Birdsong();
|
||||||
|
|
||||||
let frozen = false;
|
let frozen = false;
|
||||||
let stateStart = Date.now();
|
let stateStart = Date.now();
|
||||||
let currentState = States.IDLE;
|
let currentState = States.IDLE;
|
||||||
@@ -1908,8 +1960,8 @@
|
|||||||
/**
|
/**
|
||||||
* Bird or birb, you decide
|
* Bird or birb, you decide
|
||||||
*/
|
*/
|
||||||
function birdBirb() {
|
function birdBirb(invert = false) {
|
||||||
return settings().birbMode ? "Birb" : "Bird";
|
return settings().birbMode !== invert ? "Birb" : "Bird";
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
@@ -2498,6 +2550,9 @@
|
|||||||
|
|
||||||
function pet() {
|
function pet() {
|
||||||
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
||||||
|
if (settings().soundEnabled) {
|
||||||
|
birdsong.chirp();
|
||||||
|
}
|
||||||
birb.setAnimation(Animations.HEART);
|
birb.setAnimation(Animations.HEART);
|
||||||
lastPetTimestamp = Date.now();
|
lastPetTimestamp = Date.now();
|
||||||
}
|
}
|
||||||
|
|||||||
73
dist/web/birb.js
vendored
73
dist/web/birb.js
vendored
@@ -857,6 +857,50 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
class Birdsong {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {AudioContext}
|
||||||
|
*/
|
||||||
|
audioContext;
|
||||||
|
|
||||||
|
chirp() {
|
||||||
|
if (!this.audioContext) {
|
||||||
|
this.audioContext = new AudioContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
const TIMES = [0, 0.06, 0.10, 0.15];
|
||||||
|
const FREQUENCIES = [2200,
|
||||||
|
3500 + Math.random() * 600,
|
||||||
|
2100 + Math.random() * 200,
|
||||||
|
1600 + Math.random() * 400];
|
||||||
|
const VOLUMES = [0.0001, 0.3, 0.3, 0.0001];
|
||||||
|
|
||||||
|
const oscillator = this.audioContext.createOscillator();
|
||||||
|
oscillator.type = "sine";
|
||||||
|
const gain = this.audioContext.createGain();
|
||||||
|
oscillator.connect(gain);
|
||||||
|
gain.connect(this.audioContext.destination);
|
||||||
|
|
||||||
|
const now = this.audioContext.currentTime;
|
||||||
|
for (let i = 0; i < TIMES.length; i++) {
|
||||||
|
const time = TIMES[i] + now;
|
||||||
|
if (i === 0) {
|
||||||
|
oscillator.frequency.setValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.setValueAtTime(VOLUMES[i], time);
|
||||||
|
} else {
|
||||||
|
oscillator.frequency.exponentialRampToValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.exponentialRampToValueAtTime(VOLUMES[i], time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oscillator.start(now);
|
||||||
|
oscillator.stop(now + TIMES[TIMES.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const SAVE_KEY = "birbSaveData";
|
const SAVE_KEY = "birbSaveData";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1150,7 +1194,7 @@
|
|||||||
|
|
||||||
class MenuItem {
|
class MenuItem {
|
||||||
/**
|
/**
|
||||||
* @param {string} text
|
* @param {string|(() => string)} text
|
||||||
* @param {() => void} action
|
* @param {() => void} action
|
||||||
* @param {boolean} [removeMenu]
|
* @param {boolean} [removeMenu]
|
||||||
*/
|
*/
|
||||||
@@ -1199,7 +1243,7 @@
|
|||||||
if (item instanceof Separator) {
|
if (item instanceof Separator) {
|
||||||
return makeElement("birb-window-separator");
|
return makeElement("birb-window-separator");
|
||||||
}
|
}
|
||||||
let menuItem = makeElement("birb-menu-item", item.text);
|
let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text);
|
||||||
onClick(menuItem, () => {
|
onClick(menuItem, () => {
|
||||||
if (item.removeMenu) {
|
if (item.removeMenu) {
|
||||||
removeMenuCallback();
|
removeMenuCallback();
|
||||||
@@ -1306,7 +1350,8 @@
|
|||||||
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
||||||
*/
|
*/
|
||||||
const DEFAULT_SETTINGS = {
|
const DEFAULT_SETTINGS = {
|
||||||
birbMode: false
|
birbMode: false,
|
||||||
|
soundEnabled: true
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rendering constants
|
// Rendering constants
|
||||||
@@ -1519,6 +1564,7 @@
|
|||||||
|
|
||||||
.birb-menu-item {
|
.birb-menu-item {
|
||||||
width: calc(100% - var(--birb-double-border-size));
|
width: calc(100% - var(--birb-double-border-size));
|
||||||
|
white-space: nowrap;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
@@ -1791,12 +1837,16 @@
|
|||||||
const settingsItems = [
|
const settingsItems = [
|
||||||
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
new MenuItem("Toggle Birb Mode", () => {
|
new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => {
|
||||||
userSettings.birbMode = !userSettings.birbMode;
|
userSettings.soundEnabled = !settings().soundEnabled;
|
||||||
|
save();
|
||||||
|
}),
|
||||||
|
new MenuItem(() => `Toggle ${birdBirb(true)} Mode`, () => {
|
||||||
|
userSettings.birbMode = !settings().birbMode;
|
||||||
save();
|
save();
|
||||||
const message = makeElement("birb-message-content");
|
const message = makeElement("birb-message-content");
|
||||||
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
||||||
if (userSettings.birbMode) {
|
if (settings().birbMode) {
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
||||||
@@ -1804,7 +1854,7 @@
|
|||||||
insertModal(`${birdBirb()} Mode`, message);
|
insertModal(`${birdBirb()} Mode`, message);
|
||||||
}),
|
}),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
new MenuItem("2026.1.1", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.1.1"); }, false),
|
new MenuItem("2026.1.4", () => { alert("Thank you for using Pocket Bird! You are on version: 2026.1.4"); }, false),
|
||||||
];
|
];
|
||||||
|
|
||||||
const styleElement = document.createElement("style");
|
const styleElement = document.createElement("style");
|
||||||
@@ -1818,6 +1868,8 @@
|
|||||||
FLYING: "flying",
|
FLYING: "flying",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const birdsong = new Birdsong();
|
||||||
|
|
||||||
let frozen = false;
|
let frozen = false;
|
||||||
let stateStart = Date.now();
|
let stateStart = Date.now();
|
||||||
let currentState = States.IDLE;
|
let currentState = States.IDLE;
|
||||||
@@ -1908,8 +1960,8 @@
|
|||||||
/**
|
/**
|
||||||
* Bird or birb, you decide
|
* Bird or birb, you decide
|
||||||
*/
|
*/
|
||||||
function birdBirb() {
|
function birdBirb(invert = false) {
|
||||||
return settings().birbMode ? "Birb" : "Bird";
|
return settings().birbMode !== invert ? "Birb" : "Bird";
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
@@ -2498,6 +2550,9 @@
|
|||||||
|
|
||||||
function pet() {
|
function pet() {
|
||||||
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
||||||
|
if (settings().soundEnabled) {
|
||||||
|
birdsong.chirp();
|
||||||
|
}
|
||||||
birb.setAnimation(Animations.HEART);
|
birb.setAnimation(Animations.HEART);
|
||||||
lastPetTimestamp = Date.now();
|
lastPetTimestamp = Date.now();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import Frame from './frame.js';
|
|||||||
import Layer from './layer.js';
|
import Layer from './layer.js';
|
||||||
import Anim from './anim.js';
|
import Anim from './anim.js';
|
||||||
import { Birb, Animations } from './birb.js';
|
import { Birb, Animations } from './birb.js';
|
||||||
|
import { Birdsong } from './sound.js';
|
||||||
import { Context, ObsidianContext } from './context.js';
|
import { Context, ObsidianContext } from './context.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -60,7 +61,8 @@ import {
|
|||||||
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
* @typedef {typeof DEFAULT_SETTINGS} Settings
|
||||||
*/
|
*/
|
||||||
const DEFAULT_SETTINGS = {
|
const DEFAULT_SETTINGS = {
|
||||||
birbMode: false
|
birbMode: false,
|
||||||
|
soundEnabled: true
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rendering constants
|
// Rendering constants
|
||||||
@@ -176,12 +178,16 @@ function startApplication(birbPixels, featherPixels) {
|
|||||||
const settingsItems = [
|
const settingsItems = [
|
||||||
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
new MenuItem("Go Back", () => switchMenuItems(menuItems, updateMenuLocation), false),
|
||||||
new Separator(),
|
new Separator(),
|
||||||
new MenuItem("Toggle Birb Mode", () => {
|
new MenuItem(() => `${settings().soundEnabled ? "Disable" : "Enable"} Sound`, () => {
|
||||||
userSettings.birbMode = !userSettings.birbMode;
|
userSettings.soundEnabled = !settings().soundEnabled;
|
||||||
|
save();
|
||||||
|
}),
|
||||||
|
new MenuItem(() => `Toggle ${birdBirb(true)} Mode`, () => {
|
||||||
|
userSettings.birbMode = !settings().birbMode;
|
||||||
save();
|
save();
|
||||||
const message = makeElement("birb-message-content");
|
const message = makeElement("birb-message-content");
|
||||||
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
message.appendChild(document.createTextNode(`Your ${birdBirb().toLowerCase()} shall now be referred to as "${birdBirb()}"`));
|
||||||
if (userSettings.birbMode) {
|
if (settings().birbMode) {
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createElement("br"));
|
message.appendChild(document.createElement("br"));
|
||||||
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
message.appendChild(document.createTextNode("Welcome back to 2012"));
|
||||||
@@ -203,6 +209,8 @@ function startApplication(birbPixels, featherPixels) {
|
|||||||
FLYING: "flying",
|
FLYING: "flying",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const birdsong = new Birdsong();
|
||||||
|
|
||||||
let frozen = false;
|
let frozen = false;
|
||||||
let stateStart = Date.now();
|
let stateStart = Date.now();
|
||||||
let currentState = States.IDLE;
|
let currentState = States.IDLE;
|
||||||
@@ -293,8 +301,8 @@ function startApplication(birbPixels, featherPixels) {
|
|||||||
/**
|
/**
|
||||||
* Bird or birb, you decide
|
* Bird or birb, you decide
|
||||||
*/
|
*/
|
||||||
function birdBirb() {
|
function birdBirb(invert = false) {
|
||||||
return settings().birbMode ? "Birb" : "Bird";
|
return settings().birbMode !== invert ? "Birb" : "Bird";
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
@@ -897,6 +905,9 @@ function startApplication(birbPixels, featherPixels) {
|
|||||||
|
|
||||||
function pet() {
|
function pet() {
|
||||||
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
if (currentState === States.IDLE && birb.getCurrentAnimation() !== Animations.HEART) {
|
||||||
|
if (settings().soundEnabled) {
|
||||||
|
birdsong.chirp();
|
||||||
|
}
|
||||||
birb.setAnimation(Animations.HEART);
|
birb.setAnimation(Animations.HEART);
|
||||||
lastPetTimestamp = Date.now();
|
lastPetTimestamp = Date.now();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export const MENU_EXIT_ID = "birb-menu-exit";
|
|||||||
|
|
||||||
export class MenuItem {
|
export class MenuItem {
|
||||||
/**
|
/**
|
||||||
* @param {string} text
|
* @param {string|(() => string)} text
|
||||||
* @param {() => void} action
|
* @param {() => void} action
|
||||||
* @param {boolean} [removeMenu]
|
* @param {boolean} [removeMenu]
|
||||||
*/
|
*/
|
||||||
@@ -61,7 +61,7 @@ function makeMenuItem(item, removeMenuCallback) {
|
|||||||
if (item instanceof Separator) {
|
if (item instanceof Separator) {
|
||||||
return makeElement("birb-window-separator");
|
return makeElement("birb-window-separator");
|
||||||
}
|
}
|
||||||
let menuItem = makeElement("birb-menu-item", item.text);
|
let menuItem = makeElement("birb-menu-item", typeof item.text === "function" ? item.text() : item.text);
|
||||||
onClick(menuItem, () => {
|
onClick(menuItem, () => {
|
||||||
if (item.removeMenu) {
|
if (item.removeMenu) {
|
||||||
removeMenuCallback();
|
removeMenuCallback();
|
||||||
|
|||||||
43
src/sound.js
Normal file
43
src/sound.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
export class Birdsong {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {AudioContext}
|
||||||
|
*/
|
||||||
|
audioContext;
|
||||||
|
|
||||||
|
chirp() {
|
||||||
|
if (!this.audioContext) {
|
||||||
|
this.audioContext = new AudioContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
const TIMES = [0, 0.06, 0.10, 0.15];
|
||||||
|
const FREQUENCIES = [2200,
|
||||||
|
3500 + Math.random() * 600,
|
||||||
|
2100 + Math.random() * 200,
|
||||||
|
1600 + Math.random() * 400];
|
||||||
|
const VOLUMES = [0.0001, 0.3, 0.3, 0.0001];
|
||||||
|
|
||||||
|
const oscillator = this.audioContext.createOscillator();
|
||||||
|
oscillator.type = "sine";
|
||||||
|
const gain = this.audioContext.createGain();
|
||||||
|
oscillator.connect(gain);
|
||||||
|
gain.connect(this.audioContext.destination);
|
||||||
|
|
||||||
|
const now = this.audioContext.currentTime;
|
||||||
|
for (let i = 0; i < TIMES.length; i++) {
|
||||||
|
const time = TIMES[i] + now;
|
||||||
|
if (i === 0) {
|
||||||
|
oscillator.frequency.setValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.setValueAtTime(VOLUMES[i], time);
|
||||||
|
} else {
|
||||||
|
oscillator.frequency.exponentialRampToValueAtTime(FREQUENCIES[i], time);
|
||||||
|
gain.gain.exponentialRampToValueAtTime(VOLUMES[i], time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oscillator.start(now);
|
||||||
|
oscillator.stop(now + TIMES[TIMES.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -198,6 +198,7 @@
|
|||||||
|
|
||||||
.birb-menu-item {
|
.birb-menu-item {
|
||||||
width: calc(100% - var(--birb-double-border-size));
|
width: calc(100% - var(--birb-double-border-size));
|
||||||
|
white-space: nowrap;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
|
|||||||
Reference in New Issue
Block a user