feat: groundwork for multi-profile support

This commit is contained in:
2025-03-03 02:07:15 +01:00
parent d25841853c
commit 6410ca2721
16 changed files with 744 additions and 184 deletions

View File

@ -7,53 +7,31 @@ import TabPanel from 'primevue/tabpanel';
import TabPanels from 'primevue/tabpanels';
import Tabs from 'primevue/tabs';
import { onOpenUrl } from '@tauri-apps/plugin-deep-link';
import { open } from '@tauri-apps/plugin-dialog';
import ModList from './ModList.vue';
import ModStore from './ModStore.vue';
import Options from './Options.vue';
import ProfileList from './ProfileList.vue';
import StartButton from './StartButton.vue';
import { usePkgStore } from '../stores';
import { changePrimaryColor } from '../util';
import { usePkgStore, usePrfStore } from '../stores';
const store = usePkgStore();
store.setupListeners();
const pkg = usePkgStore();
const prf = usePrfStore();
pkg.setupListeners();
prf.setupListeners();
const currentTab = ref('3');
const loadProfile = async (openWindow: boolean) => {
await store.reloadProfile();
if (store.profile === null && openWindow) {
const exePath = await open({
multiple: false,
directory: false,
filters: [
{
name: 'mu3.exe' /* or chusanApp.exe'*/,
extensions: ['exe'],
},
],
});
if (exePath !== null) {
await store.initProfile(exePath);
}
}
if (store.profile !== null) {
changePrimaryColor(store.profile.game);
currentTab.value = '0';
}
await store.reloadAll();
};
const isProfileDisabled = computed(() => store.profile === null);
onOpenUrl((urls) => {
console.log('deep link:', urls);
});
const isProfileDisabled = computed(() => prf.current === null);
onMounted(async () => {
await loadProfile(false);
await prf.reloadList();
await prf.reload();
if (prf.current !== null) {
await pkg.reloadAll();
currentTab.value = '0';
}
});
</script>
@ -93,14 +71,10 @@ onMounted(async () => {
missing.<br />Existing features are expected to break any
time.
<div v-if="isProfileDisabled">
<br />Select <code>mu3.exe</code> to create a
profile:<br />
<Button
label="Create profile"
icon="pi pi-plus"
aria-label="open-executable"
@click="loadProfile(true)"
/><br />
<br />Select <code>mu3.exe</code> to create a profile:
</div>
<ProfileList />
<div v-if="isProfileDisabled">
<div
style="
margin-top: 5px;
@ -115,10 +89,15 @@ onMounted(async () => {
(this will change in the future)
</div>
<img
v-if="store.profile?.game === 'Ongeki'"
v-if="prf.current?.game === 'ongeki'"
src="/sticker-ongeki.svg"
class="fixed bottom-0 right-0"
/>
<img
v-else-if="prf.current?.game === 'chunithm'"
src="/sticker-chunithm.svg"
class="fixed bottom-0 right-0"
/>
<br /><br /><br />
<Button
style="position: fixed; left: 10px; bottom: 10px"

View File

@ -1,20 +1,16 @@
<script setup lang="ts">
import Fieldset from 'primevue/fieldset';
import ModListEntry from './ModListEntry.vue';
import { usePkgStore } from '../stores';
import { Profile } from '../types';
import { usePkgStore, usePrfStore } from '../stores';
defineProps({
profile: Object as () => Profile,
});
const pkgs = usePkgStore();
const pkg = usePkgStore();
const prf = usePrfStore();
const group = () => {
const a = Object.assign(
{},
Object.groupBy(
pkgs.allLocal
pkg.allLocal
.sort((p1, p2) => p1.namespace.localeCompare(p2.namespace))
.sort((p1, p2) => p1.name.localeCompare(p2.name)),
({ namespace }) => namespace
@ -23,7 +19,7 @@ const group = () => {
return a;
};
pkgs.reloadProfile();
prf.reload();
</script>
<template>

View File

@ -5,17 +5,17 @@ import { open } from '@tauri-apps/plugin-shell';
import InstallButton from './InstallButton.vue';
import ModTitlecard from './ModTitlecard.vue';
import UpdateButton from './UpdateButton.vue';
import { usePkgStore } from '../stores';
import { usePrfStore } from '../stores';
import { Package } from '../types';
const store = usePkgStore();
const prf = usePrfStore();
const props = defineProps({
pkg: Object as () => Package,
});
const toggle = async (value: boolean) => {
await store.toggle(props.pkg, value);
await prf.togglePkg(props.pkg, value);
};
</script>
@ -27,7 +27,7 @@ const toggle = async (value: boolean) => {
class="scale-[1.33] shrink-0"
inputId="switch"
:disabled="!pkg?.loc"
:modelValue="store.isEnabled(pkg)"
:modelValue="prf.isPkgEnabled(pkg)"
v-on:value-change="toggle"
/>
<InstallButton :pkg="pkg" />

View File

@ -6,18 +6,17 @@ import InputText from 'primevue/inputtext';
import RadioButton from 'primevue/radiobutton';
import Toggle from 'primevue/toggleswitch';
import { invoke } from '@tauri-apps/api/core';
import * as path from '@tauri-apps/api/path';
import { readTextFile, writeTextFile } from '@tauri-apps/plugin-fs';
import { usePkgStore } from '../stores';
import { usePrfStore } from '../stores';
const prf = usePrfStore();
const store = usePkgStore();
const _cfg = <T extends string | number | boolean>(key: string, dflt: T) =>
computed({
get() {
return (store.cfg(key) as T) ?? dflt;
return (prf.cfg(key) as T) ?? dflt;
},
async set(value) {
await store.set_cfg(key, value ?? dflt);
await prf.setCfg(key, value ?? dflt);
},
});
@ -126,7 +125,7 @@ const aimeCodeModel = computed({
<InputText
class="shrink"
size="small"
:disabled="store.cfg('aime') !== true"
:disabled="prf.cfg('aime') !== true"
:maxlength="20"
placeholder="00000000000000000000"
v-model="aimeCodeModel"

View File

@ -0,0 +1,73 @@
<script setup lang="ts">
import Button from 'primevue/button';
import { usePrfStore } from '../stores';
const prf = usePrfStore();
</script>
<template>
<div class="mt-4 flex flex-wrap align-middle gap-4">
<Button
:disabled="prf.list.length > 0"
label="Create profile"
icon="pi pi-plus"
aria-label="open-executable"
class="create-button"
@click="prf.prompt"
/>
<div v-for="p in prf.list">
<Button
:disabled="
prf.current?.game === p.game && prf.current?.name === p.name
"
:label="p.name"
:class="
(p.game === 'chunithm'
? 'chunithm-button'
: 'ongeki-button') +
' ' +
'self-center grow'
"
@click="prf.switchTo(p.game, p.name)"
/>
</div>
</div>
</template>
<style scoped>
.create-button {
background-color: var(--p-green-400);
border-color: var(--p-green-400);
width: 10em;
}
.create-button:hover,
.create-button:active {
background-color: var(--p-green-300) !important;
border-color: var(--p-green-300) !important;
}
.ongeki-button {
background-color: var(--p-pink-400);
border-color: var(--p-pink-400);
width: 10em;
}
.ongeki-button:hover,
.ongeki-button:active {
background-color: var(--p-pink-300) !important;
border-color: var(--p-pink-300) !important;
}
.chunithm-button {
background-color: var(--p-yellow-400);
border-color: var(--p-yellow-400);
width: 10em;
}
.chunithm-button:hover,
.chunithm-button:active {
background-color: var(--p-yellow-300) !important;
border-color: var(--p-yellow-300) !important;
}
</style>