import "@/public/css/specific.css"; import config from "@/utils/config.json"; import { bricksToCurrency } from "@/utils/utilities"; import { userDetails } from "@/utils/types"; import * as apiTypes from "@/utils/api/types"; export function irlBrickPrice() { try { const purchaseBtn = document.querySelector('button[onclick^="buy"], button[data-price]')!; const currency = bricksToCurrency(parseInt(purchaseBtn.getAttribute('data-price')!), "USD"); if (currency) { const spanTag = document.createElement('span'); spanTag.classList.add('text-muted'); spanTag.style.fontSize = '0.7rem'; spanTag.style.fontWeight = 'lighter'; spanTag.innerText = ` (${currency})`; purchaseBtn.appendChild(spanTag); }; } catch(e) { // The store purchase button has several different ways of being represented, this should // only happen when the item is already owned console.warn('[Poly+] Failure to find purchase button on page.'); }; }; export function tryOn(user: userDetails) { const itemId = window.location.pathname.split('/')[2] const favoriteBtn = document.querySelector('button[onclick^="toggleFavorite"]')!; const button = document.createElement('button'); button.classList.add('btn', 'btn-outline-primary', 'btn-sm', 'mt-2'); button.innerHTML = ''; const modal = document.createElement('dialog'); modal.classList.add('polyplus-modal'); Object.assign(modal.style, { width: '450px', border: '1px solid #484848', backgroundColor: '#181818', borderRadius: '20px', overflow: 'hidden' }); modal.innerHTML = `
Preview
Try this item on your avatar before purchasing it!
`; document.body.prepend(modal); favoriteBtn.parentElement!.appendChild(button); const loadFrame = async (source: apiTypes.avatarApiSchema) => { console.info('[Poly+] Loading avatar preview with avatar data: ', source); for (const [key, value] of Object.entries(source.colors)) { source.colors[key as keyof typeof source.colors] = "#" + value; }; const avatar: { [key: string]: any } = { useCharacter: true, items: [] as Array, headColor: source.colors.head, torsoColor: source.colors.torso, leftArmColor: source.colors.leftArm, rightArmColor: source.colors.rightArm, leftLegColor: source.colors.leftLeg, rightLegColor: source.colors.rightLeg, }; const itemInfo: apiTypes.itemApiSchema = (await (await fetch(config.api.urls.public + "store/" + itemId)).json()); for (const item of [ ...source.assets.filter((item: any) => (item.type != itemInfo.type || itemInfo.type == "hat")), { id: itemInfo.id, type: itemInfo.type } ]) { if (item.type == "hat" || item.type == "tool") { const mesh: apiTypes.meshApiSchema = (await (await fetch(config.api.urls.public + "assets/serve-mesh/" + item.id)).json()); if (mesh.success) { if (item.type == "hat") { avatar.items.push(mesh.url) } else { avatar.tool = mesh.url; }; }; } else { const texture: apiTypes.textureApiSchema = (await (await fetch(config.api.urls.public + "assets/serve/" + item.id + "/Asset")).json()); if (texture.success) avatar[item.type] = texture.url; }; }; const frame = document.createElement('iframe'); Object.assign(frame.style, { width: '100%', height: 'auto', aspectRatio: '1', borderRadius: '20px', background: '#1e1e1e' }) frame.src = config.api.urls.itemview + btoa(encodeURIComponent(JSON.stringify(avatar))); modal.getElementsByClassName('modal-body')[0].appendChild(frame); }; button.addEventListener('click', async () => { if (!modal.getElementsByTagName('iframe')[0]) { button.innerHTML = ` Loading... `; const avatar = await user.getAvatar(); if (avatar == "disabled") { console.error('[Poly+] API is disabled, cancelling try-on items loading..'); modal.getElementsByClassName('modal-body')[0].innerHTML = `

Sorry! This feature is currently unavailable. Please check back later!

`; modal.showModal(); return; }; await loadFrame(avatar); button.innerHTML = ''; }; modal.showModal(); }); };