diff --git a/js/constants.ts b/js/constants.ts index fa784b72..fde799b4 100644 --- a/js/constants.ts +++ b/js/constants.ts @@ -1,4 +1,4 @@ -import { Band, MediaTagRequestStatus } from "./types"; +import { Band, MediaTagRequestStatus, MediaStatus } from "./types"; import * as baseSkin from "./baseSkin.json"; export const BANDS: Band[] = [ 60, @@ -63,7 +63,8 @@ export const TIME_MODE = { REMAINING: "REMAINING" }; -export const MEDIA_STATUS = { +// TODO: Convert to enum once we are fully Typescript +export const MEDIA_STATUS: Record = { PLAYING: "PLAYING", STOPPED: "STOPPED", PAUSED: "PAUSED" diff --git a/js/media/elementSource.js b/js/media/elementSource.ts similarity index 89% rename from js/media/elementSource.js rename to js/media/elementSource.ts index 3796b380..701a2e30 100644 --- a/js/media/elementSource.js +++ b/js/media/elementSource.ts @@ -1,13 +1,22 @@ import Emitter from "../emitter"; import { clamp } from "../utils"; import { MEDIA_STATUS } from "../constants"; +import { MediaStatus } from "../types"; export default class ElementSource { - on(eventType, cb) { + _emitter: Emitter; + _context: AudioContext; + _source: AudioNode; + _destination: AudioNode; + _audio: HTMLAudioElement; + _stalled: boolean; + _status: MediaStatus; + + on(eventType: string, cb: (...args: any[]) => void) { return this._emitter.on(eventType, cb); } - constructor(context, destination) { + constructor(context: AudioContext, destination: AudioNode) { this._emitter = new Emitter(); this._context = context; this._destination = destination; @@ -36,7 +45,7 @@ export default class ElementSource { }); this._audio.addEventListener("error", e => { - switch (this._audio.error.code) { + switch (this._audio.error!.code) { case 1: // The fetching of the associated resource was aborted by the user's request. console.error("MEDIA_ERR_ABORTED", e); @@ -69,7 +78,7 @@ export default class ElementSource { this._source.connect(destination); } - _setStalled(stalled) { + _setStalled(stalled: boolean) { this._stalled = stalled; this._emitter.trigger("stallChanged"); } @@ -80,7 +89,7 @@ export default class ElementSource { // Async for now, for compatibility with BufferAudioSource // TODO: This does not need to be async - async loadUrl(url) { + async loadUrl(url: string) { this._audio.src = url; } @@ -107,7 +116,7 @@ export default class ElementSource { this._setStatus(MEDIA_STATUS.STOPPED); } - seekToTime(time) { + seekToTime(time: number) { /* TODO: We could check if this is actually seekable: const { seekable } = this._audio; for (let i = 0; i < seekable.length; i++) { @@ -148,7 +157,7 @@ export default class ElementSource { return this._context.sampleRate; } - _setStatus(status) { + _setStatus(status: MediaStatus) { this._status = status; this._emitter.trigger("statusChange"); } diff --git a/js/types.ts b/js/types.ts index e98f6d0d..e0523ca7 100644 --- a/js/types.ts +++ b/js/types.ts @@ -393,6 +393,8 @@ export type MediaTagRequestStatus = | "COMPLETE" | "NOT_REQUESTED"; +export type MediaStatus = "PLAYING" | "STOPPED" | "PAUSED"; + export interface PlaylistTrack { artist: string; title: string; diff --git a/package.json b/package.json index 94c0186c..527fd5bc 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "@types/react": "^16.4.14", "@types/react-dom": "^16.0.7", "@types/react-redux": "^6.0.8", + "@types/webaudioapi": "^0.0.27", "babel-core": "7.0.0-bridge.0", "babel-eslint": "^9.0.0-beta.3", "babel-jest": "^23.4.2", diff --git a/yarn.lock b/yarn.lock index 147f7bc1..aa14d29c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -760,6 +760,10 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/webaudioapi@^0.0.27": + version "0.0.27" + resolved "https://registry.yarnpkg.com/@types/webaudioapi/-/webaudioapi-0.0.27.tgz#8a3f98eaa07cb577be2dae22311d37c3b545f74f" + abab@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e"