A rewrite of Poly+, my quality-of-life browser extension for Polytoria. Built entirely fresh using the WXT extension framework, Typescript, and with added better overall code quality.
extension
1import { pullCache, bricksToCurrency } from "@/utils/utilities";
2import * as api from "@/utils/api";
3
4/**
5 * Adds the locale real-life dollar value next to the amount of bricks an item costs on the /store/ page item grid.
6 */
7export function irlBrickPrice() {
8 const grid = document.getElementById('assets')!;
9
10 const addPrice = (item: HTMLElement) => {
11 const brickCount = item.getElementsByClassName('text-success')[0].textContent!;
12 const currency = bricksToCurrency(parseInt(brickCount), "USD");
13
14 if (currency) {
15 const spanTag = document.createElement('span');
16 spanTag.classList.add('text-muted');
17 spanTag.style.fontSize = '0.7rem';
18 spanTag.style.fontWeight = 'lighter';
19 spanTag.innerText = ` (${currency})`;
20 item.getElementsByClassName('text-success')[0].appendChild(spanTag);
21 };
22 };
23
24 for (const item of document.getElementsByClassName('itemCardCont')) {
25 addPrice(item as HTMLElement);
26 };
27
28 const mutations = new MutationObserver((mutations) => {
29 for (const record of mutations) {
30 for (const node of record.addedNodes) {
31 const item = node as HTMLElement;
32 if ((item as HTMLElement).classList.contains('itemCardCont')) addPrice(item);
33 };
34 };
35 });
36
37 mutations.observe(grid, { childList: true });
38};
39
40/**
41 * Adds a star in the corner of items the user owns on the /store/ page item grid.
42 * @param userId The ID of the authenticated user.
43 */
44export async function ownedTags(userId: number) {
45 const grid = document.getElementById('assets')!;
46 const inventory = await pullCache(
47 'inventory',
48 async () => await api.iterate(
49 'public',
50 'users/' + userId + '/inventory?limit=100&page=',
51 {
52 data: "inventory",
53 metadata: "meta"
54 },
55 1,
56 5
57 ),
58 300000,
59 false
60 );
61
62 if (inventory == "disabled") {
63 throw new Error('[Poly+] API is disabled, cancelling item owned tags loading..');
64 };
65
66 const owns = (item: HTMLElement) => {
67 const itemId = parseInt(item.getAttribute('href')!.split('/')[2]);
68
69 if (inventory.find((item: {
70 asset: {
71 id: number
72 }
73 }) => item.asset.id == itemId)) {
74 return true;
75 };
76
77 return false;
78 };
79
80 const addTag = (item: HTMLElement) => {
81 const tag = document.createElement('span');
82 tag.classList.add('badge', 'bg-primary');
83 tag.setAttribute('style', `
84 position: absolute;
85 font-size: 0.9rem;
86 top: 0px;
87 left: 0px;
88 padding: 5.5px;
89 border-top-left-radius: var(--bs-border-radius-lg) !important;
90 border-top-right-radius: 0px;
91 border-bottom-left-radius: 0px;
92 font-size: 0.65rem;
93 `);
94 tag.innerHTML = "<i class='fas fa-star'></i>";
95
96 const image = item.getElementsByTagName('img')[0]!;
97 image.parentElement!.appendChild(tag);
98 };
99
100 for (const item of document.getElementsByClassName('itemCardCont')) {
101 const link: HTMLElement = item.getElementsByTagName('a')[0]!;
102 if (owns(link)) {
103 addTag(item as HTMLElement);
104 };
105 };
106
107 const mutations = new MutationObserver((mutations) => {
108 for (const record of mutations) {
109 for (const node of record.addedNodes) {
110 const item = node as HTMLElement;
111 if ((item as HTMLElement).classList.contains('itemCardCont')) {
112 const link: HTMLElement = item.getElementsByTagName('a')[0]!;
113 if (owns(link)) {
114 addTag(item as HTMLElement);
115 };
116 }
117 };
118 };
119 });
120
121 mutations.observe(grid, { childList: true });
122}