Overview
Controllers are implemented as Redux-Observable epics—functions that listen for specific Redux actions, perform asynchronous operations using use cases, and dispatch new actions to update the store. They coordinate complex workflows involving multiple use cases and service interactions.Epic pattern
All epics follow this structure:Stream of all dispatched actions
Observable of current Redux state
Injected services (loader, parser, decryptor, fs)
Root epic
createRootEpic
Combines all individual epics into a single root epic for the Redux store.Playlist epics
addPlaylistEpic
Listens foraddPlaylist actions and automatically fetches levels for the new playlist.
Triggers on: playlistsSlice.actions.addPlaylist
Dispatches: playlistsSlice.actions.fetchPlaylistLevels
fetchPlaylistLevelsEpic
Fetches and parses master playlist to extract available quality levels and tracks. Triggers on:playlistsSlice.actions.fetchPlaylistLevels
Dispatches:
playlistsSlice.actions.fetchPlaylistLevelsSuccessplaylistsSlice.actions.fetchPlaylistLevelsFailedlevelsSlice.actions.add
removePlaylistEpic
Removes a playlist and cleans up associated levels and jobs. Triggers on:playlistsSlice.actions.removePlaylist
Download job epics
downloadJobEpic
Orchestrates the complete download workflow: creates bucket, downloads fragments, decrypts, and writes to storage. Triggers on:jobsSlice.actions.download
Dispatches:
jobsSlice.actions.incDownloadStatus(for each fragment)jobsSlice.actions.downloadFailed(on error)
This epic respects the
concurrency setting from config to control how many fragments download simultaneously.addDownloadJobEpic
Creates a new download job with fragment details. Triggers on: Custom action for adding download jobssaveAsJobEpic
Saves a completed download job to the user’s file system. Triggers on:jobsSlice.actions.saveAs
Dispatches: jobsSlice.actions.saveAsSuccess
deleteJobEpic
Deletes a job and cleans up associated bucket storage. Triggers on:jobsSlice.actions.delete
Dispatches: jobsSlice.actions.deleteSuccess
cancelJobDeleteJobEpic
Cancels an in-progress download and deletes the job. Triggers on:jobsSlice.actions.cancel
downloadQueueEpic
Manages a queue of download jobs, ensuring onlymaxActiveDownloads run concurrently.
Triggers on: jobsSlice.actions.queue
incDownloadStatusEpic
Updates download progress and triggers completion when all fragments are done. Triggers on:jobsSlice.actions.incDownloadStatus
Dispatches: jobsSlice.actions.finishDownload (when complete)
Subtitle epics
downloadSubtitleEpic
Downloads a subtitle track and saves it as a WebVTT file. Triggers on: Custom subtitle download action Dispatches: Success/failure actionsInspection epics
inspectLevelEpic
Inspects a quality level to detect encryption and fragment details. Triggers on:levelInspectionsSlice.actions.inspect
Dispatches:
levelInspectionsSlice.actions.inspectSuccesslevelInspectionsSlice.actions.inspectFailed
Initialization epic
onInit
Runs initialization logic when the store starts. Triggers on:"init/start" action
Dispatches: "init/done" action
Complete epic list
All epics exported from the controllers module:downloadJobEpic: Download all fragments for a jobaddDownloadJobEpic: Add new download jobsaveAsJobEpic: Save completed job to fileincDownloadStatusEpic: Update download progressdownloadQueueEpic: Manage download queuefetchPlaylistLevelsEpic: Fetch playlist quality levelsaddPlaylistEpic: Add playlist and trigger fetchdeleteJobEpic: Delete job and cleanuponInit: Initialize storecancelJobDeleteJobEpic: Cancel and delete jobdownloadSubtitleEpic: Download subtitle trackinspectLevelEpic: Inspect level encryptionremovePlaylistEpic: Remove playlist and cleanup