Migrate to SQLite for Internal Launcher Data (#1300)

* initial migration

* barebones profiles

* Finish profiles

* Add back file watcher

* UI support progress

* Finish most of cache

* Fix options page

* Fix forge, finish modrinth auth

* Accounts, process cache

* Run SQLX prepare

* Finish

* Run lint + actions

* Fix version to be compat with windows

* fix lint

* actually fix lint

* actually fix lint again
This commit is contained in:
Geometrically
2024-07-24 11:03:19 -07:00
committed by GitHub
parent 90f74427d9
commit 49a20a303a
156 changed files with 9208 additions and 8547 deletions

View File

@@ -2,20 +2,10 @@
<div class="instance-container">
<div class="side-cards">
<Card class="instance-card" @contextmenu.prevent.stop="handleRightClick">
<Avatar
size="lg"
:src="
!instance.metadata.icon ||
(instance.metadata.icon && instance.metadata.icon.startsWith('http'))
? instance.metadata.icon
: convertFileSrc(instance.metadata?.icon)
"
/>
<Avatar size="lg" :src="instance.icon_path ? convertFileSrc(instance.icon_path) : null" />
<div class="instance-info">
<h2 class="name">{{ instance.metadata.name }}</h2>
<span class="metadata">
{{ instance.metadata.loader }} {{ instance.metadata.game_version }}
</span>
<h2 class="name">{{ instance.name }}</h2>
<span class="metadata"> {{ instance.loader }} {{ instance.game_version }} </span>
</div>
<span class="button-group">
<Button v-if="instance.install_stage !== 'installed'" disabled class="instance-button">
@@ -26,7 +16,6 @@
color="danger"
class="instance-button"
@click="stopInstance('InstancePage')"
@mouseover="checkProcess"
>
<StopCircleIcon />
Stop
@@ -36,7 +25,6 @@
color="primary"
class="instance-button"
@click="startInstance('InstancePage')"
@mouseover="checkProcess"
>
<PlayIcon />
Play
@@ -135,22 +123,20 @@ import {
CheckCircleIcon,
UpdatedIcon,
} from '@modrinth/assets'
import { get, run } from '@/helpers/profile'
import {
get_all_running_profile_paths,
get_uuids_by_profile_path,
kill_by_uuid,
} from '@/helpers/process'
import { offline_listener, process_listener, profile_listener } from '@/helpers/events'
import { get, kill, run } from '@/helpers/profile'
import { get_by_profile_path } from '@/helpers/process'
import { process_listener, profile_listener } from '@/helpers/events'
import { useRoute, useRouter } from 'vue-router'
import { ref, onUnmounted } from 'vue'
import { handleError, useBreadcrumbs, useLoading } from '@/store/state'
import { isOffline, showProfileInFolder } from '@/helpers/utils.js'
import { showProfileInFolder } from '@/helpers/utils.js'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import { mixpanel_track } from '@/helpers/mixpanel'
import { convertFileSrc } from '@tauri-apps/api/tauri'
import { useFetch } from '@/helpers/fetch'
import { handleSevereError } from '@/store/error.js'
import { get_project, get_version_many } from '@/helpers/cache.js'
import dayjs from 'dayjs'
const route = useRoute()
@@ -161,72 +147,71 @@ const instance = ref(await get(route.params.id).catch(handleError))
breadcrumbs.setName(
'Instance',
instance.value.metadata.name.length > 40
? instance.value.metadata.name.substring(0, 40) + '...'
: instance.value.metadata.name,
instance.value.name.length > 40
? instance.value.name.substring(0, 40) + '...'
: instance.value.name,
)
breadcrumbs.setContext({
name: instance.value.metadata.name,
name: instance.value.name,
link: route.path,
query: route.query,
})
const offline = ref(await isOffline())
const offline = ref(!navigator.onLine)
window.addEventListener('offline', () => {
offline.value = true
})
window.addEventListener('online', () => {
offline.value = false
})
const loadingBar = useLoading()
const uuid = ref(null)
const playing = ref(false)
const loading = ref(false)
const options = ref(null)
const startInstance = async (context) => {
loading.value = true
uuid.value = await run(route.params.id).catch(handleSevereError)
run(route.params.id).catch(handleSevereError)
loading.value = false
playing.value = true
mixpanel_track('InstanceStart', {
loader: instance.value.metadata.loader,
game_version: instance.value.metadata.game_version,
loader: instance.value.loader,
game_version: instance.value.game_version,
source: context,
})
}
const checkProcess = async () => {
const runningPaths = await get_all_running_profile_paths().catch(handleError)
if (runningPaths.includes(instance.value.path)) {
playing.value = true
return
}
const runningProcesses = await get_by_profile_path(route.params.id).catch(handleError)
playing.value = false
uuid.value = null
playing.value = runningProcesses.length > 0
}
// Get information on associated modrinth versions, if any
const modrinthVersions = ref([])
if (!(await isOffline()) && instance.value.metadata.linked_data?.project_id) {
modrinthVersions.value = await useFetch(
`https://api.modrinth.com/v2/project/${instance.value.metadata.linked_data.project_id}/version`,
'project',
)
if (!offline.value && instance.value.linked_data && instance.value.linked_data.project_id) {
const project = await get_project(instance.value.linked_data.project_id).catch(handleError)
if (project && project.versions) {
modrinthVersions.value = (await get_version_many(project.versions).catch(handleError)).sort(
(a, b) => dayjs(b.date_published) - dayjs(a.date_published),
)
}
}
await checkProcess()
const stopInstance = async (context) => {
playing.value = false
if (!uuid.value) {
const uuids = await get_uuids_by_profile_path(instance.value.path).catch(handleError)
uuid.value = uuids[0] // populate Uuid to listen for in the process_listener
uuids.forEach(async (u) => await kill_by_uuid(u).catch(handleError))
} else await kill_by_uuid(uuid.value).catch(handleError)
await kill(route.params.id).catch(handleError)
mixpanel_track('InstanceStop', {
loader: instance.value.metadata.loader,
game_version: instance.value.metadata.game_version,
loader: instance.value.loader,
game_version: instance.value.game_version,
source: context,
})
}
@@ -271,7 +256,7 @@ const handleOptionsClick = async (args) => {
break
case 'add_content':
await router.push({
path: `/browse/${instance.value.metadata.loader === 'vanilla' ? 'datapack' : 'mod'}`,
path: `/browse/${instance.value.loader === 'vanilla' ? 'datapack' : 'mod'}`,
query: { i: route.params.id },
})
break
@@ -302,17 +287,12 @@ const unlistenProfiles = await profile_listener(async (event) => {
})
const unlistenProcesses = await process_listener((e) => {
if (e.event === 'finished' && uuid.value === e.uuid) playing.value = false
})
const unlistenOffline = await offline_listener((b) => {
offline.value = b
if (e.event === 'finished' && e.profile_path_id === route.params.id) playing.value = false
})
onUnmounted(() => {
unlistenProcesses()
unlistenProfiles()
unlistenOffline()
})
</script>

View File

@@ -99,7 +99,7 @@ import { computed, nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, watch
import dayjs from 'dayjs'
import isToday from 'dayjs/plugin/isToday'
import isYesterday from 'dayjs/plugin/isYesterday'
import { get_uuids_by_profile_path } from '@/helpers/process.js'
import { get_by_profile_path } from '@/helpers/process.js'
import { useRoute } from 'vue-router'
import { process_listener } from '@/helpers/events.js'
import { handleError } from '@/store/notifications.js'
@@ -209,9 +209,9 @@ const processedLogs = computed(() => {
async function getLiveStdLog() {
if (route.params.id) {
const uuids = await get_uuids_by_profile_path(route.params.id).catch(handleError)
const processes = await get_by_profile_path(route.params.id).catch(handleError)
let returnValue
if (uuids.length === 0) {
if (processes.length === 0) {
returnValue = emptyText.join('\n')
} else {
const logCursor = await get_latest_log_cursor(

View File

@@ -281,7 +281,7 @@
<div class="markdown-body">
<p>
Are you sure you want to remove
<strong>{{ functionValues.length }} project(s)</strong> from {{ instance.metadata.name }}?
<strong>{{ functionValues.length }} project(s)</strong> from {{ instance.name }}?
<br />
This action <strong>cannot</strong> be undone.
</p>
@@ -304,7 +304,7 @@
>{{ Array.from(projects.values()).filter((x) => x.disabled).length }} disabled
project(s)</strong
>
from {{ instance.metadata.name }}?
from {{ instance.name }}?
<br />
This action <strong>cannot</strong> be undone.
</p>
@@ -326,7 +326,7 @@
/>
<ExportModal v-if="projects.length > 0" ref="exportModal" :instance="instance" />
<ModpackVersionModal
v-if="instance.metadata.linked_data"
v-if="instance.linked_data"
ref="modpackVersionModal"
:instance="instance"
:versions="props.versions"
@@ -364,6 +364,7 @@ import { computed, onUnmounted, ref, watch } from 'vue'
import {
add_project_from_path,
get,
get_projects,
remove_project,
toggle_disable_project,
update_all,
@@ -372,12 +373,18 @@ import {
import { handleError } from '@/store/notifications.js'
import { mixpanel_track } from '@/helpers/mixpanel'
import { listen } from '@tauri-apps/api/event'
import { convertFileSrc } from '@tauri-apps/api/tauri'
import { highlightModInProfile } from '@/helpers/utils.js'
import { MenuIcon, ToggleIcon, TextInputIcon, AddProjectImage, PackageIcon } from '@/assets/icons'
import ExportModal from '@/components/ui/ExportModal.vue'
import ModpackVersionModal from '@/components/ui/ModpackVersionModal.vue'
import AddContentButton from '@/components/ui/AddContentButton.vue'
import {
get_organization_many,
get_project_many,
get_team_many,
get_version_many,
} from '@/helpers/cache.js'
import { profile_listener } from '@/helpers/events.js'
const props = defineProps({
instance: {
@@ -404,65 +411,102 @@ const props = defineProps({
},
})
const projects = ref([])
const selectionMap = ref(new Map())
const unlistenProfiles = await profile_listener(async (event) => {
if (
event.profile_path_id === props.instance.path &&
event.event === 'synced' &&
props.instance.install_stage !== 'pack_installing'
) {
await initProjects()
}
})
onUnmounted(() => {
unlistenProfiles()
})
const showingOptions = ref(false)
const isPackLocked = computed(() => {
return props.instance.metadata.linked_data && props.instance.metadata.linked_data.locked
return props.instance.linked_data && props.instance.linked_data.locked
})
const canUpdatePack = computed(() => {
if (!props.instance.metadata.linked_data) return false
return props.instance.metadata.linked_data.version_id !== props.instance.modrinth_update_version
if (!props.instance.linked_data || !props.versions || !props.versions[0]) return false
return props.instance.linked_data.version_id !== props.versions[0].id
})
const exportModal = ref(null)
const initProjects = (initInstance) => {
projects.value = []
if (!initInstance || !initInstance.projects) return
for (const [path, project] of Object.entries(initInstance.projects)) {
if (project.metadata.type === 'modrinth' && !props.offline) {
let owner = project.metadata.members.find((x) => x.role === 'Owner')
projects.value.push({
const projects = ref([])
const selectionMap = ref(new Map())
const initProjects = async () => {
const newProjects = []
const profileProjects = await get_projects(props.instance.path)
const fetchProjects = []
const fetchVersions = []
for (const value of Object.values(profileProjects)) {
if (value.metadata) {
fetchProjects.push(value.metadata.project_id)
fetchVersions.push(value.metadata.version_id)
}
}
const [modrinthProjects, modrinthVersions] = await Promise.all([
await get_project_many(fetchProjects).catch(handleError),
await get_version_many(fetchVersions).catch(handleError),
])
const [modrinthTeams, modrinthOrganizations] = await Promise.all([
await get_team_many(modrinthProjects.map((x) => x.team)).catch(handleError),
await get_organization_many(
modrinthProjects.map((x) => x.organization).filter((x) => !!x),
).catch(handleError),
])
for (const [path, file] of Object.entries(profileProjects)) {
if (file.metadata) {
const project = modrinthProjects.find((x) => file.metadata.project_id === x.id)
const version = modrinthVersions.find((x) => file.metadata.version_id === x.id)
const org = project.organization
? modrinthOrganizations.find((x) => x.id === project.organization)
: null
const team = modrinthTeams.find((x) => x[0].team_id === project.team)
let owner = org ? org.name : team.find((x) => x.is_owner).user.username
newProjects.push({
path,
name: project.metadata.project.title,
slug: project.metadata.project.slug,
author: owner ? owner.user.username : null,
version: project.metadata.version.version_number,
file_name: project.file_name,
icon: project.metadata.project.icon_url,
disabled: project.disabled,
updateVersion: project.metadata.update_version,
outdated: !!project.metadata.update_version,
project_type: project.metadata.project.project_type,
id: project.metadata.project.id,
})
} else if (project.metadata.type === 'inferred') {
projects.value.push({
path,
name: project.metadata.title ?? project.file_name,
author: project.metadata.authors[0],
version: project.metadata.version,
file_name: project.file_name,
icon: project.metadata.icon ? convertFileSrc(project.metadata.icon) : null,
disabled: project.disabled,
outdated: false,
project_type: project.metadata.project_type,
name: project.title,
slug: project.slug,
author: owner,
version: version.version_number,
file_name: file.file_name,
icon: project.icon_url,
disabled: file.file_name.endsWith('.disabled'),
updateVersion: file.update_version_id,
outdated: !!file.update_version_id,
project_type: project.project_type,
id: project.id,
})
} else {
projects.value.push({
newProjects.push({
path,
name: project.file_name,
name: file.file_name.replace('.disabled', ''),
author: '',
version: null,
file_name: project.file_name,
file_name: file.file_name,
icon: null,
disabled: project.disabled,
disabled: file.file_name.endsWith('.disabled'),
outdated: false,
project_type: null,
project_type: file.project_type,
})
}
}
projects.value = newProjects
const newSelectionMap = new Map()
for (const project of projects.value) {
newSelectionMap.set(
@@ -475,22 +519,7 @@ const initProjects = (initInstance) => {
}
selectionMap.value = newSelectionMap
}
initProjects(props.instance)
watch(
() => props.instance.projects,
() => {
initProjects(props.instance)
},
)
watch(
() => props.offline,
() => {
if (props.instance) initProjects(props.instance)
},
)
await initProjects()
const modpackVersionModal = ref(null)
const installing = computed(() => props.instance.install_stage !== 'installed')
@@ -633,8 +662,8 @@ const updateAll = async () => {
}
mixpanel_track('InstanceUpdateAll', {
loader: props.instance.metadata.loader,
game_version: props.instance.metadata.game_version,
loader: props.instance.loader,
game_version: props.instance.game_version,
count: setProjects.length,
selected: selected.value.length > 1,
})
@@ -659,8 +688,8 @@ const updateProject = async (mod) => {
mod.updateVersion = null
mixpanel_track('InstanceProjectUpdate', {
loader: props.instance.metadata.loader,
game_version: props.instance.metadata.game_version,
loader: props.instance.loader,
game_version: props.instance.game_version,
id: mod.id,
name: mod.name,
project_type: mod.project_type,
@@ -686,8 +715,8 @@ const toggleDisableMod = async (mod) => {
mod.path = newPath
mod.disabled = !mod.disabled
mixpanel_track('InstanceProjectDisable', {
loader: props.instance.metadata.loader,
game_version: props.instance.metadata.game_version,
loader: props.instance.loader,
game_version: props.instance.game_version,
id: mod.id,
name: mod.name,
project_type: mod.project_type,
@@ -707,8 +736,8 @@ const removeMod = async (mod) => {
projects.value = projects.value.filter((x) => mod.path !== x.path)
mixpanel_track('InstanceProjectRemove', {
loader: props.instance.metadata.loader,
game_version: props.instance.metadata.game_version,
loader: props.instance.loader,
game_version: props.instance.game_version,
id: mod.id,
name: mod.name,
project_type: mod.project_type,
@@ -820,7 +849,7 @@ watch(selectAll, () => {
const unlisten = await listen('tauri://file-drop', async (event) => {
for (const file of event.payload) {
if (file.endsWith('.mrpack')) continue
await add_project_from_path(props.instance.path, file, 'mod').catch(handleError)
await add_project_from_path(props.instance.path, file).catch(handleError)
}
initProjects(await get(props.instance.path).catch(handleError))
})

View File

@@ -25,7 +25,7 @@
<XIcon />
Cancel
</button>
<button class="btn btn-danger" :disabled="action_disabled" @click="unlockProfile">
<button class="btn btn-danger" @click="unlockProfile">
<LockIcon />
Unlock
</button>
@@ -50,7 +50,7 @@
<XIcon />
Cancel
</button>
<button class="btn btn-danger" :disabled="action_disabled" @click="unpairProfile">
<button class="btn btn-danger" @click="unpairProfile">
<XIcon />
Unpair
</button>
@@ -117,21 +117,13 @@
<span class="label__title">Icon</span>
</label>
<div class="input-group">
<Avatar
:src="!icon || (icon && icon.startsWith('http')) ? icon : convertFileSrc(icon)"
size="md"
class="project__icon"
/>
<Avatar :src="icon ? convertFileSrc(icon) : icon" size="md" class="project__icon" />
<div class="input-stack">
<button id="instance-icon" class="btn" @click="setIcon">
<UploadIcon />
Select icon
</button>
<button
:disabled="!(!icon || (icon && icon.startsWith('http')) ? icon : convertFileSrc(icon))"
class="btn"
@click="resetIcon"
>
<button :disabled="!icon" class="btn" @click="resetIcon">
<TrashIcon />
Remove icon
</button>
@@ -147,7 +139,7 @@
autocomplete="off"
maxlength="80"
type="text"
:disabled="instance.metadata.linked_data"
:disabled="instance.linked_data"
/>
<div class="adjacent-input">
@@ -358,7 +350,7 @@
/>
</div>
</Card>
<Card v-if="instance.metadata.linked_data">
<Card v-if="instance.linked_data">
<div class="label">
<h3>
<span class="label__title size-card-header">Modpack</span>
@@ -366,9 +358,7 @@
</div>
<div class="adjacent-input">
<label for="general-modpack-info">
<span class="label__description">
<strong>Modpack: </strong> {{ instance.metadata.name }}
</span>
<span class="label__description"> <strong>Modpack: </strong> {{ instance.name }} </span>
<span class="label__description">
<strong>Version: </strong>
{{
@@ -414,7 +404,7 @@
</Button>
</div>
<div v-if="props.instance.metadata.linked_data.project_id" class="adjacent-input">
<div v-if="instance.linked_data.project_id" class="adjacent-input">
<label for="change-modpack-version">
<span class="label__title">Change modpack version</span>
<span class="label__description">
@@ -502,7 +492,7 @@
</div>
</Card>
<ModpackVersionModal
v-if="instance.metadata.linked_data"
v-if="instance.linked_data"
ref="modpackVersionModal"
:instance="instance"
:versions="props.versions"
@@ -553,12 +543,7 @@ import { get } from '@/helpers/settings.js'
import JavaSelector from '@/components/ui/JavaSelector.vue'
import { convertFileSrc } from '@tauri-apps/api/tauri'
import { open } from '@tauri-apps/api/dialog'
import {
get_fabric_versions,
get_forge_versions,
get_neoforge_versions,
get_quilt_versions,
} from '@/helpers/metadata.js'
import { get_loader_versions } from '@/helpers/metadata.js'
import { get_game_versions, get_loaders } from '@/helpers/tags.js'
import { handleError } from '@/store/notifications.js'
import { mixpanel_track } from '@/helpers/mixpanel'
@@ -587,17 +572,17 @@ const props = defineProps({
const themeStore = useTheming()
const title = ref(props.instance.metadata.name)
const icon = ref(props.instance.metadata.icon)
const groups = ref(props.instance.metadata.groups)
const title = ref(props.instance.name)
const icon = ref(props.instance.icon_path)
const groups = ref(props.instance.groups)
const modpackVersionModal = ref(null)
const instancesList = Object.values(await list(true))
const instancesList = await list()
const availableGroups = ref([
...new Set(
instancesList.reduce((acc, obj) => {
return acc.concat(obj.metadata.groups)
return acc.concat(obj.groups)
}, []),
),
])
@@ -632,18 +617,18 @@ const globalSettings = await get().catch(handleError)
const modalConfirmUnlock = ref(null)
const modalConfirmUnpair = ref(null)
const javaSettings = props.instance.java ?? {}
const overrideJavaInstall = ref(!!javaSettings.override_version)
const overrideJavaInstall = ref(!!props.instance.java_path)
const optimalJava = readonly(await get_optimal_jre_key(props.instance.path).catch(handleError))
const javaInstall = ref(optimalJava ?? javaSettings.override_version ?? { path: '', version: '' })
const javaInstall = ref({ path: optimalJava.path ?? props.instance.java_path })
const overrideJavaArgs = ref(!!javaSettings.extra_arguments)
const javaArgs = ref((javaSettings.extra_arguments ?? globalSettings.custom_java_args).join(' '))
const overrideJavaArgs = ref(!!props.instance.extra_launch_args)
const javaArgs = ref(
(props.instance.extra_launch_args ?? globalSettings.extra_launch_args).join(' '),
)
const overrideEnvVars = ref(!!javaSettings.custom_env_args)
const overrideEnvVars = ref(!!props.instance.custom_env_vars)
const envVars = ref(
(javaSettings.custom_env_args ?? globalSettings.custom_env_args)
(props.instance.custom_env_vars ?? globalSettings.custom_env_vars)
.map((x) => x.join('='))
.join(' '),
)
@@ -652,18 +637,22 @@ const overrideMemorySettings = ref(!!props.instance.memory)
const memory = ref(props.instance.memory ?? globalSettings.memory)
const maxMemory = Math.floor((await get_max_memory().catch(handleError)) / 1024)
const overrideWindowSettings = ref(!!props.instance.resolution || !!props.instance.fullscreen)
const resolution = ref(props.instance.resolution ?? globalSettings.game_resolution)
const overrideHooks = ref(!!props.instance.hooks)
const overrideWindowSettings = ref(
!!props.instance.game_resolution || !!props.instance.force_fullscreen,
)
const resolution = ref(props.instance.game_resolution ?? globalSettings.game_resolution)
const overrideHooks = ref(
props.instance.hooks.pre_launch || props.instance.hooks.wrapper || props.instance.hooks.post_exit,
)
const hooks = ref(props.instance.hooks ?? globalSettings.hooks)
const fullscreenSetting = ref(!!props.instance.fullscreen)
const fullscreenSetting = ref(!!props.instance.force_fullscreen)
const unlinkModpack = ref(false)
const inProgress = ref(false)
const installing = computed(() => props.instance.install_stage !== 'installed')
const installedVersion = computed(() => props.instance?.metadata?.linked_data?.version_id)
const installedVersion = computed(() => props.instance?.linked_data?.version_id)
const installedVersionData = computed(() => {
if (!installedVersion.value) return null
return props.versions.find((version) => version.id === installedVersion.value)
@@ -706,34 +695,29 @@ const getLocalVersion = (path) => {
const editProfileObject = computed(() => {
const editProfile = {
metadata: {
name: title.value.trim().substring(0, 32) ?? 'Instance',
groups: groups.value.map((x) => x.trim().substring(0, 32)).filter((x) => x.length > 0),
loader_version: props.instance.metadata.loader_version,
linked_data: props.instance.metadata.linked_data,
},
name: title.value.trim().substring(0, 32) ?? 'Instance',
groups: groups.value.map((x) => x.trim().substring(0, 32)).filter((x) => x.length > 0),
loader_version: props.instance.loader_version,
linked_data: props.instance.linked_data,
java: {},
hooks: {},
}
if (overrideJavaInstall.value) {
if (javaInstall.value.path !== '') {
editProfile.java.override_version = javaInstall.value
editProfile.java.override_version.path = editProfile.java.override_version.path.replace(
'java.exe',
'javaw.exe',
)
editProfile.java_path = javaInstall.value.path.replace('java.exe', 'javaw.exe')
}
}
if (overrideJavaArgs.value) {
if (javaArgs.value !== '') {
editProfile.java.extra_arguments = javaArgs.value.trim().split(/\s+/).filter(Boolean)
editProfile.extra_launch_args = javaArgs.value.trim().split(/\s+/).filter(Boolean)
}
}
if (overrideEnvVars.value) {
if (envVars.value !== '') {
editProfile.java.custom_env_args = envVars.value
editProfile.custom_env_vars = envVars.value
.trim()
.split(/\s+/)
.filter(Boolean)
@@ -746,10 +730,10 @@ const editProfileObject = computed(() => {
}
if (overrideWindowSettings.value) {
editProfile.fullscreen = fullscreenSetting.value
editProfile.force_fullscreen = fullscreenSetting.value
if (!fullscreenSetting.value) {
editProfile.resolution = resolution.value
editProfile.game_resolution = resolution.value
}
}
@@ -758,10 +742,10 @@ const editProfileObject = computed(() => {
}
if (unlinkModpack.value) {
editProfile.metadata.linked_data = null
editProfile.linked_data = null
}
breadcrumbs.setName('Instance', editProfile.metadata.name)
breadcrumbs.setName('Instance', editProfile.name)
return editProfile
})
@@ -771,8 +755,8 @@ const repairing = ref(false)
async function duplicateProfile() {
await duplicate(props.instance.path).catch(handleError)
mixpanel_track('InstanceDuplicate', {
loader: props.instance.metadata.loader,
game_version: props.instance.metadata.game_version,
loader: props.instance.loader,
game_version: props.instance.game_version,
})
}
@@ -782,14 +766,14 @@ async function repairProfile(force) {
repairing.value = false
mixpanel_track('InstanceRepair', {
loader: props.instance.metadata.loader,
game_version: props.instance.metadata.game_version,
loader: props.instance.loader,
game_version: props.instance.game_version,
})
}
async function unpairProfile() {
const editProfile = props.instance
editProfile.metadata.linked_data = null
editProfile.linked_data = null
await edit(props.instance.path, editProfile)
installedVersion.value = null
installedVersionData.value = null
@@ -798,13 +782,13 @@ async function unpairProfile() {
async function unlockProfile() {
const editProfile = props.instance
editProfile.metadata.linked_data.locked = false
editProfile.linked_data.locked = false
await edit(props.instance.path, editProfile)
modalConfirmUnlock.value.hide()
}
const isPackLocked = computed(() => {
return props.instance.metadata.linked_data && props.instance.metadata.linked_data.locked
return props.instance.linked_data && props.instance.linked_data.locked
})
async function repairModpack() {
@@ -813,8 +797,8 @@ async function repairModpack() {
inProgress.value = false
mixpanel_track('InstanceRepair', {
loader: props.instance.metadata.loader,
game_version: props.instance.metadata.game_version,
loader: props.instance.loader,
game_version: props.instance.game_version,
})
}
@@ -825,8 +809,8 @@ async function removeProfile() {
removing.value = false
mixpanel_track('InstanceRemove', {
loader: props.instance.metadata.loader,
game_version: props.instance.metadata.game_version,
loader: props.instance.loader,
game_version: props.instance.game_version,
})
await router.push({ path: '/' })
@@ -843,10 +827,10 @@ const [
all_game_versions,
loaders,
] = await Promise.all([
get_fabric_versions().then(shallowRef).catch(handleError),
get_forge_versions().then(shallowRef).catch(handleError),
get_quilt_versions().then(shallowRef).catch(handleError),
get_neoforge_versions().then(shallowRef).catch(handleError),
get_loader_versions('fabric').then(shallowRef).catch(handleError),
get_loader_versions('forge').then(shallowRef).catch(handleError),
get_loader_versions('quilt').then(shallowRef).catch(handleError),
get_loader_versions('neo').then(shallowRef).catch(handleError),
get_game_versions().then(shallowRef).catch(handleError),
get_loaders()
.then((value) =>
@@ -859,8 +843,8 @@ const [
])
loaders.value.unshift('vanilla')
const loader = ref(props.instance.metadata.loader)
const gameVersion = ref(props.instance.metadata.game_version)
const loader = ref(props.instance.loader)
const gameVersion = ref(props.instance.game_version)
const selectableGameVersions = computed(() => {
return all_game_versions.value
.filter((item) => {
@@ -896,9 +880,7 @@ const selectableLoaderVersions = computed(() => {
return []
})
const loaderVersionIndex = ref(
selectableLoaderVersions.value.findIndex(
(x) => x.id === props.instance.metadata.loader_version?.id,
),
selectableLoaderVersions.value.findIndex((x) => x.id === props.instance.loader_version),
)
const isValid = computed(() => {
@@ -910,10 +892,9 @@ const isValid = computed(() => {
const isChanged = computed(() => {
return (
loader.value != props.instance.metadata.loader ||
gameVersion.value != props.instance.metadata.game_version ||
JSON.stringify(selectableLoaderVersions.value[loaderVersionIndex.value]) !==
JSON.stringify(props.instance.metadata.loader_version)
loader.value !== props.instance.loader ||
gameVersion.value !== props.instance.game_version ||
selectableLoaderVersions.value[loaderVersionIndex.value].id !== props.instance.loader_version
)
})
@@ -924,11 +905,11 @@ async function saveGvLoaderEdits() {
editing.value = true
let editProfile = editProfileObject.value
editProfile.metadata.loader = loader.value
editProfile.metadata.game_version = gameVersion.value
editProfile.loader = loader.value
editProfile.game_version = gameVersion.value
if (loader.value !== 'vanilla') {
editProfile.metadata.loader_version = selectableLoaderVersions.value[loaderVersionIndex.value]
editProfile.loader_version = selectableLoaderVersions.value[loaderVersionIndex.value].id
}
await edit(props.instance.path, editProfile).catch(handleError)
await repairProfile(false)