forked from akanyan/STARTLINER
133 lines
4.1 KiB
Vue
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>
|