feat: phase 2
Newfound motivation
This commit is contained in:
@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { Ref, onMounted, ref } from 'vue';
|
||||
import { updatePrimaryPalette } from '@primevue/themes';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import Button from 'primevue/button';
|
||||
import Tab from 'primevue/tab';
|
||||
import TabList from 'primevue/tablist';
|
||||
@ -8,37 +7,23 @@ import TabPanel from 'primevue/tabpanel';
|
||||
import TabPanels from 'primevue/tabpanels';
|
||||
import Tabs from 'primevue/tabs';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
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 { Profile } from '../types';
|
||||
import { usePkgStore } from '../stores';
|
||||
import { changePrimaryColor } from '../util';
|
||||
|
||||
const changePrimaryColor = (game: 'ongeki' | 'chunithm') => {
|
||||
const color = game === 'ongeki' ? 'pink' : 'yellow';
|
||||
const store = usePkgStore();
|
||||
store.setupListeners();
|
||||
|
||||
updatePrimaryPalette({
|
||||
50: `{${color}.50}`,
|
||||
100: `{${color}.100}`,
|
||||
200: `{${color}.200}`,
|
||||
300: `{${color}.300}`,
|
||||
400: `{${color}.400}`,
|
||||
500: `{${color}.500}`,
|
||||
600: `{${color}.600}`,
|
||||
700: `{${color}.700}`,
|
||||
800: `{${color}.800}`,
|
||||
900: `{${color}.900}`,
|
||||
950: `{${color}.950}`,
|
||||
});
|
||||
};
|
||||
|
||||
let profile: Ref<Profile | null> = ref(null);
|
||||
let key = ref(0);
|
||||
const currentTab = ref('3');
|
||||
|
||||
const loadProfile = async () => {
|
||||
profile = await invoke('get_current_profile');
|
||||
await store.reloadProfile();
|
||||
|
||||
if (profile === null) {
|
||||
if (store.profile === null) {
|
||||
const file = await open({
|
||||
multiple: false,
|
||||
directory: false,
|
||||
@ -50,33 +35,46 @@ const loadProfile = async () => {
|
||||
],
|
||||
});
|
||||
if (file !== null) {
|
||||
profile = await invoke('init_profile', { path: file });
|
||||
await store.initProfile(file);
|
||||
}
|
||||
}
|
||||
key.value += 1;
|
||||
if (store.profile !== null) {
|
||||
changePrimaryColor(store.profile.game);
|
||||
currentTab.value = '0';
|
||||
}
|
||||
|
||||
await store.reloadAll();
|
||||
};
|
||||
|
||||
const isDisabled = () => profile === null;
|
||||
const isProfileDisabled = computed(() => store.profile === null);
|
||||
|
||||
const startline = () => {
|
||||
invoke('startline');
|
||||
|
||||
//startDisabled.value = true;
|
||||
};
|
||||
|
||||
onOpenUrl((urls) => {
|
||||
console.log('deep link:', urls);
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
await loadProfile();
|
||||
});
|
||||
|
||||
changePrimaryColor('ongeki');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main>
|
||||
<Tabs lazy value="3" class="h-screen">
|
||||
<Tabs lazy :value="currentTab" class="h-screen">
|
||||
<div class="fixed w-full flex z-100">
|
||||
<TabList class="grow">
|
||||
<Tab :disabled="isDisabled()" :key="key" value="0"
|
||||
<Tab :disabled="isProfileDisabled" value="0"
|
||||
><div class="pi pi-list-check"></div
|
||||
></Tab>
|
||||
<Tab :disabled="isDisabled()" :key="key" value="1"
|
||||
<Tab :disabled="isProfileDisabled" value="1"
|
||||
><div class="pi pi-download"></div
|
||||
></Tab>
|
||||
<Tab :disabled="isDisabled()" :key="key" value="2"
|
||||
<Tab :disabled="isProfileDisabled" value="2"
|
||||
><div class="pi pi-cog"></div
|
||||
></Tab>
|
||||
<Tab value="3"
|
||||
@ -84,18 +82,19 @@ changePrimaryColor('ongeki');
|
||||
></Tab>
|
||||
<div class="grow"></div>
|
||||
<Button
|
||||
disabled
|
||||
:disabled="false"
|
||||
icon="pi pi-play"
|
||||
label="START"
|
||||
aria-label="start"
|
||||
size="small"
|
||||
class="m-2.5"
|
||||
@click="startline()"
|
||||
/>
|
||||
</TabList>
|
||||
</div>
|
||||
<TabPanels class="w-full grow mt-[3rem]">
|
||||
<TabPanel value="0">
|
||||
<ModList :profile="profile!" />
|
||||
<ModList />
|
||||
</TabPanel>
|
||||
<TabPanel value="1">
|
||||
<ModStore />
|
||||
@ -106,6 +105,7 @@ changePrimaryColor('ongeki');
|
||||
<TabPanel value="3">
|
||||
UNDER CONSTRUCTION<br /><br />
|
||||
<Button
|
||||
:disabled="!isProfileDisabled"
|
||||
label="Create profile"
|
||||
icon="pi pi-plus"
|
||||
aria-label="open-executable"
|
||||
|
58
src/components/InstallButton.vue
Normal file
58
src/components/InstallButton.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<script setup lang="ts">
|
||||
import Button from 'primevue/button';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { Package } from '../types';
|
||||
import { pkgKey } from '../util';
|
||||
|
||||
const props = defineProps({
|
||||
pkg: Object as () => Package,
|
||||
});
|
||||
|
||||
const install = async () => {
|
||||
if (props.pkg === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
await invoke('install_package', { key: pkgKey(props.pkg) });
|
||||
|
||||
//if (rv === 'Deferred') { /* download progress */ }
|
||||
};
|
||||
|
||||
const remove = async () => {
|
||||
if (props.pkg === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
await invoke('delete_package', {
|
||||
key: pkgKey(props.pkg),
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Button
|
||||
v-if="pkg?.loc"
|
||||
rounded
|
||||
icon="pi pi-trash"
|
||||
severity="danger"
|
||||
aria-label="remove"
|
||||
size="small"
|
||||
class="self-center ml-4"
|
||||
style="width: 2rem; height: 2rem"
|
||||
:loading="false"
|
||||
v-on:click="remove()"
|
||||
/>
|
||||
|
||||
<Button
|
||||
v-else
|
||||
rounded
|
||||
icon="pi pi-plus"
|
||||
severity="success"
|
||||
aria-label="install"
|
||||
size="small"
|
||||
class="self-center ml-4"
|
||||
style="width: 2rem; height: 2rem"
|
||||
:loading="false"
|
||||
v-on:click="install()"
|
||||
/>
|
||||
</template>
|
@ -1,32 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { Reactive, onMounted, reactive } from 'vue';
|
||||
import Fieldset from 'primevue/fieldset';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import ModListEntry from './ModListEntry.vue';
|
||||
import { ModEntry, Profile } from '../types';
|
||||
import { usePkgStore } from '../stores';
|
||||
import { Profile } from '../types';
|
||||
|
||||
const mods: Reactive<{ [key: string]: ModEntry[] }> = reactive({});
|
||||
|
||||
const props = defineProps({
|
||||
defineProps({
|
||||
profile: Object as () => Profile,
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
const modsRaw: ModEntry[] = await invoke('get_packages');
|
||||
modsRaw.forEach((m) => {
|
||||
if (props.profile?.mods.includes(`${m.namespace}-${m.name}`)) {
|
||||
m.enabled = true;
|
||||
}
|
||||
});
|
||||
Object.assign(
|
||||
mods,
|
||||
Object.groupBy(modsRaw, ({ namespace }) => namespace)
|
||||
const pkgs = usePkgStore();
|
||||
|
||||
const group = () => {
|
||||
const a = Object.assign(
|
||||
{},
|
||||
Object.groupBy(pkgs.allLocal, ({ namespace }) => namespace)
|
||||
);
|
||||
});
|
||||
return a;
|
||||
};
|
||||
|
||||
pkgs.reloadProfile();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Fieldset v-for="(namespace, key) in mods" :legend="key.toString()">
|
||||
<ModListEntry v-for="m in namespace" :mod="m" />
|
||||
<Fieldset v-for="(namespace, key) in group()" :legend="key.toString()">
|
||||
<ModListEntry v-for="p in namespace" :pkg="p" />
|
||||
</Fieldset>
|
||||
</template>
|
||||
|
@ -2,32 +2,33 @@
|
||||
import Button from 'primevue/button';
|
||||
import ToggleSwitch from 'primevue/toggleswitch';
|
||||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import InstallButton from './InstallButton.vue';
|
||||
import ModTitlecard from './ModTitlecard.vue';
|
||||
import { ModEntry } from '../types';
|
||||
import { usePkgStore } from '../stores';
|
||||
import { Package } from '../types';
|
||||
|
||||
defineProps({
|
||||
mod: Object as () => ModEntry,
|
||||
const store = usePkgStore();
|
||||
|
||||
const props = defineProps({
|
||||
pkg: Object as () => Package,
|
||||
});
|
||||
|
||||
const toggle = (value: boolean) => {
|
||||
store.toggle(props.pkg, value);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex items-center">
|
||||
<ModTitlecard showVersion :localIcon="true" :mod="mod" />
|
||||
<ModTitlecard showVersion :pkg="pkg" />
|
||||
<ToggleSwitch
|
||||
class="scale-[1.33] shrink-0"
|
||||
inputId="switch"
|
||||
:modelValue="mod?.enabled"
|
||||
/>
|
||||
<Button
|
||||
rounded
|
||||
disabled
|
||||
icon="pi pi-trash"
|
||||
severity="danger"
|
||||
aria-label="delete"
|
||||
size="small"
|
||||
class="ml-5 self-center shrink-0"
|
||||
style="width: 2rem; height: 2rem"
|
||||
:disabled="!pkg?.loc"
|
||||
:modelValue="store.isEnabled(pkg)"
|
||||
v-on:value-change="toggle"
|
||||
/>
|
||||
<InstallButton />
|
||||
<Button
|
||||
rounded
|
||||
icon="pi pi-folder"
|
||||
@ -36,7 +37,7 @@ defineProps({
|
||||
size="small"
|
||||
class="ml-2 shrink-0"
|
||||
style="width: 2rem; height: 2rem"
|
||||
v-on:click="open(mod?.path ?? '')"
|
||||
v-on:click="pkg?.loc && open(pkg.loc.path ?? '')"
|
||||
/>
|
||||
<Button
|
||||
rounded
|
||||
@ -46,7 +47,7 @@ defineProps({
|
||||
size="small"
|
||||
class="ml-2 shrink-0"
|
||||
style="width: 2rem; height: 2rem"
|
||||
v-on:click="open(mod?.package_url ?? '')"
|
||||
v-on:click="pkg?.rmt && open(pkg.rmt.package_url ?? '')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,35 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import { Reactive, onMounted, reactive } from 'vue';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { onMounted } from 'vue';
|
||||
import ModStoreEntry from './ModStoreEntry.vue';
|
||||
import { ModEntry } from '../types';
|
||||
import { usePkgStore } from '../stores';
|
||||
|
||||
const local: Reactive<{ [key: string]: ModEntry }> = reactive({});
|
||||
const listings: Reactive<ModEntry[]> = reactive([]);
|
||||
const pkgs = usePkgStore();
|
||||
|
||||
const reload = async () => {
|
||||
const modsRaw: ModEntry[] = await invoke('get_packages');
|
||||
Object.keys(local).forEach((key) => {
|
||||
delete local[key];
|
||||
});
|
||||
for (const m of modsRaw) {
|
||||
local[`${m.namespace}-${m.name}`] = m;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
Object.assign(listings, await invoke('get_listings'));
|
||||
reload();
|
||||
onMounted(() => {
|
||||
pkgs.fetch();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-for="l in listings" class="flex flex-row">
|
||||
<ModStoreEntry
|
||||
:mod="l"
|
||||
:isLocal="local[`${l.namespace}-${l.name}`] !== undefined"
|
||||
v-on:updated="reload()"
|
||||
/>
|
||||
<div v-for="p in pkgs.allRemote" class="flex flex-row">
|
||||
<ModStoreEntry :pkg="p" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -1,48 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import Button from 'primevue/button';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import InstallButton from './InstallButton.vue';
|
||||
import ModTitlecard from './ModTitlecard.vue';
|
||||
import { ModEntry } from '../types';
|
||||
import { Package } from '../types';
|
||||
|
||||
const emit = defineEmits(['updated']);
|
||||
const props = defineProps({
|
||||
mod: Object as () => ModEntry,
|
||||
isLocal: Boolean,
|
||||
defineProps({
|
||||
pkg: Object as () => Package,
|
||||
});
|
||||
|
||||
const isLoading = ref(false);
|
||||
|
||||
const handlePackageButton = async () => {
|
||||
isLoading.value = true;
|
||||
if (!props.isLocal) {
|
||||
await invoke('download_package', { pkg: props.mod });
|
||||
} else {
|
||||
await invoke('delete_package', {
|
||||
namespace: props.mod?.namespace,
|
||||
name: props.mod?.name,
|
||||
});
|
||||
}
|
||||
await invoke('reload_packages');
|
||||
emit('updated');
|
||||
isLoading.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ModTitlecard :mod="mod" showNamespace />
|
||||
<Button
|
||||
rounded
|
||||
:icon="isLocal ? 'pi pi-trash' : 'pi pi-plus'"
|
||||
:severity="isLocal ? 'danger' : 'success'"
|
||||
aria-label="install"
|
||||
size="small"
|
||||
class="self-center"
|
||||
style="width: 2rem; height: 2rem"
|
||||
:loading="isLoading"
|
||||
v-on:click="handlePackageButton()"
|
||||
/>
|
||||
<ModTitlecard :pkg="pkg" showNamespace />
|
||||
<InstallButton :pkg="pkg" />
|
||||
<Button
|
||||
rounded
|
||||
icon="pi pi-external-link"
|
||||
@ -51,7 +21,8 @@ const handlePackageButton = async () => {
|
||||
size="small"
|
||||
class="self-center ml-2"
|
||||
style="width: 2rem; height: 2rem"
|
||||
v-on:click="open(mod?.package_url ?? '')"
|
||||
:disabled="!pkg?.rmt"
|
||||
v-on:click="open(pkg?.rmt?.package_url ?? '')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
@ -1,19 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { convertFileSrc } from '@tauri-apps/api/core';
|
||||
import { ModEntry } from '../types';
|
||||
import { Package } from '../types';
|
||||
|
||||
defineProps({
|
||||
mod: Object as () => ModEntry,
|
||||
modelValue: Boolean,
|
||||
localIcon: Boolean,
|
||||
const props = defineProps({
|
||||
pkg: Object as () => Package,
|
||||
showNamespace: Boolean,
|
||||
showVersion: Boolean,
|
||||
});
|
||||
|
||||
const iconSrc = () => {
|
||||
const icon = props.pkg?.icon;
|
||||
|
||||
if (icon === undefined) {
|
||||
return '';
|
||||
} else if (icon.startsWith('https://')) {
|
||||
return icon;
|
||||
} else {
|
||||
return convertFileSrc(icon);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<img
|
||||
:src="localIcon ? convertFileSrc(mod?.icon ?? '') : mod?.icon"
|
||||
:src="iconSrc()"
|
||||
class="self-center rounded-sm"
|
||||
width="32px"
|
||||
height="32px"
|
||||
@ -21,23 +31,23 @@ defineProps({
|
||||
<label class="m-3 align-middle text grow z-5 h-50px" for="switch">
|
||||
<div>
|
||||
<span class="text-lg">
|
||||
{{ mod?.name ?? 'Untitled' }}
|
||||
{{ pkg?.name ?? 'Untitled' }}
|
||||
</span>
|
||||
<span
|
||||
v-if="showNamespace && mod?.namespace"
|
||||
v-if="showNamespace && pkg?.namespace"
|
||||
class="text-sm opacity-75"
|
||||
>
|
||||
by {{ mod.namespace }}
|
||||
by {{ pkg.namespace }}
|
||||
</span>
|
||||
<span
|
||||
v-if="showVersion && mod?.version"
|
||||
v-if="showVersion && pkg?.loc?.version"
|
||||
class="text-sm opacity-75 m-2"
|
||||
>
|
||||
{{ mod.version ?? '?.?.?' }}
|
||||
{{ pkg?.loc?.version ?? '?.?.?' }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-sm opacity-75">
|
||||
{{ mod?.description ?? 'No description' }}
|
||||
{{ pkg?.description ?? 'No description' }}
|
||||
</div>
|
||||
</label>
|
||||
</template>
|
||||
|
Reference in New Issue
Block a user