mirror of
https://github.com/gkd-kit/docs.git
synced 2024-11-16 11:42:32 +08:00
feat: ApkTable
This commit is contained in:
parent
4e78aeff39
commit
06cc806834
|
@ -1,84 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onMounted, shallowRef } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
beta?: boolean;
|
||||
}>(),
|
||||
{},
|
||||
);
|
||||
|
||||
const apkUrl = shallowRef('');
|
||||
const apkName = computed(() =>
|
||||
(apkUrl.value.split('/').at(-1) || '').replace('.wasm', '.apk'),
|
||||
);
|
||||
|
||||
const loading = shallowRef(false);
|
||||
const downloadApk = async () => {
|
||||
if (!apkUrl.value || loading.value) return;
|
||||
loading.value = true;
|
||||
try {
|
||||
const file = await fetch(apkUrl.value)
|
||||
.then((r) => r.arrayBuffer())
|
||||
.then(
|
||||
(b) =>
|
||||
new File([b], apkName.value, {
|
||||
type: 'application/vnd.android.package-archive',
|
||||
}),
|
||||
);
|
||||
const { saveAs } = await import('file-saver');
|
||||
saveAs(file, apkName.value);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// preload file-saver in browser
|
||||
if (globalThis.document) {
|
||||
import('file-saver');
|
||||
}
|
||||
|
||||
const pkg = computed(() => (props.beta ? 'app-beta' : 'app'));
|
||||
const key = computed(() => `apkUrl-${pkg.value}`);
|
||||
|
||||
onMounted(async () => {
|
||||
apkUrl.value = localStorage.getItem(key.value) || '';
|
||||
const versionUrl = `https://registry.npmmirror.com/@gkd-kit/${pkg.value}/latest/files`;
|
||||
const r = await fetch(versionUrl);
|
||||
const data = await r.json();
|
||||
apkUrl.value = new URL(data.downloadUrl, r.url).href;
|
||||
localStorage.setItem(key.value, apkUrl.value);
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div inline-flex items-center gap-10px>
|
||||
<a
|
||||
:class="{
|
||||
'cursor-progress': loading,
|
||||
'opacity-50': loading,
|
||||
'cursor-pointer': !loading,
|
||||
}"
|
||||
@click="downloadApk"
|
||||
>
|
||||
{{ apkName }}
|
||||
</a>
|
||||
<svg v-if="loading" animate-spin size-16px viewBox="0 0 16 16" fill="none">
|
||||
<circle
|
||||
cx="8"
|
||||
cy="8"
|
||||
r="7"
|
||||
stroke="currentColor"
|
||||
stroke-opacity="0.25"
|
||||
stroke-width="2"
|
||||
vector-effect="non-scaling-stroke"
|
||||
></circle>
|
||||
<path
|
||||
d="M15 8a7.002 7.002 0 00-7-7"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
vector-effect="non-scaling-stroke"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
34
docs/.vitepress/components/ApkTable.vue
Normal file
34
docs/.vitepress/components/ApkTable.vue
Normal file
|
@ -0,0 +1,34 @@
|
|||
<script setup lang="ts">
|
||||
import DownloadText from './DownloadText.vue';
|
||||
import { data } from '../data/apk.data';
|
||||
</script>
|
||||
<template>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>版本</th>
|
||||
<th>下载链接</th>
|
||||
<th>更新日期</th>
|
||||
<th>备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>正式版</td>
|
||||
<td>
|
||||
<DownloadText :href="data.stable.href" :name="data.stable.filename" />
|
||||
</td>
|
||||
<td>{{ data.stable.date }}</td>
|
||||
<td>稳定版</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>测试版</td>
|
||||
<td>
|
||||
<DownloadText :href="data.beta.href" :name="data.beta.filename" />
|
||||
</td>
|
||||
<td>{{ data.beta.date }}</td>
|
||||
<td>更新快不稳定</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
88
docs/.vitepress/components/DownloadText.vue
Normal file
88
docs/.vitepress/components/DownloadText.vue
Normal file
|
@ -0,0 +1,88 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, shallowRef } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
href: string;
|
||||
name?: string;
|
||||
type?: string;
|
||||
}>(),
|
||||
{
|
||||
type: 'application/vnd.android.package-archive',
|
||||
},
|
||||
);
|
||||
|
||||
const filename = computed(() => {
|
||||
if (props.name) return props.name;
|
||||
return props.href.split('/').at(-1)!;
|
||||
});
|
||||
|
||||
const loading = shallowRef(false);
|
||||
const download = async () => {
|
||||
if (loading.value) return;
|
||||
loading.value = true;
|
||||
import('file-saver');
|
||||
try {
|
||||
const file = await fetch(props.href)
|
||||
.then((r) => r.arrayBuffer())
|
||||
.then((b) => {
|
||||
return new File([b], filename.value, {
|
||||
type: props.type,
|
||||
});
|
||||
});
|
||||
const { saveAs } = await import('file-saver');
|
||||
saveAs(file, filename.value);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<a
|
||||
relative
|
||||
:class="{
|
||||
'cursor-progress': loading,
|
||||
'cursor-pointer': !loading,
|
||||
}"
|
||||
@click="download"
|
||||
:data-href="href"
|
||||
>
|
||||
<span
|
||||
:class="{
|
||||
'opacity-50': loading,
|
||||
}"
|
||||
>
|
||||
{{ filename }}
|
||||
</span>
|
||||
<div
|
||||
v-if="loading"
|
||||
pointer-events-none
|
||||
absolute
|
||||
left="1/1"
|
||||
top-0
|
||||
bottom-0
|
||||
flex
|
||||
items-center
|
||||
pl-4px
|
||||
>
|
||||
<svg animate-spin size-16px viewBox="0 0 16 16" fill="none">
|
||||
<circle
|
||||
cx="8"
|
||||
cy="8"
|
||||
r="7"
|
||||
stroke="currentColor"
|
||||
stroke-opacity="0.25"
|
||||
stroke-width="2"
|
||||
vector-effect="non-scaling-stroke"
|
||||
></circle>
|
||||
<path
|
||||
d="M15 8a7.002 7.002 0 00-7-7"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
vector-effect="non-scaling-stroke"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</a>
|
||||
</template>
|
|
@ -1,13 +1,13 @@
|
|||
import naiveComponents from './naive';
|
||||
import ApkTable from './ApkTable.vue';
|
||||
import GImg from './GImg';
|
||||
import ImageTable from './ImageTable.vue';
|
||||
import IdentifierField from './IdentifierField.vue';
|
||||
import ApkDownloadButton from './ApkDownloadButton.vue';
|
||||
import ImageTable from './ImageTable.vue';
|
||||
import naiveComponents from './naive';
|
||||
|
||||
export default {
|
||||
...naiveComponents,
|
||||
GImg,
|
||||
ImageTable,
|
||||
IdentifierField,
|
||||
ApkDownloadButton
|
||||
ApkTable,
|
||||
};
|
||||
|
|
39
docs/.vitepress/data/apk.data.ts
Normal file
39
docs/.vitepress/data/apk.data.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
export interface VersionInfo {
|
||||
name: string;
|
||||
date: string;
|
||||
href: string;
|
||||
filename: string;
|
||||
}
|
||||
export interface ApkData {
|
||||
stable: VersionInfo;
|
||||
beta: VersionInfo;
|
||||
}
|
||||
|
||||
const getVersionInfo = async (url: string): Promise<VersionInfo> => {
|
||||
const r = await fetch(url).then((r) => r.json());
|
||||
return {
|
||||
name: r.versionName,
|
||||
href: new URL(r.downloadUrl, url).href,
|
||||
date: String(r.date || '').substring(0, 10),
|
||||
filename: 'gkd-v' + r.versionName + '.apk',
|
||||
};
|
||||
};
|
||||
|
||||
const stableRelease = await getVersionInfo(
|
||||
'https://registry.npmmirror.com/@gkd-kit/app/latest/files/index.json',
|
||||
);
|
||||
const betaRelease = await getVersionInfo(
|
||||
'https://registry.npmmirror.com/@gkd-kit/app-beta/latest/files/index.json',
|
||||
);
|
||||
|
||||
const load = async (): Promise<ApkData> => {
|
||||
return {
|
||||
stable: stableRelease,
|
||||
beta: betaRelease,
|
||||
};
|
||||
};
|
||||
|
||||
export default {
|
||||
load,
|
||||
};
|
||||
export declare const data: ApkData;
|
12
docs/.vitepress/data/mirror.data.ts
Normal file
12
docs/.vitepress/data/mirror.data.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
const load = async (): Promise<string> => {
|
||||
const version = await fetch(
|
||||
'https://registry.npmmirror.com/@gkd-kit/assets/latest/files/package.json',
|
||||
).then((r) => r.json().then((j) => j.version as string));
|
||||
|
||||
return `https://registry.npmmirror.com/@gkd-kit/assets/${version}/files/assets/`;
|
||||
};
|
||||
|
||||
export default {
|
||||
load,
|
||||
};
|
||||
export declare const data: string;
|
2
docs/.vitepress/env.d.ts
vendored
2
docs/.vitepress/env.d.ts
vendored
|
@ -1,3 +1 @@
|
|||
/// <reference types="vitepress/client" />
|
||||
|
||||
declare const ASSETS_VERSION: string
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
const mirrorHost = () => {
|
||||
return `https://registry.npmmirror.com/@gkd-kit/assets/${ASSETS_VERSION}/files/assets/`;
|
||||
};
|
||||
import { data as mirrorHost } from '../data/mirror.data';
|
||||
const imgHost = 'https://a.gkd.li/';
|
||||
|
||||
export const convertSrc = (name: string): string => {
|
||||
if (name && name.startsWith('https:')) {
|
||||
if (name.startsWith(imgHost)) {
|
||||
return mirrorHost() + name.slice(imgHost.length);
|
||||
return mirrorHost + name.slice(imgHost.length);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
return mirrorHost() + name;
|
||||
return mirrorHost + name;
|
||||
};
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
## 安装 {#install}
|
||||
|
||||
| 版本 | 下载链接 | 更新日期 | 备注 |
|
||||
| ------ | -------------------------- | ---------- | ------------ |
|
||||
| 正式版 | <ApkDownloadButton /> | 2024-08-27 | 稳定版 |
|
||||
| 测试版 | <ApkDownloadButton beta /> | 2024-10-03 | 更新快不稳定 |
|
||||
<ApkTable />
|
||||
|
||||
或前往 [Github Releases](https://github.com/gkd-kit/gkd/releases/latest) 下载
|
||||
|
||||
|
|
|
@ -1,17 +1,9 @@
|
|||
import { defineConfig } from 'vite';
|
||||
import unocss from 'unocss/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
import { mirror } from './.vitepress/plugins';
|
||||
|
||||
const ASSETS_VERSION = await fetch(
|
||||
'https://registry.npmmirror.com/@gkd-kit/assets/latest/files/package.json',
|
||||
).then((r) => r.json().then((j) => j.version as string));
|
||||
|
||||
export default defineConfig({
|
||||
define: { ASSETS_VERSION: JSON.stringify(ASSETS_VERSION) },
|
||||
plugins: [
|
||||
unocss(),
|
||||
mirror(),
|
||||
],
|
||||
plugins: [unocss(), mirror()],
|
||||
server: {
|
||||
host: '127.0.0.1',
|
||||
port: 8633,
|
||||
|
|
Loading…
Reference in New Issue
Block a user