Context menus (#133)

* Context Menus in home and library

* Menu impl

* FInalize context menus

* Update App.vue

* Update App.vue

* fix scrolling
This commit is contained in:
Adrian O.V
2023-06-10 15:31:52 -04:00
committed by GitHub
parent e0e9c3f166
commit e836738887
9 changed files with 672 additions and 61 deletions

View File

@@ -1,7 +1,7 @@
<template>
<div class="instance-container">
<div class="side-cards">
<Card class="instance-card">
<Card class="instance-card" @contextmenu.prevent.stop="handleRightClick">
<Avatar
size="lg"
:src="
@@ -28,7 +28,7 @@
@click="stopInstance"
@mouseover="checkProcess"
>
<XIcon />
<StopCircleIcon />
Stop
</Button>
<Button
@@ -78,40 +78,60 @@
<RouterView v-slot="{ Component }">
<template v-if="Component">
<Suspense @pending="loadingBar.startLoading()" @resolve="loadingBar.stopLoading()">
<component :is="Component" :instance="instance"></component>
<component :is="Component" :instance="instance" :options="options"></component>
</Suspense>
</template>
</RouterView>
</div>
</div>
<ContextMenu ref="options" @option-clicked="handleOptionsClick">
<template #play> <PlayIcon /> Play </template>
<template #stop> <StopCircleIcon /> Stop </template>
<template #add_content> <PlusIcon /> Add Content </template>
<template #edit> <EditIcon /> Edit </template>
<template #copy_path> <ClipboardCopyIcon /> Copy Path </template>
<template #open_folder> <ClipboardCopyIcon /> Open Folder </template>
<template #copy_link> <ClipboardCopyIcon /> Copy Link </template>
<template #open_link> <ClipboardCopyIcon /> Open In Modrinth <ExternalIcon /> </template>
<template #repair> <HammerIcon /> Repair </template>
<template #delete> <TrashIcon /> Delete </template>
</ContextMenu>
</template>
<script setup>
import {
BoxIcon,
SettingsIcon,
FileIcon,
XIcon,
Button,
Avatar,
Card,
Promotion,
PlayIcon,
StopCircleIcon,
EditIcon,
HammerIcon,
TrashIcon,
FolderOpenIcon,
ClipboardCopyIcon,
PlusIcon,
ExternalIcon,
} from 'omorphia'
import { get, run } from '@/helpers/profile'
import { get, install, remove, run } from '@/helpers/profile'
import {
get_all_running_profile_paths,
get_uuids_by_profile_path,
kill_by_uuid,
} from '@/helpers/process'
import { process_listener, profile_listener } from '@/helpers/events'
import { useRoute } from 'vue-router'
import { useRoute, useRouter } from 'vue-router'
import { ref, onUnmounted } from 'vue'
import { convertFileSrc } from '@tauri-apps/api/tauri'
import { handleError, useBreadcrumbs, useLoading, useSearch } from '@/store/state'
import { showInFolder } from '@/helpers/utils.js'
import ContextMenu from '@/components/ui/ContextMenu.vue'
const route = useRoute()
const router = useRouter()
const searchStore = useSearch()
const breadcrumbs = useBreadcrumbs()
@@ -129,6 +149,7 @@ const loadingBar = useLoading()
const uuid = ref(null)
const playing = ref(false)
const loading = ref(false)
const options = ref(null)
const startInstance = async () => {
loading.value = true
@@ -170,6 +191,91 @@ const unlistenProcesses = await process_listener((e) => {
if (e.event === 'finished' && uuid.value === e.uuid) playing.value = false
})
const handleRightClick = (event) => {
const baseOptions = [
{ name: 'add_content' },
{ type: 'divider' },
{ name: 'edit' },
{ name: 'open_folder' },
{ name: 'copy_path' },
{ type: 'divider' },
{
name: 'repair',
color: 'contrast',
},
{
name: 'delete',
color: 'danger',
},
]
options.value.showMenu(
event,
instance.value,
playing.value
? [
{
name: 'stop',
color: 'danger',
},
...baseOptions,
]
: [
{
name: 'play',
color: 'primary',
},
...baseOptions,
]
)
}
const handleOptionsClick = async (args) => {
console.log(args)
switch (args.option) {
case 'play':
await startInstance()
break
case 'stop':
await stopInstance()
break
case 'add_content':
await router.push({
path: `/browse/${instance.value.metadata.loader === 'vanilla' ? 'datapack' : 'mod'}`,
})
break
case 'edit':
await router.push({
path: `/instance/${encodeURIComponent(route.params.id)}/options`,
})
break
case 'repair':
await install(instance.value.path).catch(handleError)
break
case 'delete':
await remove(instance.value.path).catch(handleError)
break
case 'open_folder':
await showInFolder(instance.value.path)
break
case 'copy_path':
await navigator.clipboard.writeText(instance.value.path)
break
case 'open_link':
window.__TAURI_INVOKE__('tauri', {
__tauriModule: 'Shell',
message: {
cmd: 'open',
path: args.item.link,
},
})
break
case 'copy_link':
await navigator.clipboard.writeText(args.item.link)
break
}
}
onUnmounted(() => {
unlistenProcesses()
unlistenProfiles()

View File

@@ -60,7 +60,12 @@
<div class="table-cell table-text">Author</div>
<div class="table-cell table-text">Actions</div>
</div>
<div v-for="mod in search" :key="mod.file_name" class="table-row">
<div
v-for="mod in search"
:key="mod.file_name"
class="table-row"
@contextmenu.prevent.stop="(c) => handleRightClick(c, mod)"
>
<div class="table-cell table-text">
<AnimatedLogo v-if="mod.updating" class="btn icon-only updating-indicator"></AnimatedLogo>
<Button
@@ -138,6 +143,12 @@ const props = defineProps({
return {}
},
},
options: {
type: Object,
default() {
return {}
},
},
})
const projects = ref([])
@@ -302,6 +313,18 @@ async function removeMod(mod) {
await remove_project(props.instance.path, mod.path).catch(handleError)
projects.value = projects.value.filter((x) => mod.path !== x.path)
}
const handleRightClick = (event, mod) => {
if (mod.slug && mod.project_type) {
props.options.showMenu(
event,
{
link: `https://modrinth.com/${mod.project_type}/${mod.slug}`,
},
[{ name: 'open_link' }, { name: 'copy_link' }]
)
}
}
</script>
<style scoped lang="scss">