fix: final content tab qa (#5611)
* fix: queued admonition always showing * fix: dont apply grayscale to checkbox in content card item * fix: actual stable id for disable/enable/bulk state * fix: vue-router resolve workaround * fix: show disable/enable btns same time * fix: remove mr-2 on toggle * fix: type errors + add ModpackAlreadyInstalledModal * fix: bulk actions + overflow menu hitting ad container * fix: responsiveness of ContentSelectionBar * feat: better backup naming for inline backups + sorting fixes * fix: lint * fix: typo
This commit is contained in:
@@ -68,11 +68,11 @@ import ErrorModal from '@/components/ui/ErrorModal.vue'
|
||||
import FriendsList from '@/components/ui/friends/FriendsList.vue'
|
||||
import AddServerToInstanceModal from '@/components/ui/install_flow/AddServerToInstanceModal.vue'
|
||||
import IncompatibilityWarningModal from '@/components/ui/install_flow/IncompatibilityWarningModal.vue'
|
||||
import InstallConfirmModal from '@/components/ui/install_flow/InstallConfirmModal.vue'
|
||||
import MinecraftAuthErrorModal from '@/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue'
|
||||
import AppSettingsModal from '@/components/ui/modal/AppSettingsModal.vue'
|
||||
import AuthGrantFlowWaitModal from '@/components/ui/modal/AuthGrantFlowWaitModal.vue'
|
||||
import InstallToPlayModal from '@/components/ui/modal/InstallToPlayModal.vue'
|
||||
import ModpackAlreadyInstalledModal from '@/components/ui/modal/ModpackAlreadyInstalledModal.vue'
|
||||
import UpdateToPlayModal from '@/components/ui/modal/UpdateToPlayModal.vue'
|
||||
import NavButton from '@/components/ui/NavButton.vue'
|
||||
import PromotionWrapper from '@/components/ui/PromotionWrapper.vue'
|
||||
@@ -151,6 +151,9 @@ const {
|
||||
handleBrowseModpacks,
|
||||
searchModpacks,
|
||||
getProjectVersions,
|
||||
setModpackAlreadyInstalledModal,
|
||||
handleModpackDuplicateCreateAnyway,
|
||||
handleModpackDuplicateGoToInstance,
|
||||
} = setupProviders(notificationManager)
|
||||
|
||||
const news = ref([])
|
||||
@@ -424,7 +427,9 @@ const {
|
||||
handleNavigate: handleContentInstallNavigate,
|
||||
handleCancel: handleContentInstallCancel,
|
||||
setContentInstallModal,
|
||||
setInstallConfirmModal: setContentInstallConfirmModal,
|
||||
setModpackAlreadyInstalledModal: setContentInstallModpackAlreadyInstalledModal,
|
||||
handleModpackDuplicateCreateAnyway: handleContentInstallModpackDuplicateCreateAnyway,
|
||||
handleModpackDuplicateGoToInstance: handleContentInstallModpackDuplicateGoToInstance,
|
||||
setIncompatibilityWarningModal: setContentIncompatibilityWarningModal,
|
||||
} = contentInstall
|
||||
|
||||
@@ -438,8 +443,9 @@ const {
|
||||
} = serverInstall
|
||||
|
||||
const modInstallModal = ref()
|
||||
const modpackAlreadyInstalledModal = ref()
|
||||
const contentInstallModpackAlreadyInstalledModal = ref()
|
||||
const addServerToInstanceModal = ref()
|
||||
const installConfirmModal = ref()
|
||||
const incompatibilityWarningModal = ref()
|
||||
const installToPlayModal = ref()
|
||||
const updateToPlayModal = ref()
|
||||
@@ -519,8 +525,9 @@ onMounted(() => {
|
||||
error.setMinecraftAuthErrorModal(minecraftAuthErrorModal.value)
|
||||
|
||||
setContentIncompatibilityWarningModal(incompatibilityWarningModal.value)
|
||||
setContentInstallConfirmModal(installConfirmModal.value)
|
||||
setContentInstallModal(modInstallModal.value)
|
||||
setContentInstallModpackAlreadyInstalledModal(contentInstallModpackAlreadyInstalledModal.value)
|
||||
setModpackAlreadyInstalledModal(modpackAlreadyInstalledModal.value)
|
||||
setServerAddServerToInstanceModal(addServerToInstanceModal.value)
|
||||
setServerInstallToPlayModal(installToPlayModal.value)
|
||||
setServerUpdateToPlayModal(updateToPlayModal.value)
|
||||
@@ -1295,9 +1302,18 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
|
||||
@navigate="handleContentInstallNavigate"
|
||||
@cancel="handleContentInstallCancel"
|
||||
/>
|
||||
<ModpackAlreadyInstalledModal
|
||||
ref="modpackAlreadyInstalledModal"
|
||||
@create-anyway="handleModpackDuplicateCreateAnyway"
|
||||
@go-to-instance="handleModpackDuplicateGoToInstance"
|
||||
/>
|
||||
<AddServerToInstanceModal ref="addServerToInstanceModal" />
|
||||
<IncompatibilityWarningModal ref="incompatibilityWarningModal" />
|
||||
<InstallConfirmModal ref="installConfirmModal" />
|
||||
<ModpackAlreadyInstalledModal
|
||||
ref="contentInstallModpackAlreadyInstalledModal"
|
||||
@create-anyway="handleContentInstallModpackDuplicateCreateAnyway"
|
||||
@go-to-instance="handleContentInstallModpackDuplicateGoToInstance"
|
||||
/>
|
||||
<InstallToPlayModal ref="installToPlayModal" />
|
||||
<UpdateToPlayModal ref="updateToPlayModal" />
|
||||
</template>
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
<script setup>
|
||||
import { DownloadIcon, XIcon } from '@modrinth/assets'
|
||||
import { Button, injectNotificationManager } from '@modrinth/ui'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||
import { trackEvent } from '@/helpers/analytics'
|
||||
import { create_profile_and_install as pack_install } from '@/helpers/pack'
|
||||
|
||||
const { handleError } = injectNotificationManager()
|
||||
|
||||
const versionId = ref()
|
||||
const project = ref()
|
||||
const confirmModal = ref(null)
|
||||
const installing = ref(false)
|
||||
|
||||
const onInstall = ref(() => {})
|
||||
const onCreateInstance = ref(() => {})
|
||||
|
||||
defineExpose({
|
||||
show: (projectVal, versionIdVal, callback, createInstanceCallback) => {
|
||||
project.value = projectVal
|
||||
versionId.value = versionIdVal
|
||||
installing.value = false
|
||||
confirmModal.value.show()
|
||||
|
||||
onInstall.value = callback
|
||||
onCreateInstance.value = createInstanceCallback
|
||||
|
||||
trackEvent('PackInstallStart')
|
||||
},
|
||||
})
|
||||
|
||||
async function install() {
|
||||
installing.value = true
|
||||
confirmModal.value.hide()
|
||||
|
||||
await pack_install(
|
||||
project.value.id,
|
||||
versionId.value,
|
||||
project.value.title,
|
||||
project.value.icon_url,
|
||||
onCreateInstance.value,
|
||||
).catch(handleError)
|
||||
trackEvent('PackInstall', {
|
||||
id: project.value.id,
|
||||
version_id: versionId.value,
|
||||
title: project.value.title,
|
||||
source: 'ConfirmModal',
|
||||
})
|
||||
|
||||
onInstall.value(versionId.value)
|
||||
installing.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ModalWrapper ref="confirmModal" header="Are you sure?" :on-hide="onInstall">
|
||||
<div class="modal-body">
|
||||
<p>You already have this modpack installed. Are you sure you want to install it again?</p>
|
||||
<div class="input-group push-right">
|
||||
<Button @click="() => $refs.confirmModal.hide()"><XIcon />Cancel</Button>
|
||||
<Button color="primary" :disabled="installing" @click="install()"
|
||||
><DownloadIcon /> {{ installing ? 'Installing' : 'Install' }}</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.modal-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<NewModal ref="modal" :header="formatMessage(messages.header)" fade="warning" max-width="500px">
|
||||
<Admonition type="warning" :header="formatMessage(messages.admonitionHeader)">
|
||||
{{ formatMessage(messages.admonitionBody, { instanceName }) }}
|
||||
</Admonition>
|
||||
|
||||
<template #actions>
|
||||
<div class="flex gap-2 justify-end">
|
||||
<ButtonStyled type="outlined">
|
||||
<button class="!border !border-surface-4" @click="handleGoToInstance">
|
||||
<ExternalIcon />
|
||||
{{ formatMessage(messages.goToInstance) }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled color="orange">
|
||||
<button @click="handleCreateAnyway">
|
||||
<PlusIcon />
|
||||
{{ formatMessage(messages.createAnyway) }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</template>
|
||||
</NewModal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ExternalIcon, PlusIcon } from '@modrinth/assets'
|
||||
import { Admonition, ButtonStyled, defineMessages, NewModal, useVIntl } from '@modrinth/ui'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const messages = defineMessages({
|
||||
header: {
|
||||
id: 'app.instance.modpack-already-installed.header',
|
||||
defaultMessage: 'Modpack already installed',
|
||||
},
|
||||
admonitionHeader: {
|
||||
id: 'app.instance.modpack-already-installed.admonition-header',
|
||||
defaultMessage: 'Duplicate modpack',
|
||||
},
|
||||
admonitionBody: {
|
||||
id: 'app.instance.modpack-already-installed.admonition-body',
|
||||
defaultMessage: 'This modpack is already installed in the "{instanceName}" instance.',
|
||||
},
|
||||
goToInstance: {
|
||||
id: 'app.instance.modpack-already-installed.go-to-instance',
|
||||
defaultMessage: 'Go to instance',
|
||||
},
|
||||
createAnyway: {
|
||||
id: 'app.instance.modpack-already-installed.create-anyway',
|
||||
defaultMessage: 'Create anyway',
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'go-to-instance', instancePath: string): void
|
||||
(e: 'create-anyway'): void
|
||||
}>()
|
||||
|
||||
const modal = ref<InstanceType<typeof NewModal>>()
|
||||
const instanceName = ref('')
|
||||
const instancePath = ref('')
|
||||
|
||||
function show(name: string, path: string) {
|
||||
instanceName.value = name
|
||||
instancePath.value = path
|
||||
modal.value?.show()
|
||||
}
|
||||
|
||||
function handleGoToInstance() {
|
||||
modal.value?.hide()
|
||||
emit('go-to-instance', instancePath.value)
|
||||
}
|
||||
|
||||
function handleCreateAnyway() {
|
||||
modal.value?.hide()
|
||||
emit('create-anyway')
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
})
|
||||
</script>
|
||||
4
apps/app-frontend/src/helpers/types.d.ts
vendored
4
apps/app-frontend/src/helpers/types.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
import type { ModrinthId } from '@modrinth/utils'
|
||||
|
||||
type GameInstance = {
|
||||
export type GameInstance = {
|
||||
path: string
|
||||
install_stage: InstallStage
|
||||
|
||||
@@ -46,7 +46,7 @@ type LinkedData = {
|
||||
locked: boolean
|
||||
}
|
||||
|
||||
type InstanceLoader = 'vanilla' | 'forge' | 'fabric' | 'quilt' | 'neoforge'
|
||||
export type InstanceLoader = 'vanilla' | 'forge' | 'fabric' | 'quilt' | 'neoforge'
|
||||
|
||||
type ContentFile = {
|
||||
metadata?: {
|
||||
|
||||
@@ -41,6 +41,21 @@
|
||||
"app.instance.confirm-delete.header": {
|
||||
"message": "Delete instance"
|
||||
},
|
||||
"app.instance.modpack-already-installed.admonition-body": {
|
||||
"message": "This modpack is already installed in the \"{instanceName}\" instance."
|
||||
},
|
||||
"app.instance.modpack-already-installed.admonition-header": {
|
||||
"message": "Duplicate modpack"
|
||||
},
|
||||
"app.instance.modpack-already-installed.create-anyway": {
|
||||
"message": "Create anyway"
|
||||
},
|
||||
"app.instance.modpack-already-installed.go-to-instance": {
|
||||
"message": "Go to instance"
|
||||
},
|
||||
"app.instance.modpack-already-installed.header": {
|
||||
"message": "Modpack already installed"
|
||||
},
|
||||
"app.instance.mods.content-type-project": {
|
||||
"message": "project"
|
||||
},
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
<ConfirmModpackUpdateModal
|
||||
ref="modpackUpdateConfirmModal"
|
||||
:downgrade="isModpackUpdateDowngrade"
|
||||
:backup-tip="
|
||||
[linkedModpackProject?.title, pendingModpackUpdateVersion?.version_number]
|
||||
.filter(Boolean)
|
||||
.join(' ')
|
||||
"
|
||||
@confirm="handleModpackUpdateConfirm"
|
||||
@cancel="handleModpackUpdateCancel"
|
||||
/>
|
||||
@@ -471,7 +476,7 @@ async function handleModpackContentToggle(item: ContentItem) {
|
||||
}
|
||||
|
||||
async function handleModpackContentBulkToggle(items: ContentItem[]) {
|
||||
await Promise.all(items.map((item) => toggleDisableMod(item)))
|
||||
await Promise.all(items.map((item) => _toggleDisableMod(item)))
|
||||
}
|
||||
|
||||
async function handleModpackContent() {
|
||||
@@ -814,13 +819,12 @@ provideContentManager({
|
||||
isPackLocked,
|
||||
isBusy: isInstanceBusy,
|
||||
isBulkOperating,
|
||||
getItemId: (item) => item.file_path ?? item.file_name,
|
||||
contentTypeLabel: ref(formatMessage(messages.contentTypeProject)),
|
||||
toggleEnabled: toggleDisableMod,
|
||||
bulkEnableItems: (items) =>
|
||||
Promise.all(items.map((item) => toggleDisableMod(item))).then(() => {}),
|
||||
Promise.all(items.map((item) => _toggleDisableMod(item))).then(() => {}),
|
||||
bulkDisableItems: (items) =>
|
||||
Promise.all(items.map((item) => toggleDisableMod(item))).then(() => {}),
|
||||
Promise.all(items.map((item) => _toggleDisableMod(item))).then(() => {}),
|
||||
deleteItem: removeMod,
|
||||
bulkDeleteItems: (items) => Promise.all(items.map((item) => removeMod(item))).then(() => {}),
|
||||
refresh: () => initProjects('must_revalidate'),
|
||||
@@ -838,7 +842,7 @@ provideContentManager({
|
||||
dismissContentHint,
|
||||
shareItems: handleShareItems,
|
||||
mapToTableItem: (item) => ({
|
||||
id: item.file_path ?? item.file_name,
|
||||
id: item.id,
|
||||
project: item.project ?? {
|
||||
id: item.file_name,
|
||||
slug: null,
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
remove_project,
|
||||
} from '@/helpers/profile.js'
|
||||
import { get_game_versions } from '@/helpers/tags'
|
||||
import type { GameInstance, InstanceLoader } from '@/helpers/types'
|
||||
import {
|
||||
findPreferredVersion,
|
||||
installVersionDependencies,
|
||||
@@ -37,13 +38,8 @@ interface ModalRef {
|
||||
hide: () => void
|
||||
}
|
||||
|
||||
interface InstallConfirmModalRef {
|
||||
show: (
|
||||
project: Labrinth.Projects.v2.Project,
|
||||
version: string,
|
||||
callback: (versionId?: string) => void,
|
||||
createInstanceCallback: (profile: string) => void,
|
||||
) => void
|
||||
interface ModpackAlreadyInstalledModalRef {
|
||||
show: (instanceName: string, instancePath: string) => void
|
||||
}
|
||||
|
||||
interface IncompatibilityWarningModalRef {
|
||||
@@ -92,7 +88,9 @@ export interface ContentInstallContext {
|
||||
handleNavigate: (instance: ContentInstallInstance) => void
|
||||
handleCancel: () => void
|
||||
setContentInstallModal: (ref: ModalRef) => void
|
||||
setInstallConfirmModal: (ref: InstallConfirmModalRef) => void
|
||||
setModpackAlreadyInstalledModal: (ref: ModpackAlreadyInstalledModalRef) => void
|
||||
handleModpackDuplicateCreateAnyway: () => Promise<void>
|
||||
handleModpackDuplicateGoToInstance: (instancePath: string) => void
|
||||
setIncompatibilityWarningModal: (ref: IncompatibilityWarningModalRef) => void
|
||||
install: (
|
||||
projectId: string,
|
||||
@@ -140,12 +138,13 @@ export function createContentInstall(opts: {
|
||||
) {
|
||||
const primaryFile = version?.files?.find((f) => f.primary) ?? version?.files?.[0]
|
||||
const placeholder: ContentItem = {
|
||||
id: `__installing_${project.id}`,
|
||||
file_name: `__installing_${project.id}`,
|
||||
project: {
|
||||
id: project.id,
|
||||
slug: project.slug ?? null,
|
||||
slug: project.slug ?? '',
|
||||
title: project.title,
|
||||
icon_url: project.icon_url ?? null,
|
||||
icon_url: project.icon_url ?? undefined,
|
||||
},
|
||||
version: version
|
||||
? {
|
||||
@@ -183,18 +182,26 @@ export function createContentInstall(opts: {
|
||||
}
|
||||
|
||||
let modalRef: ModalRef | null = null
|
||||
let installConfirmModalRef: InstallConfirmModalRef | null = null
|
||||
let modpackAlreadyInstalledModalRef: ModpackAlreadyInstalledModalRef | null = null
|
||||
let incompatibilityWarningModalRef: IncompatibilityWarningModalRef | null = null
|
||||
let currentProject: Labrinth.Projects.v2.Project | null = null
|
||||
let currentVersions: Labrinth.Versions.v2.Version[] = []
|
||||
let currentCallback: (versionId?: string) => void = () => {}
|
||||
let profileMap: Record<string, GameInstance> = {}
|
||||
|
||||
let pendingModpackInstall: {
|
||||
project: Labrinth.Projects.v2.Project
|
||||
version: string
|
||||
source: string
|
||||
callback: (versionId?: string) => void
|
||||
createInstanceCallback: (profile: string) => void
|
||||
} | null = null
|
||||
|
||||
async function showModInstallModal(
|
||||
project: Labrinth.Projects.v2.Project,
|
||||
versions: Labrinth.Versions.v2.Version[],
|
||||
onInstall: (versionId?: string) => void,
|
||||
hints?: { preferredLoader?: string; preferredGameVersion?: string },
|
||||
hints?: { preferredLoader?: string; preferredGameVersion?: string; showProjectInfo?: boolean },
|
||||
) {
|
||||
currentProject = project
|
||||
currentVersions = versions
|
||||
@@ -379,10 +386,10 @@ export function createContentInstall(opts: {
|
||||
trackEvent('ProjectInstall', {
|
||||
loader: profile.loader,
|
||||
game_version: profile.game_version,
|
||||
id: currentProject.id,
|
||||
id: currentProject!.id,
|
||||
version_id: version.id,
|
||||
project_type: currentProject.project_type,
|
||||
title: currentProject.title,
|
||||
project_type: currentProject!.project_type,
|
||||
title: currentProject!.title,
|
||||
source: 'ProjectInstallModal',
|
||||
})
|
||||
currentCallback(version.id)
|
||||
@@ -433,10 +440,10 @@ export function createContentInstall(opts: {
|
||||
trackEvent('ProjectInstall', {
|
||||
loader: data.loader,
|
||||
game_version: data.gameVersion,
|
||||
id: currentProject.id,
|
||||
id: currentProject!.id,
|
||||
version_id: version.id,
|
||||
project_type: currentProject.project_type,
|
||||
title: currentProject.title,
|
||||
project_type: currentProject!.project_type,
|
||||
title: currentProject!.title,
|
||||
source: 'ProjectInstallModal',
|
||||
})
|
||||
|
||||
@@ -470,28 +477,28 @@ export function createContentInstall(opts: {
|
||||
if (project.project_type === 'modpack') {
|
||||
const version = versionId ?? project.versions[project.versions.length - 1]
|
||||
const packs = await list()
|
||||
const existingPack = packs.find((pack) => pack.linked_data?.project_id === project.id)
|
||||
|
||||
if (
|
||||
packs.length === 0 ||
|
||||
!packs.find((pack) => pack.linked_data?.project_id === project.id)
|
||||
) {
|
||||
await packInstall(
|
||||
project.id,
|
||||
version,
|
||||
project.title,
|
||||
project.icon_url,
|
||||
createInstanceCallback,
|
||||
)
|
||||
trackEvent('PackInstall', {
|
||||
id: project.id,
|
||||
version_id: version,
|
||||
title: project.title,
|
||||
source,
|
||||
})
|
||||
callback(version)
|
||||
} else {
|
||||
installConfirmModalRef?.show(project, version, callback, createInstanceCallback)
|
||||
if (existingPack) {
|
||||
pendingModpackInstall = { project, version, source, callback, createInstanceCallback }
|
||||
modpackAlreadyInstalledModalRef?.show(existingPack.name, existingPack.path)
|
||||
return
|
||||
}
|
||||
|
||||
await packInstall(
|
||||
project.id,
|
||||
version,
|
||||
project.title,
|
||||
project.icon_url,
|
||||
createInstanceCallback,
|
||||
)
|
||||
trackEvent('PackInstall', {
|
||||
id: project.id,
|
||||
version_id: version,
|
||||
title: project.title,
|
||||
source,
|
||||
})
|
||||
callback(version)
|
||||
} else if (instancePath) {
|
||||
const [instanceOrNull, instanceProjects, versions] = await Promise.all([
|
||||
get(instancePath),
|
||||
@@ -577,8 +584,31 @@ export function createContentInstall(opts: {
|
||||
setContentInstallModal(ref: ModalRef) {
|
||||
modalRef = ref
|
||||
},
|
||||
setInstallConfirmModal(ref: InstallConfirmModalRef) {
|
||||
installConfirmModalRef = ref
|
||||
setModpackAlreadyInstalledModal(ref: ModpackAlreadyInstalledModalRef) {
|
||||
modpackAlreadyInstalledModalRef = ref
|
||||
},
|
||||
async handleModpackDuplicateCreateAnyway() {
|
||||
if (!pendingModpackInstall) return
|
||||
const { project, version, source, callback, createInstanceCallback } = pendingModpackInstall
|
||||
pendingModpackInstall = null
|
||||
await packInstall(
|
||||
project.id,
|
||||
version,
|
||||
project.title,
|
||||
project.icon_url,
|
||||
createInstanceCallback,
|
||||
)
|
||||
trackEvent('PackInstall', {
|
||||
id: project.id,
|
||||
version_id: version,
|
||||
title: project.title,
|
||||
source,
|
||||
})
|
||||
callback(version)
|
||||
},
|
||||
handleModpackDuplicateGoToInstance(instancePath: string) {
|
||||
pendingModpackInstall = null
|
||||
opts.router.push(`/instance/${encodeURIComponent(instancePath)}/`)
|
||||
},
|
||||
setIncompatibilityWarningModal(ref: IncompatibilityWarningModalRef) {
|
||||
incompatibilityWarningModalRef = ref
|
||||
|
||||
@@ -1,18 +1,33 @@
|
||||
import type { AbstractWebNotificationManager, CreationFlowContextValue } from '@modrinth/ui'
|
||||
import { provide, useTemplateRef } from 'vue'
|
||||
import type {
|
||||
AbstractWebNotificationManager,
|
||||
CreationFlowContextValue,
|
||||
CreationFlowModal,
|
||||
} from '@modrinth/ui'
|
||||
import { provide, ref, useTemplateRef } from 'vue'
|
||||
import type { ComponentExposed } from 'vue-component-type-helpers'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import type ModpackAlreadyInstalledModal from '@/components/ui/modal/ModpackAlreadyInstalledModal.vue'
|
||||
import { trackEvent } from '@/helpers/analytics'
|
||||
import { get_project_versions, get_search_results } from '@/helpers/cache.js'
|
||||
import { import_instance } from '@/helpers/import.js'
|
||||
import { create_profile_and_install, create_profile_and_install_from_file } from '@/helpers/pack'
|
||||
import { create, list } from '@/helpers/profile.js'
|
||||
import type { InstanceLoader } from '@/helpers/types'
|
||||
|
||||
export function setupCreationModal(notificationManager: AbstractWebNotificationManager) {
|
||||
const { handleError } = notificationManager
|
||||
const router = useRouter()
|
||||
|
||||
const installationModal = useTemplateRef('installationModal')
|
||||
const installationModal =
|
||||
useTemplateRef<ComponentExposed<typeof CreationFlowModal>>('installationModal')
|
||||
const modpackAlreadyInstalledModal = ref<InstanceType<typeof ModpackAlreadyInstalledModal>>()
|
||||
|
||||
function setModpackAlreadyInstalledModal(
|
||||
modal: InstanceType<typeof ModpackAlreadyInstalledModal>,
|
||||
) {
|
||||
modpackAlreadyInstalledModal.value = modal
|
||||
}
|
||||
|
||||
async function fetchExistingInstanceNames(): Promise<string[]> {
|
||||
const instances = await list().catch(handleError)
|
||||
@@ -23,10 +38,34 @@ export function setupCreationModal(notificationManager: AbstractWebNotificationM
|
||||
installationModal.value?.show()
|
||||
})
|
||||
|
||||
async function handleCreate(config: CreationFlowContextValue) {
|
||||
installationModal.value?.hide()
|
||||
async function proceedWithModpackCreation(
|
||||
projectId: string,
|
||||
versionId: string,
|
||||
name: string,
|
||||
iconUrl?: string,
|
||||
) {
|
||||
await create_profile_and_install(projectId, versionId, name, iconUrl).catch(handleError)
|
||||
trackEvent('InstanceCreate', { source: 'CreationModalModpack' })
|
||||
}
|
||||
|
||||
async function handleCreate(config: CreationFlowContextValue) {
|
||||
try {
|
||||
if (config.modpackSelection.value) {
|
||||
const { projectId, versionId, name, iconUrl } = config.modpackSelection.value
|
||||
|
||||
const instances = await list().catch(handleError)
|
||||
const existingInstance = instances?.find((i) => i.linked_data?.project_id === projectId)
|
||||
|
||||
if (existingInstance) {
|
||||
pendingModpackCreation.value = { projectId, versionId, name, iconUrl }
|
||||
installationModal.value?.hide()
|
||||
modpackAlreadyInstalledModal.value?.show(existingInstance.name, existingInstance.path)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
installationModal.value?.hide()
|
||||
|
||||
if (config.isImportMode.value) {
|
||||
for (const [launcherName, instanceSet] of Object.entries(
|
||||
config.importSelectedInstances.value,
|
||||
@@ -43,8 +82,7 @@ export function setupCreationModal(notificationManager: AbstractWebNotificationM
|
||||
|
||||
if (config.modpackSelection.value) {
|
||||
const { projectId, versionId, name, iconUrl } = config.modpackSelection.value
|
||||
await create_profile_and_install(projectId, versionId, name, iconUrl).catch(handleError)
|
||||
trackEvent('InstanceCreate', { source: 'CreationModalModpack' })
|
||||
await proceedWithModpackCreation(projectId, versionId, name, iconUrl)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -66,26 +104,40 @@ export function setupCreationModal(notificationManager: AbstractWebNotificationM
|
||||
|
||||
await create(
|
||||
name,
|
||||
config.selectedGameVersion.value,
|
||||
loader,
|
||||
config.selectedGameVersion.value!,
|
||||
loader as InstanceLoader,
|
||||
loaderVersion,
|
||||
iconPath,
|
||||
false,
|
||||
).catch(handleError)
|
||||
|
||||
trackEvent('InstanceCreate', {
|
||||
profile_name: name,
|
||||
game_version: config.selectedGameVersion.value,
|
||||
loader,
|
||||
loader_version: loaderVersion,
|
||||
has_icon: !!iconPath,
|
||||
source: 'CreationModal',
|
||||
})
|
||||
} catch (err) {
|
||||
handleError(err)
|
||||
handleError(err as Error)
|
||||
}
|
||||
}
|
||||
|
||||
const pendingModpackCreation = ref<{
|
||||
projectId: string
|
||||
versionId: string
|
||||
name: string
|
||||
iconUrl?: string
|
||||
} | null>(null)
|
||||
|
||||
async function handleModpackDuplicateCreateAnyway() {
|
||||
if (!pendingModpackCreation.value) return
|
||||
const { projectId, versionId, name, iconUrl } = pendingModpackCreation.value
|
||||
pendingModpackCreation.value = null
|
||||
await proceedWithModpackCreation(projectId, versionId, name, iconUrl)
|
||||
}
|
||||
|
||||
function handleModpackDuplicateGoToInstance(instancePath: string) {
|
||||
pendingModpackCreation.value = null
|
||||
router.push(`/instance/${encodeURIComponent(instancePath)}/`)
|
||||
}
|
||||
|
||||
function handleBrowseModpacks() {
|
||||
installationModal.value?.hide()
|
||||
router.push('/browse/modpack')
|
||||
@@ -113,5 +165,8 @@ export function setupCreationModal(notificationManager: AbstractWebNotificationM
|
||||
handleBrowseModpacks,
|
||||
searchModpacks,
|
||||
getProjectVersions,
|
||||
setModpackAlreadyInstalledModal,
|
||||
handleModpackDuplicateCreateAnyway,
|
||||
handleModpackDuplicateGoToInstance,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
"semver": "^7.5.4",
|
||||
"three": "^0.172.0",
|
||||
"vue-confetti-explosion": "^1.0.2",
|
||||
"vue-router": "*",
|
||||
"vue-typed-virtual-list": "^1.0.10",
|
||||
"vue3-ace-editor": "^2.2.4",
|
||||
"vue3-apexcharts": "^1.5.2",
|
||||
|
||||
Reference in New Issue
Block a user