Skip to content

Commit 65b0e03

Browse files
committed
feat: support audio and spine
1 parent 6d3119d commit 65b0e03

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+18682
-720
lines changed

.gitattributes

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Auto detect text files and perform LF normalization
22
* text=auto
3-
*.lockb binary diff=lockb
43

54
# Auto generated files
65
src/auto-imports.d.ts text eol=lf

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Dev
22
/src/assets/*.ab
33

4+
# Yalc
5+
.yalc
6+
yalc.lock
7+
48
# Logs
59
logs
610
*.log

bun.lock

Lines changed: 2022 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bun.lockb

-442 KB
Binary file not shown.

env.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/// <reference types="vite/client" />
22
/// <reference types="vite-plugin-pwa/client" />
3-
/// <reference types="vite-plugin-comlink/client" />
43
/// <reference types="unplugin-icons/types/vue3" />
54
/// <reference types="vite-svg-loader" />
5+
/// <reference types="@types/wicg-file-system-access" />
66

77
declare module 'is-json' {
88
export default function (str: any): boolean;

eslint.config.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export default antfu(
1212
},
1313
typescript: {
1414
overrides: {
15+
'ts/ban-ts-comment': 'off',
1516
'ts/member-ordering': 'warn',
1617
'ts/explicit-member-accessibility': ['warn', { accessibility: 'no-public' }],
1718
'ts/consistent-type-imports': [
@@ -27,13 +28,15 @@ export default antfu(
2728
jsonc: false,
2829
yaml: false,
2930
markdown: false,
31+
ignores: ['**/*.js'],
3032
},
3133
prettierConfig as Linter.Config,
3234
{
3335
languageOptions: {
3436
globals: autoImport.globals as any as Linter.Globals,
3537
},
3638
rules: {
39+
'node/prefer-global/buffer': 'off',
3740
'antfu/consistent-list-newline': 'off',
3841
'style/semi': 'off',
3942
'style/member-delimiter-style': 'off',
@@ -67,6 +70,13 @@ export default antfu(
6770
],
6871
},
6972
],
73+
'perfectionist/sort-exports': [
74+
'warn',
75+
{
76+
ignoreCase: false,
77+
partitionByNewLine: true,
78+
},
79+
],
7080
},
7181
},
7282
);

package.json

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,51 +13,56 @@
1313
"format": "prettier --write src/"
1414
},
1515
"dependencies": {
16-
"@arkntools/jimp-png": "^1.0.0",
17-
"@arkntools/unity-js": "^3.4.2",
16+
"@arkntools/unity-js": "4.0.0",
1817
"@guolao/vue-monaco-editor": "^1.5.5",
1918
"@iconify-json/ep": "^1.2.2",
19+
"@jimp/core": "^1.6.0",
20+
"@jimp/wasm-png": "^1.6.0",
21+
"@tsuk1ko/fsa-promises": "^2.0.2",
22+
"@ungap/with-resolvers": "^0.1.0",
2023
"@vueuse/core": "^13.5.0",
24+
"buffer": "^6.0.3",
2125
"comlink": "^4.4.2",
22-
"element-plus": "^2.10.3",
23-
"es-toolkit": "^1.39.6",
26+
"element-plus": "^2.10.4",
27+
"empty-module": "^0.0.2",
28+
"es-toolkit": "^1.39.8",
2429
"eventemitter3": "^5.0.1",
2530
"file-saver": "^2.0.5",
2631
"is-json": "^2.0.1",
2732
"js-md5": "^0.8.3",
28-
"jszip": "^3.10.1",
2933
"monaco-editor": "^0.52.2",
3034
"pinia": "^3.0.3",
3135
"splitpanes": "^3.2.0",
3236
"uid": "^2.0.2",
33-
"vue": "^3.5.17",
37+
"vue": "^3.5.18",
3438
"vxe-table": "~4.6.25"
3539
},
3640
"devDependencies": {
37-
"@antfu/eslint-config": "^4.16.2",
41+
"@antfu/eslint-config": "^4.19.0",
3842
"@tsconfig/node20": "^20.1.6",
3943
"@types/file-saver": "^2.0.7",
4044
"@types/js-md5": "^0.8.0",
41-
"@types/node": "^22.16.0",
45+
"@types/node": "^22.16.5",
4246
"@types/splitpanes": "^2.2.6",
47+
"@types/wicg-file-system-access": "^2023.10.6",
4348
"@vitejs/plugin-vue": "^6.0.0",
4449
"@vue/eslint-config-typescript": "^14.6.0",
4550
"@vue/tsconfig": "^0.7.0",
4651
"@vxecli/import-unplugin-vue-components": "^1.0.4",
47-
"eslint": "^9.30.1",
48-
"eslint-config-prettier": "^10.1.5",
49-
"jiti": "^2.4.2",
52+
"eslint": "^9.32.0",
53+
"eslint-config-prettier": "^10.1.8",
54+
"jiti": "^2.5.1",
5055
"npm-run-all2": "^8.0.4",
5156
"prettier": "^3.6.2",
5257
"sass": "^1.89.2",
5358
"typescript": "^5.8.3",
5459
"unplugin-auto-import": "^19.3.0",
5560
"unplugin-icons": "^22.1.0",
5661
"unplugin-vue-components": "^28.8.0",
57-
"vite": "^7.0.2",
58-
"vite-plugin-comlink": "^5.1.0",
59-
"vite-plugin-pwa": "^1.0.1",
62+
"vite": "^7.0.6",
63+
"vite-plugin-node-polyfills": "^0.24.0",
64+
"vite-plugin-pwa": "^1.0.2",
6065
"vite-svg-loader": "^5.1.0",
61-
"vue-tsc": "3.0.1"
66+
"vue-tsc": "^3.0.4"
6267
}
6368
}

src/components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export {}
99
declare module 'vue' {
1010
export interface GlobalComponents {
1111
ElButton: typeof import('element-plus/es')['ElButton']
12+
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
1213
ElContainer: typeof import('element-plus/es')['ElContainer']
1314
ElDialog: typeof import('element-plus/es')['ElDialog']
1415
ElDropdown: typeof import('element-plus/es')['ElDropdown']
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<template>
2+
<div class="asset-audio-viewer">
3+
<audio
4+
:src="data || ''"
5+
class="audio"
6+
controls
7+
:autoPlay="settings.autoPlay ? '' : null"
8+
:loop="settings.loop"
9+
></audio>
10+
<div class="settings">
11+
<el-switch v-model="settings.autoPlay" class="setting-switch" active-text="Auto Play" />
12+
<el-switch v-model="settings.loop" class="setting-switch" active-text="Loop" />
13+
</div>
14+
<FullSizeLoading :loading="!data" />
15+
</div>
16+
</template>
17+
18+
<script setup lang="ts">
19+
import { useLocalStorage } from '@vueuse/core';
20+
import FullSizeLoading from './FullSizeLoading.vue';
21+
22+
defineProps<{
23+
asset: any;
24+
data: string | null;
25+
}>();
26+
27+
const settings = useLocalStorage(
28+
'asset-audio-viewer-settings',
29+
{ autoPlay: false, loop: false },
30+
{ mergeDefaults: true },
31+
);
32+
</script>
33+
34+
<style lang="scss" scoped>
35+
.asset-audio-viewer {
36+
display: flex;
37+
justify-content: center;
38+
align-items: center;
39+
position: relative;
40+
width: 100%;
41+
height: 100%;
42+
background-color: #808080;
43+
}
44+
45+
.audio {
46+
width: 80%;
47+
}
48+
49+
.settings {
50+
position: absolute;
51+
top: 8px;
52+
left: 12px;
53+
display: flex;
54+
flex-direction: column;
55+
gap: 4px;
56+
}
57+
58+
.setting-switch :deep(.el-switch__label) {
59+
color: #fff !important;
60+
}
61+
</style>

src/components/AssetImageViewer.vue

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,67 @@
11
<template>
22
<div class="asset-image-viewer">
33
<el-splitter>
4-
<el-splitter-panel v-if="imgList.size" :min="100" v-model:size="menuWidth" class="asset-image-viewer-panel">
4+
<el-splitter-panel v-if="imgList.length" v-model:size="menuWidth" :min="100" class="asset-image-viewer-panel">
55
<el-scrollbar class="menu-scroll-view">
66
<el-menu ref="menu" @select="handleSelect">
7-
<el-menu-item v-for="[key, item] in imgList" :key :index="key">
7+
<el-menu-item v-for="item in imgList" :key="item.key" :index="item.key">
88
<span class="img-name">{{ item.name }}</span>
99
</el-menu-item>
1010
</el-menu>
1111
</el-scrollbar>
1212
</el-splitter-panel>
1313
<el-splitter-panel :min="200" class="asset-image-viewer-panel">
14-
<ImageViewer :src :name />
14+
<ImageViewer :src="data" :name="name" />
1515
</el-splitter-panel>
1616
</el-splitter>
1717
</div>
1818
</template>
1919

2020
<script setup lang="ts">
21-
import type { AssetInfo, AssetInfoData } from '@/workers/assetManager';
22-
import ImageViewer from '@/components/ImageViewer.vue';
2321
import { useLocalStorage } from '@vueuse/core';
22+
import ImageViewer from '@/components/ImageViewer.vue';
23+
import { PreviewType } from '@/types/preview';
24+
import type { AssetInfo } from '@/workers/assetManager';
2425
25-
type ImgItem = Extract<AssetInfoData, { type: 'imageList' }>['list'][number];
26-
27-
const { asset } = defineProps<{
26+
const { asset, data } = defineProps<{
2827
asset: AssetInfo;
28+
data: string | null;
2929
}>();
3030
3131
const emits = defineEmits<{
32-
loadImage: [asset: AssetInfo, subKey?: string];
32+
updatePayload: [key?: string];
3333
}>();
3434
3535
const menuRef = useTemplateRef('menu');
3636
3737
const menuWidth = useLocalStorage('asset-image-viewer-menu-width', 200);
3838
39-
const imgList = ref<Map<string, ImgItem>>(new Map());
39+
const imgList = computed(() => (asset.preview.type === PreviewType.ImageList ? asset.preview.detail : []));
40+
const imgMap = computed(() => new Map(imgList.value.map(item => [item.key, item])));
41+
4042
const curSelectKey = ref<string>('');
41-
const curSelectItem = computed(() => imgList.value.get(curSelectKey.value));
43+
const curSelectItem = computed(() => imgMap.value.get(curSelectKey.value));
4244
43-
const data = computed(() => asset.data! as Extract<AssetInfoData, { type: 'image' | 'imageList' }>);
44-
const src = computed(() => (data.value.type === 'imageList' ? curSelectItem.value?.url : data.value.url));
45-
const name = computed(() => (data.value.type === 'imageList' ? curSelectItem.value?.name : asset.name));
45+
const name = computed(() => (imgList.value.length ? curSelectItem.value?.name : asset.name));
4646
4747
const handleSelect = (key: string) => {
4848
curSelectKey.value = key;
4949
};
5050
5151
watch(
52-
data,
53-
value => {
54-
// 单图
55-
if (value.type === 'image') {
56-
imgList.value.clear();
57-
if (value.url === undefined) emits('loadImage', asset);
58-
return;
59-
}
60-
61-
// 多图
62-
imgList.value = new Map(value.list.map(item => [item.key, item]));
63-
if (!imgList.value.has(curSelectKey.value)) {
64-
curSelectKey.value = value.list[0].key;
52+
imgList,
53+
list => {
54+
if (!imgMap.value.has(curSelectKey.value)) {
55+
curSelectKey.value = list[0]?.key || '';
6556
}
6657
},
6758
{ immediate: true },
6859
);
6960
7061
watch(
71-
curSelectItem,
72-
item => {
73-
if (item && item.url === undefined) {
74-
emits('loadImage', asset, curSelectKey.value);
75-
}
62+
curSelectKey,
63+
key => {
64+
emits('updatePayload', key);
7665
},
7766
{ immediate: true },
7867
);

0 commit comments

Comments
 (0)