@banou/media-player 0.6.2 → 0.8.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/README.md +149 -3
- package/dist/engine/index.d.ts +10 -0
- package/dist/engine/index.js +2 -0
- package/dist/engine/picture-in-picture.d.ts +27 -0
- package/dist/engine/playback.d.ts +45 -0
- package/dist/engine/source-buffer.d.ts +12 -0
- package/dist/engine/subtitles.d.ts +36 -0
- package/dist/engine/thumbnails.d.ts +22 -0
- package/dist/engine-Dmc7JSd9.js +470 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +1610 -0
- package/dist/react/components/chrome.d.ts +12 -0
- package/dist/react/components/control-bar.d.ts +2 -0
- package/dist/react/components/overlay.d.ts +4 -0
- package/dist/react/components/playback-slider.d.ts +2 -0
- package/dist/react/components/progress-bar.d.ts +2 -0
- package/dist/react/components/settings.d.ts +2 -0
- package/dist/react/components/sound.d.ts +7 -0
- package/{build → dist/react}/components/tooltip-display.d.ts +8 -8
- package/dist/react/components/volume-slider.d.ts +6 -0
- package/dist/react/hooks/use-drag-value.d.ts +23 -0
- package/dist/react/hooks/use-picture-in-picture.d.ts +2 -0
- package/dist/react/hooks/use-playback.d.ts +8 -0
- package/dist/react/hooks/use-thumbnails.d.ts +12 -0
- package/dist/react/media.d.ts +98 -0
- package/dist/react/player.d.ts +26 -0
- package/dist/react/source-feature.d.ts +106 -0
- package/dist/react/video-player.d.ts +83 -0
- package/dist/utils/source.d.ts +30 -0
- package/dist/utils/track-label.d.ts +31 -0
- package/dist/utils/volume-utils.d.ts +6 -0
- package/package.json +58 -37
- package/src/lib/engine/index.ts +14 -0
- package/src/lib/engine/picture-in-picture.ts +250 -0
- package/src/lib/engine/playback.ts +352 -0
- package/src/lib/engine/source-buffer.ts +61 -0
- package/src/lib/engine/subtitles.ts +210 -0
- package/src/lib/engine/thumbnails.ts +137 -0
- package/src/lib/globals.d.ts +8 -0
- package/src/lib/index.tsx +51 -0
- package/src/lib/react/components/chrome.tsx +130 -0
- package/src/{components → lib/react/components}/control-bar.tsx +74 -96
- package/src/lib/react/components/overlay.tsx +125 -0
- package/src/{components → lib/react/components}/playback-slider.tsx +30 -52
- package/src/lib/react/components/progress-bar.tsx +341 -0
- package/src/lib/react/components/settings.tsx +384 -0
- package/src/lib/react/components/sound.tsx +133 -0
- package/src/{components → lib/react/components}/tooltip-display.tsx +15 -12
- package/src/{components → lib/react/components}/volume-slider.tsx +32 -46
- package/src/lib/react/hooks/use-drag-value.ts +73 -0
- package/src/lib/react/hooks/use-picture-in-picture.ts +36 -0
- package/src/lib/react/hooks/use-playback.ts +146 -0
- package/src/lib/react/hooks/use-thumbnails.ts +78 -0
- package/src/lib/react/media.ts +124 -0
- package/src/lib/react/player.ts +20 -0
- package/src/lib/react/source-feature.ts +108 -0
- package/src/lib/react/video-player.tsx +223 -0
- package/src/lib/utils/fonts.ts +160 -0
- package/src/lib/utils/source.ts +60 -0
- package/src/lib/utils/track-label.ts +51 -0
- package/src/lib/utils/volume-utils.ts +13 -0
- package/build/components/chrome.d.ts +0 -7
- package/build/components/control-bar.d.ts +0 -6
- package/build/components/overlay.d.ts +0 -4
- package/build/components/playback-slider.d.ts +0 -2
- package/build/components/progress-bar.d.ts +0 -1
- package/build/components/settings.d.ts +0 -2
- package/build/components/sound.d.ts +0 -4
- package/build/components/volume-slider.d.ts +0 -6
- package/build/index.d.ts +0 -26
- package/build/index.js +0 -3416
- package/build/main.d.ts +0 -1
- package/build/state-machines/data-source.d.ts +0 -27
- package/build/state-machines/index.d.ts +0 -34038
- package/build/state-machines/media-properties.d.ts +0 -45
- package/build/state-machines/media-source.d.ts +0 -34
- package/build/state-machines/media.d.ts +0 -8558
- package/build/state-machines/subtitles.d.ts +0 -56
- package/build/state-machines/thumbnails.d.ts +0 -24
- package/build/state-machines/utils.d.ts +0 -26
- package/build/utils/actor-utils.d.ts +0 -2
- package/build/utils/context.d.ts +0 -14
- package/build/utils/index.d.ts +0 -4
- package/build/utils/languages.d.ts +0 -260
- package/build/utils/mp4box.d.ts +0 -61
- package/build/utils/use-local-storage.d.ts +0 -3
- package/build/utils/use-scrub.d.ts +0 -11
- package/build/utils/volume-utils.d.ts +0 -17
- package/build/utils/window-height.d.ts +0 -2
- package/src/components/chrome.tsx +0 -95
- package/src/components/overlay.tsx +0 -91
- package/src/components/progress-bar.tsx +0 -251
- package/src/components/settings.tsx +0 -322
- package/src/components/sound.tsx +0 -101
- package/src/index.tsx +0 -195
- package/src/main.tsx +0 -169
- package/src/state-machines/data-source.ts +0 -84
- package/src/state-machines/index.ts +0 -5
- package/src/state-machines/media-properties.ts +0 -82
- package/src/state-machines/media-source.ts +0 -129
- package/src/state-machines/media.ts +0 -255
- package/src/state-machines/subtitles.ts +0 -285
- package/src/state-machines/thumbnails.ts +0 -123
- package/src/state-machines/utils.ts +0 -94
- package/src/utils/actor-utils.ts +0 -19
- package/src/utils/context.ts +0 -23
- package/src/utils/fonts.ts +0 -160
- package/src/utils/index.ts +0 -229
- package/src/utils/languages.ts +0 -262
- package/src/utils/mp4box.ts +0 -74
- package/src/utils/use-local-storage.ts +0 -30
- package/src/utils/use-scrub.ts +0 -40
- package/src/utils/volume-utils.ts +0 -39
- package/src/utils/window-height.ts +0 -19
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.json +0 -28
- package/tsconfig.node.json +0 -9
- /package/{build → dist}/utils/colors.d.ts +0 -0
- /package/{build → dist}/utils/fonts.d.ts +0 -0
- /package/{build → dist}/utils/time.d.ts +0 -0
- /package/src/{assets → lib/assets}/picture-in-picture.svg +0 -0
- /package/src/{utils → lib/utils}/colors.ts +0 -0
- /package/src/{utils → lib/utils}/time.ts +0 -0
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import type { AnyActorSystem } from 'xstate/dist/declarations/src/system'
|
|
2
|
-
import type { AnyEventObject, CallbackActorLogic, CallbackActorRef, EventObject, NonReducibleUnknown } from 'xstate'
|
|
3
|
-
|
|
4
|
-
import PQueue from 'p-queue'
|
|
5
|
-
import { fromCallback } from 'xstate'
|
|
6
|
-
|
|
7
|
-
type Receiver<TEvent extends EventObject> = (listener: {
|
|
8
|
-
bivarianceHack(event: TEvent): void
|
|
9
|
-
}['bivarianceHack']) => void
|
|
10
|
-
|
|
11
|
-
export type CallbackLogicFunction<TEvent extends EventObject = AnyEventObject, TSentEvent extends EventObject = AnyEventObject, TInput = NonReducibleUnknown, TEmitted extends EventObject = EventObject> = ({ input, system, self, sendBack, receive, emit }: {
|
|
12
|
-
input: TInput
|
|
13
|
-
system: AnyActorSystem
|
|
14
|
-
self: CallbackActorRef<TEvent>
|
|
15
|
-
sendBack: (event: TSentEvent) => void
|
|
16
|
-
receive: Receiver<TEvent>
|
|
17
|
-
emit: (emitted: TEmitted) => void
|
|
18
|
-
}) => Promise<(() => void) | void>
|
|
19
|
-
|
|
20
|
-
type FromAsyncCallback = <TEvent extends EventObject, TInput = NonReducibleUnknown, TEmitted extends EventObject = EventObject>(callback: CallbackLogicFunction<TEvent, AnyEventObject, TInput, TEmitted>) => CallbackActorLogic<TEvent, TInput, TEmitted>
|
|
21
|
-
|
|
22
|
-
export const fromAsyncCallback =
|
|
23
|
-
((callback: (...args: any[]) => Promise<() => any>) =>
|
|
24
|
-
fromCallback((...args: any[]) => {
|
|
25
|
-
const callbackPromise = callback(...args)
|
|
26
|
-
return () => {
|
|
27
|
-
callbackPromise
|
|
28
|
-
.then(callbackResult => callbackResult?.())
|
|
29
|
-
}
|
|
30
|
-
})) as FromAsyncCallback
|
|
31
|
-
|
|
32
|
-
export const getTimeRanges = (sourceBuffer: SourceBuffer) =>
|
|
33
|
-
Array(sourceBuffer.buffered.length)
|
|
34
|
-
.fill(undefined)
|
|
35
|
-
.map((_, index) => ({
|
|
36
|
-
index,
|
|
37
|
-
start: sourceBuffer.buffered.start(index),
|
|
38
|
-
end: sourceBuffer.buffered.end(index)
|
|
39
|
-
}))
|
|
40
|
-
|
|
41
|
-
const setupListeners = (sourceBuffer: SourceBuffer, resolve: (value: Event) => void, reject: (reason: Event) => void) => {
|
|
42
|
-
const updateEndListener = (ev: Event) => {
|
|
43
|
-
resolve(ev)
|
|
44
|
-
unregisterListeners()
|
|
45
|
-
}
|
|
46
|
-
const abortListener = (ev: Event) => {
|
|
47
|
-
resolve(ev)
|
|
48
|
-
unregisterListeners()
|
|
49
|
-
}
|
|
50
|
-
const errorListener = (ev: Event) => {
|
|
51
|
-
console.error(ev)
|
|
52
|
-
reject(ev)
|
|
53
|
-
unregisterListeners()
|
|
54
|
-
}
|
|
55
|
-
const unregisterListeners = () => {
|
|
56
|
-
sourceBuffer.removeEventListener('updateend', updateEndListener)
|
|
57
|
-
sourceBuffer.removeEventListener('abort', abortListener)
|
|
58
|
-
sourceBuffer.removeEventListener('error', errorListener)
|
|
59
|
-
}
|
|
60
|
-
sourceBuffer.addEventListener('updateend', updateEndListener, { once: true })
|
|
61
|
-
sourceBuffer.addEventListener('abort', abortListener, { once: true })
|
|
62
|
-
sourceBuffer.addEventListener('error', errorListener, { once: true })
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export const updateSourceBuffer = (sourceBuffer: SourceBuffer) => {
|
|
66
|
-
const queue = new PQueue({ concurrency: 1 })
|
|
67
|
-
|
|
68
|
-
const appendBuffer = (buffer: ArrayBuffer) =>
|
|
69
|
-
queue.add(() =>
|
|
70
|
-
new Promise<Event>((resolve, reject) => {
|
|
71
|
-
setupListeners(sourceBuffer, resolve, reject)
|
|
72
|
-
sourceBuffer.appendBuffer(buffer)
|
|
73
|
-
})
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
const unbufferRange = async (start: number, end: number) =>
|
|
77
|
-
queue.add(() =>
|
|
78
|
-
new Promise((resolve, reject) => {
|
|
79
|
-
setupListeners(sourceBuffer, resolve, reject)
|
|
80
|
-
sourceBuffer.remove(start, end)
|
|
81
|
-
})
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
const updateTimestampOffset = (timestampOffset: number) =>
|
|
85
|
-
queue.add(() => {
|
|
86
|
-
sourceBuffer.timestampOffset = timestampOffset
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
appendBuffer,
|
|
91
|
-
unbufferRange,
|
|
92
|
-
updateTimestampOffset
|
|
93
|
-
}
|
|
94
|
-
}
|
package/src/utils/actor-utils.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Actor, AnyActorLogic } from "xstate"
|
|
2
|
-
|
|
3
|
-
export const togglePlay = (
|
|
4
|
-
mediaActor: Actor<AnyActorLogic>,
|
|
5
|
-
isPaused: boolean,
|
|
6
|
-
duration: number | undefined,
|
|
7
|
-
currentTime: number
|
|
8
|
-
) => {
|
|
9
|
-
if (!mediaActor) throw new Error('Media actor not found')
|
|
10
|
-
if (!duration) throw new Error('Duration not found')
|
|
11
|
-
if (duration === currentTime) {
|
|
12
|
-
mediaActor.send({ type: 'SET_TIME', value: 0 })
|
|
13
|
-
mediaActor.send({ type: 'PLAY' })
|
|
14
|
-
} else if (isPaused) {
|
|
15
|
-
mediaActor.send({ type: 'PLAY' })
|
|
16
|
-
} else {
|
|
17
|
-
mediaActor.send({ type: 'PAUSE' })
|
|
18
|
-
}
|
|
19
|
-
}
|
package/src/utils/context.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { createContext } from 'react'
|
|
2
|
-
|
|
3
|
-
export type DownloadedRange =
|
|
4
|
-
// | {
|
|
5
|
-
// startTimestamp: number
|
|
6
|
-
// endTimestamp: number
|
|
7
|
-
// }
|
|
8
|
-
| {
|
|
9
|
-
startByteOffset: number
|
|
10
|
-
endByteOffset: number
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export type MediaPlayerContextType = {
|
|
14
|
-
videoElement?: HTMLVideoElement
|
|
15
|
-
title?: string
|
|
16
|
-
subtitle?: string
|
|
17
|
-
size?: number
|
|
18
|
-
downloadedRanges?: DownloadedRange[]
|
|
19
|
-
hideUI: boolean
|
|
20
|
-
update: (context: Omit<MediaPlayerContextType, 'update'>) => void
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export const MediaPlayerContext = createContext<MediaPlayerContextType>({} as MediaPlayerContextType)
|
package/src/utils/fonts.ts
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
export const fonts = {
|
|
2
|
-
headings: {
|
|
3
|
-
large: `
|
|
4
|
-
font-weight: 600;
|
|
5
|
-
font-size: 2.8rem;
|
|
6
|
-
line-height: 3.4rem;
|
|
7
|
-
@media (min-width: 960px) {
|
|
8
|
-
font-size: 3.4rem;
|
|
9
|
-
line-height: 4.1rem;
|
|
10
|
-
}
|
|
11
|
-
`,
|
|
12
|
-
medium: `
|
|
13
|
-
font-weight: 600;
|
|
14
|
-
font-size: 2.4rem;
|
|
15
|
-
line-height: 2.9rem;
|
|
16
|
-
@media (min-width: 960px) {
|
|
17
|
-
font-size: 2.8rem;
|
|
18
|
-
line-height: 3.4rem;
|
|
19
|
-
}
|
|
20
|
-
`,
|
|
21
|
-
small: `
|
|
22
|
-
font-weight: 500;
|
|
23
|
-
font-size: 1.8rem;
|
|
24
|
-
line-height: 1.9rem;
|
|
25
|
-
@media (min-width: 960px) {
|
|
26
|
-
font-size: 1.8rem;
|
|
27
|
-
line-height: 2.2rem;
|
|
28
|
-
}
|
|
29
|
-
@media (min-width: 2560px) {
|
|
30
|
-
font-size: 2.2rem;
|
|
31
|
-
line-height: 2.6rem;
|
|
32
|
-
}
|
|
33
|
-
`,
|
|
34
|
-
extraSmall: `
|
|
35
|
-
font-weight: 500;
|
|
36
|
-
font-size: 1.4rem;
|
|
37
|
-
line-height: 1.7rem;
|
|
38
|
-
@media (min-width: 960px) {
|
|
39
|
-
font-size: 1.6rem;
|
|
40
|
-
line-height: 1.9rem;
|
|
41
|
-
}
|
|
42
|
-
`
|
|
43
|
-
},
|
|
44
|
-
bLarge: {
|
|
45
|
-
bold: `
|
|
46
|
-
font-weight: 600;
|
|
47
|
-
font-size: 1.4rem;
|
|
48
|
-
line-height: 2rem;
|
|
49
|
-
@media (min-width: 960px) {
|
|
50
|
-
font-size: 1.6rem;
|
|
51
|
-
line-height: 2.2rem;
|
|
52
|
-
}
|
|
53
|
-
`,
|
|
54
|
-
medium: `
|
|
55
|
-
font-weight: 500;
|
|
56
|
-
font-size: 1.4rem;
|
|
57
|
-
line-height: 2rem;
|
|
58
|
-
@media (min-width: 960px) {
|
|
59
|
-
font-size: 1.6rem;
|
|
60
|
-
line-height: 2.2rem;
|
|
61
|
-
}
|
|
62
|
-
`,
|
|
63
|
-
regular: `
|
|
64
|
-
font-weight: 400;
|
|
65
|
-
font-size: 1.4rem;
|
|
66
|
-
line-height: 2rem;
|
|
67
|
-
@media (min-width: 960px) {
|
|
68
|
-
font-size: 1.6rem;
|
|
69
|
-
line-height: 2.2rem;
|
|
70
|
-
}
|
|
71
|
-
`,
|
|
72
|
-
},
|
|
73
|
-
bMedium: {
|
|
74
|
-
bold: `
|
|
75
|
-
font-weight: 600;
|
|
76
|
-
font-size: 1.2rem;
|
|
77
|
-
line-height: 1.7rem;
|
|
78
|
-
@media (min-width: 960px) {
|
|
79
|
-
font-size: 1.4rem;
|
|
80
|
-
line-height: 2rem;
|
|
81
|
-
}
|
|
82
|
-
`,
|
|
83
|
-
medium: `
|
|
84
|
-
font-weight: 500;
|
|
85
|
-
font-size: 1.2rem;
|
|
86
|
-
line-height: 1.7rem;
|
|
87
|
-
@media (min-width: 960px) {
|
|
88
|
-
font-size: 1.4rem;
|
|
89
|
-
line-height: 2rem;
|
|
90
|
-
}
|
|
91
|
-
`,
|
|
92
|
-
regular: `
|
|
93
|
-
font-weight: 400;
|
|
94
|
-
font-size: 1.2rem;
|
|
95
|
-
line-height: 1.7rem;
|
|
96
|
-
@media (min-width: 960px) {
|
|
97
|
-
font-size: 1.4rem;
|
|
98
|
-
line-height: 2rem;
|
|
99
|
-
}
|
|
100
|
-
`,
|
|
101
|
-
},
|
|
102
|
-
bSmall: {
|
|
103
|
-
bold: `
|
|
104
|
-
font-weight: 600;
|
|
105
|
-
font-size: 1rem;
|
|
106
|
-
line-height: 1.4rem;
|
|
107
|
-
@media (min-width: 960px) {
|
|
108
|
-
font-size: 1.2rem;
|
|
109
|
-
line-height: 1.7rem;
|
|
110
|
-
}
|
|
111
|
-
`,
|
|
112
|
-
medium: `
|
|
113
|
-
font-weight: 500;
|
|
114
|
-
font-size: 1rem;
|
|
115
|
-
line-height: 1.4rem;
|
|
116
|
-
@media (min-width: 960px) {
|
|
117
|
-
font-size: 1.2rem;
|
|
118
|
-
line-height: 1.7rem;
|
|
119
|
-
}
|
|
120
|
-
`,
|
|
121
|
-
regular: `
|
|
122
|
-
font-weight: 400;
|
|
123
|
-
font-size: 1rem;
|
|
124
|
-
line-height: 1.4rem;
|
|
125
|
-
@media (min-width: 960px) {
|
|
126
|
-
font-size: 1.2rem;
|
|
127
|
-
line-height: 1.7rem;
|
|
128
|
-
}
|
|
129
|
-
`,
|
|
130
|
-
},
|
|
131
|
-
bExtraSmall: {
|
|
132
|
-
bold: `
|
|
133
|
-
font-weight: 600;
|
|
134
|
-
font-size: 0.8rem;
|
|
135
|
-
line-height: 1.1rem;
|
|
136
|
-
@media (min-width: 960px) {
|
|
137
|
-
font-size: 1rem;
|
|
138
|
-
line-height: 1.4rem;
|
|
139
|
-
}
|
|
140
|
-
`,
|
|
141
|
-
medium: `
|
|
142
|
-
font-weight: 500;
|
|
143
|
-
font-size: 0.8rem;
|
|
144
|
-
line-height: 1.1rem;
|
|
145
|
-
@media (min-width: 960px) {
|
|
146
|
-
font-size: 1rem;
|
|
147
|
-
line-height: 1.4rem;
|
|
148
|
-
}
|
|
149
|
-
`,
|
|
150
|
-
regular: `
|
|
151
|
-
font-weight: 400;
|
|
152
|
-
font-size: 0.8rem;
|
|
153
|
-
line-height: 1.1rem;
|
|
154
|
-
@media (min-width: 960px) {
|
|
155
|
-
font-size: 1rem;
|
|
156
|
-
line-height: 1.4rem;
|
|
157
|
-
}
|
|
158
|
-
`,
|
|
159
|
-
},
|
|
160
|
-
}
|
package/src/utils/index.ts
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export function debounceImmediateAndLatest<T extends (...args: any[]) => any>(
|
|
3
|
-
wait: number,
|
|
4
|
-
func: T
|
|
5
|
-
): T {
|
|
6
|
-
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
7
|
-
let lastArgs: any[] | null = null;
|
|
8
|
-
|
|
9
|
-
const debouncedFunction = function(...args: any[]) {
|
|
10
|
-
// @ts-expect-error
|
|
11
|
-
const context = this;
|
|
12
|
-
|
|
13
|
-
if (timeoutId === null) {
|
|
14
|
-
// Call immediately on the first call
|
|
15
|
-
func.apply(context, args);
|
|
16
|
-
} else {
|
|
17
|
-
// Store the latest arguments for the last call
|
|
18
|
-
lastArgs = args;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
clearTimeout(timeoutId as ReturnType<typeof setTimeout>);
|
|
22
|
-
|
|
23
|
-
timeoutId = setTimeout(() => {
|
|
24
|
-
if (lastArgs) {
|
|
25
|
-
func.apply(context, lastArgs);
|
|
26
|
-
lastArgs = null;
|
|
27
|
-
}
|
|
28
|
-
timeoutId = null;
|
|
29
|
-
}, wait);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
return debouncedFunction as T;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const queuedThrottleWithLastCall = <T2 extends any[], T extends (...args: T2) => any>(time: number, func: T) => {
|
|
36
|
-
let runningFunction: Promise<ReturnType<T>> | undefined
|
|
37
|
-
let lastCall: Promise<ReturnType<T>> | undefined
|
|
38
|
-
let lastCallArguments: T2 | undefined
|
|
39
|
-
|
|
40
|
-
const checkForLastCall = (
|
|
41
|
-
timeStart: number,
|
|
42
|
-
resolve: (value: ReturnType<T> | PromiseLike<ReturnType<T>>) => void,
|
|
43
|
-
reject: (reason?: any) => void
|
|
44
|
-
) =>
|
|
45
|
-
(result: ReturnType<T>) => {
|
|
46
|
-
const currentTime = performance.now()
|
|
47
|
-
setTimeout(() => {
|
|
48
|
-
if (!lastCallArguments) {
|
|
49
|
-
runningFunction = undefined
|
|
50
|
-
lastCall = undefined
|
|
51
|
-
return
|
|
52
|
-
}
|
|
53
|
-
const funcResult = (async () => (func(...lastCallArguments)))()
|
|
54
|
-
lastCallArguments = undefined
|
|
55
|
-
funcResult
|
|
56
|
-
.then(resolve)
|
|
57
|
-
.catch((err) => {
|
|
58
|
-
console.error(err)
|
|
59
|
-
reject(err)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
let _resolve: (value: ReturnType<T> | PromiseLike<ReturnType<T>>) => void
|
|
63
|
-
let _reject: (reason?: any) => void
|
|
64
|
-
lastCall = new Promise((resolve, reject) => {
|
|
65
|
-
_resolve = resolve
|
|
66
|
-
_reject = reject
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
runningFunction =
|
|
70
|
-
funcResult
|
|
71
|
-
// @ts-ignore
|
|
72
|
-
.then(checkForLastCall(currentTime, _resolve, _reject))
|
|
73
|
-
// @ts-ignore
|
|
74
|
-
.catch(err => {
|
|
75
|
-
console.error(err)
|
|
76
|
-
return checkForLastCall(timeStart, _resolve, _reject)(err)
|
|
77
|
-
})
|
|
78
|
-
}, time - (currentTime - timeStart))
|
|
79
|
-
return result
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return (...args: Parameters<T>) => {
|
|
83
|
-
lastCallArguments = args
|
|
84
|
-
if (!runningFunction) {
|
|
85
|
-
const timeStart = performance.now()
|
|
86
|
-
const funcResult = (async () => (func(...args)))()
|
|
87
|
-
lastCallArguments = undefined
|
|
88
|
-
let _resolve: (value: ReturnType<T> | PromiseLike<ReturnType<T>>) => void
|
|
89
|
-
let _reject: (reason?: any) => void
|
|
90
|
-
lastCall = new Promise((resolve, reject) => {
|
|
91
|
-
_resolve = resolve
|
|
92
|
-
_reject = reject
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
runningFunction =
|
|
96
|
-
funcResult
|
|
97
|
-
// @ts-ignore
|
|
98
|
-
.then(checkForLastCall(timeStart, _resolve, _reject))
|
|
99
|
-
// @ts-ignore
|
|
100
|
-
.catch(err => {
|
|
101
|
-
console.error(err)
|
|
102
|
-
return checkForLastCall(timeStart, _resolve, _reject)(err)
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
return funcResult
|
|
106
|
-
} else {
|
|
107
|
-
return lastCall
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// todo: reimplement this into a ReadableByteStream https://web.dev/streams/ once Safari gets support
|
|
113
|
-
export const toStreamChunkSize = (SIZE: number) => (stream: ReadableStream) =>
|
|
114
|
-
new ReadableStream<Uint8Array>({
|
|
115
|
-
reader: undefined,
|
|
116
|
-
leftOverData: undefined,
|
|
117
|
-
start() {
|
|
118
|
-
this.reader = stream.getReader()
|
|
119
|
-
},
|
|
120
|
-
async pull(controller) {
|
|
121
|
-
const { leftOverData }: { leftOverData: Uint8Array | undefined } = this
|
|
122
|
-
|
|
123
|
-
const accumulate = async ({ buffer = new Uint8Array(SIZE), currentSize = 0 } = {}): Promise<{ buffer?: Uint8Array, currentSize?: number, done: boolean }> => {
|
|
124
|
-
const { value: newBuffer, done } = await this.reader!.read()
|
|
125
|
-
if (currentSize === 0 && leftOverData) {
|
|
126
|
-
buffer.set(leftOverData)
|
|
127
|
-
currentSize += leftOverData.byteLength
|
|
128
|
-
this.leftOverData = undefined
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (done) {
|
|
132
|
-
const finalResult = { buffer: buffer.slice(0, currentSize), currentSize, done }
|
|
133
|
-
this.reader = undefined
|
|
134
|
-
this.leftOverData = undefined
|
|
135
|
-
return finalResult
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
let newSize
|
|
139
|
-
const slicedBuffer = newBuffer.slice(0, SIZE - currentSize)
|
|
140
|
-
newSize = currentSize + slicedBuffer.byteLength
|
|
141
|
-
buffer.set(slicedBuffer, currentSize)
|
|
142
|
-
|
|
143
|
-
if (newSize === SIZE) {
|
|
144
|
-
this.leftOverData = newBuffer.slice(SIZE - currentSize)
|
|
145
|
-
return { buffer, currentSize: newSize, done: false }
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return accumulate({ buffer, currentSize: newSize })
|
|
149
|
-
}
|
|
150
|
-
const { buffer, done } = await accumulate()
|
|
151
|
-
if (buffer?.byteLength) controller.enqueue(buffer)
|
|
152
|
-
if (done) controller.close()
|
|
153
|
-
},
|
|
154
|
-
cancel() {
|
|
155
|
-
this.reader?.cancel()
|
|
156
|
-
this.leftOverData = undefined
|
|
157
|
-
}
|
|
158
|
-
} as UnderlyingDefaultSource<Uint8Array> & {
|
|
159
|
-
reader: ReadableStreamDefaultReader<Uint8Array> | undefined
|
|
160
|
-
leftOverData: Uint8Array | undefined
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
export const toBufferedStream = (SIZE: number) => (stream: ReadableStream) =>
|
|
164
|
-
new ReadableStream<Uint8Array>({
|
|
165
|
-
buffers: [],
|
|
166
|
-
currentPullPromise: undefined,
|
|
167
|
-
reader: undefined,
|
|
168
|
-
leftOverData: undefined,
|
|
169
|
-
start() {
|
|
170
|
-
this.reader = stream.getReader()
|
|
171
|
-
},
|
|
172
|
-
async pull(controller) {
|
|
173
|
-
const pull = async () => {
|
|
174
|
-
if (this.buffers.length >= SIZE) return
|
|
175
|
-
this.currentPullPromise = this.reader!.read()
|
|
176
|
-
const { value: newBuffer, done } = await this.currentPullPromise
|
|
177
|
-
this.currentPullPromise = undefined
|
|
178
|
-
if (done) {
|
|
179
|
-
try {
|
|
180
|
-
for (const buffer of this.buffers) controller.enqueue(buffer)
|
|
181
|
-
controller.close()
|
|
182
|
-
} catch (err) {
|
|
183
|
-
// console.error(err)
|
|
184
|
-
}
|
|
185
|
-
return
|
|
186
|
-
}
|
|
187
|
-
this.buffers.push(newBuffer)
|
|
188
|
-
return newBuffer
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const tryToBuffer = async (): Promise<void> => {
|
|
192
|
-
if (this.buffers.length >= SIZE) return
|
|
193
|
-
|
|
194
|
-
if (this.buffers.length === 0) {
|
|
195
|
-
const buffer = await pull()
|
|
196
|
-
if (!buffer) return
|
|
197
|
-
return tryToBuffer()
|
|
198
|
-
} else {
|
|
199
|
-
pull().then((buffer) => {
|
|
200
|
-
if (!buffer) return
|
|
201
|
-
tryToBuffer()
|
|
202
|
-
})
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
await tryToBuffer()
|
|
207
|
-
try {
|
|
208
|
-
controller.enqueue(this.buffers.shift())
|
|
209
|
-
tryToBuffer()
|
|
210
|
-
} catch(err) {
|
|
211
|
-
if (!(
|
|
212
|
-
err instanceof TypeError && (
|
|
213
|
-
err.message === 'ReadableStreamDefaultController.enqueue: Cannot enqueue into a stream that has already been requested to close.' ||
|
|
214
|
-
err.message === `Failed to execute 'enqueue' on 'ReadableStreamDefaultController': Cannot enqueue a chunk into a readable stream that is closed or has been requested to be closed`
|
|
215
|
-
)
|
|
216
|
-
)) {
|
|
217
|
-
throw err
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
},
|
|
221
|
-
cancel() {
|
|
222
|
-
this.reader!.cancel()
|
|
223
|
-
}
|
|
224
|
-
} as UnderlyingDefaultSource<Uint8Array> & {
|
|
225
|
-
reader: ReadableStreamDefaultReader<Uint8Array> | undefined
|
|
226
|
-
leftOverData: Uint8Array | undefined
|
|
227
|
-
buffers: Uint8Array[]
|
|
228
|
-
currentPullPromise: Promise<ReadableStreamReadResult<Uint8Array>> | undefined
|
|
229
|
-
})
|