add emoji picker + more info to readme + additional internals

This commit is contained in:
Soph :3 2024-11-26 17:30:33 +02:00
parent c1155ef3e7
commit f9dcdf8044
Signed by: sophie
GPG key ID: EDA5D222A0C270F2
5 changed files with 189 additions and 19 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
emojis.json Normal file

File diff suppressed because one or more lines are too long

192
extra.js
View file

@ -1,7 +1,48 @@
if(window.PvInternals.services_client) {
console.log("pv.me has loaded correctly")
console.log("%c--> pv.me", `color:yellow;font-size:30pt;`)
console.log("%cinternals available at window.PvInternals", `color:yellow;font-size:20pt;`)
}
// Reimplement PopupManager.open
(() => {
const pv = window.PvInternals;
pv.popupMap = {
[pv.Modal.BAN]: pv.components_popups_pv_ban_pv_ban,
[pv.Modal.PROFILE]: pv.components_popups_pv_profile_pv_profile,
[pv.Modal.SETTINGS]: pv.components_popups_pv_settings_pv_settings,
[pv.Modal.MESSAGE]: pv.components_popups_pv_message_pv_message,
[pv.Modal.NEW_ROOM]: pv.components_popups_pv_new_room_pv_new_room,
[pv.Dialog.ROOMS]: pv.components_popups_pv_rooms_pv_rooms,
[pv.Dialog.ACTIONS]: pv.components_popups_pv_actions_pv_actions,
[pv.Dialog.DEVICES]: pv.components_popups_pv_devices_pv_devices,
[pv.Dialog.SOUNDS]: pv.components_popups_pv_sounds_pv_sounds,
[pv.Dialog.TRANSPOSE]: pv.components_popups_pv_transpose_pv_transpose,
[pv.Dialog.VELOCITY]: pv.components_popups_pv_velocity_pv_velocity,
};
pv.PopupManager.open = (popupName, ...args) => {
let dialogElement = document.querySelector(popupName)
if (dialogElement && !dialogElement.querySelector("dialog").hasAttribute("closing")) {
dialogElement.close();
return dialogElement;
}
const popupClass = pv.popupMap[popupName];
if (!popupClass) {
throw new Error(`Popup ${popupName} not found`);
}
dialogElement = new popupClass();
document.body.append(dialogElement);
dialogElement.open(...args);
return dialogElement;
}
})();
// custom rules
(() => {
const pv = window.PvInternals;
@ -14,21 +55,7 @@ if(window.PvInternals.services_client) {
customElements.define("pvme-rules-modal", PvmeRulesModal);
pv.Modal.RULES = "pvme-rules-modal";
let oldOpen = pv.PopupManager.open;
pv.PopupManager.open = (e, ...t) => {
if(pv.Modal.RULES == e) {
let i = new PvmeRulesModal();
if (i == document.querySelector(e) && !i.querySelector("dialog").hasAttribute("closing"))
return i.close();
document.body.append(i)
i.open(...t)
return i;
} else {
return oldOpen(e, ...t)
}
}
pv.popupMap[pv.Modal.RULES] = PvmeRulesModal
class PvmeRules extends HTMLElement {}
customElements.define("pvme-rules", PvmeRules);
@ -62,4 +89,137 @@ if(window.PvInternals.services_client) {
}
document.querySelector("body > pv-header > div.left > div.pianoverse > span").innerText = "pv.me"
})();
(async () => {
const style = document.createElement("style");
style.innerHTML = `pv-chat>div button:nth-child(3){position:absolute;right:40px;z-index:26;cursor:url(88b4a467a18e813218f8.cur),auto;font-size:1em;border:none;height:46px;aspect-ratio:1;padding:0;border-radius:0;box-shadow:none;margin:0;flex:0;color:var(--color-text)}pv-chat>div button:nth-child(3)>img:hover{transform-origin:50% 50%;transform:scale(1.4);transition:.1s}pv-chat>div input[type=text]{padding:0 90px 0 14px}.emoji-container{display:grid;grid-template-columns:auto auto auto auto auto auto}.emoji-container>*{text-align:center;margin:2px}`
document.head.appendChild(style);
const pv = window.PvInternals;
const emojiRequest = await fetch("emojis.json");
let emojis = await emojiRequest.json()
const discordEmojis = ['<:bratkanye:1271842184798273668>', '<a:aniblobsweat:586029851870363660>', '<:blobpensive:978314885337346089>', '<:blobsip:978314935077597231>', '<:blobheart:856700296302428170>', '<:blobsaluteban:463464097137295392>', '<:blobthinkban:812905997034061834>', '<:blobreach:474817265339203584>', '<a:blobReachAustralia:1247812442239795282>', '<:nixos:1252753664397934646>', '<:archlinux:1252754080640667658>', '<:rust:1263598244588425388>', '<:perfect:1243013970764370061>', '<:True:811294080662896640>', '<:froglove:1228043131430240407>', '<a:frogpop:1228043129811374081>', '<a:frogwave:1228043128871845979>', '<:pianoverse:1218346119705133116>', '<:restart:1257118826106064899>', '<:tape:1274061265714811054>', '<:what:1279839007714316392>', '<:boof:1261047926088663161>', '<:CHECK_CHECK_1:1075442774649872384>', '<:CHECK_CROSS_1:1075442781708898414>', '<a:pogg:947236908256362496>', '<a:peeposhy:1052873747561971732>', '<a:catfbi:1292722712212672582>', '<:cat:1184105614994063410>', '<:MBDTF:1263773146972946442>', '<a:SpeedL:906979227939778580>', '<a:SpeedR:906979227876864051>', '<a:newports:1005206666792419458>', '<a:myman:829624853845245953>', '<a:skyperock:937848388685279262>', '<:shut:714946339850420324>', '<a:sponge:854419399871561800>', '<a:weedwalker:855115903426625578>', '<a:furret:791595456147750943>', '<a:weewoo_red:706925335228317868>'];
const discordEmojiRegex = /<(a?):.*?:(\d+)>/g;
function renderEmoji(emoji, size = "64") {
const id = emoji.replace(discordEmojiRegex, "$2");
const isAnimated = !!emoji.replace(discordEmojiRegex, "$1")
const img = document.createElement("img");
img.src = `https://cdn.discordapp.com/emojis/${id}.${isAnimated ? "gif" : "png"}?size=${size}`;
img.alt = "emoji";
img.width = size;
img.height = size;
return img;
}
//#region Modal
class PvmeEmojiPicker extends pv.components_pv_popup_pv_popup {
constructor() {
super();
const dialog = document.createElement("dialog");
dialog.className = "popup"
dialog.setAttribute("modal", "")
dialog.setAttribute("blocking", "")
const header = document.createElement("div");
header.className = "header";
header.innerHTML = `<div class="title"><i class="fas fa-info-circle" aria-hidden="true"></i>Emoji picker</div><div class="x"><i class="fas fa-xmark" aria-hidden="true"></i></div>`
dialog.appendChild(header)
const content = document.createElement("div")
content.className = "content"
// #region Modal search input
const input = document.createElement("input")
input.type = "text"
input.value = pv.settingsmanager.get("latestEmojiLookup") || ""
input.addEventListener("keyup", () => {
pv.settingsmanager.set("latestEmojiLookup", input.value);
this.renderContainer(document.querySelector(".emoji-container"), input.value)
});
content.appendChild(input)
// #endregion
// #region Modal info
const info = document.createElement("p")
info.innerText = "Write 'discord' for discord emoijs, anything else for normal ones."
content.appendChild(info);
//#endregion
const container = document.createElement("div")
container.className = "emoji-container"
this.renderContainer(container, pv.settingsmanager.get("latestEmojiLookup") || "discord")
content.append(container);
dialog.appendChild(content)
this.appendChild(dialog)
}
renderContainer(container, value) {
container.innerHTML = ""
if(value !== "discord") {
emojis.filter(z => z[0].replace("_", " ").includes(value.toLowerCase()) || value.toLowerCase().includes(z[0].replace("_", " "))).slice(0, 30).forEach(z => {
const div = document.createElement("div")
div.innerText = z[1];
div.style.fontSize = "30px"
div.addEventListener("click", () => {
const chat = document.querySelector("pv-chat");
chat.input.value += z[1] + " ";
pv.PopupManager.closeModals();
setTimeout(() => {
document.querySelector("pv-chat").input.scrollLeft = document.querySelector("pv-chat").input.scrollWidth;
}, 50)
})
container.appendChild(div);
})
} else {
discordEmojis.forEach((z) => {
const img = renderEmoji(z, "64")
img.addEventListener("click", () => {
const chat = document.querySelector("pv-chat");
chat.input.value += z + " ";
pv.PopupManager.closeModals();
setTimeout(() => {
document.querySelector("pv-chat").input.scrollLeft = document.querySelector("pv-chat").input.scrollWidth;
}, 50)
})
container.appendChild(img);
})
}
}
}
customElements.define("pvme-emoji-picker", PvmeEmojiPicker);
pv.Modal.EMOJIS = "pvme-emoji-picker";
pv.popupMap[pv.Modal.EMOJIS] = PvmeEmojiPicker
//#endregion
//#region Button
const button = document.createElement("button");
button.className = "send";
button.type = "button"
button.ariaLabel = "Pick a emoji!"
function changeEmoji(emoji) {
button.firstElementChild?.remove()
button.appendChild(renderEmoji(emoji, "32"));
}
changeEmoji(discordEmojis[Math.floor(Math.random() * discordEmojis.length)]);
button.addEventListener("click", () => {
pv.PopupManager.open(pv.Modal.EMOJIS);
changeEmoji(discordEmojis[Math.floor(Math.random() * discordEmojis.length)]);
})
document.querySelector("body > div > div.chat > pv-chat > div").appendChild(button)
//#endregion
})();

View file

@ -22,7 +22,16 @@ Exposes all internal pianoverse APIs on window.PvInternals.
Use nushell and `build/createPatchedBundle.nu` in the root to create a bundle.js.
## extra.js
extra.js is a quick attempt to implement a new feature for Pianoverse with the internal APIs, which is possible, however hard. It adds a simple button for rules and a new modal. It **requires the internal patch** and for it to be added in index.html.
extra.js contains the following features
1. PopupManager.open rewrite
Rewrites a internal function called PopupManager.open, the only way to add Popups without this rewrite was to hook into PopupManager.open and jerry-rig a implenmentation. However, with this rewrite you can add popups to a map at PvInternal.popupMap.
2. Rules button & modal
This is a simple button in the top of the screen, which shows rules.
3. Emoji picker
There is a emoji picker. I hand picked some emojis from discord, ask if you want more. There are also normal emojis, for those you have to search in the search bar.
This emoji picker also requires "emojis.json", which is in the repository already.
4. Rebrand
I also added a thing that changes the title of the website from Pianoverse to pv.me, same with the top of the screen. Helps me differenciate which site I'm on.
## Sounds
Use the `build/downloadSounds.nu` nushell script to download all sounds.