mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2026-07-20 15:03:25 +10:00
Game updates (#187)
* 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
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
class="block w-full rounded-md bg-zinc-800 px-3 py-1.5 text-base text-zinc-100 outline-1 -outline-offset-1 outline-zinc-800 placeholder:text-zinc-400 focus:outline-2 focus:-outline-offset-2 focus:outline-blue-600 sm:text-sm/6"
|
||||
placeholder="{}"
|
||||
aria-describedby="launch-description"
|
||||
v-model="model.launchString"
|
||||
v-model="model.launchTemplate"
|
||||
/>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-zinc-400" id="launch-description">
|
||||
@@ -129,9 +129,9 @@
|
||||
</span>
|
||||
</li>
|
||||
</ListboxOption>
|
||||
<li v-else class="italic text-zinc-400 py-2 pr-9 pl-3"
|
||||
>No auto-discovered layers.</li
|
||||
>
|
||||
<li v-else class="italic text-zinc-400 py-2 pr-9 pl-3">
|
||||
No auto-discovered layers.
|
||||
</li>
|
||||
<h1 class="text-white text-sm font-semibold bg-zinc-900 py-2 px-2">
|
||||
Manually added
|
||||
</h1>
|
||||
@@ -170,9 +170,9 @@
|
||||
</span>
|
||||
</li>
|
||||
</ListboxOption>
|
||||
<li v-else class="italic text-zinc-400 py-2 pr-9 pl-3"
|
||||
>No manually added layers.</li
|
||||
>
|
||||
<li v-else class="italic text-zinc-400 py-2 pr-9 pl-3">
|
||||
No manually added layers.
|
||||
</li>
|
||||
</ListboxOptions>
|
||||
</transition>
|
||||
</div>
|
||||
@@ -190,7 +190,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import type { FrontendGameConfiguration, ProtonPath } from "~/composables/game";
|
||||
import type { ProtonPath } from "~/composables/game";
|
||||
import {
|
||||
Listbox,
|
||||
ListboxButton,
|
||||
@@ -201,8 +201,9 @@ import {
|
||||
import { ChevronUpDownIcon } from "@heroicons/vue/16/solid";
|
||||
import { CheckIcon } from "@heroicons/vue/20/solid";
|
||||
import { WrenchIcon } from "@heroicons/vue/24/solid";
|
||||
import type { GameVersion } from "~/types";
|
||||
|
||||
const model = defineModel<FrontendGameConfiguration>({ required: true });
|
||||
const model = defineModel<GameVersion["userConfiguration"]>({ required: true });
|
||||
|
||||
const props = defineProps<{
|
||||
protonEnabled: boolean;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div class="space-y-8">
|
||||
<div class="flex flex-row items-center justify-between">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium leading-6 text-zinc-100">
|
||||
Enable update checks
|
||||
</h3>
|
||||
<p class="mt-1 text-sm leading-6 text-zinc-400">
|
||||
Drop will automatically check for updates from your server
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
v-model="model.enableUpdates"
|
||||
:class="[
|
||||
model.enableUpdates ? 'bg-blue-600' : 'bg-zinc-700',
|
||||
'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out',
|
||||
]"
|
||||
>
|
||||
<span
|
||||
:class="[
|
||||
model.enableUpdates ? 'translate-x-5' : 'translate-x-0',
|
||||
'pointer-events-none relative inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out',
|
||||
]"
|
||||
/>
|
||||
</Switch>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Switch } from "@headlessui/vue";
|
||||
import type { GameVersion } from '~/types';
|
||||
|
||||
const model = defineModel<GameVersion["userConfiguration"]>({ required: true });
|
||||
</script>
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<ModalTemplate size-class="max-w-4xl" v-model="open">
|
||||
<template #default>
|
||||
<div class="flex flex-row gap-x-4">
|
||||
<div class="flex flex-row gap-x-4 h-96">
|
||||
<nav class="flex flex-1 flex-col" aria-label="Sidebar">
|
||||
<ul role="list" class="-mx-2 space-y-1">
|
||||
<li v-for="(tab, tabIdx) in tabs" :key="tab.name">
|
||||
@@ -29,7 +29,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="border-l-2 border-zinc-800 w-full grow pl-4">
|
||||
<div class="border-l-2 border-zinc-800 w-full grow pl-4 overflow-y-scroll">
|
||||
<component
|
||||
v-model="configuration"
|
||||
:is="tabs[currentTabIndex]?.page"
|
||||
@@ -80,8 +80,10 @@ import {
|
||||
XCircleIcon,
|
||||
} from "@heroicons/vue/20/solid";
|
||||
import Launch from "./GameOptions/Launch.vue";
|
||||
import type { FrontendGameConfiguration } from "~/composables/game";
|
||||
import Updates from "./GameOptions/Updates.vue";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { ArrowPathIcon } from "@heroicons/vue/24/solid";
|
||||
import type { GameVersion } from "~/types";
|
||||
|
||||
const appState = useAppState();
|
||||
|
||||
@@ -89,17 +91,16 @@ const open = defineModel<boolean>();
|
||||
const props = defineProps<{ gameId: string }>();
|
||||
const game = await useGame(props.gameId);
|
||||
|
||||
const configuration: Ref<FrontendGameConfiguration> = ref({
|
||||
launchString: game.version!.userConfiguration.launchTemplate,
|
||||
overrideProtonPath: game.version!.userConfiguration.overrideProtonPath,
|
||||
});
|
||||
const configuration: Ref<GameVersion["userConfiguration"]> = ref(game.version.value!.userConfiguration);
|
||||
|
||||
const hasWindows = !!(
|
||||
game.version!.setups.find((v) => v.platform === "Windows") ??
|
||||
game.version!.launches.find((v) => v.platform === "Windows")
|
||||
game.version.value!.setups.find((v) => v.platform === "Windows") ??
|
||||
game.version.value!.launches.find((v) => v.platform === "Windows")
|
||||
);
|
||||
|
||||
const protonEnabled = !!(appState.value!.umuState !== "NotNeeded" && hasWindows);
|
||||
const protonEnabled = !!(
|
||||
appState.value!.umuState !== "NotNeeded" && hasWindows
|
||||
);
|
||||
|
||||
const tabs: Array<{ name: string; icon: Component; page: Component }> = [
|
||||
{
|
||||
@@ -107,6 +108,11 @@ const tabs: Array<{ name: string; icon: Component; page: Component }> = [
|
||||
icon: RocketLaunchIcon,
|
||||
page: Launch,
|
||||
},
|
||||
{
|
||||
name: "Updates",
|
||||
icon: ArrowPathIcon,
|
||||
page: Updates,
|
||||
},
|
||||
{
|
||||
name: "Storage",
|
||||
icon: ServerIcon,
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
<div class="inline-flex divide-x divide-zinc-900">
|
||||
<button
|
||||
type="button"
|
||||
@click="() => buttonActions[props.status.type]()"
|
||||
@click="() => fetchStatusStyleData($props.status).action()"
|
||||
:class="[
|
||||
styles[props.status.type],
|
||||
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="buttonIcons[props.status.type]"
|
||||
:is="fetchStatusStyleData($props.status).icon"
|
||||
class="-mr-0.5 size-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{{ buttonNames[props.status.type] }}
|
||||
{{ fetchStatusStyleData($props.status).buttonName }}
|
||||
</button>
|
||||
<Menu
|
||||
v-if="showDropdown"
|
||||
@@ -25,7 +25,7 @@
|
||||
<div class="h-full">
|
||||
<MenuButton
|
||||
:class="[
|
||||
styles[props.status.type],
|
||||
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',
|
||||
]"
|
||||
@@ -46,6 +46,21 @@
|
||||
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')"
|
||||
@@ -53,7 +68,7 @@
|
||||
active
|
||||
? 'bg-zinc-800 text-zinc-100 outline-none'
|
||||
: 'text-zinc-400',
|
||||
'w-full block px-4 py-2 text-sm inline-flex justify-between',
|
||||
'w-full px-4 py-2 text-sm inline-flex justify-between',
|
||||
]"
|
||||
>
|
||||
Options
|
||||
@@ -67,7 +82,7 @@
|
||||
active
|
||||
? 'bg-zinc-800 text-zinc-100 outline-none'
|
||||
: 'text-zinc-400',
|
||||
'w-full block px-4 py-2 text-sm inline-flex justify-between',
|
||||
'w-full inline-flex px-4 py-2 text-sm justify-between',
|
||||
]"
|
||||
>
|
||||
Uninstall
|
||||
@@ -93,9 +108,14 @@ import {
|
||||
} from "@heroicons/vue/20/solid";
|
||||
|
||||
import type { Component } from "vue";
|
||||
import { GameStatusEnum, type GameStatus } from "~/types.js";
|
||||
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<{
|
||||
@@ -108,76 +128,105 @@ const emit = defineEmits<{
|
||||
(e: "resume"): void;
|
||||
}>();
|
||||
|
||||
const showDropdown = computed(
|
||||
() =>
|
||||
props.status.type === GameStatusEnum.Installed ||
|
||||
props.status.type === GameStatusEnum.SetupRequired ||
|
||||
props.status.type === GameStatusEnum.PartiallyInstalled
|
||||
);
|
||||
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(
|
||||
() => props.status.type === GameStatusEnum.Installed
|
||||
() =>
|
||||
showDropdown.value &&
|
||||
props.status.type === "Installed" &&
|
||||
props.status.install_type.type !== InstalledType.PartiallyInstalled,
|
||||
);
|
||||
|
||||
const styles: { [key in GameStatusEnum]: string } = {
|
||||
[GameStatusEnum.Remote]:
|
||||
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",
|
||||
[GameStatusEnum.Queued]:
|
||||
Queued:
|
||||
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
||||
[GameStatusEnum.Downloading]:
|
||||
Downloading:
|
||||
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
||||
[GameStatusEnum.Validating]:
|
||||
Validating:
|
||||
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
||||
[GameStatusEnum.SetupRequired]:
|
||||
"bg-yellow-600 text-white hover:bg-yellow-500 focus-visible:outline-yellow-600 hover:bg-yellow-500",
|
||||
[GameStatusEnum.Installed]:
|
||||
"bg-green-600 text-white hover:bg-green-500 focus-visible:outline-green-600 hover:bg-green-500",
|
||||
[GameStatusEnum.Updating]:
|
||||
Updating:
|
||||
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
||||
[GameStatusEnum.Uninstalling]:
|
||||
Uninstalling:
|
||||
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
||||
[GameStatusEnum.Running]:
|
||||
Running:
|
||||
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
||||
[GameStatusEnum.PartiallyInstalled]:
|
||||
"bg-blue-600 text-white hover:bg-blue-500 focus-visible:outline-blue-600 hover:bg-blue-500",
|
||||
};
|
||||
|
||||
const buttonNames: { [key in GameStatusEnum]: string } = {
|
||||
[GameStatusEnum.Remote]: "Install",
|
||||
[GameStatusEnum.Queued]: "Queued",
|
||||
[GameStatusEnum.Downloading]: "Downloading",
|
||||
[GameStatusEnum.Validating]: "Validating",
|
||||
[GameStatusEnum.SetupRequired]: "Setup",
|
||||
[GameStatusEnum.Installed]: "Play",
|
||||
[GameStatusEnum.Updating]: "Updating",
|
||||
[GameStatusEnum.Uninstalling]: "Uninstalling",
|
||||
[GameStatusEnum.Running]: "Stop",
|
||||
[GameStatusEnum.PartiallyInstalled]: "Resume",
|
||||
const buttonNames: { [key in EmptyGameStatusEnum]: string } = {
|
||||
Remote: "Install",
|
||||
Queued: "Queued",
|
||||
Downloading: "Downloading",
|
||||
Validating: "Validating",
|
||||
Updating: "Updating",
|
||||
Uninstalling: "Uninstalling",
|
||||
Running: "Stop",
|
||||
};
|
||||
|
||||
const buttonIcons: { [key in GameStatusEnum]: Component } = {
|
||||
[GameStatusEnum.Remote]: ArrowDownTrayIcon,
|
||||
[GameStatusEnum.Queued]: QueueListIcon,
|
||||
[GameStatusEnum.Downloading]: ArrowDownTrayIcon,
|
||||
[GameStatusEnum.Validating]: ServerIcon,
|
||||
[GameStatusEnum.SetupRequired]: WrenchIcon,
|
||||
[GameStatusEnum.Installed]: PlayIcon,
|
||||
[GameStatusEnum.Updating]: ArrowDownTrayIcon,
|
||||
[GameStatusEnum.Uninstalling]: TrashIcon,
|
||||
[GameStatusEnum.Running]: StopIcon,
|
||||
[GameStatusEnum.PartiallyInstalled]: ArrowDownTrayIcon,
|
||||
const buttonIcons: { [key in EmptyGameStatusEnum]: Component } = {
|
||||
Remote: ArrowDownTrayIcon,
|
||||
Queued: QueueListIcon,
|
||||
Downloading: ArrowDownTrayIcon,
|
||||
Validating: ServerIcon,
|
||||
Updating: ArrowDownTrayIcon,
|
||||
Uninstalling: TrashIcon,
|
||||
Running: StopIcon,
|
||||
};
|
||||
|
||||
const buttonActions: { [key in GameStatusEnum]: () => void } = {
|
||||
[GameStatusEnum.Remote]: () => emit("install"),
|
||||
[GameStatusEnum.Queued]: () => emit("queue"),
|
||||
[GameStatusEnum.Downloading]: () => emit("queue"),
|
||||
[GameStatusEnum.Validating]: () => emit("queue"),
|
||||
[GameStatusEnum.SetupRequired]: () => emit("launch"),
|
||||
[GameStatusEnum.Installed]: () => emit("launch"),
|
||||
[GameStatusEnum.Updating]: () => emit("queue"),
|
||||
[GameStatusEnum.Uninstalling]: () => {},
|
||||
[GameStatusEnum.Running]: () => emit("kill"),
|
||||
[GameStatusEnum.PartiallyInstalled]: () => emit("resume"),
|
||||
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>
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
<template>
|
||||
<NuxtLink to="/settings/compat">
|
||||
<HeaderWidget
|
||||
v-if="appState && appState.umuState !== 'NotNeeded'"
|
||||
:problem="notInstalled"
|
||||
>
|
||||
<img src="/proton-logo.png" class="relative z-50 size-5 brightness-[30%]" />
|
||||
<NuxtLink
|
||||
v-if="onLinux"
|
||||
to="/settings/compat"
|
||||
>
|
||||
<HeaderWidget :problem="protonError">
|
||||
<img
|
||||
src="/proton-logo.png"
|
||||
class="relative z-50 size-5 brightness-[30%]"
|
||||
/>
|
||||
</HeaderWidget>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const appState = useAppState();
|
||||
const onLinux = appState.value?.umuState !== "NotNeeded";
|
||||
const paths = onLinux ? await useProtonPaths() : undefined;
|
||||
|
||||
const notInstalled = appState.value?.umuState === "NotInstalled";
|
||||
const protonError = computed(
|
||||
() =>
|
||||
appState.value?.umuState === "NotInstalled" || !paths?.data.value.default,
|
||||
);
|
||||
</script>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
v-for="item in nav.items"
|
||||
:key="nav.id"
|
||||
:class="[
|
||||
'transition-all duration-300 rounded-lg flex items-center px-1 py-1.5 hover:scale-105 active:scale-95 hover:shadow-lg hover:shadow-zinc-950/50',
|
||||
'transition-all duration-300 rounded-lg flex items-center px-1 py-0.5 hover:scale-105 active:scale-95 hover:shadow-lg hover:shadow-zinc-950/50',
|
||||
currentNavigation == item.id
|
||||
? 'bg-zinc-800 text-zinc-100 shadow-md shadow-zinc-950/20'
|
||||
: item.isInstalled.value
|
||||
@@ -83,21 +83,24 @@
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div class="truncate inline-flex items-center gap-x-2">
|
||||
<div class="truncate flex flex-col">
|
||||
<p class="text-sm whitespace-nowrap font-display font-semibold">
|
||||
{{ item.label }}
|
||||
</p>
|
||||
<p
|
||||
class="truncate text-[10px] font-bold uppercase font-display"
|
||||
:class="[
|
||||
gameStatusTextStyle[games[item.id].status.value.type],
|
||||
getGameStatusStyleText(games[item.id].status.value)[0],
|
||||
]"
|
||||
>
|
||||
{{ gameStatusText[games[item.id].status.value.type] }}
|
||||
{{ getGameStatusStyleText(games[item.id].status.value)[1] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
<span v-if="nav.items.length == 0" class="text-xs text-zinc-500 mx-auto"
|
||||
>No games in this category</span
|
||||
>
|
||||
</DisclosurePanel>
|
||||
</Disclosure>
|
||||
</TransitionGroup>
|
||||
@@ -138,7 +141,8 @@ import {
|
||||
} from "@heroicons/vue/20/solid";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import {
|
||||
GameStatusEnum,
|
||||
type EmptyGameStatusEnum,
|
||||
InstalledType,
|
||||
type Collection as Collection,
|
||||
type Game,
|
||||
type GameStatus,
|
||||
@@ -147,31 +151,44 @@ import { TransitionGroup } from "vue";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
|
||||
// Style information
|
||||
const gameStatusTextStyle: { [key in GameStatusEnum]: string } = {
|
||||
[GameStatusEnum.Installed]: "text-green-500",
|
||||
[GameStatusEnum.Downloading]: "text-zinc-400",
|
||||
[GameStatusEnum.Validating]: "text-blue-300",
|
||||
[GameStatusEnum.Running]: "text-blue-500",
|
||||
[GameStatusEnum.Remote]: "text-zinc-700",
|
||||
[GameStatusEnum.Queued]: "text-zinc-400",
|
||||
[GameStatusEnum.Updating]: "text-zinc-400",
|
||||
[GameStatusEnum.Uninstalling]: "text-zinc-100",
|
||||
[GameStatusEnum.SetupRequired]: "text-yellow-500",
|
||||
[GameStatusEnum.PartiallyInstalled]: "text-gray-400",
|
||||
const gameStatusTextStyle: { [key in EmptyGameStatusEnum]: string } = {
|
||||
Downloading: "text-zinc-400",
|
||||
Validating: "text-blue-300",
|
||||
Running: "text-blue-500",
|
||||
Remote: "text-zinc-700",
|
||||
Queued: "text-zinc-400",
|
||||
Updating: "text-zinc-400",
|
||||
Uninstalling: "text-zinc-100",
|
||||
};
|
||||
const gameStatusText: { [key in GameStatusEnum]: string } = {
|
||||
[GameStatusEnum.Remote]: "Not installed",
|
||||
[GameStatusEnum.Queued]: "Queued",
|
||||
[GameStatusEnum.Downloading]: "Downloading...",
|
||||
[GameStatusEnum.Validating]: "Validating...",
|
||||
[GameStatusEnum.Installed]: "Installed",
|
||||
[GameStatusEnum.Updating]: "Updating...",
|
||||
[GameStatusEnum.Uninstalling]: "Uninstalling...",
|
||||
[GameStatusEnum.SetupRequired]: "Setup required",
|
||||
[GameStatusEnum.Running]: "Running",
|
||||
[GameStatusEnum.PartiallyInstalled]: "Partially installed",
|
||||
const gameStatusText: { [key in EmptyGameStatusEnum]: string } = {
|
||||
Remote: "Not installed",
|
||||
Queued: "Queued",
|
||||
Downloading: "Downloading...",
|
||||
Validating: "Validating...",
|
||||
Updating: "Updating...",
|
||||
Uninstalling: "Uninstalling...",
|
||||
Running: "Running",
|
||||
};
|
||||
|
||||
function getGameStatusStyleText(status: GameStatus): [string, string] {
|
||||
if (status.type === "Installed") {
|
||||
if (status.install_type.type === InstalledType.Installed) {
|
||||
return ["text-green-500", "Installed"];
|
||||
}
|
||||
if (status.install_type.type === InstalledType.PartiallyInstalled) {
|
||||
return ["text-gray-400", "Partially installed"];
|
||||
}
|
||||
if (status.install_type.type === InstalledType.SetupRequired) {
|
||||
return ["text-yellow-500", "Setup required"];
|
||||
}
|
||||
throw (
|
||||
"Non-exhaustive installed type, missing: " +
|
||||
JSON.stringify(status.install_type)
|
||||
);
|
||||
}
|
||||
return [gameStatusTextStyle[status.type], gameStatusText[status.type]];
|
||||
}
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const searchQuery = ref("");
|
||||
@@ -277,25 +294,22 @@ await new Promise<void>((r) => {
|
||||
|
||||
const navigation = computed(() =>
|
||||
collections.value.map((collection) => {
|
||||
const items = collection.entries
|
||||
.map(({ game }) => {
|
||||
const status = games[game.id].status;
|
||||
const items = collection.entries.map(({ game }) => {
|
||||
const status = games[game.id].status;
|
||||
|
||||
const isInstalled = computed(
|
||||
() => status.value.type != GameStatusEnum.Remote,
|
||||
);
|
||||
const isInstalled = computed(() => status.value.type != "Remote");
|
||||
|
||||
const item = {
|
||||
label: game.mName,
|
||||
route: `/library/${game.id}`,
|
||||
prefix: `/library/${game.id}`,
|
||||
icon: game.mIconObjectId,
|
||||
isInstalled,
|
||||
id: game.id,
|
||||
type: game.type,
|
||||
};
|
||||
return item;
|
||||
});
|
||||
const item = {
|
||||
label: game.mName,
|
||||
route: `/library/${game.id}`,
|
||||
prefix: `/library/${game.id}`,
|
||||
icon: game.mIconObjectId,
|
||||
isInstalled,
|
||||
id: game.id,
|
||||
type: game.type,
|
||||
};
|
||||
return item;
|
||||
});
|
||||
|
||||
return {
|
||||
id: collection.id,
|
||||
|
||||
Reference in New Issue
Block a user