mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-19 01:23:49 +00:00
POC: Try adding rexux-observable
I don't know how we'll feasibly solve the multide of potential race conditons and async clean up memory leaks without something like rxjs. So, this is a trial to see the following: 1. How much does it increase bundle size? 2. How effective is typechecking? 3. Does it solve some of the difficult cancelation issues we have?
This commit is contained in:
parent
f3358475fb
commit
58fd75c8a1
7 changed files with 100 additions and 36 deletions
|
|
@ -7,7 +7,6 @@ import {
|
|||
promptForFileReferences,
|
||||
genArrayBufferFromFileReference,
|
||||
genMediaDuration,
|
||||
genMediaTags,
|
||||
} from "../fileUtils";
|
||||
import skinParser from "../skinParser";
|
||||
import {
|
||||
|
|
@ -23,8 +22,6 @@ import {
|
|||
BUFFER_TRACK,
|
||||
SET_MEDIA_TAGS,
|
||||
SET_MEDIA_DURATION,
|
||||
MEDIA_TAG_REQUEST_INITIALIZED,
|
||||
MEDIA_TAG_REQUEST_FAILED,
|
||||
SET_SKIN_DATA,
|
||||
LOADED,
|
||||
LOADING,
|
||||
|
|
@ -33,7 +30,7 @@ import LoadQueue from "../loadQueue";
|
|||
|
||||
import { removeAllTracks } from "./playlist";
|
||||
import { setPreamp, setEqBand } from "./equalizer";
|
||||
import { LoadStyle, Thunk, Track, EqfPreset, SkinData } from "../types";
|
||||
import { LoadStyle, Thunk, Action, Track, EqfPreset, SkinData } from "../types";
|
||||
|
||||
// Lower is better
|
||||
const DURATION_VISIBLE_PRIORITY = 5;
|
||||
|
|
@ -297,36 +294,8 @@ function queueFetchingMediaTags(id: number): Thunk {
|
|||
};
|
||||
}
|
||||
|
||||
export function fetchMediaTags(file: string | Blob, id: number): Thunk {
|
||||
return async (dispatch, getState, { requireMusicMetadata }) => {
|
||||
dispatch({ type: MEDIA_TAG_REQUEST_INITIALIZED, id });
|
||||
|
||||
try {
|
||||
const metadata = await genMediaTags(file, await requireMusicMetadata());
|
||||
// There's more data here, but we don't have a use for it yet:
|
||||
const { artist, title, album, picture } = metadata.common;
|
||||
const { numberOfChannels, bitrate, sampleRate } = metadata.format;
|
||||
let albumArtUrl = null;
|
||||
if (picture && picture.length >= 1) {
|
||||
const byteArray = new Uint8Array(picture[0].data);
|
||||
const blob = new Blob([byteArray], { type: picture[0].format });
|
||||
albumArtUrl = URL.createObjectURL(blob);
|
||||
}
|
||||
dispatch({
|
||||
type: SET_MEDIA_TAGS,
|
||||
artist: artist ? artist : "",
|
||||
title: title ? title : "",
|
||||
album,
|
||||
albumArtUrl,
|
||||
numberOfChannels,
|
||||
bitrate,
|
||||
sampleRate,
|
||||
id,
|
||||
});
|
||||
} catch (e) {
|
||||
dispatch({ type: MEDIA_TAG_REQUEST_FAILED, id });
|
||||
}
|
||||
};
|
||||
export function fetchMediaTags(file: string | Blob, id: number): Action {
|
||||
return { type: "FETCH_MEDIA_TAGS", file, id };
|
||||
}
|
||||
|
||||
export function setEqFromFileReference(fileReference: File): Thunk {
|
||||
|
|
|
|||
|
|
@ -87,3 +87,4 @@ export const TOGGLE_RANDOMIZE_PRESETS = "TOGGLE_RANDOMIZE_PRESETS";
|
|||
export const TOGGLE_PRESET_CYCLING = "TOGGLE_PRESET_CYCLING";
|
||||
export const SCHEDULE_MILKDROP_MESSAGE = "SCHEDULE_MILKDROP_MESSAGE";
|
||||
export const SET_MILKDROP_FULLSCREEN = "SET_MILKDROP_FULLSCREEN";
|
||||
export const FETCH_MEDIA_TAGS = "FETCH_MEDIA_TAGS";
|
||||
|
|
|
|||
66
js/epics.ts
Normal file
66
js/epics.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { Observable, of, defer, concat } from "rxjs";
|
||||
import { filter, mergeMap, catchError } from "rxjs/operators";
|
||||
import { Action, AppState, Extras } from "./types";
|
||||
import {
|
||||
MEDIA_TAG_REQUEST_INITIALIZED,
|
||||
SET_MEDIA_TAGS,
|
||||
MEDIA_TAG_REQUEST_FAILED,
|
||||
FETCH_MEDIA_TAGS,
|
||||
} from "./actionTypes";
|
||||
import { genMediaTags } from "./fileUtils";
|
||||
|
||||
export const fetchMediaTagsEpic = (
|
||||
actions: Observable<Action>,
|
||||
states: Observable<AppState>,
|
||||
{ requireMusicMetadata }: Extras
|
||||
): Observable<Action> => {
|
||||
return actions.pipe(
|
||||
filter(action => action.type === FETCH_MEDIA_TAGS),
|
||||
mergeMap(action => {
|
||||
// TODO: Check out https://github.com/piotrwitek/typesafe-actions
|
||||
if (action.type !== FETCH_MEDIA_TAGS) {
|
||||
throw new Error("Invalid");
|
||||
}
|
||||
const { file, id } = action;
|
||||
|
||||
return concat(
|
||||
of({
|
||||
type: MEDIA_TAG_REQUEST_INITIALIZED,
|
||||
id,
|
||||
} as const),
|
||||
defer(async () => {
|
||||
const musicMetadata = await requireMusicMetadata();
|
||||
const metadata = await genMediaTags(file, musicMetadata);
|
||||
// There's more data here, but we don't have a use for it yet:
|
||||
const { artist, title, album, picture } = metadata.common;
|
||||
const { numberOfChannels, bitrate, sampleRate } = metadata.format;
|
||||
let albumArtUrl = null;
|
||||
if (picture && picture.length >= 1) {
|
||||
const byteArray = new Uint8Array(picture[0].data);
|
||||
const blob = new Blob([byteArray], { type: picture[0].format });
|
||||
albumArtUrl = URL.createObjectURL(blob);
|
||||
}
|
||||
return {
|
||||
type: SET_MEDIA_TAGS,
|
||||
artist: artist ? artist : "",
|
||||
title: title ? title : "",
|
||||
album,
|
||||
albumArtUrl,
|
||||
numberOfChannels,
|
||||
bitrate,
|
||||
sampleRate,
|
||||
id,
|
||||
} as const;
|
||||
}).pipe(
|
||||
catchError(e => {
|
||||
console.error("Failed to fetch media tags", e);
|
||||
return of({
|
||||
type: MEDIA_TAG_REQUEST_FAILED,
|
||||
id,
|
||||
} as const);
|
||||
})
|
||||
)
|
||||
);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
|
@ -8,6 +8,8 @@ import { UPDATE_TIME_ELAPSED, STEP_MARQUEE } from "./actionTypes";
|
|||
import Media from "./media";
|
||||
import Emitter from "./emitter";
|
||||
import { Extras, Dispatch, Action, AppState, Middleware } from "./types";
|
||||
import { createEpicMiddleware, combineEpics } from "redux-observable";
|
||||
import * as Epics from "./epics";
|
||||
|
||||
// TODO: Move to demo
|
||||
const compose = composeWithDevTools({
|
||||
|
|
@ -34,10 +36,15 @@ export default function(
|
|||
return next(action);
|
||||
};
|
||||
|
||||
const epicMiddleware = createEpicMiddleware({
|
||||
dependencies: extras,
|
||||
});
|
||||
|
||||
const enhancer = compose(
|
||||
applyMiddleware(
|
||||
...[
|
||||
thunk.withExtraArgument(extras),
|
||||
epicMiddleware,
|
||||
mediaMiddleware(media),
|
||||
emitterMiddleware,
|
||||
...customMiddlewares,
|
||||
|
|
@ -50,5 +57,7 @@ export default function(
|
|||
const store = initialState
|
||||
? createStore(reducer, initialState, enhancer)
|
||||
: createStore(reducer, enhancer);
|
||||
|
||||
epicMiddleware.run(combineEpics(...Object.values(Epics)));
|
||||
return store;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -509,7 +509,12 @@ export type Action =
|
|||
index: number;
|
||||
transitionType: TransitionType;
|
||||
}
|
||||
| { type: "TOGGLE_PRESET_OVERLAY" };
|
||||
| { type: "TOGGLE_PRESET_OVERLAY" }
|
||||
| {
|
||||
type: "FETCH_MEDIA_TAGS";
|
||||
file: string | Blob;
|
||||
id: number;
|
||||
};
|
||||
|
||||
export type MediaTagRequestStatus =
|
||||
| "INITIALIZED"
|
||||
|
|
|
|||
|
|
@ -154,7 +154,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"eslint-plugin-react-hooks": "^1.5.1",
|
||||
"fscreen": "^1.0.2"
|
||||
"fscreen": "^1.0.2",
|
||||
"redux-observable": "^1.1.0",
|
||||
"rxjs": "^6.5.2"
|
||||
},
|
||||
"bundlesize": [
|
||||
{
|
||||
|
|
|
|||
12
yarn.lock
12
yarn.lock
|
|
@ -9079,6 +9079,11 @@ redux-devtools-extension@^2.13.2:
|
|||
resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz#37b982688626e5e4993ff87220c9bbb7cd2d96e1"
|
||||
integrity sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg==
|
||||
|
||||
redux-observable@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/redux-observable/-/redux-observable-1.1.0.tgz#323a8fe53e89fdb519be2807b55f08e21c13e6f1"
|
||||
integrity sha512-G0nxgmTZwTK3Z3KoQIL8VQu9n0YCUwEP3wc3zxKQ8zAZm+iYkoZvBqAnBJfLi4EsD1E64KR4s4jFH/dFXpV9Og==
|
||||
|
||||
redux-thunk@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
|
||||
|
|
@ -9459,6 +9464,13 @@ rxjs@^6.4.0:
|
|||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
rxjs@^6.5.2:
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7"
|
||||
integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
safe-buffer@5.1.1, safe-buffer@^5.1.0, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue