@maas/vue-equipment 0.20.1 → 0.21.0
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/dist/nuxt/module.json +1 -1
- package/dist/nuxt/module.mjs +1 -1
- package/dist/plugins/MagicDrawer/src/composables/useDrawerApi.d.ts +2 -2
- package/dist/plugins/MagicPlayer/index.d.ts +3 -3
- package/dist/plugins/MagicPlayer/index.mjs +6 -3
- package/dist/plugins/MagicPlayer/src/components/MagicPlayer.vue +24 -18
- package/dist/plugins/MagicPlayer/src/components/MagicPlayer.vue.d.ts +8 -5
- package/dist/plugins/MagicPlayer/src/components/MagicPlayerControls.vue +20 -9
- package/dist/plugins/MagicPlayer/src/components/MagicPlayerMuxPopover.vue +2 -4
- package/dist/plugins/MagicPlayer/src/components/MagicPlayerOverlay.vue +29 -25
- package/dist/plugins/MagicPlayer/src/components/MagicPlayerOverlay.vue.d.ts +1 -0
- package/dist/plugins/MagicPlayer/src/components/MagicPlayerPoster.vue +27 -0
- package/dist/plugins/MagicPlayer/src/components/MagicPlayerPoster.vue.d.ts +21 -0
- package/dist/plugins/MagicPlayer/src/components/MagicPlayerTimeline.vue +10 -7
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerControlsApi.d.ts +34 -0
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerControlsApi.mjs +297 -0
- package/dist/plugins/MagicPlayer/src/composables/private/{useMediaApi.d.ts → usePlayerMediaApi.d.ts} +11 -7
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerMediaApi.mjs +263 -0
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerRuntime.d.ts +12 -0
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerRuntime.mjs +70 -0
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerStateEmitter.d.ts +15 -0
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerStateEmitter.mjs +9 -0
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerVideoApi.d.ts +22 -0
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerVideoApi.mjs +142 -0
- package/dist/plugins/MagicPlayer/src/composables/usePlayerApi.d.ts +63 -5
- package/dist/plugins/MagicPlayer/src/composables/usePlayerApi.mjs +12 -65
- package/dist/plugins/MagicPlayer/src/types/index.d.ts +12 -25
- package/package.json +1 -1
- package/dist/plugins/MagicPlayer/src/composables/private/useControlsApi.d.ts +0 -17
- package/dist/plugins/MagicPlayer/src/composables/private/useControlsApi.mjs +0 -131
- package/dist/plugins/MagicPlayer/src/composables/private/useMediaApi.mjs +0 -122
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerInternalApi.d.ts +0 -18
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerInternalApi.mjs +0 -63
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerStore.d.ts +0 -20
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerStore.mjs +0 -42
- package/dist/plugins/MagicPlayer/src/composables/private/useRuntimeSourceProvider.d.ts +0 -6
- package/dist/plugins/MagicPlayer/src/composables/private/useRuntimeSourceProvider.mjs +0 -48
- package/dist/plugins/MagicPlayer/src/utils/index.d.ts +0 -1
- package/dist/plugins/MagicPlayer/src/utils/index.mjs +0 -8
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type MaybeRef, type Ref } from 'vue';
|
|
2
|
+
export type UsePlayerVideoApiArgs = {
|
|
3
|
+
id: MaybeRef<string>;
|
|
4
|
+
playerRef?: MaybeRef<HTMLElement | undefined>;
|
|
5
|
+
videoRef?: MaybeRef<HTMLVideoElement | undefined>;
|
|
6
|
+
};
|
|
7
|
+
export declare function usePlayerVideoApi(args: UsePlayerVideoApiArgs): {
|
|
8
|
+
mouseEntered: Ref<boolean>;
|
|
9
|
+
isFullscreen: Ref<boolean>;
|
|
10
|
+
touched: Ref<boolean>;
|
|
11
|
+
play: () => void;
|
|
12
|
+
pause: () => void;
|
|
13
|
+
togglePlay: () => void;
|
|
14
|
+
seek: (time: number) => void;
|
|
15
|
+
mute: () => void;
|
|
16
|
+
unmute: () => void;
|
|
17
|
+
enterFullscreen: () => void;
|
|
18
|
+
exitFullscreen: () => void;
|
|
19
|
+
onMouseenter: () => void;
|
|
20
|
+
onMouseleave: () => void;
|
|
21
|
+
};
|
|
22
|
+
export type UsePlayerVideoApiReturn = ReturnType<typeof usePlayerVideoApi>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { ref, watch, toValue } from "vue";
|
|
2
|
+
import { useFullscreen } from "@vueuse/core";
|
|
3
|
+
import { isIOS } from "@maas/vue-equipment/utils";
|
|
4
|
+
import { usePlayerStateEmitter } from "./usePlayerStateEmitter.mjs";
|
|
5
|
+
import { usePlayerMediaApi } from "./usePlayerMediaApi.mjs";
|
|
6
|
+
export function usePlayerVideoApi(args) {
|
|
7
|
+
const fullscreenTarget = ref(void 0);
|
|
8
|
+
const { playing, currentTime, muted } = usePlayerMediaApi({
|
|
9
|
+
id: toValue(args.id)
|
|
10
|
+
});
|
|
11
|
+
const { playerRef, videoRef } = args;
|
|
12
|
+
const touched = ref(false);
|
|
13
|
+
const mouseEntered = ref(false);
|
|
14
|
+
const { isFullscreen, enter, exit } = useFullscreen(fullscreenTarget);
|
|
15
|
+
function play() {
|
|
16
|
+
playing.value = true;
|
|
17
|
+
}
|
|
18
|
+
function pause() {
|
|
19
|
+
playing.value = false;
|
|
20
|
+
}
|
|
21
|
+
function togglePlay() {
|
|
22
|
+
playing.value = !playing.value;
|
|
23
|
+
}
|
|
24
|
+
function seek(time) {
|
|
25
|
+
currentTime.value = time;
|
|
26
|
+
}
|
|
27
|
+
function mute() {
|
|
28
|
+
muted.value = true;
|
|
29
|
+
}
|
|
30
|
+
function unmute() {
|
|
31
|
+
muted.value = false;
|
|
32
|
+
}
|
|
33
|
+
function onMouseenter() {
|
|
34
|
+
mouseEntered.value = true;
|
|
35
|
+
}
|
|
36
|
+
function onMouseleave() {
|
|
37
|
+
mouseEntered.value = false;
|
|
38
|
+
}
|
|
39
|
+
function enterFullscreen() {
|
|
40
|
+
if (!fullscreenTarget.value) {
|
|
41
|
+
console.error("No fullscreen target found");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
enter();
|
|
45
|
+
}
|
|
46
|
+
function exitFullscreen() {
|
|
47
|
+
if (!fullscreenTarget.value) {
|
|
48
|
+
console.error("No fullscreen target found");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
exit();
|
|
52
|
+
}
|
|
53
|
+
watch(playing, (value) => {
|
|
54
|
+
if (!touched.value && value) {
|
|
55
|
+
touched.value = true;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
if (playerRef && !videoRef) {
|
|
59
|
+
watch(playerRef, (value) => {
|
|
60
|
+
if (value) {
|
|
61
|
+
fullscreenTarget.value = toValue(value);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (videoRef && !playerRef) {
|
|
66
|
+
watch(videoRef, (value) => {
|
|
67
|
+
if (value) {
|
|
68
|
+
fullscreenTarget.value = toValue(value);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (videoRef && playerRef) {
|
|
73
|
+
watch([playerRef, videoRef], ([player, video]) => {
|
|
74
|
+
if (player && video) {
|
|
75
|
+
fullscreenTarget.value = isIOS() ? toValue(video) : toValue(player);
|
|
76
|
+
} else if (player) {
|
|
77
|
+
fullscreenTarget.value = toValue(player);
|
|
78
|
+
} else if (video) {
|
|
79
|
+
fullscreenTarget.value = toValue(video);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const emitter = usePlayerStateEmitter();
|
|
84
|
+
emitter.on("update", (payload) => {
|
|
85
|
+
if (payload.id !== toValue(args.id))
|
|
86
|
+
return;
|
|
87
|
+
if (payload.api === "player") {
|
|
88
|
+
switch (payload.key) {
|
|
89
|
+
case "mouseEntered":
|
|
90
|
+
mouseEntered.value = payload.value;
|
|
91
|
+
break;
|
|
92
|
+
case "fullscreenTarget":
|
|
93
|
+
fullscreenTarget.value = payload.value;
|
|
94
|
+
break;
|
|
95
|
+
case "touched":
|
|
96
|
+
touched.value = payload.value;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
watch(mouseEntered, (value) => {
|
|
102
|
+
emitter.emit("update", {
|
|
103
|
+
id: toValue(args.id),
|
|
104
|
+
api: "player",
|
|
105
|
+
key: "mouseEntered",
|
|
106
|
+
value
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
watch(touched, (value) => {
|
|
110
|
+
emitter.emit("update", {
|
|
111
|
+
id: toValue(args.id),
|
|
112
|
+
api: "player",
|
|
113
|
+
key: "touched",
|
|
114
|
+
value
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
watch(fullscreenTarget, (value) => {
|
|
118
|
+
if (!value)
|
|
119
|
+
return;
|
|
120
|
+
emitter.emit("update", {
|
|
121
|
+
id: toValue(args.id),
|
|
122
|
+
api: "player",
|
|
123
|
+
key: "fullscreenTarget",
|
|
124
|
+
value
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
return {
|
|
128
|
+
mouseEntered,
|
|
129
|
+
isFullscreen,
|
|
130
|
+
touched,
|
|
131
|
+
play,
|
|
132
|
+
pause,
|
|
133
|
+
togglePlay,
|
|
134
|
+
seek,
|
|
135
|
+
mute,
|
|
136
|
+
unmute,
|
|
137
|
+
enterFullscreen,
|
|
138
|
+
exitFullscreen,
|
|
139
|
+
onMouseenter,
|
|
140
|
+
onMouseleave
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -1,6 +1,64 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
instance: import("vue").ComputedRef<import("./private/usePlayerStore").PlayerInstance>;
|
|
1
|
+
import type { MaybeRef } from '@vueuse/core';
|
|
2
|
+
type usePlayerApiArgs = {
|
|
3
|
+
id: MaybeRef<string>;
|
|
5
4
|
};
|
|
6
|
-
export
|
|
5
|
+
export declare function usePlayerApi(args: usePlayerApiArgs): {
|
|
6
|
+
mediaApi: {
|
|
7
|
+
currentTime: import("vue").Ref<number>;
|
|
8
|
+
duration: import("vue").Ref<number>;
|
|
9
|
+
seeking: import("vue").Ref<boolean>;
|
|
10
|
+
volume: import("vue").Ref<number>;
|
|
11
|
+
rate: import("vue").Ref<number>;
|
|
12
|
+
waiting: import("vue").Ref<boolean>;
|
|
13
|
+
ended: import("vue").Ref<boolean>;
|
|
14
|
+
playing: import("vue").Ref<boolean>;
|
|
15
|
+
stalled: import("vue").Ref<boolean>;
|
|
16
|
+
buffered: import("vue").Ref<[number, number][]>;
|
|
17
|
+
muted: import("vue").Ref<boolean>;
|
|
18
|
+
};
|
|
19
|
+
videoApi: {
|
|
20
|
+
mouseEntered: import("vue").Ref<boolean>;
|
|
21
|
+
isFullscreen: import("vue").Ref<boolean>;
|
|
22
|
+
touched: import("vue").Ref<boolean>;
|
|
23
|
+
play: () => void;
|
|
24
|
+
pause: () => void;
|
|
25
|
+
togglePlay: () => void;
|
|
26
|
+
seek: (time: number) => void;
|
|
27
|
+
mute: () => void;
|
|
28
|
+
unmute: () => void;
|
|
29
|
+
enterFullscreen: () => void;
|
|
30
|
+
exitFullscreen: () => void;
|
|
31
|
+
onMouseenter: () => void;
|
|
32
|
+
onMouseleave: () => void;
|
|
33
|
+
};
|
|
34
|
+
controlsApi: {
|
|
35
|
+
mouseEntered: import("vue").Ref<boolean>;
|
|
36
|
+
dragging: import("vue").Ref<boolean>;
|
|
37
|
+
seekedTime: import("vue").Ref<number>;
|
|
38
|
+
seekedPercentage: import("vue").Ref<number>;
|
|
39
|
+
scrubbedPercentage: import("vue").Ref<number>;
|
|
40
|
+
bufferedPercentage: import("vue").ComputedRef<number>;
|
|
41
|
+
thumbPercentage: import("vue").Ref<number>;
|
|
42
|
+
popoverOffsetX: import("vue").Ref<number>;
|
|
43
|
+
onMouseenter: () => void;
|
|
44
|
+
onMouseleave: () => void;
|
|
45
|
+
onPointerdown: (e: MouseEvent | TouchEvent) => void;
|
|
46
|
+
onPointerup: () => void;
|
|
47
|
+
onPointermove: (e: MouseEvent | TouchEvent) => void;
|
|
48
|
+
trackRect: import("vue").Ref<{
|
|
49
|
+
height: number;
|
|
50
|
+
width: number;
|
|
51
|
+
x: number;
|
|
52
|
+
y: number;
|
|
53
|
+
readonly bottom: number;
|
|
54
|
+
readonly left: number;
|
|
55
|
+
readonly right: number;
|
|
56
|
+
readonly top: number;
|
|
57
|
+
toJSON: () => any;
|
|
58
|
+
} | undefined>;
|
|
59
|
+
};
|
|
60
|
+
playerRuntime: {
|
|
61
|
+
loaded: import("vue").Ref<boolean>;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
export {};
|
|
@@ -1,69 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { useMediaApi } from "./private/useMediaApi.mjs";
|
|
6
|
-
import { useControlsApi } from "./private/useControlsApi.mjs";
|
|
7
|
-
import { useRuntimeSourceProvider } from "./private/useRuntimeSourceProvider.mjs";
|
|
1
|
+
import { usePlayerMediaApi } from "./private/usePlayerMediaApi.mjs";
|
|
2
|
+
import { usePlayerVideoApi } from "./private/usePlayerVideoApi.mjs";
|
|
3
|
+
import { usePlayerRuntime } from "./private/usePlayerRuntime.mjs";
|
|
4
|
+
import { usePlayerControlsApi } from "./private/usePlayerControlsApi.mjs";
|
|
8
5
|
export function usePlayerApi(args) {
|
|
9
|
-
const {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} else if ("id" in args) {
|
|
14
|
-
return toValue(args.id) || uuid();
|
|
15
|
-
} else {
|
|
16
|
-
return uuid();
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
const instance = computed(() => findInstance(toValue(mappedId)));
|
|
20
|
-
function initialize() {
|
|
21
|
-
const id = toValue(mappedId);
|
|
22
|
-
let instance2 = findInstance(id);
|
|
23
|
-
if (!instance2) {
|
|
24
|
-
instance2 = addInstance(id);
|
|
25
|
-
}
|
|
26
|
-
if (typeof args !== "string") {
|
|
27
|
-
if ("mediaRef" in args) {
|
|
28
|
-
instance2.mediaApi = useMediaApi({ mediaRef: args.mediaRef });
|
|
29
|
-
} else if ("videoRef" in args) {
|
|
30
|
-
instance2.mediaApi = useMediaApi({ mediaRef: args.videoRef });
|
|
31
|
-
}
|
|
32
|
-
if ("videoRef" in args && "playerRef" in args) {
|
|
33
|
-
instance2.playerApi = usePlayerInternalApi({
|
|
34
|
-
id,
|
|
35
|
-
playerRef: args.playerRef,
|
|
36
|
-
videoRef: args.videoRef
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
if ("videoRef" in args && "srcType" in args && "src" in args) {
|
|
40
|
-
instance2.runtimeProvider = useRuntimeSourceProvider({
|
|
41
|
-
videoRef: args.videoRef,
|
|
42
|
-
srcType: args.srcType,
|
|
43
|
-
src: args.src
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
if ("barRef" in args && "trackRef" in args) {
|
|
47
|
-
instance2.controlsApi = useControlsApi({
|
|
48
|
-
id,
|
|
49
|
-
barRef: args.barRef,
|
|
50
|
-
trackRef: args.trackRef,
|
|
51
|
-
popoverRef: args.popoverRef
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return instance2;
|
|
56
|
-
}
|
|
57
|
-
function destroy(id) {
|
|
58
|
-
if (!id)
|
|
59
|
-
return;
|
|
60
|
-
removeInstance(toValue(id));
|
|
61
|
-
}
|
|
62
|
-
onUnmounted(() => {
|
|
63
|
-
destroy(toValue(mappedId));
|
|
64
|
-
});
|
|
65
|
-
initialize();
|
|
6
|
+
const mediaApi = usePlayerMediaApi({ id: args.id });
|
|
7
|
+
const videoApi = usePlayerVideoApi({ id: args.id });
|
|
8
|
+
const controlsApi = usePlayerControlsApi({ id: args.id });
|
|
9
|
+
const playerRuntime = usePlayerRuntime({ id: args.id });
|
|
66
10
|
return {
|
|
67
|
-
|
|
11
|
+
mediaApi,
|
|
12
|
+
videoApi,
|
|
13
|
+
controlsApi,
|
|
14
|
+
playerRuntime
|
|
68
15
|
};
|
|
69
16
|
}
|
|
@@ -1,25 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
type
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
id: MaybeRef<string>;
|
|
14
|
-
playerRef: MaybeRef<HTMLElement | undefined>;
|
|
15
|
-
videoRef: MaybeRef<HTMLVideoElement | undefined>;
|
|
16
|
-
};
|
|
17
|
-
type UseRuntimeSourceProviderArgs = {
|
|
18
|
-
videoRef: MaybeRef<HTMLVideoElement | undefined>;
|
|
19
|
-
srcType: SourceType;
|
|
20
|
-
src: string;
|
|
21
|
-
};
|
|
22
|
-
type UsePlayerApiArgs = Partial<UseMediaApiArgs & UseControlsApiArgs & UsePlayerInternalApiArgs & UseRuntimeSourceProviderArgs> & {
|
|
23
|
-
id: MaybeRef<string>;
|
|
24
|
-
};
|
|
25
|
-
export type { SourceType, UseMediaApiArgs, UsePlayerApiArgs, UseControlsApiArgs, UsePlayerInternalApiArgs, UseRuntimeSourceProviderArgs, };
|
|
1
|
+
export type SourceType = 'native' | 'hls';
|
|
2
|
+
type API = 'media' | 'player' | 'controls' | 'runtime' | 'player';
|
|
3
|
+
export type Buffered = [number, number][];
|
|
4
|
+
export type PlayerPrivateEvents = {
|
|
5
|
+
update: {
|
|
6
|
+
id: string;
|
|
7
|
+
api: API;
|
|
8
|
+
key: string;
|
|
9
|
+
value: string | number | boolean | Buffered | DOMRect | HTMLElement;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maas/vue-equipment",
|
|
3
3
|
"description": "A magic collection of Vue composables, plugins, components and directives",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.21.0",
|
|
5
5
|
"author": "Robin Scholz <https://github.com/robinscholz>, Christoph Jeworutzki <https://github.com/ChristophJeworutzki>",
|
|
6
6
|
"devDependencies": {
|
|
7
7
|
"@antfu/ni": "^0.21.12",
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { UseControlsApiArgs } from '../../types.js';
|
|
2
|
-
export declare function useControlsApi(args: UseControlsApiArgs): {
|
|
3
|
-
mouseEntered: import("vue").Ref<boolean>;
|
|
4
|
-
dragging: import("vue").Ref<boolean>;
|
|
5
|
-
seekedTime: import("vue").Ref<number>;
|
|
6
|
-
seekedPercentage: import("vue").Ref<number>;
|
|
7
|
-
scrubbedPercentage: import("vue").Ref<number>;
|
|
8
|
-
bufferedPercentage: import("vue").ComputedRef<number>;
|
|
9
|
-
thumbPercentage: import("vue").Ref<number>;
|
|
10
|
-
popoverOffsetX: import("vue").Ref<number>;
|
|
11
|
-
onMouseenter: () => void;
|
|
12
|
-
onMouseleave: () => void;
|
|
13
|
-
onPointerdown: (e: MouseEvent | TouchEvent) => void;
|
|
14
|
-
onPointerup: () => void;
|
|
15
|
-
onPointermove: (e: MouseEvent | TouchEvent) => void;
|
|
16
|
-
};
|
|
17
|
-
export type UseControlsApiReturn = ReturnType<typeof useControlsApi>;
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { ref, computed, watch, toValue } from "vue";
|
|
2
|
-
import {
|
|
3
|
-
useResizeObserver,
|
|
4
|
-
useEventListener,
|
|
5
|
-
defaultWindow
|
|
6
|
-
} from "@vueuse/core";
|
|
7
|
-
import { clampValue, mapValue } from "@maas/vue-equipment/utils";
|
|
8
|
-
import { usePlayerStore } from "./usePlayerStore.mjs";
|
|
9
|
-
export function useControlsApi(args) {
|
|
10
|
-
const { findInstance } = usePlayerStore();
|
|
11
|
-
const instance = findInstance(toValue(args.id));
|
|
12
|
-
const { buffered, duration, playing, currentTime } = instance.mediaApi;
|
|
13
|
-
const { play, pause, seek } = instance.playerApi;
|
|
14
|
-
const dragging = ref(false);
|
|
15
|
-
const mouseEntered = ref(false);
|
|
16
|
-
const seekedTime = ref(0);
|
|
17
|
-
const seekedPercentage = ref(0);
|
|
18
|
-
const scrubbedPercentage = ref(0);
|
|
19
|
-
const thumbPercentage = ref(0);
|
|
20
|
-
const popoverOffsetX = ref(0);
|
|
21
|
-
const bufferedPercentage = computed(() => {
|
|
22
|
-
if (!instance?.mediaApi)
|
|
23
|
-
return 0;
|
|
24
|
-
const endBuffer = buffered.value?.length > 0 ? buffered.value[0][1] : 0;
|
|
25
|
-
const percentage = endBuffer / duration.value * 100;
|
|
26
|
-
return clampValue(percentage, 0, thumbPercentage.value);
|
|
27
|
-
});
|
|
28
|
-
const resumePlay = ref(false);
|
|
29
|
-
const barRect = ref(void 0);
|
|
30
|
-
const trackRect = ref(void 0);
|
|
31
|
-
const popoverRect = ref(void 0);
|
|
32
|
-
function getPopoverOffsetX() {
|
|
33
|
-
if (!trackRect.value || !popoverRect.value || !barRect.value) {
|
|
34
|
-
return 0;
|
|
35
|
-
} else {
|
|
36
|
-
const trackFactor = barRect.value.width / trackRect.value.width;
|
|
37
|
-
const offsetXPercentage = Math.abs(trackRect.value.x - barRect.value.x) / barRect.value.width * 100;
|
|
38
|
-
const popoverWidthPercentage = popoverRect.value.width / barRect.value.width * 100;
|
|
39
|
-
const maxPercentage = 100 - popoverWidthPercentage;
|
|
40
|
-
const percentage = seekedPercentage.value / trackFactor + offsetXPercentage - popoverWidthPercentage / 2;
|
|
41
|
-
popoverOffsetX.value = clampValue(percentage, 0, maxPercentage);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
function getTimelineTrackSize() {
|
|
45
|
-
trackRect.value = toValue(args.trackRef)?.getBoundingClientRect();
|
|
46
|
-
thumbPercentage.value = 100 - trackRect.value.height / trackRect.value.width * 100;
|
|
47
|
-
}
|
|
48
|
-
function getPopoverSizes() {
|
|
49
|
-
barRect.value = toValue(args.barRef)?.getBoundingClientRect();
|
|
50
|
-
popoverRect.value = toValue(args.popoverRef)?.getBoundingClientRect();
|
|
51
|
-
}
|
|
52
|
-
function seekToTrackPosition(absX) {
|
|
53
|
-
if (!trackRect.value) {
|
|
54
|
-
throw new Error("trackRect is undefined");
|
|
55
|
-
}
|
|
56
|
-
const relX = absX - trackRect.value.x - trackRect.value.height / 2;
|
|
57
|
-
const percentage = Math.round(relX / trackRect.value.width * 100);
|
|
58
|
-
seekedPercentage.value = clampValue(percentage, 0, thumbPercentage.value);
|
|
59
|
-
seekedTime.value = duration.value * mapValue(seekedPercentage.value, 0, thumbPercentage.value, 0, 100) / 100;
|
|
60
|
-
if (dragging.value) {
|
|
61
|
-
scrubbedPercentage.value = seekedPercentage.value;
|
|
62
|
-
seek(seekedTime.value);
|
|
63
|
-
}
|
|
64
|
-
getPopoverOffsetX();
|
|
65
|
-
}
|
|
66
|
-
function onMouseenter() {
|
|
67
|
-
getTimelineTrackSize();
|
|
68
|
-
getPopoverSizes();
|
|
69
|
-
mouseEntered.value = true;
|
|
70
|
-
}
|
|
71
|
-
function onMouseleave() {
|
|
72
|
-
mouseEntered.value = false;
|
|
73
|
-
dragging.value = false;
|
|
74
|
-
seekedTime.value = 0;
|
|
75
|
-
}
|
|
76
|
-
function onPointerdown(e) {
|
|
77
|
-
dragging.value = true;
|
|
78
|
-
resumePlay.value = playing.value;
|
|
79
|
-
pause();
|
|
80
|
-
const x = e instanceof MouseEvent ? e.pageX : e.touches[0].pageX;
|
|
81
|
-
seekToTrackPosition(x);
|
|
82
|
-
}
|
|
83
|
-
function onPointerup() {
|
|
84
|
-
dragging.value = false;
|
|
85
|
-
if (resumePlay.value) {
|
|
86
|
-
play();
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
function onPointermove(e) {
|
|
90
|
-
const x = e instanceof MouseEvent ? e.pageX : e.touches[0].pageX;
|
|
91
|
-
seekToTrackPosition(x);
|
|
92
|
-
}
|
|
93
|
-
watch(currentTime, (value) => {
|
|
94
|
-
const percentage = value / duration.value * 100;
|
|
95
|
-
scrubbedPercentage.value = mapValue(
|
|
96
|
-
percentage,
|
|
97
|
-
0,
|
|
98
|
-
100,
|
|
99
|
-
0,
|
|
100
|
-
thumbPercentage.value
|
|
101
|
-
);
|
|
102
|
-
});
|
|
103
|
-
useResizeObserver(args.trackRef, getTimelineTrackSize);
|
|
104
|
-
useResizeObserver(args.popoverRef, getPopoverSizes);
|
|
105
|
-
useEventListener(
|
|
106
|
-
defaultWindow,
|
|
107
|
-
"resize",
|
|
108
|
-
() => {
|
|
109
|
-
getTimelineTrackSize;
|
|
110
|
-
getPopoverSizes;
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
passive: true
|
|
114
|
-
}
|
|
115
|
-
);
|
|
116
|
-
return {
|
|
117
|
-
mouseEntered,
|
|
118
|
-
dragging,
|
|
119
|
-
seekedTime,
|
|
120
|
-
seekedPercentage,
|
|
121
|
-
scrubbedPercentage,
|
|
122
|
-
bufferedPercentage,
|
|
123
|
-
thumbPercentage,
|
|
124
|
-
popoverOffsetX,
|
|
125
|
-
onMouseenter,
|
|
126
|
-
onMouseleave,
|
|
127
|
-
onPointerdown,
|
|
128
|
-
onPointerup,
|
|
129
|
-
onPointermove
|
|
130
|
-
};
|
|
131
|
-
}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { ref, watch, unref, toValue } from "vue";
|
|
2
|
-
import { useEventListener, watchIgnorable } from "@vueuse/core";
|
|
3
|
-
export function useMediaApi(args) {
|
|
4
|
-
const currentTime = ref(0);
|
|
5
|
-
const duration = ref(0);
|
|
6
|
-
const seeking = ref(false);
|
|
7
|
-
const volume = ref(1);
|
|
8
|
-
const rate = ref(1);
|
|
9
|
-
const waiting = ref(false);
|
|
10
|
-
const ended = ref(false);
|
|
11
|
-
const playing = ref(false);
|
|
12
|
-
const stalled = ref(false);
|
|
13
|
-
const buffered = ref([]);
|
|
14
|
-
const muted = ref(false);
|
|
15
|
-
const { mediaRef } = args;
|
|
16
|
-
function timeRangeToArray(timeRanges) {
|
|
17
|
-
let ranges = [];
|
|
18
|
-
for (let i = 0; i < timeRanges.length; ++i)
|
|
19
|
-
ranges = [...ranges, [timeRanges.start(i), timeRanges.end(i)]];
|
|
20
|
-
return ranges;
|
|
21
|
-
}
|
|
22
|
-
watch([mediaRef, volume], () => {
|
|
23
|
-
const el = toValue(mediaRef);
|
|
24
|
-
if (!el)
|
|
25
|
-
return;
|
|
26
|
-
el.volume = volume.value;
|
|
27
|
-
});
|
|
28
|
-
watch([mediaRef, muted], () => {
|
|
29
|
-
const el = toValue(mediaRef);
|
|
30
|
-
if (!el)
|
|
31
|
-
return;
|
|
32
|
-
el.muted = muted.value;
|
|
33
|
-
});
|
|
34
|
-
watch([mediaRef, rate], () => {
|
|
35
|
-
const el = toValue(mediaRef);
|
|
36
|
-
if (!el)
|
|
37
|
-
return;
|
|
38
|
-
el.playbackRate = rate.value;
|
|
39
|
-
});
|
|
40
|
-
const { ignoreUpdates: ignoreCurrentTimeUpdates } = watchIgnorable(
|
|
41
|
-
currentTime,
|
|
42
|
-
(time) => {
|
|
43
|
-
const el = toValue(mediaRef);
|
|
44
|
-
if (!el)
|
|
45
|
-
return;
|
|
46
|
-
el.currentTime = unref(time);
|
|
47
|
-
}
|
|
48
|
-
);
|
|
49
|
-
const { ignoreUpdates: ignorePlayingUpdates } = watchIgnorable(
|
|
50
|
-
playing,
|
|
51
|
-
(isPlaying) => {
|
|
52
|
-
const el = toValue(mediaRef);
|
|
53
|
-
if (!el)
|
|
54
|
-
return;
|
|
55
|
-
isPlaying ? el.play() : el.pause();
|
|
56
|
-
}
|
|
57
|
-
);
|
|
58
|
-
useEventListener(mediaRef, "timeupdate", () => {
|
|
59
|
-
ignoreCurrentTimeUpdates(
|
|
60
|
-
() => currentTime.value = toValue(mediaRef).currentTime
|
|
61
|
-
);
|
|
62
|
-
});
|
|
63
|
-
useEventListener(mediaRef, "durationchange", () => {
|
|
64
|
-
duration.value = toValue(mediaRef).duration;
|
|
65
|
-
});
|
|
66
|
-
useEventListener(mediaRef, "progress", () => {
|
|
67
|
-
buffered.value = timeRangeToArray(toValue(mediaRef).buffered);
|
|
68
|
-
});
|
|
69
|
-
useEventListener(mediaRef, "seeking", () => {
|
|
70
|
-
seeking.value = true;
|
|
71
|
-
});
|
|
72
|
-
useEventListener(mediaRef, "seeked", () => {
|
|
73
|
-
seeking.value = false;
|
|
74
|
-
});
|
|
75
|
-
useEventListener(mediaRef, ["waiting", "loadstart"], () => {
|
|
76
|
-
waiting.value = true;
|
|
77
|
-
ignorePlayingUpdates(() => playing.value = false);
|
|
78
|
-
});
|
|
79
|
-
useEventListener(mediaRef, "loadeddata", () => {
|
|
80
|
-
waiting.value = false;
|
|
81
|
-
});
|
|
82
|
-
useEventListener(mediaRef, "playing", () => {
|
|
83
|
-
waiting.value = false;
|
|
84
|
-
ended.value = false;
|
|
85
|
-
ignorePlayingUpdates(() => playing.value = true);
|
|
86
|
-
});
|
|
87
|
-
useEventListener(mediaRef, "ratechange", () => {
|
|
88
|
-
rate.value = toValue(mediaRef).playbackRate;
|
|
89
|
-
});
|
|
90
|
-
useEventListener(mediaRef, "stalled", () => {
|
|
91
|
-
stalled.value = true;
|
|
92
|
-
});
|
|
93
|
-
useEventListener(mediaRef, "ended", () => {
|
|
94
|
-
ended.value = true;
|
|
95
|
-
});
|
|
96
|
-
useEventListener(mediaRef, "pause", () => {
|
|
97
|
-
playing.value = false;
|
|
98
|
-
});
|
|
99
|
-
useEventListener(mediaRef, "play", () => {
|
|
100
|
-
playing.value = true;
|
|
101
|
-
});
|
|
102
|
-
useEventListener(mediaRef, "volumechange", () => {
|
|
103
|
-
const el = toValue(mediaRef);
|
|
104
|
-
if (!el)
|
|
105
|
-
return;
|
|
106
|
-
volume.value = el.volume;
|
|
107
|
-
muted.value = el.muted;
|
|
108
|
-
});
|
|
109
|
-
return {
|
|
110
|
-
currentTime,
|
|
111
|
-
duration,
|
|
112
|
-
waiting,
|
|
113
|
-
seeking,
|
|
114
|
-
ended,
|
|
115
|
-
stalled,
|
|
116
|
-
buffered,
|
|
117
|
-
playing,
|
|
118
|
-
rate,
|
|
119
|
-
volume,
|
|
120
|
-
muted
|
|
121
|
-
};
|
|
122
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { UsePlayerInternalApiArgs } from '../../types.js';
|
|
2
|
-
export declare function usePlayerInternalApi(args: UsePlayerInternalApiArgs): {
|
|
3
|
-
mouseEntered: import("vue").Ref<boolean>;
|
|
4
|
-
isFullscreen: import("vue").Ref<boolean>;
|
|
5
|
-
touched: import("vue").Ref<boolean>;
|
|
6
|
-
play: () => void;
|
|
7
|
-
pause: () => void;
|
|
8
|
-
togglePlay: () => void;
|
|
9
|
-
seek: (time: number) => void;
|
|
10
|
-
mute: () => void;
|
|
11
|
-
unmute: () => void;
|
|
12
|
-
enterFullscreen: () => Promise<void>;
|
|
13
|
-
exitFullscreen: () => Promise<void>;
|
|
14
|
-
toggleFullscreen: () => Promise<void>;
|
|
15
|
-
onMouseenter: () => void;
|
|
16
|
-
onMouseleave: () => void;
|
|
17
|
-
};
|
|
18
|
-
export type UsePlayerInternalApiReturn = ReturnType<typeof usePlayerInternalApi>;
|