Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non modpack wireup & Project to profile install #90

Merged
merged 33 commits into from
May 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7ccf10b
Base impl
CodexAdrian Apr 19, 2023
de887ef
Make project type selectable
CodexAdrian Apr 19, 2023
31ac989
Update Browse.vue
CodexAdrian Apr 19, 2023
8a2264e
address changes
CodexAdrian Apr 21, 2023
8d2bfa3
Quick create
CodexAdrian Apr 21, 2023
accf5ca
Run linter
CodexAdrian Apr 21, 2023
6c03dd6
Merge branch 'master' into non-modpack-wireup
Geometrically Apr 22, 2023
34189c2
fix merge
Geometrically Apr 22, 2023
e721772
Merge branch 'master' into non-modpack-wireup
CodexAdrian Apr 22, 2023
9b944ca
Merge branch 'non-modpack-wireup' of https://github.com/modrinth/thes…
CodexAdrian Apr 22, 2023
590c586
Addressed changes
CodexAdrian Apr 22, 2023
cd7beb7
Installation improvements
CodexAdrian Apr 22, 2023
4582df8
Run lint
CodexAdrian Apr 22, 2023
001df2c
resourcepacks
CodexAdrian Apr 22, 2023
b6a36a4
automatic installation of dependencies
CodexAdrian Apr 23, 2023
8f4f8c6
Fix bugs with search
CodexAdrian Apr 24, 2023
28d717e
Merge branch 'master' into non-modpack-wireup
CodexAdrian Apr 24, 2023
015970e
Merge branch 'master' into non-modpack-wireup
CodexAdrian Apr 26, 2023
c588c53
Addressed changes
CodexAdrian Apr 26, 2023
6a794d2
Run linter
CodexAdrian Apr 26, 2023
616c4ca
Fixed direct install not working
CodexAdrian Apr 26, 2023
953c09b
Merge branch 'master' into non-modpack-wireup
CodexAdrian Apr 27, 2023
1960e2a
Remove back to search
CodexAdrian Apr 27, 2023
32d5748
Update Index.vue
CodexAdrian Apr 27, 2023
707af3a
Merge branch 'master' into non-modpack-wireup
CodexAdrian Apr 28, 2023
591ef21
Addressed some changes
CodexAdrian Apr 28, 2023
d3729a8
Shader fix
CodexAdrian Apr 28, 2023
fbc4ebe
fix resetting
CodexAdrian Apr 29, 2023
61be7f7
Update Browse.vue
CodexAdrian Apr 29, 2023
98bf704
Merge branch 'master' into non-modpack-wireup
CodexAdrian May 3, 2023
d70aee4
Merge branch 'master' into non-modpack-wireup
CodexAdrian May 8, 2023
dab504d
fixed install not working properly
CodexAdrian May 8, 2023
27e777b
Update Index.vue
CodexAdrian May 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion theseus_gui/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ list().then(
<span v-if="!themeStore.collapsedNavigation">Home</span>
</RouterLink>
<RouterLink
to="/browse"
to="/browse/modpack"
class="btn"
:class="{
'icon-only': themeStore.collapsedNavigation,
Expand Down
1 change: 1 addition & 0 deletions theseus_gui/src/assets/stylesheets/global.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

:root {
font-family: var(--font-standard);
color-scheme: dark;
}

* {
Expand Down
44 changes: 42 additions & 2 deletions theseus_gui/src/components/ui/Instance.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup>
import { RouterLink } from 'vue-router'
import { Card } from 'omorphia'
import { Avatar, Card } from 'omorphia'
import { PlayIcon } from '@/assets/icons'
import { convertFileSrc } from '@tauri-apps/api/tauri'

Expand All @@ -11,13 +11,32 @@ const props = defineProps({
return {}
},
},
small: {
type: Boolean,
default: false,
},
})
</script>

<template>
<div>
<RouterLink :to="`/instance/${encodeURIComponent(props.instance.path)}`">
<Card class="instance-card-item">
<Card v-if="props.small" class="instance-small-card button-base">
<Avatar
:src="convertFileSrc(props.instance.metadata.icon)"
:alt="props.instance.metadata.name"
size="sm"
/>
<div class="instance-small-card__info">
<span class="title">{{ props.instance.metadata.name }}</span>
{{
props.instance.metadata.loader.charAt(0).toUpperCase() +
props.instance.metadata.loader.slice(1)
}}
{{ props.instance.metadata.game_version }}
</div>
</Card>
<Card v-else class="instance-card-item">
<img :src="convertFileSrc(props.instance.metadata.icon)" alt="Trending mod card" />
<div class="project-info">
<p class="title">{{ props.instance.metadata.name }}</p>
Expand All @@ -32,6 +51,27 @@ const props = defineProps({
</template>

<style lang="scss" scoped>
.instance-small-card {
background-color: var(--color-bg) !important;
padding: 1rem !important;
display: flex;
flex-direction: row;
min-height: min-content !important;
gap: 1rem;
align-items: center;

.instance-small-card__info {
display: flex;
flex-direction: column;
justify-content: center;

.title {
color: var(--color-contrast);
font-weight: bolder;
}
}
}

.instance-card-item {
display: flex;
flex-direction: column;
Expand Down
297 changes: 297 additions & 0 deletions theseus_gui/src/components/ui/InstanceInstallModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
<script setup>
import {
Avatar,
Modal,
Button,
DownloadIcon,
PlusIcon,
Card,
UploadIcon,
XIcon,
RightArrowIcon,
CheckIcon,
} from 'omorphia'
import { computed, ref } from 'vue'
import { add_project_from_version as installMod, list } from '@/helpers/profile'
import { tauri } from '@tauri-apps/api'
import { open } from '@tauri-apps/api/dialog'
import { convertFileSrc } from '@tauri-apps/api/tauri'
import { useRouter } from 'vue-router'
import { create } from '@/helpers/profile'
import { checkInstalled, installVersionDependencies } from '@/helpers/utils'
const router = useRouter()
const versions = ref([])
const project = ref('')
const installModal = ref(null)
const searchFilter = ref('')
const showCreation = ref(false)
const icon = ref(null)
const name = ref(null)
const display_icon = ref(null)
const loader = ref(null)
const gameVersion = ref(null)
const creatingInstance = ref(false)

defineExpose({
show: (projectId, selectedVersion) => {
project.value = projectId
versions.value = selectedVersion
installModal.value.show()
searchFilter.value = ''
},
})

const profiles = ref(await list().then(Object.values))

async function install(instance) {
instance.installing = true
const version = versions.value.find((v) => {
return (
v.game_versions.includes(instance.metadata.game_version) &&
(v.loaders.includes(instance.metadata.loader) || v.loaders.includes('minecraft'))
)
})

await installMod(instance.path, version.id)
await installVersionDependencies(instance, version)

instance.installed = true
instance.installing = false
}

const filteredVersions = computed(() => {
const filtered = profiles.value
.filter((profile) => {
return profile.metadata.name.toLowerCase().includes(searchFilter.value.toLowerCase())
})
.filter((profile) => {
return (
versions.value.flatMap((v) => v.game_versions).includes(profile.metadata.game_version) &&
versions.value
.flatMap((v) => v.loaders)
.some((value) => value === profile.metadata.loader || value === 'minecraft')
)
})

filtered.map((profile) => {
profile.installing = false
profile.installed = checkInstalled(profile, project.value)
})

return filtered
})

const toggleCreation = () => {
showCreation.value = !showCreation.value
name.value = null
icon.value = null
display_icon.value = null
gameVersion.value = null
loader.value = null
}

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 createInstance = async () => {
creatingInstance.value = true
const id = await create(
name.value,
versions.value[0].game_versions[0],
versions.value[0].loaders[0] !== 'forge' ||
versions.value[0].loaders[0] !== 'fabric' ||
versions.value[0].loaders[0] !== 'quilt'
? versions.value[0].loaders[0]
: 'vanilla',
'latest',
icon.value
)

await installMod(id, versions.value[0].id)

await router.push({ path: `/instance/${encodeURIComponent(id)}` })
installModal.value.hide()
creatingInstance.value = false
}

const check_valid = computed(() => {
return name.value
})
</script>

<template>
<Modal ref="installModal" header="Install mod to instance">
<div class="modal-body">
<input v-model="searchFilter" type="text" class="search" placeholder="Search for a profile" />
<div class="profiles">
CodexAdrian marked this conversation as resolved.
Show resolved Hide resolved
<div v-for="profile in filteredVersions" :key="profile.metadata.name" class="option">
<Button
color="raised"
class="profile-button"
@click="$router.push(`/instance/${encodeURIComponent(profile.path)}`)"
>
<Avatar :src="convertFileSrc(profile.metadata.icon)" class="profile-image" />
{{ profile.metadata.name }}
</Button>
<Button :disabled="profile.installed || profile.installing" @click="install(profile)">
<DownloadIcon v-if="!profile.installed && !profile.installing" />
<CheckIcon v-else-if="profile.installed" />
{{ profile.installing ? 'Installing...' : profile.installed ? 'Installed' : 'Install' }}
</Button>
</div>
</div>
<Card v-if="showCreation" class="creation-card">
<div class="creation-container">
<div class="creation-icon">
<Avatar size="md" class="icon" :src="display_icon" />
<div class="creation-icon__description">
<Button @click="upload_icon()">
<UploadIcon />
<span class="no-wrap"> Upload Icon </span>
</Button>
<Button @click="reset_icon()">
<XIcon />
<span class="no-wrap"> Remove Icon </span>
</Button>
</div>
</div>
<div class="creation-settings">
<input v-model="name" type="text" placeholder="Name" class="creation-input" />
<Button :disabled="creatingInstance === true || !check_valid" @click="createInstance()">
<RightArrowIcon />
{{ creatingInstance ? 'Creating...' : 'Create' }}
</Button>
</div>
</div>
</Card>
<div class="footer">
<Button :color="showCreation ? '' : 'primary'" @click="toggleCreation()">
<PlusIcon />
{{ showCreation ? 'Hide New Instance' : 'Create new instance' }}
</Button>
<Button @click="installModal.hide()">Cancel</Button>
</div>
</div>
</Modal>
</template>

<style scoped lang="scss">
.creation-card {
display: flex;
flex-direction: column;
gap: 1rem;
margin: 0;
padding: 1rem;
background-color: var(--color-bg);
}

.creation-container {
display: flex;
flex-direction: row;
gap: 1rem;
}

.creation-icon {
display: flex;
flex-direction: row;
gap: 1rem;
align-items: center;
flex-grow: 1;

.creation-icon__description {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
}

.creation-input {
width: 100%;
}

.no-wrap {
white-space: nowrap;
}

.creation-dropdown {
width: min-content !important;
display: flex;
flex-direction: column;
gap: 0.5rem;
}

.creation-settings {
width: 100%;
margin-left: 0.5rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
justify-content: center;
}

.modal-body {
display: flex;
flex-direction: column;
gap: 1rem;
padding: 1rem;
}

.profiles {
max-height: 12rem;
overflow-y: auto;
}

.option {
width: calc(100%);
background: var(--color-raised-bg);
color: var(--color-base);
box-shadow: none;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 0 0.5rem;

img {
margin-right: 0.5rem;
}

.name {
display: flex;
flex-direction: column;
justify-content: center;
}

.profile-button {
padding: 0.5rem;
}
}

.profile-image {
--size: 2rem !important;
}

.footer {
display: flex;
flex-direction: row;
justify-content: flex-end;
gap: 0.5rem;
margin-left: auto;
}
</style>
Loading