This repository has been archived on 2026-01-04. You can view files and clone it, but cannot push or open issues or pull requests.
polyplus/js/store/store.js
Index f3e33ea840 v1.2.2
- Avatar Sandbox rewrite

- Updated owned item tags code

- Inventory Collectibles Category

- Great Divide Features ("Potentially Unbalanced" indicator in server list and User Statistics tab on profiles)

- Refreshed Settings Page design

- Fixed library item type detection

- Breadcrumbs on the view page for models, audios, decals, and meshes now link to the Library instead of the Store.

- If the document loads prior to the DOMContentLoaded event being registered in the sitewide.js file, then it'll still run everything as normal instead of just not running

- Updated README.md

I was bored so:
- You can now make a profile act like a birthday profile by appending ?birthday=true to the URL
2024-06-25 09:14:52 -05:00

350 lines
12 KiB
JavaScript
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const ItemID = window.location.pathname.split('/')[2];
const UserID = JSON.parse(window.localStorage.getItem('p+account_info')).ID;
const ItemGrid = document.getElementById('assets');
const Categories = document.getElementById('store-categories').children[0];
var Settings;
var Inventory = null;
var Utilities;
let EventItemsShown = false;
chrome.storage.sync.get(['PolyPlus_Settings'], async function (result) {
Settings = result.PolyPlus_Settings || {};
Utilities = await import(chrome.runtime.getURL('resources/utils.js'));
Utilities = Utilities.default;
if (Settings.IRLPriceWithCurrency && Settings.IRLPriceWithCurrency.Enabled === true) {
Array.from(ItemGrid.children).forEach((element) => {
LoadIRLPrices(element);
});
}
if (Settings.EventItemsCatOn === true) {
EventItems();
}
if (Settings.StoreOwnTagOn === true) {
chrome.storage.local.get('PolyPlus_InventoryCache', async function(result){
console.log(result)
if (result.PolyPlus_InventoryCache !== undefined && (new Date().getTime() - result.PolyPlus_InventoryCache[1] < 5000)) {
console.log('not undefined')
Inventory = result.PolyPlus_InventoryCache[0]
Array.from(ItemGrid.children).forEach((element) => {
LoadOwnedTags(element);
});
} else {
Inventory = (await (await fetch('https://api.polytoria.com/v1/users/' + UserID + '/inventory?type=hat&limit=100')).json());
if (Inventory.errors === undefined) {
Inventory = Inventory.inventory
Inventory = [...Inventory, ...(await (await fetch('https://api.polytoria.com/v1/users/' + UserID + '/inventory?type=face&limit=100')).json()).inventory];
Inventory = [...Inventory, ...(await (await fetch('https://api.polytoria.com/v1/users/' + UserID + '/inventory?type=tool&limit=100')).json()).inventory];
Inventory = [...Inventory, ...(await (await fetch('https://api.polytoria.com/v1/users/' + UserID + '/inventory?type=profileTheme&limit=100')).json()).inventory];
console.log(Inventory);
chrome.storage.local.set({'PolyPlus_InventoryCache': [Inventory, new Date().getTime()]}, function(){})
Array.from(ItemGrid.children).forEach((element) => {
LoadOwnedTags(element);
});
} else {
console.log(Inventory)
}
}
})
}
});
const observer = new MutationObserver(async function (list) {
if (Settings.EventItemsCatOn === true) {
if (document.getElementById('event-items-pagination') === null) {
ItemGrid.classList.add('itemgrid');
ItemGrid.parentElement.classList.remove('col-lg-9');
document.getElementById('pagination').style.display = 'block';
if (document.getElementById('storecat-eventitems') !== null) {
document.getElementById('storecat-eventitems').checked = false;
}
} else {
ItemGrid.classList.remove('itemgrid');
ItemGrid.parentElement.classList.add('col-lg-9');
document.getElementById('pagination').style.display = 'none';
}
}
for (const record of list) {
for (const element of record.addedNodes) {
if (element.tagName === 'DIV' && element.classList.value === 'mb-3 itemCardCont') {
if (Settings.IRLPriceWithCurrency && Settings.IRLPriceWithCurrency.Enabled === true) {
LoadIRLPrices(element);
}
if (Settings.StoreOwnTagOn === true && Inventory !== null) {
LoadOwnedTags(element);
}
}
}
observer.observe(ItemGrid, {attributes: false, childList: true, subtree: false});
}
});
observer.observe(ItemGrid, {attributes: false, childList: true, subtree: false});
async function LoadIRLPrices(element) {
if (element.tagName != 'DIV' || element.querySelector('small.text-primary')) {
return;
}
const Parent = element.getElementsByTagName('small')[1];
if (Parent.innerText !== '') {
const Span = document.createElement('span');
Span.classList = 'text-muted polyplus-price-tag';
Span.style = 'font-size: 0.7rem; font-weight: lighter;';
const Price = Parent.innerText.split(' ')[1];
const IRLResult = await Utilities.CalculateIRL(Price, Settings.IRLPriceWithCurrency.Currency);
Span.innerText = '($' + IRLResult.result + ' ' + IRLResult.display + ')';
Parent.appendChild(Span);
}
}
function LoadOwnedTags(element) {
let Item = CheckInventory(parseInt(element.querySelector('[href^="/store/"]').getAttribute('href').split('/')[2]));
if (Item !== null) {
const Tag = document.createElement('span');
Tag.classList = `badge ${Item.asset.isLimited === false ? 'bg-primary' : 'bg-warning'} polyplus-own-tag`;
Tag.style =
'position: absolute;font-size: 0.9rem;top: 0px;left: 0px;padding: 5.5px;border-top-left-radius: var(--bs-border-radius-lg)!important;border-top-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 0.65rem;';
Tag.innerHTML = "<i class='fas fa-star'></i>";
element.getElementsByTagName('img')[0].parentElement.appendChild(Tag);
if (Item.asset.isLimited === true) {
Tag.setAttribute('data-bs-toggle', 'tooltip');
Tag.setAttribute('data-bs-title', '#' + Item.serial);
Utilities.InjectResource('registerTooltips');
}
}
}
function CheckInventory(id) {
let Item = null;
Inventory.forEach((element) => {
if (element.asset.id === id) {
Item = element;
}
});
return Item;
}
function EventItems() {
const Selector = document.createElement('div');
Selector.classList = 'form-check store-category-check fw-bold';
Selector.style.borderColor = '#B008B0';
Selector.innerHTML = `
<input class="form-check-input" type="radio" name="storecat" id="storecat-eventitems">
<label class="form-check-label" for="storecat-eventitems">
<i class="fad fa-party-horn"></i> Event Items
</label>
`;
Categories.appendChild(Selector);
let EventData = null;
let Events = [];
let Groups = [];
let Page = 0;
Selector.children[0].addEventListener('click', async function () {
Array.from(Categories.children).forEach((selector) => {
selector.classList.remove('active');
});
Selector.classList.add('active');
if (EventData === null) {
EventData = await (await fetch('https://polyplus.vercel.app/data/eventItems.json')).json();
Object.values(EventData.eventDetails).forEach((x, index) => {
Events.push({
...x,
items: EventData.items.filter((x) => x.event === Object.keys(EventData.eventDetails)[index]).sort((a, b) => a.id - b.id)
});
});
while (Events.length > 0) {
Groups.push(Events.splice(0, 5));
}
}
ItemGrid.classList.remove('itemgrid');
ItemGrid.innerHTML = `
<div id="p+ei">
${Groups[Page].map((x, index) => `
<div class="row px-2 px-lg-0" style="animation-delay: 0.24s;">
<div class="col">
<h6 class="dash-ctitle2">${x.date}</h6>
<h5 class="dash-ctitle">${x.name}</h5>
</div>
${x.link !== undefined ? `
<div class="col-auto d-flex align-items-center">
<a class="text-muted" href="${x.link}">
<span class="d-none d-lg-inline">${x.link.startsWith('https://polytoria.com/places/') ? 'Event Place' : 'Blog Post'}</span>
<i class="fas fa-angle-right ms-2"></i>
</a>
</div>
`
: ''
}
</div>
<div class="card card-dash mcard mb-3" style="animation-delay: 0.27s;">
<div class="card-body p-0 m-1 scrollFadeContainer">
<div class="d-flex">
${x.items.map((x) => `
<a href="/store/${x.id}">
<div class="scrollFade card me-2 place-card force-desktop text-center mb-2" style="opacity: 1;">
<div class="card-body">
<img src="${x.thumbnail}" class="place-card-image">
<div>
<div class="mt-2 mb-1 place-card-title">
${x.name}
</div>
</div>
</div>
</div>
</a>
`).join('')}
</div>
</div>
</div>
`).join('')}
</div>
<div class="d-flex justify-content-center mt-3">
<nav id="event-items-pagination">
<ul class="pagination">
<li class="page-item disabled">
<a class="page-link" href="#!" id="p+ei-pagination-first">«</a>
</li>
<li class="page-item disabled">
<a class="page-link" href="#!" id="p+ei-pagination-prev"></a>
</li>
<li class="page-item active">
<a class="page-link">
<span class="visually-hidden">Page</span>
<span id="p+ei-pagination-current">1</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="#!" id="p+ei-pagination-next"></a>
</li>
<li class="page-item">
<a class="page-link" href="#!" id="p+ei-pagination-last">»</a>
</li>
</ul>
</nav>
</div>
`;
const Container = document.getElementById('p+ei');
const Pagination = document.getElementById('event-items-pagination');
const First = document.getElementById('p+ei-pagination-first');
const Prev = document.getElementById('p+ei-pagination-prev');
const Current = document.getElementById('p+ei-pagination-current');
const Next = document.getElementById('p+ei-pagination-next');
const Last = document.getElementById('p+ei-pagination-last');
if (Page > 0) {
Prev.parentElement.classList.remove('disabled');
First.parentElement.classList.remove('disabled');
} else {
Prev.parentElement.classList.add('disabled');
First.parentElement.classList.add('disabled');
}
if (Page < Groups.length - 1) {
Next.parentElement.classList.remove('disabled');
Last.parentElement.classList.remove('disabled');
} else {
Next.parentElement.classList.add('disabled');
Last.parentElement.classList.add('disabled');
}
First.addEventListener('click', function () {
if (Page > 0) {
Page = 0;
UpdateEventItems();
}
});
Prev.addEventListener('click', function () {
if (Page > 0) {
Page--;
UpdateEventItems();
}
});
Next.addEventListener('click', function () {
if (Page < Groups.length - 1) {
Page++;
UpdateEventItems();
}
});
Last.addEventListener('click', function () {
if (Page < Groups.length - 1) {
Page = Groups.length - 1;
UpdateEventItems();
}
});
const UpdateEventItems = function () {
Current.innerText = Page + 1;
Container.innerHTML = Groups[Page].map((x, index) => `
<div class="row px-2 px-lg-0" style="animation-delay: 0.24s;">
<div class="col">
<h6 class="dash-ctitle2">${x.date}</h6>
<h5 class="dash-ctitle">${x.name}</h5>
</div>
${x.link !== undefined ? `
<div class="col-auto d-flex align-items-center">
<a class="text-muted" href="${x.link}">
<span class="d-none d-lg-inline">${x.link.startsWith('https://polytoria.com/places/') ? 'Event Place' : 'Blog Post'}</span>
<i class="fas fa-angle-right ms-2"></i>
</a>
</div>
`
: ''
}
</div>
<div class="card card-dash mcard mb-3" style="animation-delay: 0.27s;">
<div class="card-body p-0 m-1 scrollFadeContainer">
<div class="d-flex">
${x.items.map((x) => `
<a href="/store/${x.id}">
<div class="scrollFade card me-2 place-card force-desktop text-center mb-2" style="opacity: 1;">
<div class="card-body">
<img src="${x.thumbnail}" class="place-card-image">
<div>
<div class="mt-2 mb-1 place-card-title">
${x.name}
</div>
</div>
</div>
</div>
</a>
`).join('')}
</div>
</div>
</div>
</div>
`
).join('');
if (Page > 0) {
Prev.parentElement.classList.remove('disabled');
First.parentElement.classList.remove('disabled');
} else {
Prev.parentElement.classList.add('disabled');
First.parentElement.classList.add('disabled');
}
if (Page < Groups.length - 1) {
Next.parentElement.classList.remove('disabled');
Last.parentElement.classList.remove('disabled');
} else {
Next.parentElement.classList.add('disabled');
Last.parentElement.classList.add('disabled');
}
};
});
}