Add pagination system to mod search

This commit is contained in:
2026-02-25 20:21:07 +01:00
parent 53f1afcf66
commit c47a877a36
4 changed files with 129 additions and 56 deletions

11
main.js
View File

@@ -33,7 +33,9 @@ let sevenZipPath = path7za;
const Nexus = NexusModule.default; const Nexus = NexusModule.default;
let nexus; let nexus;
let installedCachedModList; let installedCachedModList;
let installedTotalModsCount;
let onlineCachedModList; let onlineCachedModList;
let onlineTotalModsCount;
const bepinexFiles = [".doorstop_version", "changelog.txt", "doorstop_config.ini", "winhttp.dll"]; const bepinexFiles = [".doorstop_version", "changelog.txt", "doorstop_config.ini", "winhttp.dll"];
let bepinexVersion; let bepinexVersion;
@@ -438,12 +440,12 @@ ipcMain.handle("get-mods", async (event, type) => {
if (!installedCachedModList) { if (!installedCachedModList) {
await searchInstalledMods(""); await searchInstalledMods("");
} }
return installedCachedModList; return { modsInfo: installedCachedModList, installedTotalCount: installedTotalModsCount };
} else if (type == "mods-online") { } else if (type == "mods-online") {
if (!onlineCachedModList) { if (!onlineCachedModList) {
await searchNexusMods(""); await searchNexusMods("");
} }
return onlineCachedModList; return { mods: onlineCachedModList, onlineTotalCount: onlineTotalModsCount };
} }
}); });
@@ -603,7 +605,7 @@ async function searchNexusMods(keywords, offset = 0, count = 10, sortFilter = "d
} }
} }
return data.mods.totalCount; onlineTotalModsCount = data.mods.totalCount;
} }
ipcMain.handle("search-installed-mods", async (event, keywords, offset, count, sortFilter, sortOrder) => { ipcMain.handle("search-installed-mods", async (event, keywords, offset, count, sortFilter, sortOrder) => {
@@ -629,7 +631,8 @@ async function searchInstalledMods(keywords, offset = 0, count = 10, sortFilter
modsInfoSorted = modsInfoFiltered.sort((a, b) => sortFactor * (a[sortFilter] - b[sortFilter])); modsInfoSorted = modsInfoFiltered.sort((a, b) => sortFactor * (a[sortFilter] - b[sortFilter]));
} }
installedCachedModList = modsInfoSorted; installedTotalModsCount = modsInfoSorted.length;
installedCachedModList = modsInfoSorted.slice(offset, offset + count);
} }
////////////////////////////////////////////////////// //////////////////////////////////////////////////////

View File

@@ -110,6 +110,16 @@
<button class="default-button square-button" onclick="inverseSort()"><img class="icons invert-color" id="sort-order-image" src="assets/icons/sort-order-1.svg" /></button> <button class="default-button square-button" onclick="inverseSort()"><img class="icons invert-color" id="sort-order-image" src="assets/icons/sort-order-1.svg" /></button>
</div> </div>
<div class="mods-container" id="mods-container"></div> <div class="mods-container" id="mods-container"></div>
<div class="separated-div">
<div class="horizontal-div">
<button class="default-button" onclick="changeModsPage('min')">First page</button>
<button class="default-button" onclick="changeModsPage(-1)">Previous</button>
</div>
<div class="horizontal-div">
<button class="default-button" onclick="changeModsPage(1)">Next</button>
<button class="default-button" onclick="changeModsPage('max')">Last page</button>
</div>
</div>
</template> </template>
<template id="online-mods-template"> <template id="online-mods-template">
@@ -133,6 +143,16 @@
<button class="default-button square-button" onclick="inverseSort()"><img class="icons invert-color" id="sort-order-image" src="assets/icons/sort-order-1.svg" /></button> <button class="default-button square-button" onclick="inverseSort()"><img class="icons invert-color" id="sort-order-image" src="assets/icons/sort-order-1.svg" /></button>
</div> </div>
<div class="mods-container" id="mods-container"></div> <div class="mods-container" id="mods-container"></div>
<div class="separated-div">
<div class="horizontal-div">
<button class="default-button" onclick="changeModsPage('min')">First page</button>
<button class="default-button" onclick="changeModsPage(-1)">Previous</button>
</div>
<div class="horizontal-div">
<button class="default-button" onclick="changeModsPage(1)">Next</button>
<button class="default-button" onclick="changeModsPage('max')">Last page</button>
</div>
</div>
</template> </template>
<template id="installed-mod-template"> <template id="installed-mod-template">

View File

@@ -11,12 +11,21 @@ const modTemplate = document.getElementById("mod-template");
let oldPage; let oldPage;
let actualTheme = []; let actualTheme = [];
let searchValueNexus = ""; let searchValueNexus = "";
let searchValueInstalled = ""; let searchValueInstalled = "";
let onlineSortFilter = "downloads"; let onlineSortFilter = "downloads";
let installedSortFilter = "name"; let installedSortFilter = "name";
let onlineSortOrder = "DESC"; let onlineSortOrder = "DESC";
let installedSortOrder = "ASC"; let installedSortOrder = "ASC";
let onlineOffset = 0;
let installedOffset = 0;
let lastOnlineOffset = 0;
let lastInstalledOffset = 0;
let onlineModsCount = 10;
let installedModsCount = 10;
let onlineModsTotalCount;
let installedModsTotalCount;
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
///////////////// CONST FOR WELCOME ////////////////// ///////////////// CONST FOR WELCOME //////////////////
@@ -87,7 +96,8 @@ async function navigate(page) {
toggleSelectedListButton("sort-menu", installedSortFilter); toggleSelectedListButton("sort-menu", installedSortFilter);
setSortOrderButton(); setSortOrderButton();
const modsInfo = await nexus.getMods(page); const { modsInfo, installedTotalCount } = await nexus.getMods(page);
installedModsTotalCount = installedTotalCount;
if (modsInfo == []) { if (modsInfo == []) {
break; break;
} }
@@ -170,7 +180,8 @@ async function navigate(page) {
toggleSelectedListButton("sort-menu", onlineSortFilter); toggleSelectedListButton("sort-menu", onlineSortFilter);
setSortOrderButton(); setSortOrderButton();
mods = await nexus.getMods(page); const { mods, onlineTotalCount } = await nexus.getMods(page);
onlineModsTotalCount = onlineTotalCount;
if (mods == undefined) { if (mods == undefined) {
break; break;
} }
@@ -435,7 +446,7 @@ async function setBepinexVersion() {
async function searchInstalledMods() { async function searchInstalledMods() {
const searchInput = document.getElementById("search-input"); const searchInput = document.getElementById("search-input");
searchValueInstalled = searchInput.value; searchValueInstalled = searchInput.value;
await nexus.searchInstalled(searchValueInstalled, undefined, undefined, installedSortFilter, installedSortOrder); await nexus.searchInstalled(searchValueInstalled, installedOffset, installedModsCount, installedSortFilter, installedSortOrder);
await navigate("refresh"); await navigate("refresh");
} }
@@ -460,7 +471,7 @@ async function verifyNexusAPI() {
async function searchNexusMods() { async function searchNexusMods() {
let searchInput = document.getElementById("search-input"); let searchInput = document.getElementById("search-input");
searchValueNexus = searchInput.value; searchValueNexus = searchInput.value;
await nexus.search(searchValueNexus, undefined, undefined, onlineSortFilter, onlineSortOrder); await nexus.search(searchValueNexus, onlineOffset, onlineModsCount, onlineSortFilter, onlineSortOrder);
await navigate("refresh"); await navigate("refresh");
searchInput = document.getElementById("search-input"); searchInput = document.getElementById("search-input");
searchInput.value = searchValueNexus; searchInput.value = searchValueNexus;
@@ -493,7 +504,7 @@ async function resetNexusAPI() {
} }
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
/////////////////////// THEMES /////////////////////// //////////////// THEMES / SORT / LIST ////////////////
function toggleThemesMenu() { function toggleThemesMenu() {
const themesMenu = document.getElementById("themes-menu"); const themesMenu = document.getElementById("themes-menu");
@@ -557,38 +568,6 @@ function changeTheme(theme, state) {
backgroundVideo.src = backgroundVideoPath; backgroundVideo.src = backgroundVideoPath;
} }
//////////////////////////////////////////////////////
//////////////////// UNCATEGORIZE ////////////////////
async function launch(mode) {
await electronAPI.launchGame(mode);
setBepinexVersion();
}
async function autoDetectGamePath() {
await files.autoDetectGamePath();
if (document.getElementById("silksong-path-input")) {
document.getElementById("silksong-path-input").value = await files.loadSilksongPath();
}
}
function showToast(message, type = "info", duration = 3000) {
const toastDiv = document.getElementById("toast-div");
const toast = document.createElement("p");
toast.classList.add("toast", type);
toast.innerText = message;
toastDiv.appendChild(toast);
toast.classList.add("show");
setTimeout(() => {
toast.classList.remove("show");
toast.addEventListener("transitionend", () => toast.remove());
}, duration);
}
electronAPI.onShowToast(showToast);
function toggleSortMenu() { function toggleSortMenu() {
const sortMenu = document.getElementById("sort-menu"); const sortMenu = document.getElementById("sort-menu");
if (sortMenu) { if (sortMenu) {
@@ -596,6 +575,24 @@ function toggleSortMenu() {
} }
} }
function setSortOrderButton() {
let sortOrder;
if (oldPage == "mods-installed") {
sortOrder = installedSortOrder;
} else if (oldPage == "mods-online") {
sortOrder = onlineSortOrder;
}
const sortOrderButton = document.getElementById("sort-order-image");
if (sortOrderButton) {
if (sortOrder == "ASC") {
sortOrderButton.src = "assets/icons/sort-order-2.svg";
} else {
sortOrderButton.src = "assets/icons/sort-order-1.svg";
}
}
}
function changeSort(sortFilterParameter) { function changeSort(sortFilterParameter) {
toggleSortMenu(); toggleSortMenu();
toggleSelectedListButton("sort-menu", sortFilterParameter); toggleSelectedListButton("sort-menu", sortFilterParameter);
@@ -641,20 +638,70 @@ function toggleSelectedListButton(ListMenuId, buttonId) {
} }
} }
function setSortOrderButton() { //////////////////////////////////////////////////////
let sortOrder; //////////////////// UNCATEGORIZE ////////////////////
if (oldPage == "mods-installed") {
sortOrder = installedSortOrder; async function launch(mode) {
} else if (oldPage == "mods-online") { await electronAPI.launchGame(mode);
sortOrder = onlineSortOrder; setBepinexVersion();
} }
const sortOrderButton = document.getElementById("sort-order-image"); async function autoDetectGamePath() {
if (sortOrderButton) { await files.autoDetectGamePath();
if (sortOrder == "ASC") { if (document.getElementById("silksong-path-input")) {
sortOrderButton.src = "assets/icons/sort-order-2.svg"; document.getElementById("silksong-path-input").value = await files.loadSilksongPath();
}
}
function showToast(message, type = "info", duration = 3000) {
const toastDiv = document.getElementById("toast-div");
const toast = document.createElement("p");
toast.classList.add("toast", type);
toast.innerText = message;
toastDiv.appendChild(toast);
toast.classList.add("show");
setTimeout(() => {
toast.classList.remove("show");
toast.addEventListener("transitionend", () => toast.remove());
}, duration);
}
electronAPI.onShowToast(showToast);
function changeModsPage(offsetChange) {
if (oldPage == "mods-installed") {
if (offsetChange == "min") {
installedOffset = 0;
} else if (offsetChange == "max") {
installedOffset = installedModsTotalCount;
} else { } else {
sortOrderButton.src = "assets/icons/sort-order-1.svg"; installedOffset += installedModsCount * offsetChange;
installedOffset = clamp(installedOffset, 0, installedModsTotalCount);
}
installedOffset = Math.floor(installedOffset / 10) * 10;
if (lastInstalledOffset != installedOffset) {
lastInstalledOffset = installedOffset;
searchInstalledMods();
}
} else if (oldPage == "mods-online") {
if (offsetChange == "min") {
onlineOffset = 0;
} else if (offsetChange == "max") {
onlineOffset = onlineModsTotalCount;
} else {
onlineOffset += onlineModsCount * offsetChange;
onlineOffset = clamp(onlineOffset, 0, onlineModsTotalCount);
}
onlineOffset = Math.floor(onlineOffset / 10) * 10;
if (lastOnlineOffset != onlineOffset) {
lastOnlineOffset = onlineOffset;
searchNexusMods();
} }
} }
} }
function clamp(number, min, max) {
return Math.max(min, Math.min(number, max));
}

View File

@@ -138,6 +138,8 @@ body {
} }
.view { .view {
display: flex;
flex-direction: column;
background: var(--darker-transparent-black); background: var(--darker-transparent-black);
border-radius: 12px; border-radius: 12px;
padding: 40px; padding: 40px;
@@ -242,10 +244,11 @@ body {
} }
.mods-container { .mods-container {
height: 70%; flex: 1;
transform: translateY(50px);
padding: 20px;
overflow: auto; overflow: auto;
margin-top: 20px;
margin-bottom: 20px;
padding-right: 10px;
} }
.mod-container { .mod-container {