Files
STARTLINER/src/components/ModStore.vue
2025-04-27 20:30:22 +00:00

133 lines
4.1 KiB
Vue

<script setup lang="ts">
import { Ref, computed, ref } from 'vue';
import Button from 'primevue/button';
import Divider from 'primevue/divider';
import MultiSelect from 'primevue/multiselect';
import ToggleSwitch from 'primevue/toggleswitch';
import ModStoreEntry from './ModStoreEntry.vue';
import { invoke } from '../invoke';
import { usePkgStore, usePrfStore } from '../stores';
import { pkgKey } from '../util';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const pkgs = usePkgStore();
const prf = usePrfStore();
const empty = ref(true);
const props = defineProps({
search: String,
});
const gameSublist: Ref<string[]> = ref([]);
invoke('get_game_packages', {
game: prf.current?.meta.game ?? null,
}).then((list) => {
gameSublist.value = list as string[];
});
const list = () => {
const res = pkgs.allRemote
.filter((p) => gameSublist.value.includes(pkgKey(p)))
.filter(
(p) =>
props.search === undefined ||
p.name.toLowerCase().includes(props.search.toLowerCase()) ||
p.namespace
.toLowerCase()
.includes(props.search.toLowerCase()) ||
p.description.toLowerCase().includes(props.search.toLowerCase())
)
.sort((p1, p2) => p1.name.localeCompare(p2.name));
empty.value = res.length === 0;
return res;
};
const shouldShowRecommended = computed(() => {
if (prf.current?.meta.game === 'ongeki') {
return !pkgs.allLocal.some((p) => pkgKey(p) === 'segatools-mu3hook');
}
if (prf.current?.meta.game === 'chunithm') {
return (
!pkgs.allLocal.some((p) => pkgKey(p) === 'segatools-chusanhook') ||
!pkgs.allLocal.some((p) => pkgKey(p) === 'mempatcher-mempatcher')
);
}
return false;
});
const recommendedTooltip = computed(() => {
if (prf.current?.meta.game === 'ongeki') {
return 'segatools-mu3hook';
}
if (prf.current?.meta.game === 'chunithm') {
return 'segatools-chusanhook + mempatcher';
}
return '';
});
const installRecommended = () => {
if (prf.current?.meta.game === 'ongeki') {
pkgs.installFromKey('segatools-mu3hook');
}
if (prf.current?.meta.game === 'chunithm') {
pkgs.installFromKey('segatools-chusanhook');
pkgs.installFromKey('mempatcher-mempatcher');
}
};
</script>
<template>
<div class="flex gap-4 items-center">
<div class="flex flex-col gap-2">
<div class="flex gap-2">
<div class="grow">{{ t('store.installed') }}</div>
<ToggleSwitch v-model="pkgs.showInstalled" />
</div>
<div class="flex gap-2">
<div class="text-amber-400 grow">
{{ t('store.deprecated') }}
</div>
<ToggleSwitch v-model="pkgs.showDeprecated" />
</div>
<!-- <div class="flex gap-2">
<div class="text-red-400 grow">{{ t('store.nsfw') }}</div>
<ToggleSwitch v-model="pkgs.showNSFW" />
</div> -->
</div>
<div class="flex flex-col gap-2 grow">
<MultiSelect
size="small"
:showToggleAll="false"
:placeholder="t('store.includeCategories')"
v-model="pkgs.includeCategories"
:options="[...pkgs.availableCategories]"
class="w-full"
/>
<MultiSelect
size="small"
:showToggleAll="false"
:placeholder="t('store.excludeCategories')"
v-model="pkgs.excludeCategories"
:options="[...pkgs.availableCategories]"
class="w-full"
/>
</div>
</div>
<Divider />
<Button
v-if="shouldShowRecommended"
:label="t('store.installRecommended')"
v-tooltip="recommendedTooltip"
icon="pi pi-plus"
class="mb-3"
@click="installRecommended"
/>
<div v-for="p in list()" class="flex flex-row">
<ModStoreEntry :pkg="p" />
</div>
<div v-if="empty" class="text-3xl"></div>
</template>