Rewrite extensions components to setup syntax (#21)

* Rewrite extensions components to setup syntax.

* Format md.use.

* Import ElementPlus components directly for three-shaking.

* Fix SSR setting.

* Fix missing loading indicator in extensions page.
This commit is contained in:
Alessandro Jean 2023-09-08 02:42:53 -03:00 committed by GitHub
parent 359833502a
commit 1d1bf5fba9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 326 additions and 161 deletions

View File

@ -57,6 +57,7 @@
"stylelint": "^15.10.3",
"stylelint-stylus": "^0.18.0",
"stylus": "^0.60.0",
"unplugin-element-plus": "^0.8.0",
"vite-plugin-eslint": "^1.8.1",
"vitepress": "1.0.0-rc.10",
"vitepress-plugin-tabs": "^0.3.0",

View File

@ -1,9 +1,5 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies:
'@iconify-prerendered/vue-mdi':
specifier: ^0.23.1689058119
@ -109,6 +105,9 @@ devDependencies:
stylus:
specifier: ^0.60.0
version: 0.60.0
unplugin-element-plus:
specifier: ^0.8.0
version: 0.8.0
vite-plugin-eslint:
specifier: ^1.8.1
version: 1.8.1(eslint@8.48.0)(vite@4.4.9)
@ -1013,6 +1012,20 @@ packages:
picomatch: 2.3.1
dev: true
/@rollup/pluginutils@5.0.4:
resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^1.20.0||^2.0.0||^3.0.0
peerDependenciesMeta:
rollup:
optional: true
dependencies:
'@types/estree': 1.0.1
estree-walker: 2.0.2
picomatch: 2.3.1
dev: true
/@shuding/opentype.js@1.4.0-beta.0:
resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==}
engines: {node: '>= 8.0.0'}
@ -1540,6 +1553,14 @@ packages:
engines: {node: '>=12'}
dev: true
/anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
dependencies:
normalize-path: 3.0.0
picomatch: 2.3.1
dev: true
/argparse@1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
dependencies:
@ -1673,6 +1694,11 @@ packages:
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
dev: false
/binary-extensions@2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'}
dev: true
/body-parser@1.20.1:
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
@ -1781,6 +1807,21 @@ packages:
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
dev: true
/chokidar@3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 8.10.0'}
dependencies:
anymatch: 3.1.3
braces: 3.0.2
glob-parent: 5.1.2
is-binary-path: 2.1.0
is-glob: 4.0.3
normalize-path: 3.0.0
readdirp: 3.6.0
optionalDependencies:
fsevents: 2.3.3
dev: true
/cli-cursor@4.0.0:
resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -2189,6 +2230,10 @@ packages:
which-typed-array: 1.1.11
dev: true
/es-module-lexer@1.3.0:
resolution: {integrity: sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==}
dev: true
/es-set-tostringtag@2.0.1:
resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==}
engines: {node: '>= 0.4'}
@ -3032,6 +3077,13 @@ packages:
has-bigints: 1.0.2
dev: true
/is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
dependencies:
binary-extensions: 2.2.0
dev: true
/is-boolean-object@1.1.2:
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
engines: {node: '>= 0.4'}
@ -3986,6 +4038,13 @@ packages:
type-fest: 1.4.0
dev: true
/readdirp@3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
dependencies:
picomatch: 2.3.1
dev: true
/redent@4.0.0:
resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==}
engines: {node: '>=12'}
@ -4711,6 +4770,27 @@ packages:
engines: {node: '>= 0.8'}
dev: true
/unplugin-element-plus@0.8.0:
resolution: {integrity: sha512-jByUGY3FG2B8RJKFryqxx4eNtSTj+Hjlo8edcOdJymewndDQjThZ1pRUQHRjQsbKhTV2jEctJV7t7RJ405UL4g==}
engines: {node: '>=14.19.0'}
dependencies:
'@rollup/pluginutils': 5.0.4
es-module-lexer: 1.3.0
magic-string: 0.30.3
unplugin: 1.4.0
transitivePeerDependencies:
- rollup
dev: true
/unplugin@1.4.0:
resolution: {integrity: sha512-5x4eIEL6WgbzqGtF9UV8VEC/ehKptPXDS6L2b0mv4FRMkJxRtjaJfOWDd6a8+kYbqsjklix7yWP0N3SUepjXcg==}
dependencies:
acorn: 8.10.0
chokidar: 3.5.3
webpack-sources: 3.2.3
webpack-virtual-modules: 0.5.0
dev: true
/upath@2.0.1:
resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==}
engines: {node: '>=4'}
@ -4909,6 +4989,15 @@ packages:
'@vue/server-renderer': 3.3.4(vue@3.3.4)
'@vue/shared': 3.3.4
/webpack-sources@3.2.3:
resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
engines: {node: '>=10.13.0'}
dev: true
/webpack-virtual-modules@0.5.0:
resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==}
dev: true
/which-boxed-primitive@1.0.2:
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
dependencies:
@ -5022,3 +5111,7 @@ packages:
/yoga-wasm-web@0.3.3:
resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==}
dev: true
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false

View File

@ -1,4 +1,5 @@
import { defineConfig, loadEnv } from "vitepress";
import ElementPlus from "unplugin-element-plus/vite";
import markdownConfig from "./config/markdownConfig"; // For use with loading Markdown plugins
import themeConfig from "./config/themeConfig"; // Theme related config
@ -30,4 +31,10 @@ export default defineConfig({
generateFeed(context, hostname);
generateOgImages(context);
},
vite: {
plugins: [ElementPlus({})],
ssr: {
noExternal: ["element-plus"],
},
},
});

View File

@ -12,17 +12,17 @@ import shortcodes from "./shortcodes";
const markdownConfig: MarkdownOptions = {
config: (md) => {
md.use(attrs),
md.use(figure),
md.use(imgLazyload),
md.use(imgMark),
md.use(imgSize),
md.use(include, {
md
.use(attrs)
.use(figure)
.use(imgLazyload)
.use(imgMark)
.use(imgSize)
.use(include, {
currentPath: (env) => env.filePath,
}),
md.use(tabsMarkdownPlugin);
md.use(shortcode_plugin, shortcodes);
})
.use(tabsMarkdownPlugin)
.use(shortcode_plugin, shortcodes);
},
};

View File

@ -1,57 +1,80 @@
<script>
<script setup lang="ts">
import { toRefs } from "vue";
import { langName, simpleLangName } from "../../../config/scripts/languages";
import type { Extension } from "../../queries/useExtensionsRepositoryQuery";
export default {
props: ["extensions"],
emits: ["filters"],
data() {
return {
filters: {
search: "",
lang: [],
nsfw: "Show all",
sort: "Ascending",
},
};
},
watch: {
filters: {
handler(value) {
this.$emit("filters", this.filters);
},
deep: true,
},
},
methods: {
simpleLangName,
langName,
},
};
import {
ElForm,
ElFormItem,
ElInput,
ElSelect,
ElOption,
ElRadioGroup,
ElRadio,
} from "element-plus";
export type Nsfw = "Show all" | "NSFW" | "SFW";
export type Sort = "Ascending" | "Descending";
const props = defineProps<{
extensions: Extension[][];
search: string;
lang: string[];
nsfw: Nsfw;
sort: Sort;
}>();
const { extensions } = toRefs(props);
defineEmits<{
(e: 'update:search', search: string): void;
(e: 'update:lang', lang: string[]): void,
(e: 'update:nsfw', nsfw: Nsfw): void,
(e: 'update:sort', sort: Sort): void,
}>();
</script>
<template>
<div class="filters-list">
<el-form :model="filters" label-width="120px">
<el-form label-width="120px">
<el-form-item label="Search:">
<el-input v-model="filters.search" placeholder="Search extensions by name or ID..." clearable />
<el-input
:model-value="search"
placeholder="Search extensions by name or ID..."
clearable
@update:model-value="$emit('update:search', $event)"
/>
</el-form-item>
<el-form-item label="Languages:">
<el-select v-model="filters.lang" placeholder="Show specific languages..." multiple clearable>
<el-option
v-for="[group] in extensions"
:key="group.lang"
:label="group.lang === 'en' ? simpleLangName(group.lang) : langName(group.lang)"
:value="group.lang"
/>
</el-select>
<el-select
:model-value="lang"
placeholder="Show specific languages..."
multiple
clearable
@update:model-value="$emit('update:lang', $event)"
>
<el-option
v-for="[group] in extensions"
:key="group.lang"
:label="group.lang === 'en' ? simpleLangName(group.lang) : langName(group.lang)"
:value="group.lang"
/>
</el-select>
</el-form-item>
<el-form-item label="Sort by:">
<el-radio-group v-model="filters.sort">
<el-radio-group
:model-value="sort"
@update:model-value="$emit('update:sort', $event)"
>
<el-radio label="Ascending"></el-radio>
<el-radio label="Descending"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="Display mode:">
<el-radio-group v-model="filters.nsfw">
<el-radio-group
:model-value="nsfw"
@update:model-value="$emit('update:nsfw', $event)"
>
<el-radio label="NSFW"></el-radio>
<el-radio label="SFW"></el-radio>
<el-radio label="Show all"></el-radio>
@ -67,4 +90,8 @@ export default {
flex-direction: column
row-gap: 1rem
}
.el-select {
width: 100%
}
</style>

View File

@ -1,27 +1,25 @@
<script>
<script setup lang="ts">
import { computed, toRefs } from "vue";
import { langName, simpleLangName } from "../../../config/scripts/languages";
import ExtensionItem from "./ExtensionItem.vue";
import type { Extension } from "../../queries/useExtensionsRepositoryQuery";
export default {
components: { ExtensionItem },
props: ["list", "totalCount"],
computed: {
groupName: function () {
const firstItem = this.list[0];
return firstItem.lang === "en" ? simpleLangName(firstItem.lang) : langName(firstItem.lang);
},
},
methods: {
simpleLangName,
langName,
},
};
const props = defineProps<{ list: Extension[]; totalCount: number }>();
const { list } = toRefs(props);
const groupName = computed(() => {
const firstItem = list.value[0];
return firstItem.lang === "en"
? simpleLangName(firstItem.lang)
: langName(firstItem.lang);
});
</script>
<template>
<div class="extension-group">
<h2>
{{ groupName }}
<span>{{ groupName }}</span>
<span class="extensions-total">
Total:
@ -30,6 +28,7 @@ export default {
</span>
</span>
</h2>
<ExtensionItem
v-for="extension in list"
:id="extension.pkg.replace('eu.kanade.tachiyomi.extension.', '')"
@ -40,10 +39,12 @@ export default {
</template>
<style lang="stylus">
.extensions-total {
float: right
.extension-group h2 {
display: flex
align-items: center
justify-content: space-between
&-sum {
.extensions-total-sum {
color: var(--vp-c-brand)
}
}

View File

@ -1,33 +1,24 @@
<script>
export default {
props: ["item"],
computed: {
pkgId: function () {
return this.item.pkg.replace("eu.kanade.tachiyomi.extension.", "");
},
pkgName: function () {
return this.item.name.split(": ")[1];
},
pkgVersion: function () {
return this.item.version;
},
pkgIsNsfw: function () {
return !!parseInt(this.item.nsfw);
},
pkgHasReadme: function () {
return !!parseInt(this.item.hasReadme);
},
pkgHasChangelog: function () {
return !!parseInt(this.item.hasChangelog);
},
iconUrl: function () {
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/icon/${this.item.pkg}.png`;
},
apkUrl: function () {
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/apk/${this.item.apk}`;
},
},
};
<script setup lang="ts">
import { computed, toRefs } from "vue";
import type { Extension } from "../../queries/useExtensionsRepositoryQuery";
const props = defineProps<{ item: Extension }>();
const { item } = toRefs(props);
const pkgId = computed(() => {
return item.value.pkg.replace("eu.kanade.tachiyomi.extension.", "");
});
const pkgName = computed(() => item.value.name.split(": ")[1]);
const pkgIsNsfw = computed(() => item.value.nsfw === 1);
const iconUrl = computed(() => {
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/icon/${item.value.pkg}.png`;
});
const apkUrl = computed(() => {
return `https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/apk/${item.value.apk}`;
});
</script>
<template>
@ -42,8 +33,8 @@ export default {
{{ pkgId }}
</div>
</div>
<Badge v-if="pkgIsNsfw" type="danger" :text="pkgVersion" title="This extension contains NSFW entries." />
<Badge v-else type="info" :text="pkgVersion" title="This extension is free from NSFW entries." />
<Badge v-if="pkgIsNsfw" type="danger" :text="item.version" title="This extension contains NSFW entries." />
<Badge v-else type="info" :text="item.version" title="This extension is free from NSFW entries." />
<a :href="apkUrl" class="extension-download" title="Download APK" download></a>
</div>
</template>
@ -53,14 +44,20 @@ export default {
position: relative
align-items: center
display: flex
width: 100%
padding: 0.5em 0
margin: 0.8em 0
width: calc(100% + 1em)
padding: 0.5em
margin: 0.8em -0.5em
border-radius: 8px
gap: 0.675rem
&:hover {
background-color: var(--vp-c-bg-soft-mute)
background-color: var(--vp-c-bg-soft)
}
&:target {
background-color: var(--vp-c-brand-soft)
border-radius: 8px
transition: 500ms background-color
}
.anchor {
@ -142,6 +139,8 @@ export default {
border: 1px solid var(--vp-c-divider)
border-radius: 8px
padding: 0.5em
margin: 0.8em 0
width: 100%
.extension-icon {
margin-left: 0
@ -152,10 +151,4 @@ export default {
}
}
}
&:target {
background-color: var(--vp-c-bg-soft-mute)
border-radius: 8px
transition: 500ms background-color
}
</style>

View File

@ -1,21 +1,28 @@
<script>
<script setup lang="ts">
import { computed, toRefs } from "vue";
import ExtensionGroup from "./ExtensionGroup.vue";
import type { Extension } from "../../queries/useExtensionsRepositoryQuery";
export default {
components: { ExtensionGroup },
props: ["extensions"],
computed: {
totalCount() {
return this.extensions.reduce((sum, item) => sum + item.length, 0);
},
},
};
const props = defineProps<{ extensions: Extension[][] }>();
const { extensions } = toRefs(props);
const totalCount = computed(() => {
return extensions.value.reduce((sum, item) => sum + item.length, 0);
});
</script>
<template>
<div class="extension-list">
<ExtensionGroup v-for="group in extensions" :key="group[0].lang" :list="group" :class="group[0].lang" :total-count="totalCount" />
<ExtensionGroup
v-for="group in extensions"
:key="group[0].lang"
:list="group"
:class="group[0].lang"
:total-count="totalCount"
/>
</div>
</template>
<style lang="stylus">
.extension-list {
> div {

View File

@ -1,19 +1,29 @@
<script setup lang="ts">
import groupBy from "lodash.groupby";
import { ElLoading } from "element-plus";
import { simpleLangName } from "../../../config/scripts/languages";
import ExtensionFilters from "./ExtensionFilters.vue";
import ExtensionList from "./ExtensionList.vue";
import useExtensionsRepositoryQuery from "../../queries/useExtensionsRepositoryQuery";
import { computed, onUpdated, ref } from 'vue';
import { computed, nextTick, onMounted, onUpdated, reactive, ref, watch } from 'vue';
import type { Extension } from "../../queries/useExtensionsRepositoryQuery";
import type { Nsfw, Sort } from "./ExtensionFilters.vue";
const { data: extensions, isLoading } = useExtensionsRepositoryQuery();
const { data: extensions, isLoading } = useExtensionsRepositoryQuery({
select: (response) => {
const values: Extension[][] = Object.values(groupBy(response, "lang"));
values.sort(languageComparator)
const filters = ref({
return values
},
});
const filters = reactive({
search: "",
lang: [] as string[],
nsfw: "Show all",
sort: "Ascending",
nsfw: "Show all" as Nsfw,
sort: "Ascending" as Sort,
});
function languageComparator(a: Extension[], b: Extension[]) {
@ -40,33 +50,26 @@ function languageComparator(a: Extension[], b: Extension[]) {
return 0;
}
const groupedExtensions = computed(() => {
const values: Extension[][] = Object.values(groupBy(extensions.value, "lang"));
values.sort(languageComparator)
return values
})
const filteredExtensions = computed(() => {
const filtered: Extension[][] = [];
for (const group of groupedExtensions.value) {
let filteredGroup = filters.value.lang.length
? (filters.value.lang.includes(group[0].lang) ? group : [])
for (const group of (extensions.value ?? [])) {
let filteredGroup = filters.lang.length
? (filters.lang.includes(group[0].lang) ? group : [])
: group;
if (filters.value.search) {
if (filters.search) {
filteredGroup = filteredGroup.filter(
(ext) =>
ext.name.toLowerCase().includes(filters.value.search.toLowerCase()) ||
ext.sources.some((source) => source.id.includes(filters.value.search))
ext.name.toLowerCase().includes(filters.search.toLowerCase()) ||
ext.sources.some((source) => source.id.includes(filters.search))
);
}
filteredGroup = filteredGroup.filter((ext) =>
filters.value.nsfw === "Show all" ? true : ext.nsfw === (filters.value.nsfw === "NSFW" ? 1 : 0)
filters.nsfw === "Show all" ? true : ext.nsfw === (filters.nsfw === "NSFW" ? 1 : 0)
);
if (filters.value.sort && filters.value.sort === "Descending") {
if (filters.sort && filters.sort === "Descending") {
filteredGroup = filteredGroup.reverse();
}
if (filteredGroup.length) {
@ -77,15 +80,46 @@ const filteredExtensions = computed(() => {
return filtered;
});
onUpdated(() => {
const loadingInstance = ref<ReturnType<typeof ElLoading['service']>>();
onMounted(() => {
loadingInstance.value = ElLoading.service({
target: ".extensions",
fullscreen: false,
background: "transparent",
});
})
watch(extensions, async () => {
if (window.location.hash) {
window.location.replace(window.location.hash);
await nextTick()
document.getElementById(window.location.hash.substring(1))
?.scrollIntoView({ behavior: 'smooth' });
}
});
watch([isLoading, loadingInstance], async ([newIsLoading]) => {
if (!newIsLoading) {
loadingInstance.value?.close();
}
});
</script>
<template>
<ExtensionFilters :extensions="groupedExtensions" @filters="filters = $event" />
<div class="loading" v-if="isLoading" v-loading.lock="isLoading" style="min-height: 200px"></div>
<ExtensionList v-else :extensions="filteredExtensions" />
<ExtensionFilters
:extensions="extensions ?? []"
v-model:search="filters.search"
v-model:lang="filters.lang"
v-model:nsfw="filters.nsfw"
v-model:sort="filters.sort"
/>
<div class="extensions">
<ExtensionList v-if="!isLoading" :extensions="filteredExtensions" />
</div>
</template>
<style lang="stylus" scoped>
.extensions {
min-height: 200px
}
</style>

View File

@ -5,8 +5,6 @@ import DefaultTheme from "vitepress/theme";
import "./styles/base.styl";
// Import Global plugins
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import "element-plus/theme-chalk/dark/css-vars.css";
import { VueQueryPlugin } from "@tanstack/vue-query";
@ -19,7 +17,6 @@ import { IconDownload, IconNewspaperVariant, IconBugReport } from "@iconify-prer
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
app.use(ElementPlus);
app.use(VueQueryPlugin);
enhanceAppWithTabs(app);
app.component("IconDownload", IconDownload);

View File

@ -1,4 +1,4 @@
import { useQuery } from "@tanstack/vue-query";
import { UseQueryOptions, useQuery } from "@tanstack/vue-query";
import axios from "axios";
import { GITHUB_EXTENSION_JSON } from "../../config/constants";
@ -26,14 +26,11 @@ export interface Source {
hasCloudflare: string;
}
export interface GitHubAsset {
name: string;
content_type: string;
browser_download_url: string;
}
type UseExtensionsRepositoryQueryOptions<S = Extension[]> =
UseQueryOptions<Extension[], Error, S>
export default function useExtensionsRepositoryQuery() {
return useQuery({
export default function useExtensionsRepositoryQuery<S = Extension[]>(options: UseExtensionsRepositoryQueryOptions<S> = {}) {
return useQuery<Extension[], Error, S>({
queryKey: ["extensions"],
queryFn: async () => {
const { data } = await axios.get<Extension[]>(GITHUB_EXTENSION_JSON);
@ -42,5 +39,6 @@ export default function useExtensionsRepositoryQuery() {
},
initialData: () => [],
refetchOnWindowFocus: false,
...options,
});
}

View File

@ -217,3 +217,10 @@ main :where(h1, h2, h3, h4, h5, h6) + figure {
margin-right: 4px
}
}
/**
* Component: Element Plus
*/
body {
--el-color-primary: var(--vp-c-brand-1)
}