Instance creation (#91)
* Base impl * Image upload preview * Run lint * Add metadata * Clean uo * fix tauri conf * Addressed changes * Update InstanceCreationModal.vue --------- Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com> Co-authored-by: Jai A <jaiagr+gpg@pm.me>
This commit is contained in:
parent
79ef48549f
commit
c53104c28e
@ -15,7 +15,7 @@
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^1.2.0",
|
||||
"ofetch": "^1.0.1",
|
||||
"omorphia": "^0.4.9",
|
||||
"omorphia": "^0.4.10",
|
||||
"pinia": "^2.0.33",
|
||||
"vite-svg-loader": "^4.0.0",
|
||||
"vue": "^3.2.45",
|
||||
|
||||
@ -12,6 +12,7 @@ import {
|
||||
} from 'omorphia'
|
||||
import { useTheming } from '@/store/state'
|
||||
import AccountsCard from '@/components/ui/AccountsCard.vue'
|
||||
import InstanceCreationModal from '@/components/ui/InstanceCreationModal.vue'
|
||||
import { list } from '@/helpers/profile'
|
||||
import { get } from '@/helpers/settings'
|
||||
|
||||
@ -44,9 +45,17 @@ list().then(
|
||||
<RouterLink to="/" class="button-base nav-button"><HomeIcon /></RouterLink>
|
||||
<RouterLink to="/browse" class="button-base nav-button"> <SearchIcon /></RouterLink>
|
||||
<RouterLink to="/library" class="button-base nav-button"> <LibraryIcon /></RouterLink>
|
||||
<button color="primary" class="button-base primary nav-button" icon-only>
|
||||
<button
|
||||
color="primary"
|
||||
class="button-base primary nav-button"
|
||||
icon-only
|
||||
@click="() => $refs.installationModal.show()"
|
||||
>
|
||||
<PlusIcon />
|
||||
</button>
|
||||
<Suspense>
|
||||
<InstanceCreationModal ref="installationModal" />
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings pages-list">
|
||||
|
||||
BIN
theseus_gui/src/assets/external/default.png
vendored
Normal file
BIN
theseus_gui/src/assets/external/default.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
1
theseus_gui/src/assets/external/index.js
vendored
1
theseus_gui/src/assets/external/index.js
vendored
@ -4,3 +4,4 @@ export { default as KoFiIcon } from './kofi.svg'
|
||||
export { default as PatreonIcon } from './patreon.svg'
|
||||
export { default as PaypalIcon } from './paypal.svg'
|
||||
export { default as OpenCollectiveIcon } from './opencollective.svg'
|
||||
export { default as Default } from './default.png'
|
||||
|
||||
265
theseus_gui/src/components/ui/InstanceCreationModal.vue
Normal file
265
theseus_gui/src/components/ui/InstanceCreationModal.vue
Normal file
@ -0,0 +1,265 @@
|
||||
<template>
|
||||
<Modal ref="modal" header="Create Instance">
|
||||
<div v-if="showContent" class="modal-body">
|
||||
<div class="image-upload">
|
||||
<Avatar :src="display_icon" size="md" :rounded="true" />
|
||||
<div class="image-input">
|
||||
<Button @click="upload_icon()">
|
||||
<UploadIcon />
|
||||
Upload Icon
|
||||
</Button>
|
||||
<Button @click="reset_icon">
|
||||
<XIcon />
|
||||
Remove Icon
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<p class="input-label">Name</p>
|
||||
<input v-model="profile_name" class="text-input" type="text" />
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<p class="input-label">Game Version</p>
|
||||
<div class="versions">
|
||||
<DropdownSelect
|
||||
v-model="game_version"
|
||||
:options="game_versions"
|
||||
:render-up="!showAdvanced"
|
||||
/>
|
||||
<Checkbox
|
||||
v-if="showAdvanced"
|
||||
v-model="showSnapshots"
|
||||
class="filter-checkbox"
|
||||
label="Include snapshots"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<p class="input-label">Loader</p>
|
||||
<Chips v-model="loader" :items="loaders" />
|
||||
</div>
|
||||
<div v-if="showAdvanced" class="input-row">
|
||||
<p class="input-label">Loader Version</p>
|
||||
<Chips v-model="loader_version" :items="['stable', 'latest', 'other']" />
|
||||
</div>
|
||||
<div v-if="showAdvanced && loader_version === 'other'">
|
||||
<div v-if="game_version" class="input-row">
|
||||
<p class="input-label">Select Version</p>
|
||||
<DropdownSelect
|
||||
v-model="specified_loader_version"
|
||||
:options="selectable_versions"
|
||||
render-up
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="input-row">
|
||||
<p class="warning">Select a game version before you select a loader version</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="button-group">
|
||||
<Button @click="toggle_advanced">
|
||||
<CodeIcon />
|
||||
{{ showAdvanced ? 'Hide Advanced' : 'Show Advanced' }}
|
||||
</Button>
|
||||
<Button @click="$refs.modal.hide()">
|
||||
<XIcon />
|
||||
Cancel
|
||||
</Button>
|
||||
<Button color="primary" :disabled="!check_valid || creating" @click="create_instance()">
|
||||
<PlusIcon v-if="!creating" />
|
||||
{{ creating ? 'Creating...' : 'Create' }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
Chips,
|
||||
DropdownSelect,
|
||||
Modal,
|
||||
PlusIcon,
|
||||
UploadIcon,
|
||||
XIcon,
|
||||
CodeIcon,
|
||||
Checkbox,
|
||||
} from 'omorphia'
|
||||
import { computed, ref } from 'vue'
|
||||
import { get_game_versions, get_loaders } from '@/helpers/tags'
|
||||
import { create } from '@/helpers/profile'
|
||||
import { open } from '@tauri-apps/api/dialog'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { tauri } from '@tauri-apps/api'
|
||||
import { get_fabric_versions, get_forge_versions } from '@/helpers/metadata'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const profile_name = ref('')
|
||||
const game_version = ref('')
|
||||
const loader = ref('')
|
||||
const loader_version = ref('stable')
|
||||
const specified_loader_version = ref('')
|
||||
const showContent = ref(false)
|
||||
const icon = ref(null)
|
||||
const display_icon = ref(null)
|
||||
const showAdvanced = ref(false)
|
||||
const creating = ref(false)
|
||||
const showSnapshots = ref(false)
|
||||
|
||||
defineExpose({
|
||||
show: () => {
|
||||
showContent.value = false
|
||||
modal.value.show()
|
||||
game_version.value = ''
|
||||
specified_loader_version.value = ''
|
||||
profile_name.value = ''
|
||||
creating.value = false
|
||||
showAdvanced.value = false
|
||||
showSnapshots.value = false
|
||||
loader.value = ''
|
||||
loader_version.value = 'stable'
|
||||
icon.value = null
|
||||
display_icon.value = null
|
||||
|
||||
setTimeout(() => {
|
||||
showContent.value = true
|
||||
}, 100)
|
||||
},
|
||||
})
|
||||
|
||||
const all_game_versions = ref(await get_game_versions())
|
||||
|
||||
const game_versions = computed(() => {
|
||||
return all_game_versions.value
|
||||
.filter((item) => item.version_type === 'release' || showSnapshots.value)
|
||||
.map((item) => item.version)
|
||||
})
|
||||
const loaders = ref(
|
||||
await get_loaders().then((value) =>
|
||||
value
|
||||
.filter((item) => item.supported_project_types.includes('modpack'))
|
||||
.map((item) => item.name.toLowerCase())
|
||||
)
|
||||
)
|
||||
const modal = ref(null)
|
||||
|
||||
const check_valid = computed(() => {
|
||||
return profile_name.value && game_version.value
|
||||
})
|
||||
|
||||
const create_instance = async () => {
|
||||
try {
|
||||
creating.value = true
|
||||
const loader_version_value =
|
||||
loader_version.value === 'other' ? specified_loader_version.value : loader_version.value
|
||||
|
||||
const id = await create(
|
||||
profile_name.value,
|
||||
game_version.value,
|
||||
loader.value,
|
||||
loader_version_value ?? 'stable',
|
||||
icon.value
|
||||
)
|
||||
|
||||
await router.push({ path: `/instance/${encodeURIComponent(id)}` })
|
||||
modal.value.hide()
|
||||
creating.value = false
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
creating.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const upload_icon = async () => {
|
||||
icon.value = await open({
|
||||
multiple: false,
|
||||
filters: [
|
||||
{
|
||||
name: 'Image',
|
||||
extensions: ['png', 'jpeg'],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
display_icon.value = tauri.convertFileSrc(icon.value)
|
||||
}
|
||||
|
||||
const reset_icon = () => {
|
||||
icon.value = null
|
||||
display_icon.value = null
|
||||
}
|
||||
|
||||
const fabric_versions = ref(await get_fabric_versions())
|
||||
const forge_versions = ref(await get_forge_versions())
|
||||
|
||||
const selectable_versions = computed(() => {
|
||||
if (game_version.value) {
|
||||
if (loader.value === 'fabric') {
|
||||
return fabric_versions.value.gameVersions[0].loaders.map((item) => item.id)
|
||||
} else if (loader.value === 'forge') {
|
||||
return forge_versions.value.gameVersions
|
||||
.find((item) => item.id === game_version.value)
|
||||
.loaders.map((item) => item.id)
|
||||
}
|
||||
}
|
||||
return []
|
||||
})
|
||||
|
||||
const toggle_advanced = () => {
|
||||
showAdvanced.value = !showAdvanced.value
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.modal-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
font-size: 1rem;
|
||||
font-weight: bolder;
|
||||
color: var(--color-contrast);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.text-input {
|
||||
width: 20rem;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.image-upload {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.image-input {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.warning {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.versions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
:deep(button.checkbox) {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
@ -21,8 +21,8 @@ export async function create_empty() {
|
||||
- icon is a path to an image file, which will be copied into the profile directory
|
||||
*/
|
||||
|
||||
export async function create(name, game_version, modloader, loader_version, icon) {
|
||||
return await invoke('profile_create', { name, game_version, modloader, loader_version, icon })
|
||||
export async function create(name, gameVersion, modloader, loaderVersion, icon) {
|
||||
return await invoke('profile_create', { name, gameVersion, modloader, loaderVersion, icon })
|
||||
}
|
||||
|
||||
// Remove a profile
|
||||
|
||||
@ -1168,10 +1168,10 @@ ofetch@^1.0.1:
|
||||
node-fetch-native "^1.0.2"
|
||||
ufo "^1.1.0"
|
||||
|
||||
omorphia@^0.4.9:
|
||||
version "0.4.9"
|
||||
resolved "https://registry.yarnpkg.com/omorphia/-/omorphia-0.4.9.tgz#2c13cee8892dfdf892e1912794c783c379c8c5a8"
|
||||
integrity sha512-LbCCVhMmxiNdlFjJRsL4QBgBS1csA1YhV0jiKwGWp0D659ZOoatUbiY7V7gpzPv1IgI6rXC1no06cRWgSzDOKA==
|
||||
omorphia@^0.4.11:
|
||||
version "0.4.10"
|
||||
resolved "https://registry.yarnpkg.com/omorphia/-/omorphia-0.4.10.tgz#93c0e6a08a233f27d76587286e42450af44bb55d"
|
||||
integrity sha512-WgSFosOqoM0IRpzGNYyprfZSRyBLgqs6sTmKRuWo96ZpzrHRWAom2upIm/HAxAC+YBwFni5sgUeBemXYI7wmuw==
|
||||
dependencies:
|
||||
dayjs "^1.11.7"
|
||||
floating-vue "^2.0.0-beta.20"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user