Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
601 changes: 601 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@
"webpack-merge": "^5.9.0",
"zip-webpack-plugin": "^4.0.1"
}
}
}
2 changes: 1 addition & 1 deletion public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
{
"run_at": "document_start",
"matches": ["*://*.vlr.gg/*"],
"resources": ["bettervlr.js"]
"resources": ["bettervlr.js","trophies.js"]
}
]
}
7 changes: 6 additions & 1 deletion src/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ if (typeof browser === "undefined") {
var browser = chrome;
}

// Load the main extension script
const script = document.createElement("script");
script.src = browser.runtime.getURL("bettervlr.js");

document.documentElement.append(script);

// Load the trophies script
const trophiesScript = document.createElement("script");
trophiesScript.src = browser.runtime.getURL("trophies.js");
document.documentElement.append(trophiesScript);
15 changes: 15 additions & 0 deletions src/quick-links.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ function displayQuickLinksInSettings() {
const quick_links = `
<div id="sortable-container" class="wf-card mod-form mod-dark">
<div class="form-section" style="margin-top: 0;">Quick Links</div>
<div class="quick-links">
<a class="wf-module-item" href="/vct-2025"><img src="https://i.imgur.com/2dqrmN2.png" alt="VCT 2025">VCT 2025</a>
<div class="wf-module-item" style="cursor: not-allowed;">EDIT<i class="fa fa-pencil" aria-hidden="true"></i></div>
<div class="wf-module-item" style="cursor: not-allowed;">REMOVE<i class="fa fa-ban" aria-hidden="true"></i></div>
</div>
<div class="quick-links">
<a class="wf-module-item" href="/vct-2024"><img src="https://i.imgur.com/2dqrmN2.png" alt="VCT 2024">VCT 2024</a>
<div class="wf-module-item" style="cursor: not-allowed;">EDIT<i class="fa fa-pencil" aria-hidden="true"></i></div>
<div class="wf-module-item" style="cursor: not-allowed;">REMOVE<i class="fa fa-ban" aria-hidden="true"></i></div>
</div>
<div class="quick-links">
<a class="wf-module-item" href="/vct-2023"><img src="https://i.imgur.com/2dqrmN2.png" alt="VCT 2023">VCT 2023</a>
<div class="wf-module-item" style="cursor: not-allowed;">EDIT<i class="fa fa-pencil" aria-hidden="true"></i></div>
Expand Down Expand Up @@ -97,10 +107,13 @@ const quick_links = `


// ANCHOR Add dropdown to the header
// #TODO: Update VCT 24 and 25 images. there might be a more efficient way to do this.
$(".header-nav-item.mod-stats").next().after(`
<div class="header-nav-item dropdown mod-vlr" style="align-items: center;" tabindex="0">
<i class="fa fa-chevron-right" aria-hidden="true"></i>
<div class="dropdown-content wf-card">
<a class="wf-module-item" href="/vct-2025"><img src="https://i.imgur.com/2dqrmN2.png" alt="VCT 2025">VCT 2025</a>
<a class="wf-module-item" href="/vct-2024"><img src="https://i.imgur.com/2dqrmN2.png" alt="VCT 2024">VCT 2024</a>
<a class="wf-module-item" href="/vct-2023"><img src="https://i.imgur.com/2dqrmN2.png" alt="VCT 2023">VCT 2023</a>
<a class="wf-module-item" href="/vct-2022"><img src="https://i.imgur.com/wiQInjN.png" alt="VCT 2022">VCT 2022</a>
<a class="wf-module-item" href="/vct-2021"><img src="https://i.imgur.com/bgkt9iS.png" alt="VCT 2021">VCT 2021</a>
Expand All @@ -121,6 +134,8 @@ $(".header-switch, .mod-dropdown").on("keydown", function (event) {
$(".header-menu-item:first").before(`
<div class="header-menu-item dropdown">
<i class="fa fa-chevron-right"></i> Quick Links</div>
<a class="header-menu-item quick-link" href="/vct-2025">VCT 2025</a>
<a class="header-menu-item quick-link" href="/vct-2024">VCT 2024</a>
<a class="header-menu-item quick-link" href="/vct-2023">VCT 2023</a>
<a class="header-menu-item quick-link" href="/vct-2022">VCT 2022</a>
<a class="header-menu-item quick-link" href="/vct-2021">VCT 2021</a>
Expand Down
165 changes: 133 additions & 32 deletions src/trophies.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,150 @@
// Function to generate a single trophy item HTML
function generateTrophyItemHTML(trophy) {
const default_image = "https://i.imgur.com/GKATx36.png";
const trophy_image = trophy.image ? trophy.image : default_image;
//#NOTE: Browser console give error, but could be false positve as trophies work as e
// basic check to see if trophies.js is loaded
console.log('[BetterVLR] trophies.js loaded');
console.log('jQuery version:', $?.fn?.jquery || 'jQuery not loaded');

// Constants
const DEFAULT_IMAGE = "https://i.imgur.com/GKATx36.png";
const TROPHIES_API_URL = "https://json.link/6zoXT2JZBV.json";

// Cache for storing fetched trophies data
let cachedTrophies = null;

/**
* Generates HTML for a single trophy item
* @param {Object} trophy - The trophy object containing trophy data
* @returns {string} HTML string for the trophy item
*/
function generateTrophyItemHTML(trophy) {
const trophyImage = trophy.image || DEFAULT_IMAGE;
const eventTitle = trophy.event ? trophy.event : 'Trophy';

return `
<a class="wf-nav-item" href="${trophy.link}" style="padding: 5px">
<a class="wf-nav-item" href="${trophy.link || '#'}" style="padding: 5px">
<div class="wf-nav-item-title">
<img src="${trophy_image}" height="36" width="36" style="object-fit: cover;" title="${trophy.event}"></img>
<img src="${trophyImage}"
height="36"
width="36"
style="object-fit: cover;"
title="${eventTitle}"
alt="${eventTitle} trophy">
</div>
</a>`;
}

// Function to generate trophy container HTML
function insertTrophies(selector, trophies_HTML) {
const trophies_container = `
<div class="wf-nav trophies">
${trophies_HTML}
</div>`;
/**
* Inserts trophies container after the specified selector
* @param {string} selector - CSS selector for the element to insert after
* @param {Array} trophies - Array of trophy objects
*/
function insertTrophies(selector, trophies) {
const $target = $(selector);
if (!$target.length || !trophies.length) return;

const trophiesHTML = trophies.map(generateTrophyItemHTML).join('');
const $trophiesContainer = $(`<div class="wf-nav trophies">${trophiesHTML}</div>`);

$target.after($trophiesContainer);
$trophiesContainer.find("> a:first").addClass("mod-first");
}

$(selector).after(trophies_container);
/**
* Fetches trophies data with caching
* @returns {Promise<Array>} Promise resolving to trophies data
*/
async function fetchTrophies() {
console.log('[BetterVLR] Fetching trophies...');
if (cachedTrophies) {
console.log('[BetterVLR] Using cached trophies');
return cachedTrophies;
}

$(".trophies > a:first").addClass("mod-first");
try {
console.log(`[BetterVLR] Making API request to: ${TROPHIES_API_URL}`);
const response = await $.getJSON(TROPHIES_API_URL);
console.log('[BetterVLR] API response received');
cachedTrophies = response.trophies || [];
console.log(`[BetterVLR] Found ${cachedTrophies.length} trophies`);
return cachedTrophies;
} catch (error) {
console.error('Failed to fetch trophies:', error);
return [];
}
}

const url = window.location.href;
if (url.includes("/team/")) {
$.getJSON("https://json.link/6zoXT2JZBV.json", function (data) {
const team_and_id = url.split("/").slice(-2).join("/");
/**
* Main function to initialize trophies display
*/
async function initTrophies() {
console.log('[BetterVLR] Initializing trophies...');
const url = window.location.href;
console.log(`[BetterVLR] Current URL: ${url}`);
let selector, filterFn;

const trophies_data = data.trophies.filter(trophy => trophy.id + "/" + trophy.team.toLowerCase() === team_and_id);
const trophies_HTML = trophies_data.map(generateTrophyItemHTML).join("");
if (url.includes("/team/")) {
const teamAndId = url.split("/").slice(-2).join("/");
console.log(`[BetterVLR] Detected team page. Team ID: ${teamAndId}`);
selector = ".team-header";
filterFn = trophy => {
const trophyId = `${trophy.id}/${trophy.team?.toLowerCase()}`;
const isMatch = trophyId === teamAndId;
if (isMatch) {
console.log(`[BetterVLR] Found matching trophy:`, trophy);
}
return isMatch;
};
}
else if (url.includes("/player/")) {
const playerAndId = url.split("/").slice(-2).join("/");
selector = ".player-header";
filterFn = trophy =>
trophy.players?.some(player =>
`${player.id}/${player.alias?.toLowerCase()}` === playerAndId
);
}
else {
return; // Not a team or player page
}

if (trophies_HTML) {
insertTrophies(".team-header", trophies_HTML);
}
});
} else if (url.includes("/player/")) {
$.getJSON("https://json.link/6zoXT2JZBV.json", function (data) {
const player_and_id = url.split("/").slice(-2).join("/");
const allTrophies = await fetchTrophies();
console.log(`[BetterVLR] Total trophies: ${allTrophies.length}`);

const filteredTrophies = allTrophies.filter(filterFn);
console.log(`[BetterVLR] Filtered trophies: ${filteredTrophies.length}`);

if (filteredTrophies.length > 0) {
console.log(`[BetterVLR] Inserting ${filteredTrophies.length} trophies after selector: ${selector}`);
console.log('Target element exists:', $(selector).length > 0);
insertTrophies(selector, filteredTrophies);
} else {
console.log('[BetterVLR] No matching trophies found');
}

const trophies_data = data.trophies.filter(trophy => trophy.players.some(player => player.id + "/" + player.alias.toLowerCase() === player_and_id));
const trophies_HTML = trophies_data.map(generateTrophyItemHTML).join("");
}

if (trophies_HTML) {
insertTrophies(".player-header", trophies_HTML);
// Wrap the initialization in a function that can be called from bettervlr.js
window.initTrophies = function () {
$(document).ready(async () => {
try {
console.log('[BetterVLR] Document ready, initializing trophies...');
await initTrophies();
console.log('[BetterVLR] Trophy initialization complete');
} catch (error) {
console.error('[BetterVLR] Error initializing trophies:', error);
}
});
}
};

// Call it immediately in case bettervlr.js is loaded after this script
initTrophies();

// Initialize the trophies when the document is ready
$(document).ready(async () => {
try {
console.log('[BetterVLR] Document ready, initializing trophies...');
await initTrophies();
console.log('[BetterVLR] Trophy initialization complete');
} catch (error) {
console.error('[BetterVLR] Error initializing trophies:', error);
}
});