diff --git a/apps/frontend/src/components/ui/moderation/ModpackPermissionsFlow.vue b/apps/frontend/src/components/ui/moderation/ModpackPermissionsFlow.vue index 124a49336f..cdb97d7c06 100644 --- a/apps/frontend/src/components/ui/moderation/ModpackPermissionsFlow.vue +++ b/apps/frontend/src/components/ui/moderation/ModpackPermissionsFlow.vue @@ -8,7 +8,7 @@
Loading data...
-

All permissions obtained. You may skip this step!

+

All permissions already obtained.

@@ -157,7 +157,7 @@ import type { } from "@modrinth/utils"; import { ButtonStyled } from "@modrinth/ui"; import { ref, computed, watch, onMounted } from "vue"; -import { useLocalStorage } from "@vueuse/core"; +import { useLocalStorage, useSessionStorage } from "@vueuse/core"; const props = defineProps<{ projectId: string; @@ -182,7 +182,26 @@ const persistedModPackData = useLocalStorage( const persistedIndex = useLocalStorage(`modpack-permissions-index-${props.projectId}`, 0); -const modPackData = ref(null); +const modPackData = useSessionStorage( + `modpack-permissions-data-${props.projectId}`, + null, + { + serializer: { + read: (v: any) => (v ? JSON.parse(v) : null), + write: (v: any) => JSON.stringify(v), + }, + }, +); +const permanentNoFiles = useSessionStorage( + `modpack-permissions-permanent-no-${props.projectId}`, + [], + { + serializer: { + read: (v: any) => (v ? JSON.parse(v) : []), + write: (v: any) => JSON.stringify(v), + }, + }, +); const currentIndex = ref(0); const fileApprovalTypes: ModerationModpackPermissionApprovalType[] = [ @@ -251,7 +270,45 @@ async function fetchModPackData(): Promise { const data = (await useBaseFetch(`moderation/project/${props.projectId}`, { internal: true, })) as ModerationModpackResponse; + + const permanentNoItems: ModerationModpackItem[] = Object.entries(data.identified || {}) + .filter(([_, file]) => file.status === "permanent-no") + .map( + ([sha1, file]): ModerationModpackItem => ({ + sha1, + file_name: file.file_name, + type: "identified", + status: file.status, + approved: null, + }), + ) + .sort((a, b) => a.file_name.localeCompare(b.file_name)); + + permanentNoFiles.value = permanentNoItems; + const sortedData: ModerationModpackItem[] = [ + ...Object.entries(data.identified || {}) + .filter( + ([_, file]) => + file.status !== "yes" && + file.status !== "with-attribution-and-source" && + file.status !== "permanent-no", + ) + .map( + ([sha1, file]): ModerationModpackItem => ({ + sha1, + file_name: file.file_name, + type: "identified", + status: file.status, + approved: null, + ...(file.status === "unidentified" && { + proof: "", + url: "", + title: "", + }), + }), + ) + .sort((a, b) => a.file_name.localeCompare(b.file_name)), ...Object.entries(data.unknown_files || {}) .map( ([sha1, fileName]): ModerationUnknownModpackItem => ({ @@ -310,6 +367,7 @@ async function fetchModPackData(): Promise { } catch (error) { console.error("Failed to fetch modpack data:", error); modPackData.value = []; + permanentNoFiles.value = []; persistAll(); } } @@ -321,6 +379,14 @@ function goToPrevious(): void { } } +watch( + modPackData, + (newValue) => { + persistedModPackData.value = newValue; + }, + { deep: true }, +); + function goToNext(): void { if (modPackData.value && currentIndex.value < modPackData.value.length) { currentIndex.value++; @@ -396,6 +462,17 @@ onMounted(() => { } }); +watch( + modPackData, + (newValue) => { + if (newValue && newValue.length === 0) { + emit("complete"); + clearPersistedData(); + } + }, + { immediate: true }, +); + watch( () => props.projectId, () => { @@ -406,6 +483,20 @@ watch( } }, ); + +function getModpackFiles(): { + interactive: ModerationModpackItem[]; + permanentNo: ModerationModpackItem[]; +} { + return { + interactive: modPackData.value || [], + permanentNo: permanentNoFiles.value, + }; +} + +defineExpose({ + getModpackFiles, +});