@banou/media-player 0.6.0 → 0.6.2

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.
Files changed (37) hide show
  1. package/README.md +6 -6
  2. package/package.json +51 -51
  3. package/src/assets/picture-in-picture.svg +5 -5
  4. package/src/components/chrome.tsx +95 -95
  5. package/src/components/control-bar.tsx +333 -333
  6. package/src/components/overlay.tsx +91 -91
  7. package/src/components/playback-slider.tsx +174 -174
  8. package/src/components/progress-bar.tsx +251 -251
  9. package/src/components/settings.tsx +321 -321
  10. package/src/components/sound.tsx +100 -100
  11. package/src/components/tooltip-display.tsx +83 -83
  12. package/src/components/volume-slider.tsx +156 -156
  13. package/src/index.tsx +195 -195
  14. package/src/main.tsx +169 -169
  15. package/src/state-machines/data-source.ts +84 -84
  16. package/src/state-machines/index.ts +5 -5
  17. package/src/state-machines/media-properties.ts +82 -82
  18. package/src/state-machines/media-source.ts +129 -129
  19. package/src/state-machines/media.ts +255 -255
  20. package/src/state-machines/subtitles.ts +285 -285
  21. package/src/state-machines/thumbnails.ts +123 -123
  22. package/src/state-machines/utils.ts +94 -94
  23. package/src/utils/actor-utils.ts +19 -19
  24. package/src/utils/colors.ts +8 -8
  25. package/src/utils/context.ts +23 -23
  26. package/src/utils/fonts.ts +159 -159
  27. package/src/utils/index.ts +229 -229
  28. package/src/utils/languages.ts +262 -262
  29. package/src/utils/mp4box.ts +74 -74
  30. package/src/utils/time.ts +15 -15
  31. package/src/utils/use-local-storage.ts +30 -30
  32. package/src/utils/use-scrub.ts +40 -40
  33. package/src/utils/volume-utils.ts +39 -39
  34. package/src/utils/window-height.ts +19 -19
  35. package/src/vite-env.d.ts +1 -1
  36. package/tsconfig.json +28 -28
  37. package/tsconfig.node.json +9 -9
@@ -1,255 +1,255 @@
1
- import type { Attachment, Index, SubtitleFragment } from 'libav-wasm/build/worker'
2
-
3
- import { makeRemuxer } from 'libav-wasm'
4
- import { assign, setup, sendTo, enqueueActions } from 'xstate'
5
-
6
- import mediaPropertiesLogic from './media-properties'
7
- import mediaSourceLogic, { MediaSourceOptions } from './media-source'
8
- import dataSourceLogic from './data-source'
9
- import subtitlesLogic, { SubtitleStream } from './subtitles'
10
- import thumbnailsLogic, { Thumbnail } from './thumbnails'
11
- import { JassubOptions } from 'jassub'
12
- import { DownloadedRange } from '../utils/context'
13
-
14
- export default setup({
15
- types: {} as {
16
- context: {
17
- mediaSourceOptions: MediaSourceOptions | undefined
18
- subtitlesRendererOptions: Omit<JassubOptions, 'video' | 'canvas'> | undefined
19
- remuxerOptions: Parameters<typeof makeRemuxer>[0] | undefined
20
- videoElement: HTMLVideoElement | undefined
21
- canvasElement: HTMLCanvasElement | undefined
22
- media: {
23
- duration?: number
24
- paused: boolean
25
- currentTime: number
26
- volume: number
27
- muted: boolean
28
- playbackRate: number
29
- },
30
- attachments: Attachment[]
31
- subtitleFragments: SubtitleFragment[]
32
- subtitleStreams: SubtitleStream[]
33
- selectedSubtitleStreamIndex: number | undefined
34
- indexes: Index[]
35
- thumbnails: Thumbnail[]
36
- isReady: boolean
37
- },
38
- events:
39
- | { type: 'MEDIA_SOURCE_OPTIONS', mediaSourceOptions: MediaSourceOptions }
40
- | { type: 'SUBTITLES_RENDERER_OPTIONS', subtitlesRendererOptions: Omit<JassubOptions, 'video' | 'canvas'> }
41
- | { type: 'REMUXER_OPTIONS', remuxerOptions: Parameters<typeof makeRemuxer>[0] }
42
- | { type: 'SET_VIDEO_ELEMENT', videoElement: HTMLVideoElement }
43
- | { type: 'SET_CANVAS_ELEMENT', canvasElement: HTMLCanvasElement }
44
- | { type: 'IS_READY' }
45
- | { type: 'PLAY' }
46
- | { type: 'PAUSE' }
47
- | { type: 'SET_TIME', value: number }
48
- | { type: 'PLAYING' }
49
- | { type: 'PAUSED' }
50
- | { type: 'ENDED' }
51
- | { type: 'TIME_UPDATE', currentTime: number }
52
- | { type: 'VOLUME_UPDATE', muted: boolean, volume: number }
53
- | { type: 'PLAYBACK_RATE_UPDATE', playbackRate: number }
54
- | { type: 'DURATION_UPDATE', duration: number }
55
- | { type: 'SET_VOLUME', muted: boolean, volume: number }
56
- | { type: 'SET_PLAYBACK_RATE', playbackRate: number }
57
- | { type: 'SEEKING', currentTime: number }
58
- | { type: 'NEED_DATA' }
59
- | { type: 'METADATA', mimeType: string, duration: number, data: ArrayBuffer }
60
- | { type: 'DATA', data: ArrayBuffer }
61
- | { type: 'TIMESTAMP_OFFSET', timestampOffset: number }
62
- | { type: 'NEW_ATTACHMENTS', attachments: Attachment[] }
63
- | { type: 'NEW_SUBTITLE_FRAGMENTS', subtitles: SubtitleFragment[] }
64
- | { type: 'SUBTITLE_STREAMS_UPDATED', subtitlesStreams: SubtitleStream[] }
65
- | { type: 'SELECT_SUBTITLE_STREAM', streamIndex: number | undefined }
66
- | { type: 'NEW_THUMBNAIL', thumbnail: Thumbnail }
67
- | { type: 'DOWNLOADED_RANGES_UPDATED', downloadedRanges: DownloadedRange[] }
68
- | { type: 'DESTROY' }
69
- },
70
- actions: {
71
- isReady: enqueueActions(({ context, enqueue }) => {
72
- if (context.videoElement && context.canvasElement && context.remuxerOptions && context.subtitlesRendererOptions && context.mediaSourceOptions) {
73
- enqueue.raise({ type: 'IS_READY' })
74
- }
75
- })
76
- },
77
- actors: {
78
- mediaLogic: mediaPropertiesLogic,
79
- mediaSourceLogic: mediaSourceLogic,
80
- dataSourceLogic: dataSourceLogic,
81
- thumbnailsLogic: thumbnailsLogic,
82
- subtitlesLogic: subtitlesLogic,
83
- },
84
- }).createMachine({
85
- context: {
86
- mediaSourceOptions: undefined,
87
- subtitlesRendererOptions: undefined,
88
- remuxerOptions: undefined,
89
- videoElement: undefined,
90
- canvasElement: undefined,
91
- media: {
92
- paused: true,
93
- currentTime: 0,
94
- volume: 1,
95
- muted: false,
96
- playbackRate: 1,
97
- duration: undefined
98
- },
99
- attachments: [],
100
- subtitleFragments: [],
101
- subtitleStreams: [],
102
- selectedSubtitleStreamIndex: undefined,
103
- indexes: [],
104
- thumbnails: [],
105
- isReady: false
106
- },
107
- initial: 'WAITING',
108
- on: {
109
- 'SET_VIDEO_ELEMENT': {
110
- actions: [
111
- assign({
112
- videoElement: ({ event }) => event.videoElement,
113
- }),
114
- { type: 'isReady' }
115
- ]
116
- },
117
- 'SET_CANVAS_ELEMENT': {
118
- actions: [
119
- assign({
120
- canvasElement: ({ event }) => event.canvasElement,
121
- }),
122
- { type: 'isReady' }
123
- ]
124
- },
125
- 'IS_READY': {
126
- target: '.OK',
127
- actions: assign({ isReady: () => true })
128
- },
129
- },
130
- states: {
131
- WAITING: {
132
- on: {
133
- 'MEDIA_SOURCE_OPTIONS': {
134
- actions: [
135
- assign({
136
- mediaSourceOptions: ({ event }) => event.mediaSourceOptions
137
- }),
138
- { type: 'isReady' }
139
- ]
140
- },
141
- 'REMUXER_OPTIONS': {
142
- actions: [
143
- assign({
144
- remuxerOptions: ({ event }) => event.remuxerOptions
145
- }),
146
- { type: 'isReady' }
147
- ]
148
- },
149
- 'SUBTITLES_RENDERER_OPTIONS': {
150
- actions: [
151
- assign({
152
- subtitlesRendererOptions: ({ event }) => event.subtitlesRendererOptions
153
- }),
154
- { type: 'isReady' }
155
- ]
156
- },
157
- }
158
- },
159
- OK: {
160
- type: 'parallel',
161
- invoke: [
162
- {
163
- id: 'media',
164
- src: 'mediaLogic',
165
- input: ({ context }) => ({ videoElement: context.videoElement!, remuxerOptions: context.remuxerOptions! }),
166
- },
167
- {
168
- id: 'mediaSource',
169
- src: 'mediaSourceLogic',
170
- input: ({ context }) => ({ videoElement: context.videoElement!, remuxerOptions: context.remuxerOptions! }),
171
- },
172
- {
173
- id: 'dataSource',
174
- src: 'dataSourceLogic',
175
- input: ({ context }) => ({ remuxerOptions: context.remuxerOptions! }),
176
- },
177
- {
178
- id: 'thumbnails',
179
- src: 'thumbnailsLogic',
180
- input: ({ context }) => ({ remuxerOptions: context.remuxerOptions! }),
181
- },
182
- {
183
- id: 'subtitles',
184
- src: 'subtitlesLogic',
185
- input: ({ context }) => ({
186
- publicPath: context.remuxerOptions!.publicPath,
187
- videoElement: context.videoElement!,
188
- canvasElement: context.canvasElement!,
189
- subtitlesRendererOptions: context.subtitlesRendererOptions!
190
- }),
191
- }
192
- ],
193
- on: {
194
- 'PLAY': { actions: sendTo('media', ({ event }) => event) },
195
- 'PAUSE': { actions: sendTo('media', ({ event }) => event) },
196
- 'SET_TIME': { actions: sendTo('media', ({ event }) => event) },
197
- 'SET_PLAYBACK_RATE': { actions: sendTo('media', ({ event }) => event) },
198
- 'PLAYING': { actions: assign({ media: ({ context }) => ({ ...context.media, paused: false }) }) },
199
- 'PAUSED': { actions: assign({ media: ({ context }) => ({ ...context.media, paused: true }) }) },
200
- 'ENDED': { actions: assign({ media: ({ context }) => ({ ...context.media, paused: true }) }) },
201
- 'TIME_UPDATE': { actions: [
202
- assign({ media: ({ context, event }) => ({ ...context.media, currentTime: event.currentTime }) }),
203
- sendTo('subtitles', ({ event }) => event)
204
- ] },
205
- 'VOLUME_UPDATE': { actions: assign({ media: ({ context, event }) => ({ ...context.media, muted: event.muted, volume: event.volume }) }) },
206
- 'SET_VOLUME': { actions: sendTo('media', ({ event }) => event) },
207
- 'PLAYBACK_RATE_UPDATE': { actions: assign({ media: ({ context, event }) => ({ ...context.media, playbackRate: event.playbackRate }) }) },
208
- 'DURATION_UPDATE': { actions: assign({ media: ({ context, event }) => ({ ...context.media, duration: event.duration }) }) },
209
- 'NEED_DATA': { actions: sendTo('dataSource', ({ event }) => event) },
210
- 'METADATA': { actions: sendTo('mediaSource', ({ event }) => event) },
211
- 'SEEKING': { actions: sendTo('dataSource', ({ event }) => event) },
212
- 'DATA': { actions: sendTo('mediaSource', ({ event }) => event) },
213
- 'TIMESTAMP_OFFSET': { actions: sendTo('mediaSource', ({ event }) => event) },
214
- 'NEW_THUMBNAIL': { actions: [assign({ thumbnails: ({ context, event }) => [...context.thumbnails, event.thumbnail] })] },
215
- 'DOWNLOADED_RANGES_UPDATED': { actions: sendTo('thumbnails', ({ event }) => event) },
216
- 'INDEXES': {
217
- actions: [
218
- assign({ indexes: ({ event }) => event.indexes })
219
- ]
220
- },
221
- 'NEW_ATTACHMENTS': {
222
- actions: [
223
- assign({ attachments: ({ context, event }) => [...context.attachments, ...event.attachments] }),
224
- sendTo('subtitles', ({ event }) => event)
225
- ]
226
- },
227
- 'NEW_SUBTITLE_FRAGMENTS': {
228
- actions: [
229
- assign({ subtitleFragments: ({ context, event }) => [...context.subtitleFragments, ...event.subtitles] }),
230
- sendTo('subtitles', ({ event }) => event)
231
- // emit(({ event }) => ({ type: 'NEW_SUBTITLE_FRAGMENTS', subtitles: event.subtitles }))
232
- ]
233
- },
234
- 'SUBTITLE_STREAMS_UPDATED': {
235
- actions: [
236
- assign({ subtitleStreams: ({ event }) => event.subtitlesStreams }),
237
- sendTo('subtitles', ({ event }) => event)
238
- ]
239
- },
240
- 'SELECT_SUBTITLE_STREAM': {
241
- actions: [
242
- sendTo('subtitles', ({ event }) => event)
243
- ]
244
- },
245
- 'SELECTED_SUBTITLE_STREAM_UPDATED': {
246
- actions: [
247
- assign({ selectedSubtitleStreamIndex: ({ event }) => event.streamIndex })
248
- ]
249
- },
250
- 'DESTROY': { target: 'WAITING' }
251
- }
252
- },
253
- DESTROYED: {}
254
- }
255
- })
1
+ import type { Attachment, Index, SubtitleFragment } from 'libav-wasm/build/worker'
2
+
3
+ import { makeRemuxer } from 'libav-wasm'
4
+ import { assign, setup, sendTo, enqueueActions } from 'xstate'
5
+
6
+ import mediaPropertiesLogic from './media-properties'
7
+ import mediaSourceLogic, { MediaSourceOptions } from './media-source'
8
+ import dataSourceLogic from './data-source'
9
+ import subtitlesLogic, { SubtitleStream } from './subtitles'
10
+ import thumbnailsLogic, { Thumbnail } from './thumbnails'
11
+ import { JassubOptions } from 'jassub'
12
+ import { DownloadedRange } from '../utils/context'
13
+
14
+ export default setup({
15
+ types: {} as {
16
+ context: {
17
+ mediaSourceOptions: MediaSourceOptions | undefined
18
+ subtitlesRendererOptions: Omit<JassubOptions, 'video' | 'canvas'> | undefined
19
+ remuxerOptions: Parameters<typeof makeRemuxer>[0] | undefined
20
+ videoElement: HTMLVideoElement | undefined
21
+ canvasElement: HTMLCanvasElement | undefined
22
+ media: {
23
+ duration?: number
24
+ paused: boolean
25
+ currentTime: number
26
+ volume: number
27
+ muted: boolean
28
+ playbackRate: number
29
+ },
30
+ attachments: Attachment[]
31
+ subtitleFragments: SubtitleFragment[]
32
+ subtitleStreams: SubtitleStream[]
33
+ selectedSubtitleStreamIndex: number | undefined
34
+ indexes: Index[]
35
+ thumbnails: Thumbnail[]
36
+ isReady: boolean
37
+ },
38
+ events:
39
+ | { type: 'MEDIA_SOURCE_OPTIONS', mediaSourceOptions: MediaSourceOptions }
40
+ | { type: 'SUBTITLES_RENDERER_OPTIONS', subtitlesRendererOptions: Omit<JassubOptions, 'video' | 'canvas'> }
41
+ | { type: 'REMUXER_OPTIONS', remuxerOptions: Parameters<typeof makeRemuxer>[0] }
42
+ | { type: 'SET_VIDEO_ELEMENT', videoElement: HTMLVideoElement }
43
+ | { type: 'SET_CANVAS_ELEMENT', canvasElement: HTMLCanvasElement }
44
+ | { type: 'IS_READY' }
45
+ | { type: 'PLAY' }
46
+ | { type: 'PAUSE' }
47
+ | { type: 'SET_TIME', value: number }
48
+ | { type: 'PLAYING' }
49
+ | { type: 'PAUSED' }
50
+ | { type: 'ENDED' }
51
+ | { type: 'TIME_UPDATE', currentTime: number }
52
+ | { type: 'VOLUME_UPDATE', muted: boolean, volume: number }
53
+ | { type: 'PLAYBACK_RATE_UPDATE', playbackRate: number }
54
+ | { type: 'DURATION_UPDATE', duration: number }
55
+ | { type: 'SET_VOLUME', muted: boolean, volume: number }
56
+ | { type: 'SET_PLAYBACK_RATE', playbackRate: number }
57
+ | { type: 'SEEKING', currentTime: number }
58
+ | { type: 'NEED_DATA' }
59
+ | { type: 'METADATA', mimeType: string, duration: number, data: ArrayBuffer }
60
+ | { type: 'DATA', data: ArrayBuffer }
61
+ | { type: 'TIMESTAMP_OFFSET', timestampOffset: number }
62
+ | { type: 'NEW_ATTACHMENTS', attachments: Attachment[] }
63
+ | { type: 'NEW_SUBTITLE_FRAGMENTS', subtitles: SubtitleFragment[] }
64
+ | { type: 'SUBTITLE_STREAMS_UPDATED', subtitlesStreams: SubtitleStream[] }
65
+ | { type: 'SELECT_SUBTITLE_STREAM', streamIndex: number | undefined }
66
+ | { type: 'NEW_THUMBNAIL', thumbnail: Thumbnail }
67
+ | { type: 'DOWNLOADED_RANGES_UPDATED', downloadedRanges: DownloadedRange[] }
68
+ | { type: 'DESTROY' }
69
+ },
70
+ actions: {
71
+ isReady: enqueueActions(({ context, enqueue }) => {
72
+ if (context.videoElement && context.canvasElement && context.remuxerOptions && context.subtitlesRendererOptions && context.mediaSourceOptions) {
73
+ enqueue.raise({ type: 'IS_READY' })
74
+ }
75
+ })
76
+ },
77
+ actors: {
78
+ mediaLogic: mediaPropertiesLogic,
79
+ mediaSourceLogic: mediaSourceLogic,
80
+ dataSourceLogic: dataSourceLogic,
81
+ thumbnailsLogic: thumbnailsLogic,
82
+ subtitlesLogic: subtitlesLogic,
83
+ },
84
+ }).createMachine({
85
+ context: {
86
+ mediaSourceOptions: undefined,
87
+ subtitlesRendererOptions: undefined,
88
+ remuxerOptions: undefined,
89
+ videoElement: undefined,
90
+ canvasElement: undefined,
91
+ media: {
92
+ paused: true,
93
+ currentTime: 0,
94
+ volume: 1,
95
+ muted: false,
96
+ playbackRate: 1,
97
+ duration: undefined
98
+ },
99
+ attachments: [],
100
+ subtitleFragments: [],
101
+ subtitleStreams: [],
102
+ selectedSubtitleStreamIndex: undefined,
103
+ indexes: [],
104
+ thumbnails: [],
105
+ isReady: false
106
+ },
107
+ initial: 'WAITING',
108
+ on: {
109
+ 'SET_VIDEO_ELEMENT': {
110
+ actions: [
111
+ assign({
112
+ videoElement: ({ event }) => event.videoElement,
113
+ }),
114
+ { type: 'isReady' }
115
+ ]
116
+ },
117
+ 'SET_CANVAS_ELEMENT': {
118
+ actions: [
119
+ assign({
120
+ canvasElement: ({ event }) => event.canvasElement,
121
+ }),
122
+ { type: 'isReady' }
123
+ ]
124
+ },
125
+ 'IS_READY': {
126
+ target: '.OK',
127
+ actions: assign({ isReady: () => true })
128
+ },
129
+ },
130
+ states: {
131
+ WAITING: {
132
+ on: {
133
+ 'MEDIA_SOURCE_OPTIONS': {
134
+ actions: [
135
+ assign({
136
+ mediaSourceOptions: ({ event }) => event.mediaSourceOptions
137
+ }),
138
+ { type: 'isReady' }
139
+ ]
140
+ },
141
+ 'REMUXER_OPTIONS': {
142
+ actions: [
143
+ assign({
144
+ remuxerOptions: ({ event }) => event.remuxerOptions
145
+ }),
146
+ { type: 'isReady' }
147
+ ]
148
+ },
149
+ 'SUBTITLES_RENDERER_OPTIONS': {
150
+ actions: [
151
+ assign({
152
+ subtitlesRendererOptions: ({ event }) => event.subtitlesRendererOptions
153
+ }),
154
+ { type: 'isReady' }
155
+ ]
156
+ },
157
+ }
158
+ },
159
+ OK: {
160
+ type: 'parallel',
161
+ invoke: [
162
+ {
163
+ id: 'media',
164
+ src: 'mediaLogic',
165
+ input: ({ context }) => ({ videoElement: context.videoElement!, remuxerOptions: context.remuxerOptions! }),
166
+ },
167
+ {
168
+ id: 'mediaSource',
169
+ src: 'mediaSourceLogic',
170
+ input: ({ context }) => ({ videoElement: context.videoElement!, remuxerOptions: context.remuxerOptions! }),
171
+ },
172
+ {
173
+ id: 'dataSource',
174
+ src: 'dataSourceLogic',
175
+ input: ({ context }) => ({ remuxerOptions: context.remuxerOptions! }),
176
+ },
177
+ {
178
+ id: 'thumbnails',
179
+ src: 'thumbnailsLogic',
180
+ input: ({ context }) => ({ remuxerOptions: context.remuxerOptions! }),
181
+ },
182
+ {
183
+ id: 'subtitles',
184
+ src: 'subtitlesLogic',
185
+ input: ({ context }) => ({
186
+ publicPath: context.remuxerOptions!.publicPath,
187
+ videoElement: context.videoElement!,
188
+ canvasElement: context.canvasElement!,
189
+ subtitlesRendererOptions: context.subtitlesRendererOptions!
190
+ }),
191
+ }
192
+ ],
193
+ on: {
194
+ 'PLAY': { actions: sendTo('media', ({ event }) => event) },
195
+ 'PAUSE': { actions: sendTo('media', ({ event }) => event) },
196
+ 'SET_TIME': { actions: sendTo('media', ({ event }) => event) },
197
+ 'SET_PLAYBACK_RATE': { actions: sendTo('media', ({ event }) => event) },
198
+ 'PLAYING': { actions: assign({ media: ({ context }) => ({ ...context.media, paused: false }) }) },
199
+ 'PAUSED': { actions: assign({ media: ({ context }) => ({ ...context.media, paused: true }) }) },
200
+ 'ENDED': { actions: assign({ media: ({ context }) => ({ ...context.media, paused: true }) }) },
201
+ 'TIME_UPDATE': { actions: [
202
+ assign({ media: ({ context, event }) => ({ ...context.media, currentTime: event.currentTime }) }),
203
+ sendTo('subtitles', ({ event }) => event)
204
+ ] },
205
+ 'VOLUME_UPDATE': { actions: assign({ media: ({ context, event }) => ({ ...context.media, muted: event.muted, volume: event.volume }) }) },
206
+ 'SET_VOLUME': { actions: sendTo('media', ({ event }) => event) },
207
+ 'PLAYBACK_RATE_UPDATE': { actions: assign({ media: ({ context, event }) => ({ ...context.media, playbackRate: event.playbackRate }) }) },
208
+ 'DURATION_UPDATE': { actions: assign({ media: ({ context, event }) => ({ ...context.media, duration: event.duration }) }) },
209
+ 'NEED_DATA': { actions: sendTo('dataSource', ({ event }) => event) },
210
+ 'METADATA': { actions: sendTo('mediaSource', ({ event }) => event) },
211
+ 'SEEKING': { actions: sendTo('dataSource', ({ event }) => event) },
212
+ 'DATA': { actions: sendTo('mediaSource', ({ event }) => event) },
213
+ 'TIMESTAMP_OFFSET': { actions: sendTo('mediaSource', ({ event }) => event) },
214
+ 'NEW_THUMBNAIL': { actions: [assign({ thumbnails: ({ context, event }) => [...context.thumbnails, event.thumbnail] })] },
215
+ 'DOWNLOADED_RANGES_UPDATED': { actions: sendTo('thumbnails', ({ event }) => event) },
216
+ 'INDEXES': {
217
+ actions: [
218
+ assign({ indexes: ({ event }) => event.indexes })
219
+ ]
220
+ },
221
+ 'NEW_ATTACHMENTS': {
222
+ actions: [
223
+ assign({ attachments: ({ context, event }) => [...context.attachments, ...event.attachments] }),
224
+ sendTo('subtitles', ({ event }) => event)
225
+ ]
226
+ },
227
+ 'NEW_SUBTITLE_FRAGMENTS': {
228
+ actions: [
229
+ assign({ subtitleFragments: ({ context, event }) => [...context.subtitleFragments, ...event.subtitles] }),
230
+ sendTo('subtitles', ({ event }) => event)
231
+ // emit(({ event }) => ({ type: 'NEW_SUBTITLE_FRAGMENTS', subtitles: event.subtitles }))
232
+ ]
233
+ },
234
+ 'SUBTITLE_STREAMS_UPDATED': {
235
+ actions: [
236
+ assign({ subtitleStreams: ({ event }) => event.subtitlesStreams }),
237
+ sendTo('subtitles', ({ event }) => event)
238
+ ]
239
+ },
240
+ 'SELECT_SUBTITLE_STREAM': {
241
+ actions: [
242
+ sendTo('subtitles', ({ event }) => event)
243
+ ]
244
+ },
245
+ 'SELECTED_SUBTITLE_STREAM_UPDATED': {
246
+ actions: [
247
+ assign({ selectedSubtitleStreamIndex: ({ event }) => event.streamIndex })
248
+ ]
249
+ },
250
+ 'DESTROY': { target: 'WAITING' }
251
+ }
252
+ },
253
+ DESTROYED: {}
254
+ }
255
+ })