You've already forked AstralRinth
forked from didirus/AstralRinth
Adding things from button or file (#136)
* Initial commit * Update Mods.vue * instances * Run lint * Update pnpm-lock.yaml * Update pnpm-lock.yaml * Buttons colorized * Update pnpm-lock.yaml * Switch to chips * Close modal when file is selected * fix icons --------- Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com> Co-authored-by: Jai A <jaiagr+gpg@pm.me>
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<Modal ref="modal" header="Create instance">
|
<Modal ref="modal" header="Create instance">
|
||||||
<div class="modal-body">
|
<div class="modal-header">
|
||||||
|
<Chips v-model="creationType" :items="['custom', 'from file']" />
|
||||||
|
</div>
|
||||||
|
<div v-if="creationType === 'custom'" class="modal-body">
|
||||||
<div class="image-upload">
|
<div class="image-upload">
|
||||||
<Avatar :src="display_icon" size="md" :rounded="true" />
|
<Avatar :src="display_icon" size="md" :rounded="true" />
|
||||||
<div class="image-input">
|
<div class="image-input">
|
||||||
@@ -79,6 +82,10 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else class="modal-body">
|
||||||
|
<Button @click="openFile"> <FolderOpenIcon /> Import from file </Button>
|
||||||
|
<div class="info"><InfoIcon /> Or drag and drop your .mrpack file</div>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -93,6 +100,8 @@ import {
|
|||||||
XIcon,
|
XIcon,
|
||||||
CodeIcon,
|
CodeIcon,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
|
FolderOpenIcon,
|
||||||
|
InfoIcon,
|
||||||
} from 'omorphia'
|
} from 'omorphia'
|
||||||
import { computed, ref, shallowRef } from 'vue'
|
import { computed, ref, shallowRef } from 'vue'
|
||||||
import { get_loaders } from '@/helpers/tags'
|
import { get_loaders } from '@/helpers/tags'
|
||||||
@@ -107,6 +116,8 @@ import {
|
|||||||
} from '@/helpers/metadata'
|
} from '@/helpers/metadata'
|
||||||
import { handleError } from '@/store/notifications.js'
|
import { handleError } from '@/store/notifications.js'
|
||||||
import Multiselect from 'vue-multiselect'
|
import Multiselect from 'vue-multiselect'
|
||||||
|
import { listen } from '@tauri-apps/api/event'
|
||||||
|
import { install_from_file } from '@/helpers/pack.js'
|
||||||
|
|
||||||
const profile_name = ref('')
|
const profile_name = ref('')
|
||||||
const game_version = ref('')
|
const game_version = ref('')
|
||||||
@@ -118,6 +129,7 @@ const display_icon = ref(null)
|
|||||||
const showAdvanced = ref(false)
|
const showAdvanced = ref(false)
|
||||||
const creating = ref(false)
|
const creating = ref(false)
|
||||||
const showSnapshots = ref(false)
|
const showSnapshots = ref(false)
|
||||||
|
const creationType = ref('from file')
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
show: () => {
|
show: () => {
|
||||||
@@ -184,16 +196,16 @@ const create_instance = async () => {
|
|||||||
const loader_version_value =
|
const loader_version_value =
|
||||||
loader_version.value === 'other' ? specified_loader_version.value : loader_version.value
|
loader_version.value === 'other' ? specified_loader_version.value : loader_version.value
|
||||||
|
|
||||||
create(
|
modal.value.hide()
|
||||||
|
creating.value = false
|
||||||
|
|
||||||
|
await create(
|
||||||
profile_name.value,
|
profile_name.value,
|
||||||
game_version.value,
|
game_version.value,
|
||||||
loader.value,
|
loader.value,
|
||||||
loader.value === 'vanilla' ? null : loader_version_value ?? 'stable',
|
loader.value === 'vanilla' ? null : loader_version_value ?? 'stable',
|
||||||
icon.value
|
icon.value
|
||||||
).catch(handleError)
|
).catch(handleError)
|
||||||
|
|
||||||
modal.value.hide()
|
|
||||||
creating.value = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const upload_icon = async () => {
|
const upload_icon = async () => {
|
||||||
@@ -234,14 +246,27 @@ const selectable_versions = computed(() => {
|
|||||||
const toggle_advanced = () => {
|
const toggle_advanced = () => {
|
||||||
showAdvanced.value = !showAdvanced.value
|
showAdvanced.value = !showAdvanced.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const openFile = async () => {
|
||||||
|
const newProject = await open({ multiple: false })
|
||||||
|
if (!newProject) return
|
||||||
|
|
||||||
|
modal.value.hide()
|
||||||
|
await install_from_file(newProject).catch(handleError)
|
||||||
|
}
|
||||||
|
|
||||||
|
listen('tauri://file-drop', async (event) => {
|
||||||
|
modal.value.hide()
|
||||||
|
await install_from_file(event.payload[0]).catch(handleError)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.modal-body {
|
.modal-body {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 1rem;
|
padding: var(--gap-lg);
|
||||||
gap: 1rem;
|
gap: var(--gap-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-label {
|
.input-label {
|
||||||
@@ -284,4 +309,33 @@ const toggle_advanced = () => {
|
|||||||
.selector {
|
.selector {
|
||||||
max-width: 20rem;
|
max-width: 20rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.labeled-divider {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labeled-divider:after {
|
||||||
|
background-color: var(--color-raised-bg);
|
||||||
|
content: 'Or';
|
||||||
|
color: var(--color-base);
|
||||||
|
padding: var(--gap-sm);
|
||||||
|
position: relative;
|
||||||
|
top: -0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 0.5rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: var(--gap-lg);
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -28,18 +28,22 @@
|
|||||||
class="dropdown"
|
class="dropdown"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<Button
|
<DropdownButton
|
||||||
|
:options="['search', 'from_file']"
|
||||||
|
default-value="search"
|
||||||
|
name="add-content-dropdown"
|
||||||
color="primary"
|
color="primary"
|
||||||
@click="
|
@option-click="handleContentOptionClick"
|
||||||
router.push({
|
|
||||||
path: `/browse/${props.instance.metadata.loader === 'vanilla' ? 'datapack' : 'mod'}`,
|
|
||||||
query: { i: $route.params.id },
|
|
||||||
})
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<PlusIcon />
|
<template #search>
|
||||||
<span class="no-wrap"> Add content </span>
|
<SearchIcon />
|
||||||
</Button>
|
<span class="no-wrap"> Search addons </span>
|
||||||
|
</template>
|
||||||
|
<template #from_file>
|
||||||
|
<FolderOpenIcon />
|
||||||
|
<span class="no-wrap"> Add from file </span>
|
||||||
|
</template>
|
||||||
|
</DropdownButton>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="second-row">
|
<div class="second-row">
|
||||||
@@ -63,15 +67,15 @@
|
|||||||
@option-click="toggleSelected"
|
@option-click="toggleSelected"
|
||||||
>
|
>
|
||||||
<template #toggle>
|
<template #toggle>
|
||||||
<GlobeIcon />
|
<EditIcon />
|
||||||
Toggle selected
|
Toggle selected
|
||||||
</template>
|
</template>
|
||||||
<template #disable>
|
<template #disable>
|
||||||
<EditIcon />
|
<XIcon />
|
||||||
Disable selected
|
Disable selected
|
||||||
</template>
|
</template>
|
||||||
<template #enable>
|
<template #enable>
|
||||||
<HashIcon />
|
<CheckCircleIcon />
|
||||||
Enable selected
|
Enable selected
|
||||||
</template>
|
</template>
|
||||||
</DropdownButton>
|
</DropdownButton>
|
||||||
@@ -182,7 +186,6 @@ import {
|
|||||||
Avatar,
|
Avatar,
|
||||||
Button,
|
Button,
|
||||||
TrashIcon,
|
TrashIcon,
|
||||||
PlusIcon,
|
|
||||||
Card,
|
Card,
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
SearchIcon,
|
SearchIcon,
|
||||||
@@ -190,6 +193,7 @@ import {
|
|||||||
DropdownSelect,
|
DropdownSelect,
|
||||||
AnimatedLogo,
|
AnimatedLogo,
|
||||||
Chips,
|
Chips,
|
||||||
|
FolderOpenIcon,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
formatProjectType,
|
formatProjectType,
|
||||||
DropdownButton,
|
DropdownButton,
|
||||||
@@ -198,17 +202,22 @@ import {
|
|||||||
HashIcon,
|
HashIcon,
|
||||||
Modal,
|
Modal,
|
||||||
XIcon,
|
XIcon,
|
||||||
|
CheckCircleIcon,
|
||||||
} from 'omorphia'
|
} from 'omorphia'
|
||||||
import { computed, ref, watch } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import { convertFileSrc } from '@tauri-apps/api/tauri'
|
import { convertFileSrc } from '@tauri-apps/api/tauri'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import {
|
import {
|
||||||
|
add_project_from_path,
|
||||||
|
get,
|
||||||
remove_project,
|
remove_project,
|
||||||
toggle_disable_project,
|
toggle_disable_project,
|
||||||
update_all,
|
update_all,
|
||||||
update_project,
|
update_project,
|
||||||
} from '@/helpers/profile.js'
|
} from '@/helpers/profile.js'
|
||||||
import { handleError } from '@/store/notifications.js'
|
import { handleError } from '@/store/notifications.js'
|
||||||
|
import { open } from '@tauri-apps/api/dialog'
|
||||||
|
import { listen } from '@tauri-apps/api/event'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@@ -228,49 +237,55 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const projects = ref([])
|
const projects = ref([])
|
||||||
for (const [path, project] of Object.entries(props.instance.projects)) {
|
|
||||||
if (project.metadata.type === 'modrinth') {
|
const initProjects = (initInstance) => {
|
||||||
let owner = project.metadata.members.find((x) => x.role === 'Owner')
|
projects.value = []
|
||||||
projects.value.push({
|
for (const [path, project] of Object.entries(initInstance.projects)) {
|
||||||
path,
|
if (project.metadata.type === 'modrinth') {
|
||||||
name: project.metadata.project.title,
|
let owner = project.metadata.members.find((x) => x.role === 'Owner')
|
||||||
slug: project.metadata.project.slug,
|
projects.value.push({
|
||||||
author: owner ? owner.user.username : null,
|
path,
|
||||||
version: project.metadata.version.version_number,
|
name: project.metadata.project.title,
|
||||||
file_name: project.file_name,
|
slug: project.metadata.project.slug,
|
||||||
icon: project.metadata.project.icon_url,
|
author: owner ? owner.user.username : null,
|
||||||
disabled: project.disabled,
|
version: project.metadata.version.version_number,
|
||||||
updateVersion: project.metadata.update_version,
|
file_name: project.file_name,
|
||||||
outdated: !!project.metadata.update_version,
|
icon: project.metadata.project.icon_url,
|
||||||
project_type: project.metadata.project.project_type,
|
disabled: project.disabled,
|
||||||
})
|
updateVersion: project.metadata.update_version,
|
||||||
} else if (project.metadata.type === 'inferred') {
|
outdated: !!project.metadata.update_version,
|
||||||
projects.value.push({
|
project_type: project.metadata.project.project_type,
|
||||||
path,
|
})
|
||||||
name: project.metadata.title ?? project.file_name,
|
} else if (project.metadata.type === 'inferred') {
|
||||||
author: project.metadata.authors[0],
|
projects.value.push({
|
||||||
version: project.metadata.version,
|
path,
|
||||||
file_name: project.file_name,
|
name: project.metadata.title ?? project.file_name,
|
||||||
icon: project.metadata.icon ? convertFileSrc(project.metadata.icon) : null,
|
author: project.metadata.authors[0],
|
||||||
disabled: project.disabled,
|
version: project.metadata.version,
|
||||||
outdated: false,
|
file_name: project.file_name,
|
||||||
project_type: project.metadata.project_type,
|
icon: project.metadata.icon ? convertFileSrc(project.metadata.icon) : null,
|
||||||
})
|
disabled: project.disabled,
|
||||||
} else {
|
outdated: false,
|
||||||
projects.value.push({
|
project_type: project.metadata.project_type,
|
||||||
path,
|
})
|
||||||
name: project.file_name,
|
} else {
|
||||||
author: '',
|
projects.value.push({
|
||||||
version: null,
|
path,
|
||||||
file_name: project.file_name,
|
name: project.file_name,
|
||||||
icon: null,
|
author: '',
|
||||||
disabled: project.disabled,
|
version: null,
|
||||||
outdated: false,
|
file_name: project.file_name,
|
||||||
project_type: null,
|
icon: null,
|
||||||
})
|
disabled: project.disabled,
|
||||||
|
outdated: false,
|
||||||
|
project_type: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initProjects(props.instance)
|
||||||
|
|
||||||
const searchFilter = ref('')
|
const searchFilter = ref('')
|
||||||
const selectAll = ref(false)
|
const selectAll = ref(false)
|
||||||
const sortFilter = ref('')
|
const sortFilter = ref('')
|
||||||
@@ -392,6 +407,31 @@ async function removeMod(mod) {
|
|||||||
projects.value = projects.value.filter((x) => mod.path !== x.path)
|
projects.value = projects.value.filter((x) => mod.path !== x.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleContentOptionClick = async (args) => {
|
||||||
|
if (args.option === 'search') {
|
||||||
|
await router.push({
|
||||||
|
path: `/browse/${props.instance.metadata.loader === 'vanilla' ? 'datapack' : 'mod'}`,
|
||||||
|
})
|
||||||
|
} else if (args.option === 'from_file') {
|
||||||
|
const newProject = await open({ multiple: true })
|
||||||
|
console.log(newProject)
|
||||||
|
if (!newProject) return
|
||||||
|
|
||||||
|
for (const project of newProject) {
|
||||||
|
console.log(project)
|
||||||
|
await add_project_from_path(props.instance.path, project, 'mod').catch(handleError)
|
||||||
|
initProjects(await get(props.instance.path).catch(handleError))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listen('tauri://file-drop', async (event) => {
|
||||||
|
for (const file of event.payload) {
|
||||||
|
await add_project_from_path(props.instance.path, file, 'mod').catch(handleError)
|
||||||
|
initProjects(await get(props.instance.path).catch(handleError))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
async function deleteSelected() {
|
async function deleteSelected() {
|
||||||
for (const project of selected.value) {
|
for (const project of selected.value) {
|
||||||
await remove_project(props.instance.path, project.path).catch(handleError)
|
await remove_project(props.instance.path, project.path).catch(handleError)
|
||||||
|
|||||||
Reference in New Issue
Block a user