diff --git a/.env.development b/.env.development index 10b1237..cd1c9c3 100644 --- a/.env.development +++ b/.env.development @@ -1,4 +1,4 @@ -VITE_APP_VERSION="3.0.27" +VITE_APP_VERSION="3.0.28" VITE_API_URL="http://10.5.7.5:8000/" VITE_API_KEY="your_api_key_should_be_here" VITE_ASSET_PATH="/assets" diff --git a/.env.production b/.env.production index 46c01ff..8682841 100644 --- a/.env.production +++ b/.env.production @@ -1,4 +1,4 @@ -VITE_APP_VERSION="3.0.27" +VITE_APP_VERSION="3.0.28" VITE_API_URL="https://restfulsleep.phaseii.network" VITE_API_KEY="your_api_key_should_be_here" VITE_ASSET_PATH="https://cdn.phaseii.network/file/PhaseII/web-assets" diff --git a/public/assets/games/ddr/card/20.webp b/public/assets/games/ddr/card/20.webp new file mode 100644 index 0000000..de028f0 Binary files /dev/null and b/public/assets/games/ddr/card/20.webp differ diff --git a/public/data-sources/changelog.json b/public/data-sources/changelog.json index 94b86b7..cc8849f 100644 --- a/public/data-sources/changelog.json +++ b/public/data-sources/changelog.json @@ -26,5 +26,6 @@ "3.0.24": ["- (Bugfix) Fix theme forcing for dark mode", "- (Bugfix) Fix animations across entire app", "- (Bugfix) Fix cursor on login screen easter egg", "- (Minor) Add new greeting"], "3.0.25-oMini": ["- (Major ++) Move from Material Design Icons to Phosphor Icons. Icons are currently set to their initial picks, but may change (suggest a change!)", "- (Major) Add initial icon animations, start work on icon color standards", "- (Optimization) Improve random greeting selection (SoftieTechCat) ", "- (Minor) Fix ESlint config"], "3.0.26": ["- (Minor) Game player table is more sortable", "- (Minor) Greetings now support custom styling", "- (Minor) Added the first styled greeting"], - "3.0.27": ["- (Major) Profile data exporting added.", "- (Minor) More work for rivals."] + "3.0.27": ["- (Major) Profile data exporting added.", "- (Minor) More work for rivals."], + "3.0.28": ["- (Major) Full support for rivals across applicable games", "- (Major) Move from Vue Hash routing to standard routing", "- (Bugfix) Fix issue when customizing on iOS"] } \ No newline at end of file diff --git a/src/components/ArcadeCard.vue b/src/components/ArcadeCard.vue index 7b02d76..809ef37 100644 --- a/src/components/ArcadeCard.vue +++ b/src/components/ArcadeCard.vue @@ -95,26 +95,26 @@ function getCardStyle(path) {
setTimeout(resolve, 200)); + } + const userId = mainStore.userId; + + try { + await mainStore.callApi(`/profile/${game}/link`, "PUT", { + version: version, + userId: userId, + otherUserId: otherUserId, + type: type, + }); + return true; + } catch (error) { + console.log("Error putting profile link:", error); + throw error; + } +} + +export async function APIDeleteLink(game, version, otherUserId, type) { + while (!mainStore.userId) { + await new Promise((resolve) => setTimeout(resolve, 200)); + } + const userId = mainStore.userId; + + const confirmed = window.confirm("Are you really?"); + if (confirmed) { + try { + await mainStore.callApi(`/profile/${game}/link`, "DELETE", { + version: version, + userId: userId, + otherUserId: otherUserId, + type: type, + }); + return true; + } catch (error) { + console.log("Error deleting profile link:", error); + throw error; + } + } else { + return false; + } +} diff --git a/src/views/Arcade/ClaimView.vue b/src/views/Arcade/ClaimView.vue index 67062a7..879d8c8 100644 --- a/src/views/Arcade/ClaimView.vue +++ b/src/views/Arcade/ClaimView.vue @@ -132,7 +132,7 @@ async function saveSettings() {
diff --git a/src/views/Auth/LoginView.vue b/src/views/Auth/LoginView.vue index 5d81ebc..5471a4f 100644 --- a/src/views/Auth/LoginView.vue +++ b/src/views/Auth/LoginView.vue @@ -100,18 +100,10 @@ const submit = async () => {

Not Registered?

- +

Forgot Password?

- +
diff --git a/src/views/Auth/RegisterView.vue b/src/views/Auth/RegisterView.vue index daa76fe..e9d5ed3 100644 --- a/src/views/Auth/RegisterView.vue +++ b/src/views/Auth/RegisterView.vue @@ -186,7 +186,7 @@ async function registerProfile() {

Have an Account?

- +
diff --git a/src/views/Auth/ResetView.vue b/src/views/Auth/ResetView.vue index 248791d..2647058 100644 --- a/src/views/Auth/ResetView.vue +++ b/src/views/Auth/ResetView.vue @@ -177,7 +177,7 @@ async function resetPassword() {

Remember it?

- +
diff --git a/src/views/ErrorView.vue b/src/views/ErrorView.vue index 298f2f1..85db1d8 100644 --- a/src/views/ErrorView.vue +++ b/src/views/ErrorView.vue @@ -26,7 +26,7 @@ import LayoutGuest from "@/layouts/LayoutGuest.vue";

The server was unable to locate the page you're trying to go to.

- + diff --git a/src/views/Game/NetworkRecords.vue b/src/views/Game/NetworkRecords.vue index 74e1a5e..edec9f2 100644 --- a/src/views/Game/NetworkRecords.vue +++ b/src/views/Game/NetworkRecords.vue @@ -87,7 +87,7 @@ const filteredSongs = computed(() => { diff --git a/src/views/Game/PersonalRecords.vue b/src/views/Game/PersonalRecords.vue index 5a1a7c3..d637039 100644 --- a/src/views/Game/PersonalRecords.vue +++ b/src/views/Game/PersonalRecords.vue @@ -92,14 +92,14 @@ const filteredSongs = computed(() => {
{
diff --git a/src/views/Game/PersonalScores.vue b/src/views/Game/PersonalScores.vue index 2023022..02b331e 100644 --- a/src/views/Game/PersonalScores.vue +++ b/src/views/Game/PersonalScores.vue @@ -185,14 +185,14 @@ const navigateToSong = (item) => {
versionForm.currentVersion, @@ -41,19 +48,25 @@ watch( loadProfile(); loadLinks(); loadAllProfiles(); + versionMaxRivals(); }, ); onMounted(async () => { - loadAllProfiles(); - await loadProfile(); - loadLinks(); + await loadAll(); }); if (!thisGame.versions) { versionForm.currentVersion = 1; } +async function loadAll() { + loadAllProfiles(); + await loadProfile(); + loadLinks(); + filterForm.filter = null; +} + async function loadProfile() { try { profile.value = null; @@ -63,6 +76,10 @@ async function loadProfile() { if (data && !versionForm.currentVersion) { versionForm.currentVersion = data.versions[data.versions.length - 1]; } + + if (thisGame.useActiveRival) { + getActiveRivals(); + } } catch (error) { console.error("Failed to fetch user profile data:", error); } @@ -71,7 +88,7 @@ async function loadProfile() { async function loadLinks() { try { links.value = null; - const linkData = await APIGetLinks(gameID, versionForm.currentVersion); + var linkData = await APIGetLinks(gameID, versionForm.currentVersion); links.value = linkData; } catch (error) { console.error("Failed to fetch user link data:", error); @@ -111,19 +128,196 @@ if (!thisGame) { } function filterProfiles() { - if (filterForm.filter) { + var inputForm = JSON.parse(JSON.stringify(filterForm.filter)); + if (inputForm) { + inputForm = inputForm.replace(/-/g, ""); return allProfiles.value.filter( (rival) => - rival.username - .toLowerCase() - .includes(filterForm.filter.toLowerCase()) || - rival.extid - .toString() - .toLowerCase() - .includes(filterForm.filter.toLowerCase()), + rival.username.toLowerCase().includes(inputForm.toLowerCase()) || + rival.extid.toString().toLowerCase().includes(inputForm.toLowerCase()), ); } } + +function checkDisabled(rivalId) { + if (rivalId == profile.value?.userId) { + return true; + } + + if (links.value == null) { + return false; + } + + if (links.value.length >= maxRivals.value) { + return true; + } + + return links.value.some((link) => link.otherUserId === rivalId); +} + +function versionMaxRivals() { + const versionInfo = thisGame.versions.find( + (version) => version.id == versionForm.currentVersion, + ); + + maxRivals.value = versionInfo?.maxRivals ?? 3; + maxActiveRivals.value = versionInfo?.maxActiveRivals ?? 3; +} + +function getActiveRivals() { + if (!profile.value?.last) { + activeRivals.value = []; + return; + } + + var rivalList = []; + const keys = ["fri", "rival1", "rival2", "rival3"]; + for (const key of keys) { + const rivalId = profile.value?.last[key]; + if (rivalId >= 1) { + rivalList.push(rivalId); + } + } + + activeRivals.value = rivalList; +} + +async function addRival(otherUserId) { + if (links.value && links.value.length >= maxRivals.value) { + return; + } + + var type = "rival"; + if (thisGame?.useActiveRival) { + const usedTypes = new Set( + (links.value ?? []) + .map((link) => { + if (link?.type?.startsWith("friend_")) { + return parseInt(link.type.replace("friend_", ""), 10); + } + return null; + }) + .filter((v) => v !== null && !isNaN(v)), + ); + + var availableId = null; + for (let i = 0; i <= 9; i++) { + if (!usedTypes.has(i)) { + availableId = i; + break; + } + } + type = `friend_${availableId}`; + } + + try { + await APIPutLink(gameID, versionForm.currentVersion, otherUserId, type); + await loadAll(); + } catch (error) { + console.error("Failed to add rival:", error); + } +} + +async function deleteRival(otherUserId, type) { + try { + const deleteState = await APIDeleteLink( + gameID, + versionForm.currentVersion, + otherUserId, + type, + ); + if (deleteState) { + if (thisGame.useActiveRival) { + await setInactive(type); + } + } + + await loadAll(); + } catch (error) { + console.error("Failed to delete rival:", error); + } +} + +async function setActive(type) { + var lastObject = profile.value?.last ?? {}; + var rivalPosition = null; + if (type.startsWith("friend_")) { + rivalPosition = parseInt(type.replace("friend_", ""), 10); + } else { + return; + } + + if ([GameConstants.DDR, GameConstants.DDROMNI].includes(gameID)) { + if ( + [VersionConstants.DDR_X, VersionConstants.DDR_X2].includes( + versionForm.currentVersion, + ) + ) { + lastObject.fri = rivalPosition + 1; + } else { + if (!lastObject.rival1 || lastObject.rival1 < 1) { + lastObject.rival1 = rivalPosition + 1; + } else if (!lastObject.rival2 || lastObject.rival2 < 1) { + lastObject.rival2 = rivalPosition + 1; + } else if (!lastObject.rival3 || lastObject.rival3 < 1) { + lastObject.rival3 = rivalPosition + 1; + } + } + } + + await APIUpdateProfile(gameID, versionForm.currentVersion, { + last: lastObject, + }); + await loadAll(); +} + +async function setInactive(type) { + var lastObject = profile.value?.last ?? {}; + var rivalPosition = null; + + if (type.startsWith("friend_")) { + rivalPosition = parseInt(type.replace("friend_", ""), 10); + } else { + return; + } + + if ([GameConstants.DDR, GameConstants.DDROMNI].includes(gameID)) { + if ( + [VersionConstants.DDR_X, VersionConstants.DDR_X2].includes( + versionForm.currentVersion, + ) + ) { + if (lastObject.fri === rivalPosition + 1) { + lastObject.fri = 0; + } + } else { + if (lastObject.rival1 === rivalPosition + 1) { + lastObject.rival1 = 0; + } else if (lastObject.rival2 === rivalPosition + 1) { + lastObject.rival2 = 0; + } else if (lastObject.rival3 === rivalPosition + 1) { + lastObject.rival3 = 0; + } + } + } + + await APIUpdateProfile(gameID, versionForm.currentVersion, { + last: lastObject, + }); + await loadAll(); +} + +const getLinkNum = (type) => { + if (type.startsWith("friend_")) { + return parseInt(type.replace("friend_", ""), 10) + 1; + } else { + return; + } +}; + +const navigateToProfile = (userID) => { + $router.push(`/games/${gameID}/profiles/${userID}`); +};