feat: improve caching of individual repositories

This commit adds the possibility to provide to the caching component data already known and to be
cached immediately without the need of a callback function. This allows caching individual
repositories without having to rely on additional API calls. However, repos can also be retrieved
individually from the GitHub API based on their full name.
此提交包含在:
2023-05-08 11:19:41 +02:00
父節點 e0bcdb6dd3
當前提交 1678100198
共有 4 個檔案被更改,包括 60 行新增21 行删除

查看文件

@@ -1,5 +1,10 @@
<template>
<Cache name="repos" :callback="fetchData" @cached="processCachedData" />
<Cache
:name="props.cacheName"
:callback="fetchData"
:data="alreadyKnownData"
@cached="processCachedData"
/>
<slot v-if="loading" name="loader">
<Loader />
</slot>
@@ -23,6 +28,11 @@ const props = defineProps({
required: true,
type: String,
},
cacheName: {
required: true,
type: String,
},
alreadyKnownData: Object,
});
const emits = defineEmits(['dataLoaded', 'dataError', 'loading']);

查看文件

@@ -19,6 +19,10 @@ const props = defineProps({
required: false,
type: Number,
},
data: {
default: null,
type: Object,
},
});
const emits = defineEmits(['cached']);
@@ -29,25 +33,31 @@ const isDataOutdated = (name: string): boolean => {
return elapsedTime > props.lifetime;
};
const storeInCache = (data: Observable<any>, name: string): Observable<any> => {
data.subscribe({
const storeInCache = (
callback: Function,
data: any,
name: string
): Observable<any> => {
let response: Observable<any> = data ? of(data) : callback();
response.subscribe({
next: (response) => {
localStorage.setItem(name, JSON.stringify(response));
localStorage.setItem(name + '-timestamp', `${Date.now()}`);
},
});
return data;
return response;
};
if (isDataOutdated(props.name)) {
emits('cached', storeInCache(props.callback(), props.name));
emits('cached', storeInCache(props.callback, props.data, props.name));
} else {
let data = localStorage.getItem(props.name);
try {
emits('cached', of(JSON.parse(data)));
} catch (err) {
console.error(`Could not parse data found in cache: ${err}`);
emits('cached', storeInCache(props.callback(), props.name));
emits('cached', storeInCache(props.callback, props.data, props.name));
}
}
</script>

查看文件

@@ -1,26 +1,45 @@
<template>
<div class="githubRepo flex-row flex-space-between gap-1rem rounded-corners">
<ApiLoader
:cache-name="repoName()"
:url="fetchUrl"
:already-known-data="props.data"
@data-loaded="(repo: GithubRepo) => (repository = repo)"
>
<div class="flex-col info">
<h3>{{ props.repo.name }}</h3>
<h3>{{ props.data.name }}</h3>
<div>
<p>
{{ props.repo.description }}
{{ props.data.description }}
</p>
</div>
</div>
<div class="flex-col flex-start gap-1rem stats">
<p>Stars: {{ repo.stargazers_count }}</p>
<p>Forks: {{ repo.forks_count }}</p>
<p>Stars: {{ data.stargazers_count }}</p>
<p>Forks: {{ data.forks_count }}</p>
</div>
</ApiLoader>
</div>
</template>
<script setup lang="ts">
import ApiLoader from '../ApiLoader.vue';
import { GithubRepo } from '../../composables/github';
import { PropType } from 'vue';
import { PropType, Ref, ref } from 'vue';
const props = defineProps({
repo: Object as PropType<GithubRepo>,
data: Object as PropType<GithubRepo>,
repoName: String,
fetcher: String as PropType<'gitea' | 'github'>,
});
const repoName = (): string => {
return props.data ? props.data.full_name : props.repoName;
};
const fetchUrl = `https://api.github.com/repos/${repoName()}`;
const repository: Ref<GithubRepo> = ref(null);
</script>
<style lang="less">

查看文件

@@ -1,8 +1,8 @@
<template>
<div class="flex-col gap-1rem list-repos">
<ApiLoader :url="fetchUrl" @dataLoaded="filterRepos">
<ApiLoader :url="fetchUrl" @dataLoaded="filterRepos" cache-name="repos">
<GithubRepository
:repo="repo"
:data="repo"
type="repositories"
v-for="repo in repos"
class="center"