217 lines
6.0 KiB
Vue
217 lines
6.0 KiB
Vue
<script setup lang="ts">
|
|
import { Ref, computed, ref } from 'vue';
|
|
import Button from 'primevue/button';
|
|
import ContextMenu from 'primevue/contextmenu';
|
|
import { useConfirm } from 'primevue/useconfirm';
|
|
import { listen } from '@tauri-apps/api/event';
|
|
import { getCurrentWindow } from '@tauri-apps/api/window';
|
|
import Onboarding from './Onboarding.vue';
|
|
import { invoke } from '../invoke';
|
|
import { useClientStore, usePrfStore } from '../stores';
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
const { t } = useI18n();
|
|
|
|
const prf = usePrfStore();
|
|
const client = useClientStore();
|
|
const confirmDialog = useConfirm();
|
|
|
|
type StartStatus = 'ready' | 'preparing' | 'running';
|
|
const startStatus: Ref<StartStatus> = ref('ready');
|
|
|
|
const startline = async (force: boolean, refresh: boolean) => {
|
|
startStatus.value = 'preparing';
|
|
|
|
if (!force) {
|
|
const start_check: object[] = await invoke('start_check');
|
|
if (start_check.length > 0) {
|
|
const message = start_check.map((o) => {
|
|
if ('MissingRemotePackage' in o) {
|
|
return `${t('start.error.package')}: ${o.MissingRemotePackage}`;
|
|
} else if ('MissingLocalPackage' in o) {
|
|
return `${t('start.error.package')}: ${o.MissingLocalPackage}`;
|
|
} else if ('MissingDependency' in o) {
|
|
return `${t('start.error.dependency')}: ${(o.MissingDependency as string[]).join(' ')}`;
|
|
} else if ('MissingTool' in o) {
|
|
return `${t('start.error.tool')}: ${o.MissingTool}`;
|
|
} else {
|
|
return t('start.error.unknown');
|
|
}
|
|
});
|
|
confirmDialog.require({
|
|
message: message.join('\n'),
|
|
header: t('start.failed'),
|
|
acceptLabel: t('start.accept'),
|
|
rejectLabel: t('cancel'),
|
|
accept: () => {
|
|
startline(true, refresh);
|
|
},
|
|
});
|
|
startStatus.value = 'ready';
|
|
return;
|
|
}
|
|
}
|
|
try {
|
|
await invoke('save_current_profile');
|
|
await invoke('startline', { refresh });
|
|
} catch (_) {
|
|
startStatus.value = 'ready';
|
|
}
|
|
};
|
|
|
|
const kill = async () => {
|
|
await invoke('kill');
|
|
};
|
|
|
|
const disabledTooltip = computed(() => {
|
|
if (prf.current?.data.sgt.target.length === 0) {
|
|
return t('start.tooltip.game');
|
|
}
|
|
if (prf.current?.data.sgt.amfs.length === 0) {
|
|
return t('start.tooltip.amfs');
|
|
}
|
|
if (
|
|
prf.current?.data.sgt.hook === null ||
|
|
prf.current?.data.sgt.hook === undefined
|
|
) {
|
|
return t('start.tooltip.segatools');
|
|
}
|
|
return null;
|
|
});
|
|
|
|
listen('launch-start', () => {
|
|
startStatus.value = 'running';
|
|
getCurrentWindow().minimize();
|
|
});
|
|
|
|
listen('launch-end', () => {
|
|
startStatus.value = 'ready';
|
|
getCurrentWindow().unminimize();
|
|
getCurrentWindow().setFocus();
|
|
});
|
|
|
|
const createShortcut = async () => {
|
|
const current = prf.current;
|
|
if (current !== null) {
|
|
await invoke('create_shortcut', {
|
|
profileMeta: current.meta,
|
|
});
|
|
}
|
|
};
|
|
|
|
const menuItems = computed(() => {
|
|
const base = [
|
|
{
|
|
label: t('start.button.unchecked'),
|
|
icon: 'pi pi-exclamation-circle',
|
|
command: async () => await startline(true, false),
|
|
},
|
|
{
|
|
label: t('start.button.shortcut'),
|
|
icon: 'pi pi-link',
|
|
command: createShortcut,
|
|
},
|
|
{
|
|
label: t('start.button.help'),
|
|
icon: 'pi pi-question-circle',
|
|
command: () => {
|
|
onboardingFirstTime.value = false;
|
|
onboardingVisible.value = true;
|
|
},
|
|
},
|
|
];
|
|
if (prf.current === null) {
|
|
return [];
|
|
}
|
|
if (prf.current.meta.game === 'chunithm') {
|
|
return base;
|
|
}
|
|
if (prf.current.meta.game === 'ongeki') {
|
|
return [
|
|
{
|
|
label: t('start.button.refresh'),
|
|
icon: 'pi pi-sync',
|
|
command: async () => await startline(false, true),
|
|
},
|
|
...base,
|
|
{
|
|
label: t('start.button.cache'),
|
|
icon: 'pi pi-trash',
|
|
command: async () => {},
|
|
},
|
|
];
|
|
}
|
|
});
|
|
|
|
const menu = ref();
|
|
|
|
const showContextMenu = (event: Event) => {
|
|
event.preventDefault();
|
|
menu.value.show(event);
|
|
};
|
|
|
|
const onboardingVisible = ref(false);
|
|
const onboardingFirstTime = ref(false);
|
|
|
|
const tryStart = () => {
|
|
const game = prf.current?.meta.game;
|
|
|
|
if (game !== undefined) {
|
|
if (client.onboarded.includes(game)) {
|
|
startline(false, false);
|
|
} else {
|
|
onboardingVisible.value = true;
|
|
onboardingFirstTime.value = true;
|
|
client.setOnboarded(game);
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<Onboarding
|
|
:visible="onboardingVisible"
|
|
:first-time="onboardingFirstTime"
|
|
:on-finish="
|
|
() => {
|
|
onboardingVisible = false;
|
|
if (onboardingFirstTime === true) {
|
|
startline(false, false);
|
|
}
|
|
}
|
|
"
|
|
/>
|
|
<ContextMenu ref="menu" :model="menuItems" />
|
|
<Button
|
|
v-if="startStatus === 'ready'"
|
|
v-tooltip="disabledTooltip"
|
|
:disabled="disabledTooltip !== null"
|
|
icon="pi pi-play"
|
|
label="START"
|
|
aria-label="start"
|
|
size="small"
|
|
class="m-2.5"
|
|
@click="tryStart"
|
|
@contextmenu="showContextMenu"
|
|
/>
|
|
<Button
|
|
v-else-if="startStatus === 'preparing'"
|
|
disabled
|
|
icon="pi pi-spin pi-spinner"
|
|
:label="t('start.button.start')"
|
|
aria-label="start"
|
|
size="small"
|
|
class="m-2.5"
|
|
/>
|
|
<Button
|
|
v-else
|
|
:disabled="false"
|
|
icon="pi pi-ban"
|
|
:label="t('start.button.stop')"
|
|
aria-label="stop"
|
|
size="small"
|
|
class="m-2.5"
|
|
@click="kill()"
|
|
/>
|
|
</template>
|