@maas/vue-equipment 1.0.0-beta.27 → 1.0.0-beta.29
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/plugins/MagicPlayer/src/components/MagicPlayerAudioControls.vue +2 -0
- package/dist/plugins/MagicPlayer/src/components/MagicPlayerMuxPopover.vue +40 -27
- package/dist/plugins/MagicPlayer/src/components/MagicPlayerProvider.vue +2 -4
- package/dist/plugins/MagicPlayer/src/components/MagicPlayerVideoControls.vue +14 -11
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerControlsApi.mjs +6 -1
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerProvider.d.ts +0 -1
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerProvider.mjs +8 -9
- package/dist/plugins/MagicPlayer/src/composables/private/usePlayerState.mjs +2 -2
- package/dist/plugins/MagicPlayer/src/composables/useMagicPlayer.d.ts +2 -2
- package/dist/plugins/MagicPlayer/src/css/magic-player-audio-controls.css +0 -1
- package/dist/plugins/MagicPlayer/src/css/magic-player-timeline.css +4 -0
- package/dist/plugins/MagicPlayer/src/types/index.d.ts +2 -2
- package/package.json +1 -1
package/dist/nuxt/module.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
<div
|
|
3
3
|
class="magic-player-audio-controls"
|
|
4
4
|
:data-touched="touched"
|
|
5
|
+
:data-dragging="dragging"
|
|
5
6
|
:data-started="started"
|
|
6
7
|
:data-playing="playing"
|
|
7
8
|
:data-paused="paused"
|
|
@@ -105,6 +106,7 @@ const {
|
|
|
105
106
|
muted,
|
|
106
107
|
waiting,
|
|
107
108
|
touched,
|
|
109
|
+
dragging,
|
|
108
110
|
controlsMouseEntered
|
|
109
111
|
} = toRefs(state);
|
|
110
112
|
const { idle } = useIdle(injectedOptions?.threshold?.idle);
|
|
@@ -46,42 +46,25 @@ const storyboard = shallowRef();
|
|
|
46
46
|
let context = void 0;
|
|
47
47
|
let image = void 0;
|
|
48
48
|
const thumbWidth = computed(() => {
|
|
49
|
-
if (!storyboard.value)
|
|
49
|
+
if (!storyboard.value) {
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
50
52
|
return storyboard.value.tile_width / pixelRatio.value;
|
|
51
53
|
});
|
|
52
54
|
const thumbHeight = computed(() => {
|
|
53
|
-
if (!storyboard.value)
|
|
55
|
+
if (!storyboard.value) {
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
54
58
|
return storyboard.value.tile_height / pixelRatio.value;
|
|
55
59
|
});
|
|
56
60
|
function getMuxId(url) {
|
|
57
61
|
const match = url?.match(/mux\.com\/([^\/]+)/);
|
|
58
62
|
return match?.[1]?.replace(/\.(m3u8|mp4)$/, "");
|
|
59
63
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const mappedPlaybackId = playbackId ?? parsedPlaybackId;
|
|
63
|
-
if (!mappedPlaybackId) {
|
|
64
|
-
console.error(
|
|
65
|
-
"MagicPlayerMuxPopover must be nested inside MagicPlayerProvider or a playbackId must be provided"
|
|
66
|
-
);
|
|
64
|
+
function drawFrame(time) {
|
|
65
|
+
if (!storyboard.value || !context || !image || !time) {
|
|
67
66
|
return;
|
|
68
67
|
}
|
|
69
|
-
try {
|
|
70
|
-
storyboard.value = await fetch(
|
|
71
|
-
`https://image.mux.com/${mappedPlaybackId}/storyboard.json`
|
|
72
|
-
).then((res) => res.json());
|
|
73
|
-
if (!storyboard.value) throw new Error();
|
|
74
|
-
image = new Image();
|
|
75
|
-
image.src = storyboard.value.url;
|
|
76
|
-
await image.decode();
|
|
77
|
-
context = canvasRef.value?.getContext("2d");
|
|
78
|
-
context?.drawImage(image, 0, 0);
|
|
79
|
-
} catch (e) {
|
|
80
|
-
console.error("Can not initialize timeine preview.", e);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
function drawFrame(time) {
|
|
84
|
-
if (!storyboard.value || !context || !image) return;
|
|
85
68
|
const { tile_height, tile_width, tiles } = storyboard.value;
|
|
86
69
|
let closestIndex = -1;
|
|
87
70
|
let minDifference = Infinity;
|
|
@@ -106,8 +89,38 @@ function drawFrame(time) {
|
|
|
106
89
|
tile_height
|
|
107
90
|
);
|
|
108
91
|
}
|
|
109
|
-
|
|
110
|
-
|
|
92
|
+
async function initialize() {
|
|
93
|
+
const parsedPlaybackId = getMuxId(injectedOptions?.src);
|
|
94
|
+
const mappedPlaybackId = playbackId ?? parsedPlaybackId;
|
|
95
|
+
if (!mappedPlaybackId) {
|
|
96
|
+
console.error(
|
|
97
|
+
"MagicPlayerMuxPopover must be nested inside MagicPlayerProvider or a playbackId must be provided"
|
|
98
|
+
);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
storyboard.value = await fetch(
|
|
103
|
+
`https://image.mux.com/${mappedPlaybackId}/storyboard.json`
|
|
104
|
+
).then((res) => res.json());
|
|
105
|
+
if (!storyboard.value) {
|
|
106
|
+
throw new Error();
|
|
107
|
+
}
|
|
108
|
+
image = new Image();
|
|
109
|
+
image.src = storyboard.value.url;
|
|
110
|
+
await image.decode();
|
|
111
|
+
context = canvasRef.value?.getContext("2d");
|
|
112
|
+
drawFrame(seekedTime.value);
|
|
113
|
+
} catch (e) {
|
|
114
|
+
console.error("Can not initialize timeline preview", e);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
onMounted(() => {
|
|
118
|
+
initialize();
|
|
119
|
+
});
|
|
120
|
+
watch(
|
|
121
|
+
() => seekedTime?.value,
|
|
122
|
+
(value) => drawFrame(value)
|
|
123
|
+
);
|
|
111
124
|
</script>
|
|
112
125
|
|
|
113
126
|
<style>
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
:data-waiting="waiting"
|
|
13
13
|
:data-loaded="loaded"
|
|
14
14
|
:data-muted="muted"
|
|
15
|
-
@touchstart="onTouchstart"
|
|
16
15
|
@mouseenter="onMouseenter"
|
|
17
16
|
@mouseleave="onMouseleave"
|
|
18
17
|
@pointerdown="onPointerdown"
|
|
@@ -54,10 +53,9 @@ const {
|
|
|
54
53
|
muted,
|
|
55
54
|
loaded,
|
|
56
55
|
fullscreen,
|
|
57
|
-
touched
|
|
58
|
-
hasOverlay
|
|
56
|
+
touched
|
|
59
57
|
} = toRefs(state);
|
|
60
|
-
const {
|
|
58
|
+
const { onMouseenter, onMouseleave, onPointerdown } = usePlayerProvider(id);
|
|
61
59
|
const playerRef = useTemplateRef("player");
|
|
62
60
|
const { initializeEmitter } = usePlayerEmitter({ id });
|
|
63
61
|
onMounted(() => {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
-
ref="el"
|
|
4
3
|
class="magic-player-video-controls"
|
|
5
4
|
:data-fullscreen="fullscreen"
|
|
6
5
|
:data-touched="touched"
|
|
6
|
+
:data-dragging="dragging"
|
|
7
7
|
:data-started="started"
|
|
8
8
|
:data-playing="playing"
|
|
9
9
|
:data-paused="paused"
|
|
@@ -18,13 +18,16 @@
|
|
|
18
18
|
<transition :name="mappedTransition">
|
|
19
19
|
<div v-show="visible" class="magic-player-video-controls__bar">
|
|
20
20
|
<div
|
|
21
|
-
v-if="$slots.popover"
|
|
22
|
-
v-show="!!seekedTime && touched"
|
|
21
|
+
v-if="$slots.popover && seekedTime !== null && seekedTime >= 0"
|
|
23
22
|
ref="popover"
|
|
24
23
|
class="magic-player-video-controls__popover"
|
|
25
|
-
:style="{
|
|
24
|
+
:style="{
|
|
25
|
+
marginLeft: `${popoverOffsetX}%`
|
|
26
|
+
}"
|
|
26
27
|
>
|
|
27
|
-
<
|
|
28
|
+
<div v-show="popoverOffsetX !== null">
|
|
29
|
+
<slot name="popover" />
|
|
30
|
+
</div>
|
|
28
31
|
</div>
|
|
29
32
|
<div ref="bar" class="magic-player-video-controls__bar--inner">
|
|
30
33
|
<div class="magic-player-video-controls__item -shrink-0">
|
|
@@ -85,7 +88,7 @@ import {
|
|
|
85
88
|
useTemplateRef,
|
|
86
89
|
onBeforeUnmount
|
|
87
90
|
} from "vue";
|
|
88
|
-
import {
|
|
91
|
+
import { useIdle } from "@vueuse/core";
|
|
89
92
|
import IconPlay from "./icons/Play.vue";
|
|
90
93
|
import IconPause from "./icons/Pause.vue";
|
|
91
94
|
import IconVolumeOn from "./icons/VolumeOn.vue";
|
|
@@ -141,7 +144,8 @@ const {
|
|
|
141
144
|
fullscreen,
|
|
142
145
|
popoverOffsetX,
|
|
143
146
|
hasOverlay,
|
|
144
|
-
seekedTime
|
|
147
|
+
seekedTime,
|
|
148
|
+
dragging
|
|
145
149
|
} = toRefs(state);
|
|
146
150
|
const { play, pause, mute, unmute, enterFullscreen, exitFullscreen } = usePlayerVideoApi({ id: mappedInstanceId.value });
|
|
147
151
|
const { initialize, destroy, onMouseenter, onMouseleave } = usePlayerControlsApi({
|
|
@@ -150,18 +154,17 @@ const { initialize, destroy, onMouseenter, onMouseleave } = usePlayerControlsApi
|
|
|
150
154
|
trackRef,
|
|
151
155
|
popoverRef
|
|
152
156
|
});
|
|
153
|
-
const elRef = useTemplateRef("el");
|
|
154
|
-
const isVisible = useElementVisibility(elRef);
|
|
155
157
|
const { idle } = useIdle(injectedOptions?.threshold?.idle);
|
|
156
158
|
const visible = computed(() => {
|
|
157
159
|
switch (true) {
|
|
158
160
|
case standalone:
|
|
159
161
|
return true;
|
|
160
|
-
case !isVisible.value:
|
|
161
162
|
case (hasOverlay.value && !started.value):
|
|
162
163
|
case (playing.value && idle.value):
|
|
163
164
|
case (playing.value && !mouseEntered.value && !controlsMouseEntered.value):
|
|
164
|
-
case (injectedOptions?.autoplay &&
|
|
165
|
+
case (injectedOptions?.autoplay && !started.value):
|
|
166
|
+
case (injectedOptions?.autoplay && !mouseEntered.value):
|
|
167
|
+
case (injectedOptions?.autoplay && !mouseEntered.value && !touched.value):
|
|
165
168
|
return false;
|
|
166
169
|
default:
|
|
167
170
|
return true;
|
|
@@ -101,6 +101,7 @@ export function usePlayerControlsApi(args) {
|
|
|
101
101
|
}
|
|
102
102
|
function resetStateAndListeners() {
|
|
103
103
|
dragging.value = false;
|
|
104
|
+
touched.value = false;
|
|
104
105
|
cancelTouchend?.();
|
|
105
106
|
cancelPointerup?.();
|
|
106
107
|
cancelPointermove?.();
|
|
@@ -149,7 +150,11 @@ export function usePlayerControlsApi(args) {
|
|
|
149
150
|
function onMouseleave() {
|
|
150
151
|
controlsMouseEntered.value = false;
|
|
151
152
|
if (!dragging.value) {
|
|
152
|
-
seekedTime.value =
|
|
153
|
+
seekedTime.value = null;
|
|
154
|
+
popoverOffsetX.value = null;
|
|
155
|
+
seekedPercentage.value = 0;
|
|
156
|
+
scrubbedPercentage.value = 0;
|
|
157
|
+
thumbPercentage.value = 0;
|
|
153
158
|
}
|
|
154
159
|
}
|
|
155
160
|
let watchTrack = null;
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { toRefs } from "vue";
|
|
2
2
|
import { useEventListener } from "@vueuse/core";
|
|
3
|
+
import { isIOS } from "@maas/vue-equipment/utils";
|
|
3
4
|
import { usePlayerState } from "./usePlayerState.mjs";
|
|
4
5
|
export function usePlayerProvider(id) {
|
|
5
6
|
const { initializeState } = usePlayerState(id);
|
|
6
7
|
const state = initializeState();
|
|
7
8
|
const { mouseEntered, touched } = toRefs(state);
|
|
9
|
+
let cancelPointerup = void 0;
|
|
8
10
|
let cancelTouchend = void 0;
|
|
9
|
-
function
|
|
11
|
+
function onPointerup() {
|
|
12
|
+
touched.value = false;
|
|
13
|
+
cancelPointerup?.();
|
|
10
14
|
cancelTouchend?.();
|
|
15
|
+
cancelPointerup = void 0;
|
|
11
16
|
cancelTouchend = void 0;
|
|
12
|
-
mouseEntered.value = false;
|
|
13
|
-
}
|
|
14
|
-
function onTouchstart() {
|
|
15
|
-
mouseEntered.value = true;
|
|
16
|
-
cancelTouchend = useEventListener(document, "touchend", onTouchend, {
|
|
17
|
-
passive: true
|
|
18
|
-
});
|
|
19
17
|
}
|
|
20
18
|
function onMouseenter() {
|
|
21
19
|
mouseEntered.value = true;
|
|
@@ -25,9 +23,10 @@ export function usePlayerProvider(id) {
|
|
|
25
23
|
}
|
|
26
24
|
function onPointerdown() {
|
|
27
25
|
touched.value = true;
|
|
26
|
+
cancelPointerup = useEventListener(document, "pointerup", onPointerup);
|
|
27
|
+
cancelTouchend = isIOS() ? useEventListener(document, "touchend", onPointerup) : void 0;
|
|
28
28
|
}
|
|
29
29
|
return {
|
|
30
|
-
onTouchstart,
|
|
31
30
|
onMouseenter,
|
|
32
31
|
onMouseleave,
|
|
33
32
|
onPointerdown
|
|
@@ -24,11 +24,11 @@ export function usePlayerState(id) {
|
|
|
24
24
|
fullscreenTarget: null,
|
|
25
25
|
mouseEntered: false,
|
|
26
26
|
controlsMouseEntered: false,
|
|
27
|
-
seekedTime:
|
|
27
|
+
seekedTime: null,
|
|
28
28
|
seekedPercentage: 0,
|
|
29
29
|
scrubbedPercentage: 0,
|
|
30
30
|
thumbPercentage: 0,
|
|
31
|
-
popoverOffsetX:
|
|
31
|
+
popoverOffsetX: null,
|
|
32
32
|
hasOverlay: false,
|
|
33
33
|
hasControls: false,
|
|
34
34
|
controlsBarRect: void 0,
|
|
@@ -17,11 +17,11 @@ export declare function useMagicPlayer(id: MaybeRef<string>): {
|
|
|
17
17
|
dragging: import("vue").Ref<boolean, boolean>;
|
|
18
18
|
fullscreen: import("vue").Ref<boolean, boolean>;
|
|
19
19
|
currentTime: import("vue").Ref<number, number>;
|
|
20
|
-
seekedTime: import("vue").Ref<number, number>;
|
|
20
|
+
seekedTime: import("vue").Ref<number | null, number | null>;
|
|
21
21
|
seekedPercentage: import("vue").Ref<number, number>;
|
|
22
22
|
scrubbedPercentage: import("vue").Ref<number, number>;
|
|
23
23
|
thumbPercentage: import("vue").Ref<number, number>;
|
|
24
|
-
popoverOffsetX: import("vue").Ref<number, number>;
|
|
24
|
+
popoverOffsetX: import("vue").Ref<number | null, number | null>;
|
|
25
25
|
audioApi: {
|
|
26
26
|
play: () => void;
|
|
27
27
|
pause: () => void;
|
|
@@ -55,11 +55,11 @@ export interface PlayerState {
|
|
|
55
55
|
fullscreenTarget: HTMLElement | null;
|
|
56
56
|
mouseEntered: boolean;
|
|
57
57
|
controlsMouseEntered: boolean;
|
|
58
|
-
seekedTime: number;
|
|
58
|
+
seekedTime: number | null;
|
|
59
59
|
seekedPercentage: number;
|
|
60
60
|
scrubbedPercentage: number;
|
|
61
61
|
thumbPercentage: number;
|
|
62
|
-
popoverOffsetX: number;
|
|
62
|
+
popoverOffsetX: number | null;
|
|
63
63
|
hasOverlay: boolean;
|
|
64
64
|
hasControls: boolean;
|
|
65
65
|
controlsBarRect: DOMRect | undefined;
|