refactor: project saving logic (#5225)

* fix: project data saving not visually shown immediately

* feat: useSavable improvements

* feat: migrate where possible to useSavable

* fix: gitignore

* feat: use es-toolkit
This commit is contained in:
Calum H.
2026-01-28 16:46:14 +00:00
committed by GitHub
parent e57c15b3ce
commit 400c571fe6
15 changed files with 699 additions and 507 deletions

View File

@@ -1,5 +1,6 @@
<script setup lang="ts" generic="T">
import { HistoryIcon, SaveIcon, SpinnerIcon } from '@modrinth/assets'
import { isEqual } from 'es-toolkit'
import { type Component, computed } from 'vue'
import { defineMessage, type MessageDescriptor, useVIntl } from '../../composables/i18n'
@@ -38,15 +39,9 @@ const props = withDefaults(
},
)
const shown = computed(() => {
let changed = false
for (const key of Object.keys(props.modified)) {
if (props.original[key] !== props.modified[key]) {
changed = true
}
}
return changed
})
const shown = computed(() =>
Object.keys(props.modified).some((key) => !isEqual(props.original[key], props.modified[key])),
)
function localizeIfPossible(message: MessageDescriptor | string) {
return typeof message === 'string' ? message : formatMessage(message)

View File

@@ -12,7 +12,7 @@ import {
useSavable,
useVIntl,
} from '@modrinth/ui'
import { computed, ref } from 'vue'
import { computed } from 'vue'
const { formatMessage } = useVIntl()
@@ -20,8 +20,6 @@ const { currentMember, projectV2, projectV3, refreshProject } = injectProjectPag
const { handleError } = injectNotificationManager()
const client = injectModrinthClient()
const saving = ref(false)
const supportsEnvironment = computed(() =>
projectV3.value.project_types.some((type) => ['mod', 'modpack'].includes(type)),
)
@@ -36,26 +34,29 @@ const needsToVerify = computed(
const hasPermission = computed(() => {
const EDIT_DETAILS = 1 << 2
return (currentMember.value?.permissions & EDIT_DETAILS) === EDIT_DETAILS
return ((currentMember.value?.permissions ?? 0) & EDIT_DETAILS) === EDIT_DETAILS
})
function getInitialEnv() {
return projectV3.value.environment?.length === 1 ? projectV3.value.environment[0] : undefined
}
const { saved, current, reset, save } = useSavable(
const { saved, current, saving, reset, save } = useSavable(
() => ({
environment: getInitialEnv(),
side_types_migration_review_status: projectV3.value.side_types_migration_review_status,
}),
({ environment, side_types_migration_review_status }) => {
saving.value = true
side_types_migration_review_status = 'reviewed'
client.labrinth.projects_v3
.edit(projectV2.value.id, { environment, side_types_migration_review_status })
.then(() => refreshProject().then(reset))
.catch(handleError)
.finally(() => (saving.value = false))
async ({ environment }) => {
try {
await client.labrinth.projects_v3.edit(projectV2.value.id, {
environment,
side_types_migration_review_status: 'reviewed',
})
await refreshProject()
reset()
} catch (err) {
handleError(err as Error)
}
},
)
// Set current to reviewed, which will trigger unsaved changes popup.