mirror of
https://github.com/Drop-OSS/drop.git
synced 2026-06-22 20:31:31 +10:00
82b9912bd0
* refactor: split umu launcher * feat: latest version picker + fixes * feat: frontend latest changes * feat: game update detection w/ setting * feat: fixes and refactor for game update * fix: windows ui * fix: deps * feat: update modifications * feat: missing ui and lock update * fix: create install dir on init * fix: clippy * fix: clippy x2 * feat: add configuration option to toggle updates * feat: uninstall dropdown on partiallyinstalled
233 lines
7.5 KiB
Vue
233 lines
7.5 KiB
Vue
<template>
|
|
<!-- Do not add scale animations to this: https://stackoverflow.com/a/35683068 -->
|
|
<div class="inline-flex divide-x divide-zinc-900">
|
|
<button
|
|
type="button"
|
|
@click="() => fetchStatusStyleData($props.status).action()"
|
|
:class="[
|
|
fetchStatusStyleData($props.status).style,
|
|
showDropdown ? 'rounded-l-md' : 'rounded-md',
|
|
'inline-flex uppercase font-display items-center gap-x-2 px-4 py-3 text-md font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2',
|
|
]"
|
|
>
|
|
<component
|
|
:is="fetchStatusStyleData($props.status).icon"
|
|
class="-mr-0.5 size-5"
|
|
aria-hidden="true"
|
|
/>
|
|
{{ fetchStatusStyleData($props.status).buttonName }}
|
|
</button>
|
|
<Menu
|
|
v-if="showDropdown"
|
|
as="div"
|
|
class="relative inline-block text-left grow"
|
|
>
|
|
<div class="h-full">
|
|
<MenuButton
|
|
:class="[
|
|
fetchStatusStyleData($props.status).style,
|
|
'inline-flex w-full h-full justify-center items-center rounded-r-md px-1 py-2 text-sm font-semibold shadow-sm group',
|
|
'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2',
|
|
]"
|
|
>
|
|
<ChevronDownIcon class="size-5" aria-hidden="true" />
|
|
</MenuButton>
|
|
</div>
|
|
|
|
<transition
|
|
enter-active-class="transition ease-out duration-100"
|
|
enter-from-class="transform opacity-0 scale-95"
|
|
enter-to-class="transform opacity-100 scale-100"
|
|
leave-active-class="transition ease-in duration-75"
|
|
leave-from-class="transform opacity-100 scale-100"
|
|
leave-to-class="transform opacity-0 scale-95"
|
|
>
|
|
<MenuItems
|
|
class="absolute right-0 z-[500] mt-2 w-32 origin-top-right rounded-md bg-zinc-900 shadow-lg ring-1 ring-zinc-100/5 focus:outline-none"
|
|
>
|
|
<div class="py-1">
|
|
<MenuItem v-slot="{ active }">
|
|
<button
|
|
@click="() => emit('install')"
|
|
:class="[
|
|
active
|
|
? 'bg-zinc-800 text-zinc-100 outline-none'
|
|
: 'text-zinc-400',
|
|
'w-full px-4 py-2 text-sm inline-flex justify-between',
|
|
]"
|
|
>
|
|
Install
|
|
<ArrowDownTrayIcon class="size-5" />
|
|
</button>
|
|
</MenuItem>
|
|
|
|
<MenuItem v-if="showOptions" v-slot="{ active }">
|
|
<button
|
|
@click="() => emit('options')"
|
|
:class="[
|
|
active
|
|
? 'bg-zinc-800 text-zinc-100 outline-none'
|
|
: 'text-zinc-400',
|
|
'w-full px-4 py-2 text-sm inline-flex justify-between',
|
|
]"
|
|
>
|
|
Options
|
|
<Cog6ToothIcon class="size-5" />
|
|
</button>
|
|
</MenuItem>
|
|
<MenuItem v-slot="{ active }">
|
|
<button
|
|
@click="() => emit('uninstall')"
|
|
:class="[
|
|
active
|
|
? 'bg-zinc-800 text-zinc-100 outline-none'
|
|
: 'text-zinc-400',
|
|
'w-full inline-flex px-4 py-2 text-sm justify-between',
|
|
]"
|
|
>
|
|
Uninstall
|
|
<TrashIcon class="size-5" />
|
|
</button>
|
|
</MenuItem>
|
|
</div>
|
|
</MenuItems>
|
|
</transition>
|
|
</Menu>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import {
|
|
ArrowDownTrayIcon,
|
|
ChevronDownIcon,
|
|
PlayIcon,
|
|
QueueListIcon,
|
|
ServerIcon,
|
|
StopIcon,
|
|
WrenchIcon,
|
|
} from "@heroicons/vue/20/solid";
|
|
|
|
import type { Component } from "vue";
|
|
import {
|
|
type EmptyGameStatusEnum,
|
|
InstalledType,
|
|
type GameStatus,
|
|
} from "~/types.js";
|
|
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/vue";
|
|
import { Cog6ToothIcon, TrashIcon } from "@heroicons/vue/24/outline";
|
|
import { ArrowsRightLeftIcon, ArrowUpTrayIcon } from "@heroicons/vue/24/solid";
|
|
|
|
const props = defineProps<{ status: GameStatus }>();
|
|
const emit = defineEmits<{
|
|
(e: "install"): void;
|
|
(e: "launch"): void;
|
|
(e: "queue"): void;
|
|
(e: "uninstall"): void;
|
|
(e: "kill"): void;
|
|
(e: "options"): void;
|
|
(e: "resume"): void;
|
|
}>();
|
|
|
|
interface StatusStyleData {
|
|
style: string;
|
|
buttonName: string;
|
|
icon: Component;
|
|
action: () => void;
|
|
}
|
|
|
|
function fetchStatusStyleData(status: GameStatus): StatusStyleData {
|
|
if (status.type === "Installed") {
|
|
if (status.install_type.type === InstalledType.Installed) {
|
|
return {
|
|
style:
|
|
"bg-green-600 text-white hover:bg-green-500 focus-visible:outline-green-600 hover:bg-green-500",
|
|
buttonName: "Play",
|
|
icon: PlayIcon,
|
|
action: () => emit("launch"),
|
|
};
|
|
}
|
|
if (status.install_type.type === InstalledType.SetupRequired) {
|
|
return {
|
|
style:
|
|
"bg-yellow-600 text-white hover:bg-yellow-500 focus-visible:outline-yellow-600 hover:bg-yellow-500",
|
|
buttonName: "Setup",
|
|
icon: WrenchIcon,
|
|
action: () => emit("launch"),
|
|
};
|
|
}
|
|
if (status.install_type.type === InstalledType.PartiallyInstalled) {
|
|
return {
|
|
style:
|
|
"bg-blue-600 text-white hover:bg-blue-500 focus-visible:outline-blue-600 hover:bg-blue-500",
|
|
buttonName: "Resume",
|
|
icon: ArrowDownTrayIcon,
|
|
action: () => emit("resume"),
|
|
};
|
|
}
|
|
throw "Non-exhaustive install type: " + JSON.stringify(status.install_type);
|
|
}
|
|
return {
|
|
style: styles[status.type],
|
|
buttonName: buttonNames[status.type],
|
|
icon: buttonIcons[status.type],
|
|
action: buttonActions[status.type],
|
|
};
|
|
}
|
|
|
|
const showDropdown = computed(() => props.status.type === "Installed");
|
|
|
|
const showOptions = computed(
|
|
() =>
|
|
showDropdown.value &&
|
|
props.status.type === "Installed" &&
|
|
props.status.install_type.type !== InstalledType.PartiallyInstalled,
|
|
);
|
|
|
|
const styles: { [key in EmptyGameStatusEnum]: string } = {
|
|
Remote:
|
|
"bg-blue-600 text-white hover:bg-blue-500 focus-visible:outline-blue-600 hover:bg-blue-500",
|
|
Queued:
|
|
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
|
Downloading:
|
|
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
|
Validating:
|
|
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
|
Updating:
|
|
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
|
Uninstalling:
|
|
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
|
Running:
|
|
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
|
};
|
|
|
|
const buttonNames: { [key in EmptyGameStatusEnum]: string } = {
|
|
Remote: "Install",
|
|
Queued: "Queued",
|
|
Downloading: "Downloading",
|
|
Validating: "Validating",
|
|
Updating: "Updating",
|
|
Uninstalling: "Uninstalling",
|
|
Running: "Stop",
|
|
};
|
|
|
|
const buttonIcons: { [key in EmptyGameStatusEnum]: Component } = {
|
|
Remote: ArrowDownTrayIcon,
|
|
Queued: QueueListIcon,
|
|
Downloading: ArrowDownTrayIcon,
|
|
Validating: ServerIcon,
|
|
Updating: ArrowDownTrayIcon,
|
|
Uninstalling: TrashIcon,
|
|
Running: StopIcon,
|
|
};
|
|
|
|
const buttonActions: { [key in EmptyGameStatusEnum]: () => void } = {
|
|
Remote: () => emit("install"),
|
|
Queued: () => emit("queue"),
|
|
Downloading: () => emit("queue"),
|
|
Validating: () => emit("queue"),
|
|
Updating: () => emit("queue"),
|
|
Uninstalling: () => {},
|
|
Running: () => emit("kill"),
|
|
};
|
|
</script>
|