@eternalheart/vue-file-preview 1.3.11 → 1.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/README.zh-CN.md +27 -0
- package/lib/FilePreviewContent.vue.d.ts.map +1 -1
- package/lib/chunks/{index-DLPnWmJm.mjs → index-B2lqsdp7.mjs} +2 -2
- package/lib/chunks/{index-DLPnWmJm.mjs.map → index-B2lqsdp7.mjs.map} +1 -1
- package/lib/chunks/{index-hRgOoqVw.mjs → index-BHi1WRQZ.mjs} +2 -2
- package/lib/chunks/{index-hRgOoqVw.mjs.map → index-BHi1WRQZ.mjs.map} +1 -1
- package/lib/chunks/{index-BHPmd4HF.mjs → index-BTW1xwB9.mjs} +2 -2
- package/lib/chunks/{index-BHPmd4HF.mjs.map → index-BTW1xwB9.mjs.map} +1 -1
- package/lib/chunks/{index-C0vSFXmh.mjs → index-BvegaxQF.mjs} +2 -2
- package/lib/chunks/{index-C0vSFXmh.mjs.map → index-BvegaxQF.mjs.map} +1 -1
- package/lib/chunks/{index-C65zV1vs.mjs → index-CYt6tpQC.mjs} +2 -2
- package/lib/chunks/{index-C65zV1vs.mjs.map → index-CYt6tpQC.mjs.map} +1 -1
- package/lib/chunks/{index-t1Plo3ud.mjs → index-Cjnw238n.mjs} +2 -2
- package/lib/chunks/{index-t1Plo3ud.mjs.map → index-Cjnw238n.mjs.map} +1 -1
- package/lib/chunks/{index-BT-U9HYI.mjs → index-Ctd0JQ6K.mjs} +2 -2
- package/lib/chunks/{index-BT-U9HYI.mjs.map → index-Ctd0JQ6K.mjs.map} +1 -1
- package/lib/chunks/index-CyrFxdIJ.mjs +318 -0
- package/lib/chunks/index-CyrFxdIJ.mjs.map +1 -0
- package/lib/chunks/{index-Cu1up6RM.mjs → index-DBw8tvyb.mjs} +2 -2
- package/lib/chunks/{index-Cu1up6RM.mjs.map → index-DBw8tvyb.mjs.map} +1 -1
- package/lib/chunks/{index-BKu5DkdG.mjs → index-DEoR7aDN.mjs} +2 -2
- package/lib/chunks/{index-BKu5DkdG.mjs.map → index-DEoR7aDN.mjs.map} +1 -1
- package/lib/chunks/{index-CMgtGmRN.mjs → index-DIe0vHlt.mjs} +9 -9
- package/lib/chunks/{index-CMgtGmRN.mjs.map → index-DIe0vHlt.mjs.map} +1 -1
- package/lib/chunks/index-DT9dPz8I.mjs +279 -0
- package/lib/chunks/index-DT9dPz8I.mjs.map +1 -0
- package/lib/chunks/{index-B9RAbllH.mjs → index-DTtHrdBl.mjs} +6 -6
- package/lib/chunks/{index-B9RAbllH.mjs.map → index-DTtHrdBl.mjs.map} +1 -1
- package/lib/chunks/{index-Dln8hyPZ.mjs → index-DX_NBPzS.mjs} +2 -2
- package/lib/chunks/{index-Dln8hyPZ.mjs.map → index-DX_NBPzS.mjs.map} +1 -1
- package/lib/chunks/{index-BA-SUKkf.mjs → index-Dw1U4YqT.mjs} +2 -2
- package/lib/chunks/{index-BA-SUKkf.mjs.map → index-Dw1U4YqT.mjs.map} +1 -1
- package/lib/chunks/{index-DNFQFaF3.mjs → index-DyipSoKh.mjs} +2 -2
- package/lib/chunks/{index-DNFQFaF3.mjs.map → index-DyipSoKh.mjs.map} +1 -1
- package/lib/chunks/{index-B3-ezDVJ.mjs → index-GGGDPwxX.mjs} +2 -2
- package/lib/chunks/{index-B3-ezDVJ.mjs.map → index-GGGDPwxX.mjs.map} +1 -1
- package/lib/chunks/{index-CQFN4h-t.mjs → index-Oxwizt6-.mjs} +609 -581
- package/lib/chunks/index-Oxwizt6-.mjs.map +1 -0
- package/lib/chunks/{index-CY2vJrBJ.mjs → index-Zwl5J-Uw.mjs} +2 -2
- package/lib/chunks/{index-CY2vJrBJ.mjs.map → index-Zwl5J-Uw.mjs.map} +1 -1
- package/lib/components/NavArrows.vue.d.ts +17 -0
- package/lib/components/NavArrows.vue.d.ts.map +1 -0
- package/lib/components/ResizableSplit.vue.d.ts +17 -2
- package/lib/components/ResizableSplit.vue.d.ts.map +1 -1
- package/lib/index.cjs +32 -32
- package/lib/index.cjs.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.mjs +1 -1
- package/lib/renderers/Image/index.vue.d.ts.map +1 -1
- package/lib/renderers/Text/index.vue.d.ts.map +1 -1
- package/lib/renderers/Xml/index.vue.d.ts.map +1 -1
- package/lib/renderers/Zip/index.vue.d.ts.map +1 -1
- package/package.json +1 -1
- package/lib/chunks/index-CQFN4h-t.mjs.map +0 -1
- package/lib/chunks/index-ijv9F2cZ.mjs +0 -280
- package/lib/chunks/index-ijv9F2cZ.mjs.map +0 -1
- package/lib/chunks/index-y7gaKu36.mjs +0 -234
- package/lib/chunks/index-y7gaKu36.mjs.map +0 -1
- package/lib/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/78-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/78-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Add-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Add-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
- package/lib/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
- package/lib/pdfjs/cmaps/B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/B5pc-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/B5pc-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS1-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS1-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS2-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/CNS2-V.bcmap +0 -3
- package/lib/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/ETenms-B5-H.bcmap +0 -3
- package/lib/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Ext-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Ext-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GB-H.bcmap +0 -4
- package/lib/pdfjs/cmaps/GB-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBT-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBT-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Hankaku.bcmap +0 -0
- package/lib/pdfjs/cmaps/Hiragana.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Katakana.bcmap +0 -0
- package/lib/pdfjs/cmaps/LICENSE +0 -36
- package/lib/pdfjs/cmaps/NWP-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/NWP-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/Roman.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
- package/lib/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
- package/lib/pdfjs/cmaps/V.bcmap +0 -0
- package/lib/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
- package/lib/pdfjs/pdf.worker.min.mjs +0 -21
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ref as p, watch as B, onUnmounted as D, defineComponent as U, toRef as O, computed as $, onMounted as q, onBeforeUnmount as H, unref as t, openBlock as g, createBlock as V, createElementBlock as z, createElementVNode as a, normalizeStyle as G, createStaticVNode as W, toDisplayString as C, normalizeClass as A, createVNode as P, resolveDynamicComponent as X, Transition as J, withCtx as K, createCommentVNode as Q } from "vue";
|
|
2
2
|
import { VolumeX as Y, Volume1 as Z, Volume2 as ee, Repeat as te, SkipBack as ae, Pause as re, Play as ne, SkipForward as oe } from "lucide-vue-next";
|
|
3
|
-
import { k as se, u as le, _ as ie } from "./index-
|
|
3
|
+
import { k as se, u as le, _ as ie } from "./index-Oxwizt6-.mjs";
|
|
4
4
|
import { _ as pe } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
|
|
5
5
|
function fe(x) {
|
|
6
6
|
const f = p(null), b = p(!1), o = p(!0), h = p(0), d = p(0), y = p(1), c = p(!1), v = p(!1), u = p(null);
|
|
@@ -385,4 +385,4 @@ const de = {
|
|
|
385
385
|
export {
|
|
386
386
|
Be as default
|
|
387
387
|
};
|
|
388
|
-
//# sourceMappingURL=index-
|
|
388
|
+
//# sourceMappingURL=index-BvegaxQF.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-C0vSFXmh.mjs","sources":["../../src/composables/useAudioPlayer.ts","../../src/renderers/Audio/index.vue"],"sourcesContent":["import { ref, watch, onUnmounted, type Ref } from 'vue';\nimport { formatTime } from '@eternalheart/file-preview-core';\n\n/**\n * Vue 3 版本的音频播放器 composable\n * 与 React 版的 useAudioPlayer 行为对齐\n */\nexport function useAudioPlayer(url: Ref<string>) {\n const audioRef = ref<HTMLAudioElement | null>(null);\n const isPlaying = ref(false);\n const isLoading = ref(true);\n const currentTime = ref(0);\n const duration = ref(0);\n const volume = ref(1);\n const isMuted = ref(false);\n const isLoop = ref(false);\n const error = ref<string | null>(null);\n\n let cleanup: (() => void) | null = null;\n\n const bindEvents = () => {\n const audio = audioRef.value;\n if (!audio) return;\n\n isLoading.value = true;\n error.value = null;\n\n const onTimeUpdate = () => {\n if (!isNaN(audio.currentTime)) {\n currentTime.value = audio.currentTime;\n }\n };\n\n const onDurationChange = () => {\n if (!isNaN(audio.duration) && isFinite(audio.duration)) {\n duration.value = audio.duration;\n }\n };\n\n const onCanPlay = () => {\n isLoading.value = false;\n onDurationChange();\n };\n\n const onWaiting = () => {\n isLoading.value = true;\n };\n const onPlaying = () => {\n isLoading.value = false;\n isPlaying.value = true;\n };\n\n const onPlay = () => {\n isPlaying.value = true;\n };\n const onPause = () => {\n isPlaying.value = false;\n };\n const onEnded = () => {\n isPlaying.value = false;\n };\n\n const onError = () => {\n error.value = '音频加载失败';\n isLoading.value = false;\n };\n\n audio.addEventListener('timeupdate', onTimeUpdate);\n audio.addEventListener('loadedmetadata', onDurationChange);\n audio.addEventListener('durationchange', onDurationChange);\n audio.addEventListener('canplay', onCanPlay);\n audio.addEventListener('waiting', onWaiting);\n audio.addEventListener('playing', onPlaying);\n audio.addEventListener('play', onPlay);\n audio.addEventListener('pause', onPause);\n audio.addEventListener('ended', onEnded);\n audio.addEventListener('error', onError);\n\n if (audio.readyState >= 3) {\n isLoading.value = false;\n onDurationChange();\n } else if (audio.readyState >= 1) {\n onDurationChange();\n }\n\n cleanup = () => {\n audio.removeEventListener('timeupdate', onTimeUpdate);\n audio.removeEventListener('loadedmetadata', onDurationChange);\n audio.removeEventListener('durationchange', onDurationChange);\n audio.removeEventListener('canplay', onCanPlay);\n audio.removeEventListener('waiting', onWaiting);\n audio.removeEventListener('playing', onPlaying);\n audio.removeEventListener('play', onPlay);\n audio.removeEventListener('pause', onPause);\n audio.removeEventListener('ended', onEnded);\n audio.removeEventListener('error', onError);\n };\n };\n\n // url 变化时重新绑定\n watch(\n url,\n () => {\n cleanup?.();\n cleanup = null;\n // 等待 DOM 更新(audio src 变化)\n requestAnimationFrame(() => bindEvents());\n },\n { flush: 'post' }\n );\n\n // 在 audioRef 挂载后首次绑定\n watch(\n audioRef,\n (el) => {\n if (el) bindEvents();\n },\n { flush: 'post' }\n );\n\n onUnmounted(() => {\n cleanup?.();\n cleanup = null;\n });\n\n const togglePlay = () => {\n const audio = audioRef.value;\n if (!audio) return;\n if (audio.paused) {\n audio.play().catch(() => {});\n } else {\n audio.pause();\n }\n };\n\n const seek = (time: number) => {\n const audio = audioRef.value;\n if (!audio) return;\n audio.currentTime = time;\n currentTime.value = time;\n };\n\n const skip = (seconds: number) => {\n const audio = audioRef.value;\n if (!audio) return;\n audio.currentTime = Math.max(\n 0,\n Math.min(audio.currentTime + seconds, audio.duration || Infinity)\n );\n };\n\n const setVolume = (vol: number) => {\n const audio = audioRef.value;\n if (!audio) return;\n const clamped = Math.max(0, Math.min(1, vol));\n audio.volume = clamped;\n volume.value = clamped;\n if (clamped > 0) {\n audio.muted = false;\n isMuted.value = false;\n }\n };\n\n const toggleMute = () => {\n const audio = audioRef.value;\n if (!audio) return;\n audio.muted = !audio.muted;\n isMuted.value = audio.muted;\n };\n\n const toggleLoop = () => {\n const audio = audioRef.value;\n if (!audio) return;\n const next = !audio.loop;\n audio.loop = next;\n isLoop.value = next;\n };\n\n return {\n audioRef,\n isPlaying,\n isLoading,\n isLoop,\n currentTime,\n duration,\n volume,\n isMuted,\n error,\n togglePlay,\n seek,\n skip,\n setVolume,\n toggleMute,\n toggleLoop,\n formatTime,\n };\n}\n","<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onBeforeUnmount, toRef } from 'vue';\nimport { Play, Pause, Volume2, VolumeX, Volume1, SkipBack, SkipForward, Repeat } from 'lucide-vue-next';\nimport { useAudioPlayer } from '../../composables/useAudioPlayer';\nimport { useTranslator } from '../../composables/useTranslator';\nimport RendererError from '../RendererError.vue';\n\nconst props = defineProps<{\n url: string;\n fileName: string;\n}>();\n\nconst urlRef = toRef(props, 'url');\n\nconst { t } = useTranslator();\n\nconst {\n audioRef,\n isPlaying,\n isLoop,\n currentTime,\n duration,\n volume,\n isMuted,\n error,\n togglePlay,\n seek,\n skip,\n setVolume,\n toggleMute,\n toggleLoop,\n formatTime,\n} = useAudioPlayer(urlRef);\n\nconst showVolume = ref(false);\nlet volumeHideTimer: number | null = null;\nconst volumeRef = ref<HTMLDivElement | null>(null);\n\nconst progress = computed(() => (duration.value > 0 ? currentTime.value / duration.value : 0));\n\nconst VolumeIcon = computed(() => {\n if (isMuted.value || volume.value === 0) return VolumeX;\n if (volume.value < 0.5) return Volume1;\n return Volume2;\n});\n\nconst handleClickOutside = (e: MouseEvent) => {\n if (volumeRef.value && !volumeRef.value.contains(e.target as Node)) {\n showVolume.value = false;\n }\n};\n\nonMounted(() => {\n document.addEventListener('mousedown', handleClickOutside);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('mousedown', handleClickOutside);\n if (volumeHideTimer !== null) clearTimeout(volumeHideTimer);\n});\n\nconst handleVolumeEnter = () => {\n if (volumeHideTimer !== null) clearTimeout(volumeHideTimer);\n showVolume.value = true;\n};\n\nconst handleVolumeLeave = () => {\n volumeHideTimer = window.setTimeout(() => {\n showVolume.value = false;\n }, 300);\n};\n</script>\n\n<template>\n <RendererError v-if=\"error\" :message=\"error\" />\n\n <div\n v-else\n class=\"vfp-flex vfp-flex-col vfp-items-center vfp-justify-center vfp-w-full vfp-h-full vfp-p-4 md:vfp-p-8 vfp-gap-5 md:vfp-gap-8 vfp-select-none\"\n >\n <!-- 唱片机 -->\n <div class=\"vfp-relative\" style=\"width: 260px; height: 240px\">\n <!-- 外圈光晕 -->\n <div\n class=\"vfp-absolute vfp-rounded-full\"\n :style=\"{\n width: '220px',\n height: '220px',\n top: '18px',\n left: '8px',\n background: 'radial-gradient(circle, rgba(129,140,248,0.12) 0%, transparent 70%)',\n opacity: isPlaying ? 0.7 : 0.2,\n transition: 'opacity 0.5s',\n }\"\n />\n\n <!-- 唱片主体 -->\n <div\n class=\"vfp-absolute vfp-rounded-full vfp-overflow-hidden\"\n :style=\"{\n width: '200px',\n height: '200px',\n top: '28px',\n left: '18px',\n background: `\n radial-gradient(circle at center, transparent 95%, rgba(30,30,30,0.8) 95.5%, #111 97%),\n radial-gradient(circle at center, transparent 38%, rgba(50,50,50,0.5) 38.15%, transparent 38.4%),\n radial-gradient(circle at center, transparent 45%, rgba(50,50,50,0.3) 45.15%, transparent 45.4%),\n radial-gradient(circle at center, transparent 52%, rgba(50,50,50,0.5) 52.15%, transparent 52.4%),\n radial-gradient(circle at center, transparent 59%, rgba(50,50,50,0.3) 59.15%, transparent 59.4%),\n radial-gradient(circle at center, transparent 66%, rgba(50,50,50,0.5) 66.15%, transparent 66.4%),\n radial-gradient(circle at center, transparent 73%, rgba(50,50,50,0.3) 73.15%, transparent 73.4%),\n radial-gradient(circle at center, transparent 80%, rgba(50,50,50,0.4) 80.15%, transparent 80.4%),\n radial-gradient(circle at center, transparent 87%, rgba(50,50,50,0.3) 87.15%, transparent 87.4%),\n conic-gradient(from 0deg, #1c1c1c, #232323, #1a1a1a, #262626, #1c1c1c, #212121, #1a1a1a, #252525, #1c1c1c, #232323, #1a1a1a, #262626, #1c1c1c)\n `,\n boxShadow: isPlaying\n ? '0 0 36px rgba(129,140,248,0.1), 0 8px 32px rgba(0,0,0,0.4), inset 0 0 20px rgba(0,0,0,0.4)'\n : '0 8px 32px rgba(0,0,0,0.4), inset 0 0 20px rgba(0,0,0,0.4)',\n animation: 'vfp-vinyl-spin 8s linear infinite',\n animationPlayState: isPlaying ? 'running' : 'paused',\n }\"\n >\n <!-- 中心标签 -->\n <div\n class=\"vfp-absolute vfp-rounded-full\"\n :style=\"{\n width: '34%',\n height: '34%',\n top: '33%',\n left: '33%',\n background: 'radial-gradient(circle at 40% 38%, #818cf8, #6366f1, #4f46e5, #4338ca)',\n boxShadow: 'inset 0 1px 3px rgba(255,255,255,0.25), inset 0 -1px 3px rgba(0,0,0,0.3), 0 0 8px rgba(0,0,0,0.3)',\n }\"\n >\n <div\n class=\"vfp-absolute vfp-rounded-full\"\n :style=\"{\n width: '14%',\n height: '14%',\n top: '43%',\n left: '43%',\n background: 'radial-gradient(circle at 40% 40%, #333, #0d0d0d)',\n boxShadow: 'inset 0 1px 3px rgba(0,0,0,0.9), 0 0 2px rgba(0,0,0,0.5)',\n }\"\n />\n </div>\n </div>\n\n <!-- 唱臂 -->\n <div\n class=\"vfp-absolute\"\n :style=\"{\n top: '-6px',\n right: '2px',\n width: '100px',\n height: '120px',\n transformOrigin: '76px 16px',\n zIndex: 5,\n transform: isPlaying ? 'rotate(16deg)' : 'rotate(0deg)',\n transition: 'transform 0.8s cubic-bezier(0.4, 0, 0.2, 1)',\n }\"\n >\n <svg width=\"100\" height=\"120\" viewBox=\"0 0 100 120\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"76\" cy=\"16\" r=\"13\" fill=\"rgba(0,0,0,0.3)\" />\n <circle cx=\"76\" cy=\"16\" r=\"11\" fill=\"url(#vfp-baseGrad)\" />\n <circle cx=\"76\" cy=\"16\" r=\"6\" fill=\"url(#vfp-baseInnerGrad)\" />\n <circle cx=\"76\" cy=\"16\" r=\"2.5\" fill=\"#222\" stroke=\"#555\" stroke-width=\"0.5\" />\n <path d=\"M74 22 L56 88\" stroke=\"url(#vfp-armGrad)\" stroke-width=\"3.5\" stroke-linecap=\"round\" />\n <rect x=\"50\" y=\"86\" width=\"12\" height=\"7\" rx=\"1.5\" fill=\"url(#vfp-headGrad)\" />\n <rect x=\"52.5\" y=\"92\" width=\"7\" height=\"9\" rx=\"1\" fill=\"url(#vfp-cartridgeGrad)\" />\n <line x1=\"56\" y1=\"101\" x2=\"56\" y2=\"105\" stroke=\"#bbb\" stroke-width=\"1.2\" stroke-linecap=\"round\" />\n <circle cx=\"56\" cy=\"105.5\" r=\"0.8\" fill=\"#ddd\" />\n\n <defs>\n <radialGradient id=\"vfp-baseGrad\" cx=\"40%\" cy=\"35%\">\n <stop offset=\"0%\" stop-color=\"#555\" />\n <stop offset=\"100%\" stop-color=\"#1a1a1a\" />\n </radialGradient>\n <radialGradient id=\"vfp-baseInnerGrad\" cx=\"40%\" cy=\"35%\">\n <stop offset=\"0%\" stop-color=\"#666\" />\n <stop offset=\"100%\" stop-color=\"#333\" />\n </radialGradient>\n <linearGradient id=\"vfp-armGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#555\" />\n <stop offset=\"50%\" stop-color=\"#444\" />\n <stop offset=\"100%\" stop-color=\"#333\" />\n </linearGradient>\n <linearGradient id=\"vfp-headGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#555\" />\n <stop offset=\"100%\" stop-color=\"#333\" />\n </linearGradient>\n <linearGradient id=\"vfp-cartridgeGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#444\" />\n <stop offset=\"100%\" stop-color=\"#222\" />\n </linearGradient>\n </defs>\n </svg>\n </div>\n </div>\n\n <!-- 文件名 -->\n <div class=\"vfp-text-center vfp-max-w-sm md:vfp-max-w-md vfp-px-4\">\n <div class=\"vfp-text-lg md:vfp-text-xl vfp-font-medium vfp-mb-1 vfp-truncate vfp-text-fg-primary\">\n {{ fileName }}\n </div>\n <p class=\"vfp-text-xs vfp-tracking-widest vfp-uppercase vfp-text-accent\">Audio</p>\n </div>\n\n <!-- 控制面板 -->\n <div\n class=\"vfp-w-full vfp-max-w-sm md:vfp-max-w-md vfp-rounded-2xl vfp-p-4 md:vfp-p-6 vfp-border vfp-bg-surface-1 vfp-border-line-weak\"\n :style=\"{ backdropFilter: 'blur(16px)' }\"\n >\n <!-- 进度条 -->\n <div class=\"vfp-mb-5\">\n <div class=\"vfp-relative vfp-h-4 vfp-flex vfp-items-center\">\n <div\n class=\"vfp-absolute vfp-w-full vfp-h-[5px] vfp-rounded-full vfp-bg-surface-2\"\n />\n <div\n class=\"vfp-absolute vfp-h-[5px] vfp-rounded-full vfp-pointer-events-none\"\n :style=\"{\n width: `${progress * 100}%`,\n background: 'linear-gradient(90deg, var(--fp-accent), var(--fp-accent-hover))',\n boxShadow: isPlaying ? '0 0 8px rgba(129,140,248,0.4)' : 'none',\n transition: 'width 0.1s linear',\n }\"\n />\n <input\n type=\"range\"\n min=\"0\"\n :max=\"duration > 0 ? duration : currentTime || 100\"\n step=\"any\"\n :value=\"currentTime\"\n :disabled=\"duration <= 0\"\n :aria-label=\"t('audio.aria.progress')\"\n class=\"audio-slider vfp-absolute vfp-w-full\"\n @input=\"(e) => seek(parseFloat((e.target as HTMLInputElement).value))\"\n />\n </div>\n <div\n class=\"vfp-flex vfp-justify-between vfp-text-xs vfp-mt-2.5 vfp-text-fg-tertiary\"\n >\n <span style=\"font-variant-numeric: tabular-nums\">{{ formatTime(currentTime) }}</span>\n <span style=\"font-variant-numeric: tabular-nums\">{{ duration > 0 ? formatTime(duration) : '--:--' }}</span>\n </div>\n </div>\n\n <!-- 控制按钮 -->\n <div class=\"vfp-flex vfp-items-center vfp-justify-center vfp-gap-3\">\n <!-- 循环 -->\n <button\n :class=\"[\n 'vfp-w-9 vfp-h-9 vfp-rounded-full vfp-flex vfp-items-center vfp-justify-center vfp-transition-colors audio-ctrl-btn',\n isLoop ? 'vfp-bg-accent-soft vfp-text-accent' : 'vfp-bg-surface-2 vfp-text-fg-tertiary',\n ]\"\n :aria-label=\"isLoop ? t('audio.aria.loop_off') : t('audio.aria.loop_on')\"\n @click=\"toggleLoop\"\n >\n <Repeat class=\"vfp-w-4 vfp-h-4\" />\n </button>\n\n <!-- 后退 -->\n <button\n class=\"vfp-w-10 vfp-h-10 vfp-rounded-full vfp-flex vfp-items-center vfp-justify-center vfp-transition-colors audio-ctrl-btn vfp-bg-surface-2 vfp-text-fg-secondary\"\n :aria-label=\"t('audio.aria.backward_10')\"\n @click=\"skip(-10)\"\n >\n <SkipBack class=\"vfp-w-[18px] vfp-h-[18px]\" />\n </button>\n\n <!-- 播放/暂停 -->\n <button\n class=\"vfp-w-14 vfp-h-14 vfp-rounded-full vfp-flex vfp-items-center vfp-justify-center audio-ctrl-btn\"\n :style=\"{\n background: 'linear-gradient(135deg, var(--fp-accent-hover), var(--fp-accent))',\n color: '#fff',\n boxShadow: '0 4px 20px rgba(99,102,241,0.35)',\n }\"\n :aria-label=\"isPlaying ? t('audio.aria.pause') : t('audio.aria.play')\"\n @click=\"togglePlay\"\n >\n <Pause v-if=\"isPlaying\" class=\"vfp-w-6 vfp-h-6\" />\n <Play v-else class=\"vfp-w-6 vfp-h-6 vfp-ml-0.5\" />\n </button>\n\n <!-- 前进 -->\n <button\n class=\"vfp-w-10 vfp-h-10 vfp-rounded-full vfp-flex vfp-items-center vfp-justify-center vfp-transition-colors audio-ctrl-btn vfp-bg-surface-2 vfp-text-fg-secondary\"\n :aria-label=\"t('audio.aria.forward_10')\"\n @click=\"skip(10)\"\n >\n <SkipForward class=\"vfp-w-[18px] vfp-h-[18px]\" />\n </button>\n\n <!-- 音量 -->\n <div ref=\"volumeRef\" class=\"vfp-relative\" @mouseenter=\"handleVolumeEnter\" @mouseleave=\"handleVolumeLeave\">\n <button\n :class=\"[\n 'vfp-w-9 vfp-h-9 vfp-rounded-full vfp-flex vfp-items-center vfp-justify-center vfp-transition-colors audio-ctrl-btn',\n showVolume ? 'vfp-bg-accent-soft vfp-text-accent' : 'vfp-bg-surface-2 vfp-text-fg-secondary',\n ]\"\n :aria-label=\"isMuted ? t('audio.aria.unmute') : t('audio.aria.mute')\"\n @click=\"toggleMute\"\n >\n <component :is=\"VolumeIcon\" class=\"vfp-w-4 vfp-h-4\" />\n </button>\n\n <Transition name=\"vfp-fade\">\n <div\n v-if=\"showVolume\"\n class=\"vfp-absolute vfp-bottom-full vfp-mb-2 vfp-rounded-xl vfp-p-3 vfp-border vfp-bg-surface-3 vfp-border-line\"\n :style=\"{\n left: '50%',\n marginLeft: '-27px',\n backdropFilter: 'blur(16px)',\n }\"\n @mouseenter=\"handleVolumeEnter\"\n @mouseleave=\"handleVolumeLeave\"\n >\n <div class=\"vfp-flex vfp-flex-col vfp-items-center vfp-gap-2\" style=\"height: 100px\">\n <div\n class=\"vfp-relative vfp-flex vfp-items-center vfp-justify-center\"\n style=\"width: 24px; height: 80px\"\n >\n <div\n class=\"vfp-absolute vfp-rounded-full vfp-bg-surface-2\"\n style=\"width: 3px; height: 100%\"\n />\n <div\n class=\"vfp-absolute vfp-bottom-0 vfp-rounded-full vfp-pointer-events-none\"\n :style=\"{\n width: '3px',\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background: 'var(--fp-accent-hover)',\n transition: 'height 0.1s linear',\n }\"\n />\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.01\"\n :value=\"isMuted ? 0 : volume\"\n :aria-label=\"t('audio.aria.volume')\"\n class=\"volume-slider-vertical vfp-absolute\"\n style=\"width: 80px; height: 24px; transform: rotate(-90deg); transform-origin: center center\"\n @input=\"(e) => setVolume(parseFloat((e.target as HTMLInputElement).value))\"\n />\n </div>\n <span class=\"vfp-text-[10px] vfp-tabular-nums vfp-text-fg-tertiary\">\n {{ Math.round((isMuted ? 0 : volume) * 100) }}\n </span>\n </div>\n </div>\n </Transition>\n </div>\n </div>\n </div>\n\n <audio ref=\"audioRef\" :src=\"url\" class=\"vfp-hidden\" />\n </div>\n</template>\n\n<style scoped>\n.audio-ctrl-btn {\n border: 0;\n cursor: pointer;\n}\n</style>\n"],"names":["useAudioPlayer","url","audioRef","ref","isPlaying","isLoading","currentTime","duration","volume","isMuted","isLoop","error","cleanup","bindEvents","audio","onTimeUpdate","onDurationChange","onCanPlay","onWaiting","onPlaying","onPlay","onPause","onEnded","onError","watch","el","onUnmounted","time","seconds","vol","clamped","next","formatTime","urlRef","toRef","__props","t","useTranslator","togglePlay","seek","skip","setVolume","toggleMute","toggleLoop","showVolume","volumeHideTimer","volumeRef","progress","computed","VolumeIcon","VolumeX","Volume1","Volume2","handleClickOutside","e","onMounted","onBeforeUnmount","handleVolumeEnter","handleVolumeLeave","_unref","_createBlock","RendererError","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_normalizeStyle","_hoisted_3","_hoisted_4","_toDisplayString","_cache","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_normalizeClass","args","_createVNode","Repeat","SkipBack","Pause","Play","SkipForward","_resolveDynamicComponent","_Transition","_hoisted_18","_hoisted_19","_hoisted_21"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-BvegaxQF.mjs","sources":["../../src/composables/useAudioPlayer.ts","../../src/renderers/Audio/index.vue"],"sourcesContent":["import { ref, watch, onUnmounted, type Ref } from 'vue';\nimport { formatTime } from '@eternalheart/file-preview-core';\n\n/**\n * Vue 3 版本的音频播放器 composable\n * 与 React 版的 useAudioPlayer 行为对齐\n */\nexport function useAudioPlayer(url: Ref<string>) {\n const audioRef = ref<HTMLAudioElement | null>(null);\n const isPlaying = ref(false);\n const isLoading = ref(true);\n const currentTime = ref(0);\n const duration = ref(0);\n const volume = ref(1);\n const isMuted = ref(false);\n const isLoop = ref(false);\n const error = ref<string | null>(null);\n\n let cleanup: (() => void) | null = null;\n\n const bindEvents = () => {\n const audio = audioRef.value;\n if (!audio) return;\n\n isLoading.value = true;\n error.value = null;\n\n const onTimeUpdate = () => {\n if (!isNaN(audio.currentTime)) {\n currentTime.value = audio.currentTime;\n }\n };\n\n const onDurationChange = () => {\n if (!isNaN(audio.duration) && isFinite(audio.duration)) {\n duration.value = audio.duration;\n }\n };\n\n const onCanPlay = () => {\n isLoading.value = false;\n onDurationChange();\n };\n\n const onWaiting = () => {\n isLoading.value = true;\n };\n const onPlaying = () => {\n isLoading.value = false;\n isPlaying.value = true;\n };\n\n const onPlay = () => {\n isPlaying.value = true;\n };\n const onPause = () => {\n isPlaying.value = false;\n };\n const onEnded = () => {\n isPlaying.value = false;\n };\n\n const onError = () => {\n error.value = '音频加载失败';\n isLoading.value = false;\n };\n\n audio.addEventListener('timeupdate', onTimeUpdate);\n audio.addEventListener('loadedmetadata', onDurationChange);\n audio.addEventListener('durationchange', onDurationChange);\n audio.addEventListener('canplay', onCanPlay);\n audio.addEventListener('waiting', onWaiting);\n audio.addEventListener('playing', onPlaying);\n audio.addEventListener('play', onPlay);\n audio.addEventListener('pause', onPause);\n audio.addEventListener('ended', onEnded);\n audio.addEventListener('error', onError);\n\n if (audio.readyState >= 3) {\n isLoading.value = false;\n onDurationChange();\n } else if (audio.readyState >= 1) {\n onDurationChange();\n }\n\n cleanup = () => {\n audio.removeEventListener('timeupdate', onTimeUpdate);\n audio.removeEventListener('loadedmetadata', onDurationChange);\n audio.removeEventListener('durationchange', onDurationChange);\n audio.removeEventListener('canplay', onCanPlay);\n audio.removeEventListener('waiting', onWaiting);\n audio.removeEventListener('playing', onPlaying);\n audio.removeEventListener('play', onPlay);\n audio.removeEventListener('pause', onPause);\n audio.removeEventListener('ended', onEnded);\n audio.removeEventListener('error', onError);\n };\n };\n\n // url 变化时重新绑定\n watch(\n url,\n () => {\n cleanup?.();\n cleanup = null;\n // 等待 DOM 更新(audio src 变化)\n requestAnimationFrame(() => bindEvents());\n },\n { flush: 'post' }\n );\n\n // 在 audioRef 挂载后首次绑定\n watch(\n audioRef,\n (el) => {\n if (el) bindEvents();\n },\n { flush: 'post' }\n );\n\n onUnmounted(() => {\n cleanup?.();\n cleanup = null;\n });\n\n const togglePlay = () => {\n const audio = audioRef.value;\n if (!audio) return;\n if (audio.paused) {\n audio.play().catch(() => {});\n } else {\n audio.pause();\n }\n };\n\n const seek = (time: number) => {\n const audio = audioRef.value;\n if (!audio) return;\n audio.currentTime = time;\n currentTime.value = time;\n };\n\n const skip = (seconds: number) => {\n const audio = audioRef.value;\n if (!audio) return;\n audio.currentTime = Math.max(\n 0,\n Math.min(audio.currentTime + seconds, audio.duration || Infinity)\n );\n };\n\n const setVolume = (vol: number) => {\n const audio = audioRef.value;\n if (!audio) return;\n const clamped = Math.max(0, Math.min(1, vol));\n audio.volume = clamped;\n volume.value = clamped;\n if (clamped > 0) {\n audio.muted = false;\n isMuted.value = false;\n }\n };\n\n const toggleMute = () => {\n const audio = audioRef.value;\n if (!audio) return;\n audio.muted = !audio.muted;\n isMuted.value = audio.muted;\n };\n\n const toggleLoop = () => {\n const audio = audioRef.value;\n if (!audio) return;\n const next = !audio.loop;\n audio.loop = next;\n isLoop.value = next;\n };\n\n return {\n audioRef,\n isPlaying,\n isLoading,\n isLoop,\n currentTime,\n duration,\n volume,\n isMuted,\n error,\n togglePlay,\n seek,\n skip,\n setVolume,\n toggleMute,\n toggleLoop,\n formatTime,\n };\n}\n","<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onBeforeUnmount, toRef } from 'vue';\nimport { Play, Pause, Volume2, VolumeX, Volume1, SkipBack, SkipForward, Repeat } from 'lucide-vue-next';\nimport { useAudioPlayer } from '../../composables/useAudioPlayer';\nimport { useTranslator } from '../../composables/useTranslator';\nimport RendererError from '../RendererError.vue';\n\nconst props = defineProps<{\n url: string;\n fileName: string;\n}>();\n\nconst urlRef = toRef(props, 'url');\n\nconst { t } = useTranslator();\n\nconst {\n audioRef,\n isPlaying,\n isLoop,\n currentTime,\n duration,\n volume,\n isMuted,\n error,\n togglePlay,\n seek,\n skip,\n setVolume,\n toggleMute,\n toggleLoop,\n formatTime,\n} = useAudioPlayer(urlRef);\n\nconst showVolume = ref(false);\nlet volumeHideTimer: number | null = null;\nconst volumeRef = ref<HTMLDivElement | null>(null);\n\nconst progress = computed(() => (duration.value > 0 ? currentTime.value / duration.value : 0));\n\nconst VolumeIcon = computed(() => {\n if (isMuted.value || volume.value === 0) return VolumeX;\n if (volume.value < 0.5) return Volume1;\n return Volume2;\n});\n\nconst handleClickOutside = (e: MouseEvent) => {\n if (volumeRef.value && !volumeRef.value.contains(e.target as Node)) {\n showVolume.value = false;\n }\n};\n\nonMounted(() => {\n document.addEventListener('mousedown', handleClickOutside);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('mousedown', handleClickOutside);\n if (volumeHideTimer !== null) clearTimeout(volumeHideTimer);\n});\n\nconst handleVolumeEnter = () => {\n if (volumeHideTimer !== null) clearTimeout(volumeHideTimer);\n showVolume.value = true;\n};\n\nconst handleVolumeLeave = () => {\n volumeHideTimer = window.setTimeout(() => {\n showVolume.value = false;\n }, 300);\n};\n</script>\n\n<template>\n <RendererError v-if=\"error\" :message=\"error\" />\n\n <div\n v-else\n class=\"vfp-flex vfp-flex-col vfp-items-center vfp-justify-center vfp-w-full vfp-h-full vfp-p-4 md:vfp-p-8 vfp-gap-5 md:vfp-gap-8 vfp-select-none\"\n >\n <!-- 唱片机 -->\n <div class=\"vfp-relative\" style=\"width: 260px; height: 240px\">\n <!-- 外圈光晕 -->\n <div\n class=\"vfp-absolute vfp-rounded-full\"\n :style=\"{\n width: '220px',\n height: '220px',\n top: '18px',\n left: '8px',\n background: 'radial-gradient(circle, rgba(129,140,248,0.12) 0%, transparent 70%)',\n opacity: isPlaying ? 0.7 : 0.2,\n transition: 'opacity 0.5s',\n }\"\n />\n\n <!-- 唱片主体 -->\n <div\n class=\"vfp-absolute vfp-rounded-full vfp-overflow-hidden\"\n :style=\"{\n width: '200px',\n height: '200px',\n top: '28px',\n left: '18px',\n background: `\n radial-gradient(circle at center, transparent 95%, rgba(30,30,30,0.8) 95.5%, #111 97%),\n radial-gradient(circle at center, transparent 38%, rgba(50,50,50,0.5) 38.15%, transparent 38.4%),\n radial-gradient(circle at center, transparent 45%, rgba(50,50,50,0.3) 45.15%, transparent 45.4%),\n radial-gradient(circle at center, transparent 52%, rgba(50,50,50,0.5) 52.15%, transparent 52.4%),\n radial-gradient(circle at center, transparent 59%, rgba(50,50,50,0.3) 59.15%, transparent 59.4%),\n radial-gradient(circle at center, transparent 66%, rgba(50,50,50,0.5) 66.15%, transparent 66.4%),\n radial-gradient(circle at center, transparent 73%, rgba(50,50,50,0.3) 73.15%, transparent 73.4%),\n radial-gradient(circle at center, transparent 80%, rgba(50,50,50,0.4) 80.15%, transparent 80.4%),\n radial-gradient(circle at center, transparent 87%, rgba(50,50,50,0.3) 87.15%, transparent 87.4%),\n conic-gradient(from 0deg, #1c1c1c, #232323, #1a1a1a, #262626, #1c1c1c, #212121, #1a1a1a, #252525, #1c1c1c, #232323, #1a1a1a, #262626, #1c1c1c)\n `,\n boxShadow: isPlaying\n ? '0 0 36px rgba(129,140,248,0.1), 0 8px 32px rgba(0,0,0,0.4), inset 0 0 20px rgba(0,0,0,0.4)'\n : '0 8px 32px rgba(0,0,0,0.4), inset 0 0 20px rgba(0,0,0,0.4)',\n animation: 'vfp-vinyl-spin 8s linear infinite',\n animationPlayState: isPlaying ? 'running' : 'paused',\n }\"\n >\n <!-- 中心标签 -->\n <div\n class=\"vfp-absolute vfp-rounded-full\"\n :style=\"{\n width: '34%',\n height: '34%',\n top: '33%',\n left: '33%',\n background: 'radial-gradient(circle at 40% 38%, #818cf8, #6366f1, #4f46e5, #4338ca)',\n boxShadow: 'inset 0 1px 3px rgba(255,255,255,0.25), inset 0 -1px 3px rgba(0,0,0,0.3), 0 0 8px rgba(0,0,0,0.3)',\n }\"\n >\n <div\n class=\"vfp-absolute vfp-rounded-full\"\n :style=\"{\n width: '14%',\n height: '14%',\n top: '43%',\n left: '43%',\n background: 'radial-gradient(circle at 40% 40%, #333, #0d0d0d)',\n boxShadow: 'inset 0 1px 3px rgba(0,0,0,0.9), 0 0 2px rgba(0,0,0,0.5)',\n }\"\n />\n </div>\n </div>\n\n <!-- 唱臂 -->\n <div\n class=\"vfp-absolute\"\n :style=\"{\n top: '-6px',\n right: '2px',\n width: '100px',\n height: '120px',\n transformOrigin: '76px 16px',\n zIndex: 5,\n transform: isPlaying ? 'rotate(16deg)' : 'rotate(0deg)',\n transition: 'transform 0.8s cubic-bezier(0.4, 0, 0.2, 1)',\n }\"\n >\n <svg width=\"100\" height=\"120\" viewBox=\"0 0 100 120\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"76\" cy=\"16\" r=\"13\" fill=\"rgba(0,0,0,0.3)\" />\n <circle cx=\"76\" cy=\"16\" r=\"11\" fill=\"url(#vfp-baseGrad)\" />\n <circle cx=\"76\" cy=\"16\" r=\"6\" fill=\"url(#vfp-baseInnerGrad)\" />\n <circle cx=\"76\" cy=\"16\" r=\"2.5\" fill=\"#222\" stroke=\"#555\" stroke-width=\"0.5\" />\n <path d=\"M74 22 L56 88\" stroke=\"url(#vfp-armGrad)\" stroke-width=\"3.5\" stroke-linecap=\"round\" />\n <rect x=\"50\" y=\"86\" width=\"12\" height=\"7\" rx=\"1.5\" fill=\"url(#vfp-headGrad)\" />\n <rect x=\"52.5\" y=\"92\" width=\"7\" height=\"9\" rx=\"1\" fill=\"url(#vfp-cartridgeGrad)\" />\n <line x1=\"56\" y1=\"101\" x2=\"56\" y2=\"105\" stroke=\"#bbb\" stroke-width=\"1.2\" stroke-linecap=\"round\" />\n <circle cx=\"56\" cy=\"105.5\" r=\"0.8\" fill=\"#ddd\" />\n\n <defs>\n <radialGradient id=\"vfp-baseGrad\" cx=\"40%\" cy=\"35%\">\n <stop offset=\"0%\" stop-color=\"#555\" />\n <stop offset=\"100%\" stop-color=\"#1a1a1a\" />\n </radialGradient>\n <radialGradient id=\"vfp-baseInnerGrad\" cx=\"40%\" cy=\"35%\">\n <stop offset=\"0%\" stop-color=\"#666\" />\n <stop offset=\"100%\" stop-color=\"#333\" />\n </radialGradient>\n <linearGradient id=\"vfp-armGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#555\" />\n <stop offset=\"50%\" stop-color=\"#444\" />\n <stop offset=\"100%\" stop-color=\"#333\" />\n </linearGradient>\n <linearGradient id=\"vfp-headGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#555\" />\n <stop offset=\"100%\" stop-color=\"#333\" />\n </linearGradient>\n <linearGradient id=\"vfp-cartridgeGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#444\" />\n <stop offset=\"100%\" stop-color=\"#222\" />\n </linearGradient>\n </defs>\n </svg>\n </div>\n </div>\n\n <!-- 文件名 -->\n <div class=\"vfp-text-center vfp-max-w-sm md:vfp-max-w-md vfp-px-4\">\n <div class=\"vfp-text-lg md:vfp-text-xl vfp-font-medium vfp-mb-1 vfp-truncate vfp-text-fg-primary\">\n {{ fileName }}\n </div>\n <p class=\"vfp-text-xs vfp-tracking-widest vfp-uppercase vfp-text-accent\">Audio</p>\n </div>\n\n <!-- 控制面板 -->\n <div\n class=\"vfp-w-full vfp-max-w-sm md:vfp-max-w-md vfp-rounded-2xl vfp-p-4 md:vfp-p-6 vfp-border vfp-bg-surface-1 vfp-border-line-weak\"\n :style=\"{ backdropFilter: 'blur(16px)' }\"\n >\n <!-- 进度条 -->\n <div class=\"vfp-mb-5\">\n <div class=\"vfp-relative vfp-h-4 vfp-flex vfp-items-center\">\n <div\n class=\"vfp-absolute vfp-w-full vfp-h-[5px] vfp-rounded-full vfp-bg-surface-2\"\n />\n <div\n class=\"vfp-absolute vfp-h-[5px] vfp-rounded-full vfp-pointer-events-none\"\n :style=\"{\n width: `${progress * 100}%`,\n background: 'linear-gradient(90deg, var(--fp-accent), var(--fp-accent-hover))',\n boxShadow: isPlaying ? '0 0 8px rgba(129,140,248,0.4)' : 'none',\n transition: 'width 0.1s linear',\n }\"\n />\n <input\n type=\"range\"\n min=\"0\"\n :max=\"duration > 0 ? duration : currentTime || 100\"\n step=\"any\"\n :value=\"currentTime\"\n :disabled=\"duration <= 0\"\n :aria-label=\"t('audio.aria.progress')\"\n class=\"audio-slider vfp-absolute vfp-w-full\"\n @input=\"(e) => seek(parseFloat((e.target as HTMLInputElement).value))\"\n />\n </div>\n <div\n class=\"vfp-flex vfp-justify-between vfp-text-xs vfp-mt-2.5 vfp-text-fg-tertiary\"\n >\n <span style=\"font-variant-numeric: tabular-nums\">{{ formatTime(currentTime) }}</span>\n <span style=\"font-variant-numeric: tabular-nums\">{{ duration > 0 ? formatTime(duration) : '--:--' }}</span>\n </div>\n </div>\n\n <!-- 控制按钮 -->\n <div class=\"vfp-flex vfp-items-center vfp-justify-center vfp-gap-3\">\n <!-- 循环 -->\n <button\n :class=\"[\n 'vfp-w-9 vfp-h-9 vfp-rounded-full vfp-flex vfp-items-center vfp-justify-center vfp-transition-colors audio-ctrl-btn',\n isLoop ? 'vfp-bg-accent-soft vfp-text-accent' : 'vfp-bg-surface-2 vfp-text-fg-tertiary',\n ]\"\n :aria-label=\"isLoop ? t('audio.aria.loop_off') : t('audio.aria.loop_on')\"\n @click=\"toggleLoop\"\n >\n <Repeat class=\"vfp-w-4 vfp-h-4\" />\n </button>\n\n <!-- 后退 -->\n <button\n class=\"vfp-w-10 vfp-h-10 vfp-rounded-full vfp-flex vfp-items-center vfp-justify-center vfp-transition-colors audio-ctrl-btn vfp-bg-surface-2 vfp-text-fg-secondary\"\n :aria-label=\"t('audio.aria.backward_10')\"\n @click=\"skip(-10)\"\n >\n <SkipBack class=\"vfp-w-[18px] vfp-h-[18px]\" />\n </button>\n\n <!-- 播放/暂停 -->\n <button\n class=\"vfp-w-14 vfp-h-14 vfp-rounded-full vfp-flex vfp-items-center vfp-justify-center audio-ctrl-btn\"\n :style=\"{\n background: 'linear-gradient(135deg, var(--fp-accent-hover), var(--fp-accent))',\n color: '#fff',\n boxShadow: '0 4px 20px rgba(99,102,241,0.35)',\n }\"\n :aria-label=\"isPlaying ? t('audio.aria.pause') : t('audio.aria.play')\"\n @click=\"togglePlay\"\n >\n <Pause v-if=\"isPlaying\" class=\"vfp-w-6 vfp-h-6\" />\n <Play v-else class=\"vfp-w-6 vfp-h-6 vfp-ml-0.5\" />\n </button>\n\n <!-- 前进 -->\n <button\n class=\"vfp-w-10 vfp-h-10 vfp-rounded-full vfp-flex vfp-items-center vfp-justify-center vfp-transition-colors audio-ctrl-btn vfp-bg-surface-2 vfp-text-fg-secondary\"\n :aria-label=\"t('audio.aria.forward_10')\"\n @click=\"skip(10)\"\n >\n <SkipForward class=\"vfp-w-[18px] vfp-h-[18px]\" />\n </button>\n\n <!-- 音量 -->\n <div ref=\"volumeRef\" class=\"vfp-relative\" @mouseenter=\"handleVolumeEnter\" @mouseleave=\"handleVolumeLeave\">\n <button\n :class=\"[\n 'vfp-w-9 vfp-h-9 vfp-rounded-full vfp-flex vfp-items-center vfp-justify-center vfp-transition-colors audio-ctrl-btn',\n showVolume ? 'vfp-bg-accent-soft vfp-text-accent' : 'vfp-bg-surface-2 vfp-text-fg-secondary',\n ]\"\n :aria-label=\"isMuted ? t('audio.aria.unmute') : t('audio.aria.mute')\"\n @click=\"toggleMute\"\n >\n <component :is=\"VolumeIcon\" class=\"vfp-w-4 vfp-h-4\" />\n </button>\n\n <Transition name=\"vfp-fade\">\n <div\n v-if=\"showVolume\"\n class=\"vfp-absolute vfp-bottom-full vfp-mb-2 vfp-rounded-xl vfp-p-3 vfp-border vfp-bg-surface-3 vfp-border-line\"\n :style=\"{\n left: '50%',\n marginLeft: '-27px',\n backdropFilter: 'blur(16px)',\n }\"\n @mouseenter=\"handleVolumeEnter\"\n @mouseleave=\"handleVolumeLeave\"\n >\n <div class=\"vfp-flex vfp-flex-col vfp-items-center vfp-gap-2\" style=\"height: 100px\">\n <div\n class=\"vfp-relative vfp-flex vfp-items-center vfp-justify-center\"\n style=\"width: 24px; height: 80px\"\n >\n <div\n class=\"vfp-absolute vfp-rounded-full vfp-bg-surface-2\"\n style=\"width: 3px; height: 100%\"\n />\n <div\n class=\"vfp-absolute vfp-bottom-0 vfp-rounded-full vfp-pointer-events-none\"\n :style=\"{\n width: '3px',\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background: 'var(--fp-accent-hover)',\n transition: 'height 0.1s linear',\n }\"\n />\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.01\"\n :value=\"isMuted ? 0 : volume\"\n :aria-label=\"t('audio.aria.volume')\"\n class=\"volume-slider-vertical vfp-absolute\"\n style=\"width: 80px; height: 24px; transform: rotate(-90deg); transform-origin: center center\"\n @input=\"(e) => setVolume(parseFloat((e.target as HTMLInputElement).value))\"\n />\n </div>\n <span class=\"vfp-text-[10px] vfp-tabular-nums vfp-text-fg-tertiary\">\n {{ Math.round((isMuted ? 0 : volume) * 100) }}\n </span>\n </div>\n </div>\n </Transition>\n </div>\n </div>\n </div>\n\n <audio ref=\"audioRef\" :src=\"url\" class=\"vfp-hidden\" />\n </div>\n</template>\n\n<style scoped>\n.audio-ctrl-btn {\n border: 0;\n cursor: pointer;\n}\n</style>\n"],"names":["useAudioPlayer","url","audioRef","ref","isPlaying","isLoading","currentTime","duration","volume","isMuted","isLoop","error","cleanup","bindEvents","audio","onTimeUpdate","onDurationChange","onCanPlay","onWaiting","onPlaying","onPlay","onPause","onEnded","onError","watch","el","onUnmounted","time","seconds","vol","clamped","next","formatTime","urlRef","toRef","__props","t","useTranslator","togglePlay","seek","skip","setVolume","toggleMute","toggleLoop","showVolume","volumeHideTimer","volumeRef","progress","computed","VolumeIcon","VolumeX","Volume1","Volume2","handleClickOutside","e","onMounted","onBeforeUnmount","handleVolumeEnter","handleVolumeLeave","_unref","_createBlock","RendererError","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_normalizeStyle","_hoisted_3","_hoisted_4","_toDisplayString","_cache","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_normalizeClass","args","_createVNode","Repeat","SkipBack","Pause","Play","SkipForward","_resolveDynamicComponent","_Transition","_hoisted_18","_hoisted_19","_hoisted_21"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineComponent as P, ref as y, watch as S, computed as h, openBlock as a, createElementBlock as r, createElementVNode as e, createBlock as V, unref as c, normalizeClass as b, Fragment as w, renderList as k, toDisplayString as o, createCommentVNode as N } from "vue";
|
|
2
|
-
import { u as j, a as z, P as A, N as d, E as D, _ as I } from "./index-
|
|
2
|
+
import { u as j, a as z, P as A, N as d, E as D, _ as I } from "./index-Oxwizt6-.mjs";
|
|
3
3
|
import { _ as M } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
|
|
4
4
|
const O = {
|
|
5
5
|
key: 0,
|
|
@@ -111,4 +111,4 @@ const O = {
|
|
|
111
111
|
export {
|
|
112
112
|
re as default
|
|
113
113
|
};
|
|
114
|
-
//# sourceMappingURL=index-
|
|
114
|
+
//# sourceMappingURL=index-CYt6tpQC.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-C65zV1vs.mjs","sources":["../../src/renderers/Subtitle/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, watch } from 'vue';\nimport {\n parseSubtitle,\n formatSubtitleTime,\n fetchTextUtf8,\n type SubtitleParseResult,\n type SubtitleFormat,\n} from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport RendererError from '../RendererError.vue';\n\nconst props = defineProps<{\n url: string;\n fileName: string;\n}>();\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\n\nconst text = ref<string>('');\nconst loading = ref(true);\nconst error = ref<string | null>(null);\n\nconst FORMAT_BY_EXT: Record<string, SubtitleFormat> = {\n srt: 'srt',\n vtt: 'vtt',\n lrc: 'lrc',\n elrc: 'elrc',\n ass: 'ass',\n ssa: 'ssa',\n ttml: 'ttml',\n dfxp: 'ttml',\n};\n\nconst getFormat = (fileName: string): SubtitleFormat | undefined => {\n const ext = fileName.split('.').pop()?.toLowerCase() || '';\n return FORMAT_BY_EXT[ext];\n};\n\nconst load = async () => {\n loading.value = true;\n error.value = null;\n try {\n text.value = await fetchTextUtf8(props.url, { fetcher: fetcher.value });\n } catch (err) {\n console.error(err);\n error.value = t.value('subtitle.load_failed');\n } finally {\n loading.value = false;\n }\n};\n\nwatch(() => props.url, load, { immediate: true });\n\nconst parsed = computed<SubtitleParseResult | null>(() => {\n if (!text.value) return null;\n try {\n return parseSubtitle(text.value, getFormat(props.fileName));\n } catch (err) {\n console.error(err);\n return null;\n }\n});\n\nconst isLyric = computed(() => parsed.value?.format === 'lrc' || parsed.value?.format === 'elrc');\n\nconst meta = computed<Record<string, string>>(() => parsed.value?.metadata ?? {});\n\nconst wordTimeShort = (t: number) => formatSubtitleTime(t).slice(3, 8);\n</script>\n\n<template>\n <div\n v-if=\"loading\"\n class=\"vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full vfp-bg-[#0f0f12]\"\n >\n <div\n class=\"vfp-w-12 vfp-h-12 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\"\n />\n </div>\n\n <RendererError\n v-else-if=\"error || !parsed\"\n :message=\"error || t('subtitle.parse_failed')\"\n class=\"vfp-bg-[#0f0f12]\"\n />\n\n <div\n v-else\n class=\"vfp-relative vfp-w-full vfp-h-full vfp-bg-[#0f0f12]\"\n :class=\"isLyric ? 'flavor-lyric' : 'flavor-subtitle'\"\n >\n <!-- 内容滚动区 -->\n <div class=\"content-scroll\">\n <div class=\"timeline\">\n <div class=\"timeline-line\" />\n <ol class=\"cues\">\n <li v-for=\"(cue, i) in parsed.cues\" :key=\"'cue-' + i\" class=\"cue-row\">\n <div class=\"cue-dot\" />\n <div class=\"cue-meta\">\n <span class=\"cue-time\">{{ formatSubtitleTime(cue.start) }}</span>\n <span class=\"cue-arrow\">→</span>\n <span class=\"cue-time\">{{ formatSubtitleTime(cue.end) }}</span>\n <span class=\"cue-id\">#{{ cue.id ?? i + 1 }}</span>\n <span v-if=\"cue.style\" class=\"cue-style\">{{ cue.style }}</span>\n </div>\n <div v-if=\"cue.words && cue.words.length > 0\" class=\"cue-words\">\n <span\n v-for=\"(word, wi) in cue.words\"\n :key=\"'w-' + wi\"\n class=\"cue-word\"\n :title=\"formatSubtitleTime(word.start)\"\n >\n <span class=\"cue-word-time\">{{ wordTimeShort(word.start) }}</span>\n <span class=\"cue-word-text\">{{ word.text }}</span>\n </span>\n </div>\n <p v-else class=\"cue-text\" :class=\"{ lyric: isLyric }\">{{ cue.text }}</p>\n </li>\n </ol>\n </div>\n </div>\n\n <!-- 右下角浮签 -->\n <div class=\"status-pill\">\n <span>{{ parsed.cues.length }} {{ isLyric ? t('subtitle.lines') : t('subtitle.cues') }}</span>\n <template v-if=\"meta.length\">\n <span class=\"dot\">·</span>\n <span>{{ meta.length }}</span>\n </template>\n </div>\n </div>\n</template>\n\n<style scoped>\n.content-scroll {\n width: 100%;\n height: 100%;\n overflow: auto;\n padding: 1.5rem 1.5rem 4rem;\n}\n@media (min-width: 768px) {\n .content-scroll {\n padding: 1.5rem 2.5rem 5rem;\n }\n}\n.status-pill {\n pointer-events: none;\n position: absolute;\n bottom: 0.75rem;\n right: 0.75rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.25rem 0.625rem;\n border-radius: 9999px;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(8px);\n border: 1px solid var(--fp-line);\n font-size: 0.625rem;\n color: var(--fp-fg-tertiary);\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n font-variant-numeric: tabular-nums;\n}\n@media (min-width: 768px) {\n .status-pill {\n bottom: 1rem;\n right: 1rem;\n }\n}\n.dot {\n color: var(--fp-fg-disabled);\n}\n\n.timeline {\n position: relative;\n max-width: 64rem;\n margin: 0 auto;\n}\n.timeline-line {\n position: absolute;\n left: 5px;\n top: 0.5rem;\n bottom: 0.5rem;\n width: 1px;\n background: var(--fp-line-weak);\n}\n@media (min-width: 768px) {\n .timeline-line {\n left: 7px;\n }\n}\n.cues {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 1.25rem;\n}\n@media (min-width: 768px) {\n .cues {\n gap: 1.5rem;\n }\n}\n.cue-row {\n position: relative;\n padding-left: 1.5rem;\n}\n@media (min-width: 768px) {\n .cue-row {\n padding-left: 2rem;\n }\n}\n.cue-dot {\n position: absolute;\n left: 0;\n top: 0.5rem;\n width: 0.75rem;\n height: 0.75rem;\n border-radius: 9999px;\n background: var(--fp-surface-3);\n border: 2px solid #0f0f12;\n transition: background-color 0.2s;\n}\n.flavor-lyric .cue-row:hover .cue-dot {\n background: rgb(167, 139, 250);\n}\n.flavor-subtitle .cue-row:hover .cue-dot {\n background: rgb(56, 189, 248);\n}\n.cue-meta {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 0.25rem 0.75rem;\n margin-bottom: 0.375rem;\n}\n.cue-time {\n font-size: 0.6875rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n color: var(--fp-fg-muted);\n font-variant-numeric: tabular-nums;\n}\n.cue-arrow {\n font-size: 0.6875rem;\n color: var(--fp-fg-disabled);\n}\n.cue-id {\n font-size: 0.625rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n color: var(--fp-fg-disabled);\n font-variant-numeric: tabular-nums;\n}\n.cue-style {\n font-size: 0.5625rem;\n text-transform: uppercase;\n letter-spacing: 0.1em;\n color: var(--fp-fg-tertiary);\n padding: 0.125rem 0.375rem;\n border-radius: 0.25rem;\n background: var(--fp-line-weak);\n border: 1px solid var(--fp-line);\n}\n.cue-text {\n margin: 0;\n white-space: pre-wrap;\n word-break: break-word;\n line-height: 1.625;\n color: var(--fp-fg-primary);\n font-size: 0.875rem;\n transition: color 0.2s;\n}\n@media (min-width: 768px) {\n .cue-text {\n font-size: 1rem;\n }\n}\n.cue-text.lyric {\n font-size: 1rem;\n font-weight: 500;\n}\n@media (min-width: 768px) {\n .cue-text.lyric {\n font-size: 1.25rem;\n }\n}\n.cue-row:hover .cue-text {\n color: #fff;\n}\n.cue-words {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem 0.375rem;\n font-size: 1rem;\n color: var(--fp-fg-primary);\n line-height: 1.625;\n transition: color 0.2s;\n}\n@media (min-width: 768px) {\n .cue-words {\n font-size: 1.125rem;\n }\n}\n.cue-row:hover .cue-words {\n color: #fff;\n}\n.cue-word {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n}\n.cue-word-time {\n font-size: 0.5625rem;\n color: var(--fp-fg-disabled);\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n line-height: 1;\n font-variant-numeric: tabular-nums;\n}\n.cue-word-text {\n line-height: 1.4;\n}\n</style>\n"],"names":["props","__props","t","useTranslator","fetcher","useFetcher","text","ref","loading","error","FORMAT_BY_EXT","getFormat","fileName","ext","_a","watch","fetchTextUtf8","err","parsed","computed","parseSubtitle","isLyric","_b","meta","wordTimeShort","formatSubtitleTime","_openBlock","_createElementBlock","_hoisted_1","_cache","_createElementVNode","_createBlock","RendererError","_unref","_normalizeClass","_hoisted_2","_hoisted_3","_hoisted_4","_Fragment","cue","i","_hoisted_5","_hoisted_6","_toDisplayString","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","word","wi","_hoisted_12","_hoisted_13","_hoisted_14"],"mappings":";;;;;;;;;;;;;;;;;;;AAaA,UAAMA,IAAQC,GAKR,EAAE,GAAAC,EAAA,IAAMC,EAAA,GACRC,IAAUC,EAAA,GAEVC,IAAOC,EAAY,EAAE,GACrBC,IAAUD,EAAI,EAAI,GAClBE,IAAQF,EAAmB,IAAI,GAE/BG,IAAgD;AAAA,MACpD,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,IAAA,GAGFC,IAAY,CAACC,MAAiD;;AAClE,YAAMC,MAAMC,IAAAF,EAAS,MAAM,GAAG,EAAE,IAAA,MAApB,gBAAAE,EAA2B,kBAAiB;AACxD,aAAOJ,EAAcG,CAAG;AAAA,IAC1B;AAeA,IAAAE,EAAM,MAAMf,EAAM,KAbL,YAAY;AACvB,MAAAQ,EAAQ,QAAQ,IAChBC,EAAM,QAAQ;AACd,UAAI;AACF,QAAAH,EAAK,QAAQ,MAAMU,EAAchB,EAAM,KAAK,EAAE,SAASI,EAAQ,OAAO;AAAA,MACxE,SAASa,GAAK;AACZ,gBAAQ,MAAMA,CAAG,GACjBR,EAAM,QAAQP,EAAE,MAAM,sBAAsB;AAAA,MAC9C,UAAA;AACE,QAAAM,EAAQ,QAAQ;AAAA,MAClB;AAAA,IACF,GAE6B,EAAE,WAAW,IAAM;AAEhD,UAAMU,IAASC,EAAqC,MAAM;AACxD,UAAI,CAACb,EAAK,MAAO,QAAO;AACxB,UAAI;AACF,eAAOc,EAAcd,EAAK,OAAOK,EAAUX,EAAM,QAAQ,CAAC;AAAA,MAC5D,SAASiB,GAAK;AACZ,uBAAQ,MAAMA,CAAG,GACV;AAAA,MACT;AAAA,IACF,CAAC,GAEKI,IAAUF,EAAS,MAAA;;AAAM,eAAAL,IAAAI,EAAO,UAAP,gBAAAJ,EAAc,YAAW,WAASQ,IAAAJ,EAAO,UAAP,gBAAAI,EAAc,YAAW;AAAA,KAAM,GAE1FC,IAAOJ,EAAiC,MAAA;;AAAM,eAAAL,IAAAI,EAAO,UAAP,gBAAAJ,EAAc,aAAY;KAAE,GAE1EU,IAAgB,CAACtB,MAAcuB,EAAmBvB,CAAC,EAAE,MAAM,GAAG,CAAC;qBAK3DM,EAAA,SADRkB,EAAA,GAAAC,EAOM,OAPNC,GAOM,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,MAHJC,EAEE,OAAA,EADA,OAAM,oHAAA,GAAmH,MAAA,EAAA;AAAA,IAAA,QAKhHrB,EAAA,UAAUS,EAAA,cADvBa,EAIEC,GAAA;AAAA;MAFC,SAASvB,EAAA,SAASwB,EAAA/B,CAAA,EAAC,uBAAA;AAAA,MACpB,OAAM;AAAA,IAAA,kCAGRyB,EA4CM,OAAA;AAAA;MA1CJ,OAAKO,EAAA,CAAC,uDACEb,EAAA,QAAO,iBAAA,iBAAA,CAAA;AAAA,IAAA;MAGfS,EA4BM,OA5BNK,GA4BM;AAAA,QA3BJL,EA0BM,OA1BNM,GA0BM;AAAA,0BAzBJN,EAA6B,OAAA,EAAxB,OAAM,gBAAA,GAAe,MAAA,EAAA;AAAA,UAC1BA,EAuBK,MAvBLO,GAuBK;AAAA,aAtBHX,EAAA,EAAA,GAAAC,EAqBKW,WArBkBpB,EAAA,MAAO,MAAI,CAAtBqB,GAAKC,YAAjBb,EAqBK,MAAA;AAAA,cArBgC,cAAca;AAAA,cAAG,OAAM;AAAA,YAAA;8BAC1DV,EAAuB,OAAA,EAAlB,OAAM,UAAA,GAAS,MAAA,EAAA;AAAA,cACpBA,EAMM,OANNW,GAMM;AAAA,gBALJX,EAAiE,QAAjEY,GAAiEC,EAAvCV,KAAmBM,EAAI,KAAK,CAAA,GAAA,CAAA;AAAA,gBACtDV,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAC,EAAgC,QAAA,EAA1B,OAAM,YAAA,GAAY,KAAC,EAAA;AAAA,gBACzBA,EAA+D,QAA/Dc,GAA+DD,EAArCV,KAAmBM,EAAI,GAAG,CAAA,GAAA,CAAA;AAAA,gBACpDT,EAAkD,QAAlDe,GAAqB,QAAIN,EAAI,MAAMC,IAAC,CAAA,GAAA,CAAA;AAAA,gBACxBD,EAAI,SAAhBb,EAAA,GAAAC,EAA+D,QAA/DmB,GAA+DH,EAAnBJ,EAAI,KAAK,GAAA,CAAA;;cAE5CA,EAAI,SAASA,EAAI,MAAM,SAAM,KAAxCb,KAAAC,EAUM,OAVNoB,GAUM;AAAA,iBATJrB,EAAA,EAAA,GAAAC,EAQOW,WAPgBC,EAAI,OAAK,CAAtBS,GAAMC,YADhBtB,EAQO,QAAA;AAAA,kBANJ,YAAYsB;AAAA,kBACb,OAAM;AAAA,kBACL,OAAOhB,EAAAR,CAAA,EAAmBuB,EAAK,KAAK;AAAA,gBAAA;kBAErClB,EAAkE,QAAlEoB,GAAkEP,EAAnCnB,EAAcwB,EAAK,KAAK,CAAA,GAAA,CAAA;AAAA,kBACvDlB,EAAkD,QAAlDqB,GAAkDR,EAAnBK,EAAK,IAAI,GAAA,CAAA;AAAA,gBAAA;0BAG5CrB,EAAyE,KAAA;AAAA;gBAA/D,OAAKO,EAAA,CAAC,YAAU,EAAA,OAAkBb,EAAA,OAAO,CAAA;AAAA,cAAA,GAAOsB,EAAAJ,EAAI,IAAI,GAAA,CAAA;AAAA,YAAA;;;;MAO1ET,EAMM,OANNsB,GAMM;AAAA,QALJtB,EAA8F,QAAA,MAAAa,EAArFzB,EAAA,MAAO,KAAK,MAAM,IAAG,MAACyB,EAAGtB,EAAA,QAAUY,EAAA/B,CAAA,sBAAsB+B,EAAA/B,CAAA,EAAC,eAAA,CAAA,GAAA,CAAA;AAAA,QACnDqB,EAAA,MAAK,eAArBI,EAGWW,GAAA,EAAA,KAAA,KAAA;AAAA,UAFTT,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAC,EAA0B,QAAA,EAApB,OAAM,MAAA,GAAM,KAAC,EAAA;AAAA,UACnBA,EAA8B,QAAA,MAAAa,EAArBpB,EAAA,MAAK,MAAM,GAAA,CAAA;AAAA,QAAA;;;;;"}
|
|
1
|
+
{"version":3,"file":"index-CYt6tpQC.mjs","sources":["../../src/renderers/Subtitle/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, watch } from 'vue';\nimport {\n parseSubtitle,\n formatSubtitleTime,\n fetchTextUtf8,\n type SubtitleParseResult,\n type SubtitleFormat,\n} from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport RendererError from '../RendererError.vue';\n\nconst props = defineProps<{\n url: string;\n fileName: string;\n}>();\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\n\nconst text = ref<string>('');\nconst loading = ref(true);\nconst error = ref<string | null>(null);\n\nconst FORMAT_BY_EXT: Record<string, SubtitleFormat> = {\n srt: 'srt',\n vtt: 'vtt',\n lrc: 'lrc',\n elrc: 'elrc',\n ass: 'ass',\n ssa: 'ssa',\n ttml: 'ttml',\n dfxp: 'ttml',\n};\n\nconst getFormat = (fileName: string): SubtitleFormat | undefined => {\n const ext = fileName.split('.').pop()?.toLowerCase() || '';\n return FORMAT_BY_EXT[ext];\n};\n\nconst load = async () => {\n loading.value = true;\n error.value = null;\n try {\n text.value = await fetchTextUtf8(props.url, { fetcher: fetcher.value });\n } catch (err) {\n console.error(err);\n error.value = t.value('subtitle.load_failed');\n } finally {\n loading.value = false;\n }\n};\n\nwatch(() => props.url, load, { immediate: true });\n\nconst parsed = computed<SubtitleParseResult | null>(() => {\n if (!text.value) return null;\n try {\n return parseSubtitle(text.value, getFormat(props.fileName));\n } catch (err) {\n console.error(err);\n return null;\n }\n});\n\nconst isLyric = computed(() => parsed.value?.format === 'lrc' || parsed.value?.format === 'elrc');\n\nconst meta = computed<Record<string, string>>(() => parsed.value?.metadata ?? {});\n\nconst wordTimeShort = (t: number) => formatSubtitleTime(t).slice(3, 8);\n</script>\n\n<template>\n <div\n v-if=\"loading\"\n class=\"vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full vfp-bg-[#0f0f12]\"\n >\n <div\n class=\"vfp-w-12 vfp-h-12 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\"\n />\n </div>\n\n <RendererError\n v-else-if=\"error || !parsed\"\n :message=\"error || t('subtitle.parse_failed')\"\n class=\"vfp-bg-[#0f0f12]\"\n />\n\n <div\n v-else\n class=\"vfp-relative vfp-w-full vfp-h-full vfp-bg-[#0f0f12]\"\n :class=\"isLyric ? 'flavor-lyric' : 'flavor-subtitle'\"\n >\n <!-- 内容滚动区 -->\n <div class=\"content-scroll\">\n <div class=\"timeline\">\n <div class=\"timeline-line\" />\n <ol class=\"cues\">\n <li v-for=\"(cue, i) in parsed.cues\" :key=\"'cue-' + i\" class=\"cue-row\">\n <div class=\"cue-dot\" />\n <div class=\"cue-meta\">\n <span class=\"cue-time\">{{ formatSubtitleTime(cue.start) }}</span>\n <span class=\"cue-arrow\">→</span>\n <span class=\"cue-time\">{{ formatSubtitleTime(cue.end) }}</span>\n <span class=\"cue-id\">#{{ cue.id ?? i + 1 }}</span>\n <span v-if=\"cue.style\" class=\"cue-style\">{{ cue.style }}</span>\n </div>\n <div v-if=\"cue.words && cue.words.length > 0\" class=\"cue-words\">\n <span\n v-for=\"(word, wi) in cue.words\"\n :key=\"'w-' + wi\"\n class=\"cue-word\"\n :title=\"formatSubtitleTime(word.start)\"\n >\n <span class=\"cue-word-time\">{{ wordTimeShort(word.start) }}</span>\n <span class=\"cue-word-text\">{{ word.text }}</span>\n </span>\n </div>\n <p v-else class=\"cue-text\" :class=\"{ lyric: isLyric }\">{{ cue.text }}</p>\n </li>\n </ol>\n </div>\n </div>\n\n <!-- 右下角浮签 -->\n <div class=\"status-pill\">\n <span>{{ parsed.cues.length }} {{ isLyric ? t('subtitle.lines') : t('subtitle.cues') }}</span>\n <template v-if=\"meta.length\">\n <span class=\"dot\">·</span>\n <span>{{ meta.length }}</span>\n </template>\n </div>\n </div>\n</template>\n\n<style scoped>\n.content-scroll {\n width: 100%;\n height: 100%;\n overflow: auto;\n padding: 1.5rem 1.5rem 4rem;\n}\n@media (min-width: 768px) {\n .content-scroll {\n padding: 1.5rem 2.5rem 5rem;\n }\n}\n.status-pill {\n pointer-events: none;\n position: absolute;\n bottom: 0.75rem;\n right: 0.75rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.25rem 0.625rem;\n border-radius: 9999px;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(8px);\n border: 1px solid var(--fp-line);\n font-size: 0.625rem;\n color: var(--fp-fg-tertiary);\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n font-variant-numeric: tabular-nums;\n}\n@media (min-width: 768px) {\n .status-pill {\n bottom: 1rem;\n right: 1rem;\n }\n}\n.dot {\n color: var(--fp-fg-disabled);\n}\n\n.timeline {\n position: relative;\n max-width: 64rem;\n margin: 0 auto;\n}\n.timeline-line {\n position: absolute;\n left: 5px;\n top: 0.5rem;\n bottom: 0.5rem;\n width: 1px;\n background: var(--fp-line-weak);\n}\n@media (min-width: 768px) {\n .timeline-line {\n left: 7px;\n }\n}\n.cues {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 1.25rem;\n}\n@media (min-width: 768px) {\n .cues {\n gap: 1.5rem;\n }\n}\n.cue-row {\n position: relative;\n padding-left: 1.5rem;\n}\n@media (min-width: 768px) {\n .cue-row {\n padding-left: 2rem;\n }\n}\n.cue-dot {\n position: absolute;\n left: 0;\n top: 0.5rem;\n width: 0.75rem;\n height: 0.75rem;\n border-radius: 9999px;\n background: var(--fp-surface-3);\n border: 2px solid #0f0f12;\n transition: background-color 0.2s;\n}\n.flavor-lyric .cue-row:hover .cue-dot {\n background: rgb(167, 139, 250);\n}\n.flavor-subtitle .cue-row:hover .cue-dot {\n background: rgb(56, 189, 248);\n}\n.cue-meta {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 0.25rem 0.75rem;\n margin-bottom: 0.375rem;\n}\n.cue-time {\n font-size: 0.6875rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n color: var(--fp-fg-muted);\n font-variant-numeric: tabular-nums;\n}\n.cue-arrow {\n font-size: 0.6875rem;\n color: var(--fp-fg-disabled);\n}\n.cue-id {\n font-size: 0.625rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n color: var(--fp-fg-disabled);\n font-variant-numeric: tabular-nums;\n}\n.cue-style {\n font-size: 0.5625rem;\n text-transform: uppercase;\n letter-spacing: 0.1em;\n color: var(--fp-fg-tertiary);\n padding: 0.125rem 0.375rem;\n border-radius: 0.25rem;\n background: var(--fp-line-weak);\n border: 1px solid var(--fp-line);\n}\n.cue-text {\n margin: 0;\n white-space: pre-wrap;\n word-break: break-word;\n line-height: 1.625;\n color: var(--fp-fg-primary);\n font-size: 0.875rem;\n transition: color 0.2s;\n}\n@media (min-width: 768px) {\n .cue-text {\n font-size: 1rem;\n }\n}\n.cue-text.lyric {\n font-size: 1rem;\n font-weight: 500;\n}\n@media (min-width: 768px) {\n .cue-text.lyric {\n font-size: 1.25rem;\n }\n}\n.cue-row:hover .cue-text {\n color: #fff;\n}\n.cue-words {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem 0.375rem;\n font-size: 1rem;\n color: var(--fp-fg-primary);\n line-height: 1.625;\n transition: color 0.2s;\n}\n@media (min-width: 768px) {\n .cue-words {\n font-size: 1.125rem;\n }\n}\n.cue-row:hover .cue-words {\n color: #fff;\n}\n.cue-word {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n}\n.cue-word-time {\n font-size: 0.5625rem;\n color: var(--fp-fg-disabled);\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n line-height: 1;\n font-variant-numeric: tabular-nums;\n}\n.cue-word-text {\n line-height: 1.4;\n}\n</style>\n"],"names":["props","__props","t","useTranslator","fetcher","useFetcher","text","ref","loading","error","FORMAT_BY_EXT","getFormat","fileName","ext","_a","watch","fetchTextUtf8","err","parsed","computed","parseSubtitle","isLyric","_b","meta","wordTimeShort","formatSubtitleTime","_openBlock","_createElementBlock","_hoisted_1","_cache","_createElementVNode","_createBlock","RendererError","_unref","_normalizeClass","_hoisted_2","_hoisted_3","_hoisted_4","_Fragment","cue","i","_hoisted_5","_hoisted_6","_toDisplayString","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","word","wi","_hoisted_12","_hoisted_13","_hoisted_14"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent as M, ref as y, onMounted as R, watch as W, onBeforeUnmount as F, openBlock as g, createElementBlock as b, createElementVNode as _, toDisplayString as L, unref as B, createCommentVNode as E, createBlock as P, normalizeStyle as q } from "vue";
|
|
2
2
|
import { init as T } from "pptx-preview";
|
|
3
|
-
import { u as A, a as H } from "./index-
|
|
3
|
+
import { u as A, a as H } from "./index-Oxwizt6-.mjs";
|
|
4
4
|
import { _ as I } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
|
|
5
5
|
const N = { class: "vfp-relative vfp-flex vfp-flex-col vfp-items-center vfp-w-full vfp-h-full" }, O = {
|
|
6
6
|
key: 0,
|
|
@@ -137,4 +137,4 @@ const N = { class: "vfp-relative vfp-flex vfp-flex-col vfp-items-center vfp-w-fu
|
|
|
137
137
|
export {
|
|
138
138
|
J as default
|
|
139
139
|
};
|
|
140
|
-
//# sourceMappingURL=index-
|
|
140
|
+
//# sourceMappingURL=index-Cjnw238n.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-t1Plo3ud.mjs","sources":["../../src/renderers/Pptx/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount } from 'vue';\nimport { init } from 'pptx-preview';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport RendererError from '../RendererError.vue';\n\nconst props = withDefaults(\n defineProps<{\n url: string;\n tiled?: boolean;\n }>(),\n { tiled: true }\n);\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\n\nconst loading = ref(true);\nconst error = ref<string | null>(null);\nconst slideCount = ref(0);\nconst containerRef = ref<HTMLDivElement | null>(null);\nlet previewer: ReturnType<typeof init> | null = null;\nlet resizeObserver: ResizeObserver | null = null;\nlet arrayBufferRef: ArrayBuffer | null = null;\nlet resizeTimeout: number | null = null;\nlet lastDimensions = { width: 0, height: 0 };\n\nconst calculateDimensions = () => {\n if (!containerRef.value) return { width: 960, height: 540 };\n const rawWidth = containerRef.value.clientWidth;\n const parentWidth = containerRef.value.parentElement?.clientWidth || 0;\n const containerWidth = rawWidth > 100 ? rawWidth : parentWidth > 100 ? parentWidth : 300;\n const height = Math.floor((containerWidth * 9) / 16);\n return { width: containerWidth, height };\n};\n\nconst reinitializePreviewer = async () => {\n if (!containerRef.value || !arrayBufferRef || slideCount.value === 0) return;\n\n try {\n if (previewer) {\n try {\n previewer.destroy();\n } catch {\n // ignore\n }\n }\n\n containerRef.value.innerHTML = '';\n\n const currentDimensions = calculateDimensions();\n previewer = init(containerRef.value, {\n width: currentDimensions.width,\n height: props.tiled ? currentDimensions.height * slideCount.value : currentDimensions.height,\n mode: props.tiled ? 'list' : 'slide',\n });\n\n await previewer.preview(arrayBufferRef);\n } catch {\n // 静默处理\n }\n};\n\nconst loadPptx = async () => {\n if (!containerRef.value) return;\n\n loading.value = true;\n error.value = null;\n\n let timeoutId: number | null = window.setTimeout(() => {\n error.value = t.value('pptx.timeout');\n loading.value = false;\n }, 30000);\n\n try {\n const response = await fetcher.value(props.url, {\n mode: 'cors',\n credentials: 'omit',\n redirect: 'follow',\n });\n\n if (!response.ok) {\n if (response.status === 404) throw new Error(t.value('pptx.not_found'));\n if (response.status === 403) throw new Error('无权限访问此文件');\n if (response.status >= 500) throw new Error('服务器错误,请稍后重试');\n throw new Error(`文件加载失败 (${response.status})`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n if (arrayBuffer.byteLength === 0) throw new Error('文件为空');\n\n arrayBufferRef = arrayBuffer;\n\n // 步骤 1: 创建隐藏容器获取 slideCount\n const hiddenContainer = document.createElement('div');\n hiddenContainer.style.cssText = 'position:absolute;left:-9999px;top:-9999px;visibility:hidden';\n document.body.appendChild(hiddenContainer);\n\n try {\n const tempPreviewer = init(hiddenContainer, {\n width: 100,\n height: 100,\n mode: 'slide',\n });\n\n try {\n await tempPreviewer.preview(arrayBuffer);\n } catch {\n throw new Error(t.value('pptx.invalid_format'));\n }\n\n const count = tempPreviewer.slideCount;\n if (!count || count === 0) throw new Error(t.value('pptx.no_pages'));\n\n tempPreviewer.destroy();\n\n slideCount.value = count;\n\n if (containerRef.value) {\n containerRef.value.innerHTML = '';\n }\n\n const currentDimensions = calculateDimensions();\n previewer = init(containerRef.value, {\n width: currentDimensions.width,\n height: props.tiled ? currentDimensions.height * count : currentDimensions.height,\n mode: props.tiled ? 'list' : 'slide',\n });\n\n await previewer.preview(arrayBuffer);\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n loading.value = false;\n } finally {\n if (document.body.contains(hiddenContainer)) {\n document.body.removeChild(hiddenContainer);\n }\n }\n } catch (err) {\n if (timeoutId !== null) clearTimeout(timeoutId);\n let errorMsg = t.value('pptx.parse_failed');\n if (err instanceof Error) errorMsg = err.message;\n else if (typeof err === 'string') errorMsg = err;\n error.value = errorMsg;\n loading.value = false;\n }\n};\n\nonMounted(() => {\n if (!containerRef.value) return;\n\n let isInitialRender = true;\n\n resizeObserver = new ResizeObserver(() => {\n if (isInitialRender) {\n isInitialRender = false;\n lastDimensions = calculateDimensions();\n return;\n }\n\n const newDimensions = calculateDimensions();\n const widthDiff = Math.abs(lastDimensions.width - newDimensions.width);\n const heightDiff = Math.abs(lastDimensions.height - newDimensions.height);\n\n if (widthDiff < 10 && heightDiff < 10) return;\n\n lastDimensions = newDimensions;\n\n if (resizeTimeout !== null) clearTimeout(resizeTimeout);\n\n resizeTimeout = window.setTimeout(() => {\n if (previewer && arrayBufferRef) reinitializePreviewer();\n }, 800);\n });\n\n resizeObserver.observe(containerRef.value);\n\n setTimeout(() => {\n requestAnimationFrame(() => requestAnimationFrame(() => loadPptx()));\n }, 150);\n});\n\nwatch(\n () => props.url,\n (newUrl) => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (newUrl) {\n loadPptx();\n }\n }\n);\n\nonBeforeUnmount(() => {\n if (resizeObserver) resizeObserver.disconnect();\n if (resizeTimeout !== null) clearTimeout(resizeTimeout);\n arrayBufferRef = null;\n slideCount.value = 0;\n if (previewer) {\n try {\n previewer.destroy();\n } catch {\n // ignore\n }\n }\n previewer = null;\n});\n</script>\n\n<template>\n <div class=\"vfp-relative vfp-flex vfp-flex-col vfp-items-center vfp-w-full vfp-h-full\">\n <div\n v-if=\"loading\"\n class=\"vfp-absolute vfp-inset-0 vfp-flex vfp-items-center vfp-justify-center vfp-bg-surface-toolbar vfp-backdrop-blur-sm vfp-z-10\"\n >\n <div class=\"vfp-text-center\">\n <div\n class=\"vfp-w-10 vfp-h-10 md:vfp-w-12 md:vfp-h-12 vfp-mx-auto vfp-mb-3 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\"\n />\n <p class=\"vfp-text-xs md:vfp-text-sm vfp-text-fg-secondary vfp-font-medium\">{{ t('pptx.loading') }}</p>\n </div>\n </div>\n\n <RendererError\n v-if=\"error && !loading\"\n :message=\"t('pptx.load_failed')\"\n :detail=\"error\"\n class=\"vfp-absolute vfp-inset-0 vfp-bg-surface-toolbar vfp-backdrop-blur-sm vfp-z-10\"\n />\n\n <div\n v-if=\"!error\"\n ref=\"containerRef\"\n class=\"pptx-wrapper vfp-w-full vfp-max-w-full md:vfp-max-w-6xl\"\n :style=\"{ opacity: loading ? 0 : 1 }\"\n />\n </div>\n</template>\n"],"names":["props","__props","t","useTranslator","fetcher","useFetcher","loading","ref","error","slideCount","containerRef","previewer","resizeObserver","arrayBufferRef","resizeTimeout","lastDimensions","calculateDimensions","rawWidth","parentWidth","_a","containerWidth","height","reinitializePreviewer","currentDimensions","init","loadPptx","timeoutId","response","arrayBuffer","hiddenContainer","tempPreviewer","count","err","errorMsg","onMounted","isInitialRender","newDimensions","widthDiff","heightDiff","watch","newUrl","onBeforeUnmount","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_createElementVNode","_hoisted_3","_hoisted_4","_toDisplayString","_unref","_createBlock","RendererError"],"mappings":";;;;;;;;;;;;;;AAOA,UAAMA,IAAQC,GAQR,EAAE,GAAAC,EAAA,IAAMC,EAAA,GACRC,IAAUC,EAAA,GAEVC,IAAUC,EAAI,EAAI,GAClBC,IAAQD,EAAmB,IAAI,GAC/BE,IAAaF,EAAI,CAAC,GAClBG,IAAeH,EAA2B,IAAI;AACpD,QAAII,IAA4C,MAC5CC,IAAwC,MACxCC,IAAqC,MACrCC,IAA+B,MAC/BC,IAAiB,EAAE,OAAO,GAAG,QAAQ,EAAA;AAEzC,UAAMC,IAAsB,MAAM;;AAChC,UAAI,CAACN,EAAa,MAAO,QAAO,EAAE,OAAO,KAAK,QAAQ,IAAA;AACtD,YAAMO,IAAWP,EAAa,MAAM,aAC9BQ,MAAcC,IAAAT,EAAa,MAAM,kBAAnB,gBAAAS,EAAkC,gBAAe,GAC/DC,IAAiBH,IAAW,MAAMA,IAAWC,IAAc,MAAMA,IAAc,KAC/EG,IAAS,KAAK,MAAOD,IAAiB,IAAK,EAAE;AACnD,aAAO,EAAE,OAAOA,GAAgB,QAAAC,EAAA;AAAA,IAClC,GAEMC,IAAwB,YAAY;AACxC,UAAI,GAACZ,EAAa,SAAS,CAACG,KAAkBJ,EAAW,UAAU;AAEnE,YAAI;AACF,cAAIE;AACF,gBAAI;AACF,cAAAA,EAAU,QAAA;AAAA,YACZ,QAAQ;AAAA,YAER;AAGF,UAAAD,EAAa,MAAM,YAAY;AAE/B,gBAAMa,IAAoBP,EAAA;AAC1B,UAAAL,IAAYa,EAAKd,EAAa,OAAO;AAAA,YACnC,OAAOa,EAAkB;AAAA,YACzB,QAAQvB,EAAM,QAAQuB,EAAkB,SAASd,EAAW,QAAQc,EAAkB;AAAA,YACtF,MAAMvB,EAAM,QAAQ,SAAS;AAAA,UAAA,CAC9B,GAED,MAAMW,EAAU,QAAQE,CAAc;AAAA,QACxC,QAAQ;AAAA,QAER;AAAA,IACF,GAEMY,IAAW,YAAY;AAC3B,UAAI,CAACf,EAAa,MAAO;AAEzB,MAAAJ,EAAQ,QAAQ,IAChBE,EAAM,QAAQ;AAEd,UAAIkB,IAA2B,OAAO,WAAW,MAAM;AACrD,QAAAlB,EAAM,QAAQN,EAAE,MAAM,cAAc,GACpCI,EAAQ,QAAQ;AAAA,MAClB,GAAG,GAAK;AAER,UAAI;AACF,cAAMqB,IAAW,MAAMvB,EAAQ,MAAMJ,EAAM,KAAK;AAAA,UAC9C,MAAM;AAAA,UACN,aAAa;AAAA,UACb,UAAU;AAAA,QAAA,CACX;AAED,YAAI,CAAC2B,EAAS;AACZ,gBAAIA,EAAS,WAAW,MAAW,IAAI,MAAMzB,EAAE,MAAM,gBAAgB,CAAC,IAClEyB,EAAS,WAAW,MAAW,IAAI,MAAM,UAAU,IACnDA,EAAS,UAAU,MAAW,IAAI,MAAM,aAAa,IACnD,IAAI,MAAM,WAAWA,EAAS,MAAM,GAAG;AAG/C,cAAMC,IAAc,MAAMD,EAAS,YAAA;AACnC,YAAIC,EAAY,eAAe,EAAG,OAAM,IAAI,MAAM,MAAM;AAExD,QAAAf,IAAiBe;AAGjB,cAAMC,IAAkB,SAAS,cAAc,KAAK;AACpD,QAAAA,EAAgB,MAAM,UAAU,gEAChC,SAAS,KAAK,YAAYA,CAAe;AAEzC,YAAI;AACF,gBAAMC,IAAgBN,EAAKK,GAAiB;AAAA,YAC1C,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,MAAM;AAAA,UAAA,CACP;AAED,cAAI;AACF,kBAAMC,EAAc,QAAQF,CAAW;AAAA,UACzC,QAAQ;AACN,kBAAM,IAAI,MAAM1B,EAAE,MAAM,qBAAqB,CAAC;AAAA,UAChD;AAEA,gBAAM6B,IAAQD,EAAc;AAC5B,cAAI,CAACC,KAASA,MAAU,EAAG,OAAM,IAAI,MAAM7B,EAAE,MAAM,eAAe,CAAC;AAEnE,UAAA4B,EAAc,QAAA,GAEdrB,EAAW,QAAQsB,GAEfrB,EAAa,UACfA,EAAa,MAAM,YAAY;AAGjC,gBAAMa,IAAoBP,EAAA;AAC1B,UAAAL,IAAYa,EAAKd,EAAa,OAAO;AAAA,YACnC,OAAOa,EAAkB;AAAA,YACzB,QAAQvB,EAAM,QAAQuB,EAAkB,SAASQ,IAAQR,EAAkB;AAAA,YAC3E,MAAMvB,EAAM,QAAQ,SAAS;AAAA,UAAA,CAC9B,GAED,MAAMW,EAAU,QAAQiB,CAAW,GAE/BF,MAAc,SAChB,aAAaA,CAAS,GACtBA,IAAY,OAGdpB,EAAQ,QAAQ;AAAA,QAClB,UAAA;AACE,UAAI,SAAS,KAAK,SAASuB,CAAe,KACxC,SAAS,KAAK,YAAYA,CAAe;AAAA,QAE7C;AAAA,MACF,SAASG,GAAK;AACZ,QAAIN,MAAc,QAAM,aAAaA,CAAS;AAC9C,YAAIO,IAAW/B,EAAE,MAAM,mBAAmB;AAC1C,QAAI8B,aAAe,QAAOC,IAAWD,EAAI,UAChC,OAAOA,KAAQ,aAAUC,IAAWD,IAC7CxB,EAAM,QAAQyB,GACd3B,EAAQ,QAAQ;AAAA,MAClB;AAAA,IACF;AAEA,WAAA4B,EAAU,MAAM;AACd,UAAI,CAACxB,EAAa,MAAO;AAEzB,UAAIyB,IAAkB;AAEtB,MAAAvB,IAAiB,IAAI,eAAe,MAAM;AACxC,YAAIuB,GAAiB;AACnB,UAAAA,IAAkB,IAClBpB,IAAiBC,EAAA;AACjB;AAAA,QACF;AAEA,cAAMoB,IAAgBpB,EAAA,GAChBqB,IAAY,KAAK,IAAItB,EAAe,QAAQqB,EAAc,KAAK,GAC/DE,IAAa,KAAK,IAAIvB,EAAe,SAASqB,EAAc,MAAM;AAExE,QAAIC,IAAY,MAAMC,IAAa,OAEnCvB,IAAiBqB,GAEbtB,MAAkB,QAAM,aAAaA,CAAa,GAEtDA,IAAgB,OAAO,WAAW,MAAM;AACtC,UAAIH,KAAaE,KAAgBS,EAAA;AAAA,QACnC,GAAG,GAAG;AAAA,MACR,CAAC,GAEDV,EAAe,QAAQF,EAAa,KAAK,GAEzC,WAAW,MAAM;AACf,8BAAsB,MAAM,sBAAsB,MAAMe,EAAA,CAAU,CAAC;AAAA,MACrE,GAAG,GAAG;AAAA,IACR,CAAC,GAEDc;AAAA,MACE,MAAMvC,EAAM;AAAA,MACZ,CAACwC,MAAW;AAEV,QAAIA,KACFf,EAAA;AAAA,MAEJ;AAAA,IAAA,GAGFgB,EAAgB,MAAM;AAKpB,UAJI7B,OAA+B,WAAA,GAC/BE,MAAkB,QAAM,aAAaA,CAAa,GACtDD,IAAiB,MACjBJ,EAAW,QAAQ,GACfE;AACF,YAAI;AACF,UAAAA,EAAU,QAAA;AAAA,QACZ,QAAQ;AAAA,QAER;AAEF,MAAAA,IAAY;AAAA,IACd,CAAC,cAIC+B,EAAA,GAAAC,EA0BM,OA1BNC,GA0BM;AAAA,MAxBItC,EAAA,SADRoC,EAAA,GAAAC,EAUM,OAVNE,GAUM;AAAA,QANJC,EAKM,OALNC,GAKM;AAAA,0BAJJD,EAEE,OAAA,EADA,OAAM,iKAAA,GAAgK,MAAA,EAAA;AAAA,UAExKA,EAAuG,KAAvGE,GAAuGC,EAAxBC,EAAAhD,CAAA,EAAC,cAAA,CAAA,GAAA,CAAA;AAAA,QAAA;;MAK5EM,EAAA,UAAUF,EAAA,cADlB6C,EAKEC,GAAA;AAAA;QAHC,SAASF,EAAAhD,CAAA,EAAC,kBAAA;AAAA,QACV,QAAQM,EAAA;AAAA,QACT,OAAM;AAAA,MAAA;MAICA,EAAA,0BADTmC,EAKE,OAAA;AAAA;iBAHI;AAAA,QAAJ,KAAIjC;AAAA,QACJ,OAAM;AAAA,QACL,oBAAkBJ,EAAA,QAAO,IAAA,GAAA;AAAA,MAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"index-Cjnw238n.mjs","sources":["../../src/renderers/Pptx/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount } from 'vue';\nimport { init } from 'pptx-preview';\nimport { useTranslator } from '../../composables/useTranslator';\nimport { useFetcher } from '../../composables/useRequest';\nimport RendererError from '../RendererError.vue';\n\nconst props = withDefaults(\n defineProps<{\n url: string;\n tiled?: boolean;\n }>(),\n { tiled: true }\n);\n\nconst { t } = useTranslator();\nconst fetcher = useFetcher();\n\nconst loading = ref(true);\nconst error = ref<string | null>(null);\nconst slideCount = ref(0);\nconst containerRef = ref<HTMLDivElement | null>(null);\nlet previewer: ReturnType<typeof init> | null = null;\nlet resizeObserver: ResizeObserver | null = null;\nlet arrayBufferRef: ArrayBuffer | null = null;\nlet resizeTimeout: number | null = null;\nlet lastDimensions = { width: 0, height: 0 };\n\nconst calculateDimensions = () => {\n if (!containerRef.value) return { width: 960, height: 540 };\n const rawWidth = containerRef.value.clientWidth;\n const parentWidth = containerRef.value.parentElement?.clientWidth || 0;\n const containerWidth = rawWidth > 100 ? rawWidth : parentWidth > 100 ? parentWidth : 300;\n const height = Math.floor((containerWidth * 9) / 16);\n return { width: containerWidth, height };\n};\n\nconst reinitializePreviewer = async () => {\n if (!containerRef.value || !arrayBufferRef || slideCount.value === 0) return;\n\n try {\n if (previewer) {\n try {\n previewer.destroy();\n } catch {\n // ignore\n }\n }\n\n containerRef.value.innerHTML = '';\n\n const currentDimensions = calculateDimensions();\n previewer = init(containerRef.value, {\n width: currentDimensions.width,\n height: props.tiled ? currentDimensions.height * slideCount.value : currentDimensions.height,\n mode: props.tiled ? 'list' : 'slide',\n });\n\n await previewer.preview(arrayBufferRef);\n } catch {\n // 静默处理\n }\n};\n\nconst loadPptx = async () => {\n if (!containerRef.value) return;\n\n loading.value = true;\n error.value = null;\n\n let timeoutId: number | null = window.setTimeout(() => {\n error.value = t.value('pptx.timeout');\n loading.value = false;\n }, 30000);\n\n try {\n const response = await fetcher.value(props.url, {\n mode: 'cors',\n credentials: 'omit',\n redirect: 'follow',\n });\n\n if (!response.ok) {\n if (response.status === 404) throw new Error(t.value('pptx.not_found'));\n if (response.status === 403) throw new Error('无权限访问此文件');\n if (response.status >= 500) throw new Error('服务器错误,请稍后重试');\n throw new Error(`文件加载失败 (${response.status})`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n if (arrayBuffer.byteLength === 0) throw new Error('文件为空');\n\n arrayBufferRef = arrayBuffer;\n\n // 步骤 1: 创建隐藏容器获取 slideCount\n const hiddenContainer = document.createElement('div');\n hiddenContainer.style.cssText = 'position:absolute;left:-9999px;top:-9999px;visibility:hidden';\n document.body.appendChild(hiddenContainer);\n\n try {\n const tempPreviewer = init(hiddenContainer, {\n width: 100,\n height: 100,\n mode: 'slide',\n });\n\n try {\n await tempPreviewer.preview(arrayBuffer);\n } catch {\n throw new Error(t.value('pptx.invalid_format'));\n }\n\n const count = tempPreviewer.slideCount;\n if (!count || count === 0) throw new Error(t.value('pptx.no_pages'));\n\n tempPreviewer.destroy();\n\n slideCount.value = count;\n\n if (containerRef.value) {\n containerRef.value.innerHTML = '';\n }\n\n const currentDimensions = calculateDimensions();\n previewer = init(containerRef.value, {\n width: currentDimensions.width,\n height: props.tiled ? currentDimensions.height * count : currentDimensions.height,\n mode: props.tiled ? 'list' : 'slide',\n });\n\n await previewer.preview(arrayBuffer);\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n loading.value = false;\n } finally {\n if (document.body.contains(hiddenContainer)) {\n document.body.removeChild(hiddenContainer);\n }\n }\n } catch (err) {\n if (timeoutId !== null) clearTimeout(timeoutId);\n let errorMsg = t.value('pptx.parse_failed');\n if (err instanceof Error) errorMsg = err.message;\n else if (typeof err === 'string') errorMsg = err;\n error.value = errorMsg;\n loading.value = false;\n }\n};\n\nonMounted(() => {\n if (!containerRef.value) return;\n\n let isInitialRender = true;\n\n resizeObserver = new ResizeObserver(() => {\n if (isInitialRender) {\n isInitialRender = false;\n lastDimensions = calculateDimensions();\n return;\n }\n\n const newDimensions = calculateDimensions();\n const widthDiff = Math.abs(lastDimensions.width - newDimensions.width);\n const heightDiff = Math.abs(lastDimensions.height - newDimensions.height);\n\n if (widthDiff < 10 && heightDiff < 10) return;\n\n lastDimensions = newDimensions;\n\n if (resizeTimeout !== null) clearTimeout(resizeTimeout);\n\n resizeTimeout = window.setTimeout(() => {\n if (previewer && arrayBufferRef) reinitializePreviewer();\n }, 800);\n });\n\n resizeObserver.observe(containerRef.value);\n\n setTimeout(() => {\n requestAnimationFrame(() => requestAnimationFrame(() => loadPptx()));\n }, 150);\n});\n\nwatch(\n () => props.url,\n (newUrl) => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (newUrl) {\n loadPptx();\n }\n }\n);\n\nonBeforeUnmount(() => {\n if (resizeObserver) resizeObserver.disconnect();\n if (resizeTimeout !== null) clearTimeout(resizeTimeout);\n arrayBufferRef = null;\n slideCount.value = 0;\n if (previewer) {\n try {\n previewer.destroy();\n } catch {\n // ignore\n }\n }\n previewer = null;\n});\n</script>\n\n<template>\n <div class=\"vfp-relative vfp-flex vfp-flex-col vfp-items-center vfp-w-full vfp-h-full\">\n <div\n v-if=\"loading\"\n class=\"vfp-absolute vfp-inset-0 vfp-flex vfp-items-center vfp-justify-center vfp-bg-surface-toolbar vfp-backdrop-blur-sm vfp-z-10\"\n >\n <div class=\"vfp-text-center\">\n <div\n class=\"vfp-w-10 vfp-h-10 md:vfp-w-12 md:vfp-h-12 vfp-mx-auto vfp-mb-3 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\"\n />\n <p class=\"vfp-text-xs md:vfp-text-sm vfp-text-fg-secondary vfp-font-medium\">{{ t('pptx.loading') }}</p>\n </div>\n </div>\n\n <RendererError\n v-if=\"error && !loading\"\n :message=\"t('pptx.load_failed')\"\n :detail=\"error\"\n class=\"vfp-absolute vfp-inset-0 vfp-bg-surface-toolbar vfp-backdrop-blur-sm vfp-z-10\"\n />\n\n <div\n v-if=\"!error\"\n ref=\"containerRef\"\n class=\"pptx-wrapper vfp-w-full vfp-max-w-full md:vfp-max-w-6xl\"\n :style=\"{ opacity: loading ? 0 : 1 }\"\n />\n </div>\n</template>\n"],"names":["props","__props","t","useTranslator","fetcher","useFetcher","loading","ref","error","slideCount","containerRef","previewer","resizeObserver","arrayBufferRef","resizeTimeout","lastDimensions","calculateDimensions","rawWidth","parentWidth","_a","containerWidth","height","reinitializePreviewer","currentDimensions","init","loadPptx","timeoutId","response","arrayBuffer","hiddenContainer","tempPreviewer","count","err","errorMsg","onMounted","isInitialRender","newDimensions","widthDiff","heightDiff","watch","newUrl","onBeforeUnmount","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_createElementVNode","_hoisted_3","_hoisted_4","_toDisplayString","_unref","_createBlock","RendererError"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent as k, ref as d, onMounted as x, watch as b, onBeforeUnmount as w, openBlock as f, createBlock as T, createElementBlock as m, createElementVNode as n, toDisplayString as E, unref as C, createCommentVNode as D } from "vue";
|
|
2
2
|
import j from "video.js";
|
|
3
|
-
import { u as B, b as _ } from "./index-
|
|
3
|
+
import { u as B, b as _ } from "./index-Oxwizt6-.mjs";
|
|
4
4
|
import { _ as N } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
|
|
5
5
|
const P = {
|
|
6
6
|
key: 1,
|
|
@@ -114,4 +114,4 @@ const P = {
|
|
|
114
114
|
export {
|
|
115
115
|
F as default
|
|
116
116
|
};
|
|
117
|
-
//# sourceMappingURL=index-
|
|
117
|
+
//# sourceMappingURL=index-Ctd0JQ6K.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-Ctd0JQ6K.mjs","sources":["../../src/renderers/Video/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, onMounted, onBeforeUnmount, watch } from 'vue';\nimport videojs from 'video.js';\nimport 'video.js/dist/video-js.css';\nimport { getVideoMimeType } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../composables/useTranslator';\nimport RendererError from '../RendererError.vue';\n\ntype VideoJsPlayer = ReturnType<typeof videojs>;\n\nconst props = defineProps<{\n url: string;\n fileName?: string;\n}>();\n\nconst { t } = useTranslator();\n\ninterface ErrorState {\n title: string;\n detail: string;\n}\n\n// 浏览器原生不支持的视频容器(无论编码,<video> 都无法播放)\nconst BROWSER_UNSUPPORTED_EXTS = new Set(['avi', 'wmv', 'flv']);\n\nconst error = ref<ErrorState | null>(null);\nconst isLoading = ref(true);\nconst videoContainerRef = ref<HTMLDivElement | null>(null);\nlet player: VideoJsPlayer | null = null;\n\nconst getVideoExt = (url: string, fileName?: string): string => {\n const source = fileName || url;\n return source.split('.').pop()?.toLowerCase().split('?')[0] || '';\n};\n\nconst initPlayer = () => {\n if (!videoContainerRef.value || player) return;\n\n const videoExt = getVideoExt(props.url, props.fileName);\n\n // 已知浏览器不支持的容器:跳过 videojs 初始化,直接展示友好提示\n if (BROWSER_UNSUPPORTED_EXTS.has(videoExt)) {\n error.value = {\n title: t.value('video.unsupported_title'),\n detail: t.value('video.unsupported_detail', { format: videoExt.toUpperCase() }),\n };\n isLoading.value = false;\n return;\n }\n\n const videoElement = document.createElement('video-js');\n videoElement.classList.add('vjs-big-play-centered', 'vjs-theme-apple');\n videoContainerRef.value.appendChild(videoElement);\n\n const videoType = getVideoMimeType(props.url);\n\n // 为特定格式提供多个 MIME 类型作为备用\n let sources: Array<{ src: string; type: string }>;\n\n if (videoType === 'video/quicktime') {\n // MOV 格式 fallback\n sources = [\n { src: props.url, type: 'video/quicktime' },\n { src: props.url, type: 'video/mp4' }\n ];\n } else {\n sources = [{ src: props.url, type: videoType }];\n }\n\n player = videojs(videoElement, {\n controls: true,\n fill: true,\n preload: 'auto',\n controlBar: {\n children: [\n 'playToggle',\n 'volumePanel',\n 'currentTimeDisplay',\n 'timeDivider',\n 'durationDisplay',\n 'progressControl',\n 'remainingTimeDisplay',\n 'fullscreenToggle',\n ],\n volumePanel: {\n inline: false,\n },\n },\n html5: {\n vhs: {\n overrideNative: true,\n },\n nativeVideoTracks: false,\n nativeAudioTracks: false,\n nativeTextTracks: false,\n },\n sources,\n });\n\n const videoEl = player.el().querySelector('video');\n if (videoEl) {\n (videoEl as HTMLVideoElement).style.objectFit = 'contain';\n }\n\n player.on('loadeddata', () => {\n isLoading.value = false;\n });\n\n player.on('error', () => {\n const err = player?.error();\n console.warn('[VideoRenderer] Video playback error:', err?.message || 'Unknown error');\n\n // MEDIA_ERR_SRC_NOT_SUPPORTED(code=4):编码或容器层面浏览器解不了\n if (err?.code === 4) {\n error.value = {\n title: t.value('video.unsupported_title'),\n detail: t.value('video.unsupported_detail', {\n format: videoExt ? videoExt.toUpperCase() : t.value('common.unknown_error'),\n }),\n };\n } else {\n error.value = {\n title: t.value('video.load_failed'),\n detail: err?.message || t.value('common.unknown_error'),\n };\n }\n isLoading.value = false;\n });\n};\n\nonMounted(initPlayer);\n\nwatch(\n () => props.url,\n () => {\n if (player && !player.isDisposed()) {\n player.src({ src: props.url, type: getVideoMimeType(props.url) });\n }\n }\n);\n\nonBeforeUnmount(() => {\n if (player && !player.isDisposed()) {\n player.dispose();\n player = null;\n }\n});\n</script>\n\n<template>\n <RendererError v-if=\"error\" :message=\"error.title\" :detail=\"error.detail\" />\n\n <div v-else class=\"vfp-flex vfp-items-center vfp-justify-center vfp-w-full vfp-h-full\">\n <div class=\"vfp-w-full vfp-h-full vfp-relative\">\n <div\n v-if=\"isLoading\"\n class=\"vfp-absolute vfp-inset-0 vfp-flex vfp-items-center vfp-justify-center vfp-bg-surface-3 vfp-backdrop-blur-sm vfp-z-10\"\n >\n <div class=\"vfp-text-center\">\n <div\n class=\"vfp-w-12 vfp-h-12 vfp-mx-auto vfp-mb-3 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\"\n />\n <p class=\"vfp-text-sm vfp-text-fg-secondary vfp-font-medium\">{{ t('video.loading') }}</p>\n </div>\n </div>\n\n <div\n ref=\"videoContainerRef\"\n class=\"vfp-overflow-hidden vfp-w-full vfp-h-full\"\n style=\"box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.05)\"\n />\n </div>\n </div>\n</template>\n"],"names":["props","__props","t","useTranslator","BROWSER_UNSUPPORTED_EXTS","error","ref","isLoading","videoContainerRef","player","getVideoExt","url","fileName","_a","onMounted","videoExt","videoElement","videoType","getVideoMimeType","sources","videojs","videoEl","err","watch","onBeforeUnmount","_createBlock","RendererError","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_toDisplayString","_unref"],"mappings":";;;;;;;;;;;;;;;;;AAUA,UAAMA,IAAQC,GAKR,EAAE,GAAAC,EAAA,IAAMC,EAAA,GAQRC,IAA2B,oBAAI,IAAI,CAAC,OAAO,OAAO,KAAK,CAAC,GAExDC,IAAQC,EAAuB,IAAI,GACnCC,IAAYD,EAAI,EAAI,GACpBE,IAAoBF,EAA2B,IAAI;AACzD,QAAIG,IAA+B;AAEnC,UAAMC,IAAc,CAACC,GAAaC,MAA8B;;AAE9D,eAAOC,KADQD,KAAYD,GACb,MAAM,GAAG,EAAE,IAAA,MAAlB,gBAAAE,EAAyB,cAAc,MAAM,KAAK,OAAM;AAAA,IACjE;AAiGA,WAAAC,EA/FmB,MAAM;AACvB,UAAI,CAACN,EAAkB,SAASC,EAAQ;AAExC,YAAMM,IAAWL,EAAYV,EAAM,KAAKA,EAAM,QAAQ;AAGtD,UAAII,EAAyB,IAAIW,CAAQ,GAAG;AAC1C,QAAAV,EAAM,QAAQ;AAAA,UACZ,OAAOH,EAAE,MAAM,yBAAyB;AAAA,UACxC,QAAQA,EAAE,MAAM,4BAA4B,EAAE,QAAQa,EAAS,cAAY,CAAG;AAAA,QAAA,GAEhFR,EAAU,QAAQ;AAClB;AAAA,MACF;AAEA,YAAMS,IAAe,SAAS,cAAc,UAAU;AACtD,MAAAA,EAAa,UAAU,IAAI,yBAAyB,iBAAiB,GACrER,EAAkB,MAAM,YAAYQ,CAAY;AAEhD,YAAMC,IAAYC,EAAiBlB,EAAM,GAAG;AAG5C,UAAImB;AAEJ,MAAIF,MAAc,oBAEhBE,IAAU;AAAA,QACR,EAAE,KAAKnB,EAAM,KAAK,MAAM,kBAAA;AAAA,QACxB,EAAE,KAAKA,EAAM,KAAK,MAAM,YAAA;AAAA,MAAY,IAGtCmB,IAAU,CAAC,EAAE,KAAKnB,EAAM,KAAK,MAAMiB,GAAW,GAGhDR,IAASW,EAAQJ,GAAc;AAAA,QAC7B,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,QACT,YAAY;AAAA,UACV,UAAU;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAAA,UAEF,aAAa;AAAA,YACX,QAAQ;AAAA,UAAA;AAAA,QACV;AAAA,QAEF,OAAO;AAAA,UACL,KAAK;AAAA,YACH,gBAAgB;AAAA,UAAA;AAAA,UAElB,mBAAmB;AAAA,UACnB,mBAAmB;AAAA,UACnB,kBAAkB;AAAA,QAAA;AAAA,QAEpB,SAAAG;AAAA,MAAA,CACD;AAED,YAAME,IAAUZ,EAAO,GAAA,EAAK,cAAc,OAAO;AACjD,MAAIY,MACDA,EAA6B,MAAM,YAAY,YAGlDZ,EAAO,GAAG,cAAc,MAAM;AAC5B,QAAAF,EAAU,QAAQ;AAAA,MACpB,CAAC,GAEDE,EAAO,GAAG,SAAS,MAAM;AACvB,cAAMa,IAAMb,KAAA,gBAAAA,EAAQ;AACpB,gBAAQ,KAAK,0CAAyCa,KAAA,gBAAAA,EAAK,YAAW,eAAe,IAGjFA,KAAA,gBAAAA,EAAK,UAAS,IAChBjB,EAAM,QAAQ;AAAA,UACZ,OAAOH,EAAE,MAAM,yBAAyB;AAAA,UACxC,QAAQA,EAAE,MAAM,4BAA4B;AAAA,YAC1C,QAAQa,IAAWA,EAAS,gBAAgBb,EAAE,MAAM,sBAAsB;AAAA,UAAA,CAC3E;AAAA,QAAA,IAGHG,EAAM,QAAQ;AAAA,UACZ,OAAOH,EAAE,MAAM,mBAAmB;AAAA,UAClC,SAAQoB,KAAA,gBAAAA,EAAK,YAAWpB,EAAE,MAAM,sBAAsB;AAAA,QAAA,GAG1DK,EAAU,QAAQ;AAAA,MACpB,CAAC;AAAA,IACH,CAEoB,GAEpBgB;AAAA,MACE,MAAMvB,EAAM;AAAA,MACZ,MAAM;AACJ,QAAIS,KAAU,CAACA,EAAO,gBACpBA,EAAO,IAAI,EAAE,KAAKT,EAAM,KAAK,MAAMkB,EAAiBlB,EAAM,GAAG,GAAG;AAAA,MAEpE;AAAA,IAAA,GAGFwB,EAAgB,MAAM;AACpB,MAAIf,KAAU,CAACA,EAAO,iBACpBA,EAAO,QAAA,GACPA,IAAS;AAAA,IAEb,CAAC,aAIsBJ,EAAA,cAArBoB,EAA4EC,GAAA;AAAA;MAA/C,SAASrB,EAAA,MAAM;AAAA,MAAQ,QAAQA,EAAA,MAAM;AAAA,IAAA,uCAElEsB,KAAAC,EAoBM,OApBNC,GAoBM;AAAA,MAnBJC,EAkBM,OAlBNC,GAkBM;AAAA,QAhBIxB,EAAA,SADRoB,EAAA,GAAAC,EAUM,OAVNI,GAUM;AAAA,UANJF,EAKM,OALNG,GAKM;AAAA,4BAJJH,EAEE,OAAA,EADA,OAAM,yIAAA,GAAwI,MAAA,EAAA;AAAA,YAEhJA,EAAyF,KAAzFI,GAAyFC,EAAzBC,EAAAlC,CAAA,EAAC,eAAA,CAAA,GAAA,CAAA;AAAA,UAAA;;QAIrE4B,EAIE,OAAA;AAAA,mBAHI;AAAA,UAAJ,KAAItB;AAAA,UACJ,OAAM;AAAA,UACN,OAAA,EAAA,cAAA,sEAAA;AAAA,QAAA;;;;;"}
|