From 55fbb15deb78be5c9c76d5f70c0513e84356b06e Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Fri, 1 Jan 2021 16:48:42 -0800 Subject: [PATCH] Pull demo site webamp config into typed module --- packages/webamp/demo/js/Webamp.ts | 7 +- packages/webamp/demo/js/config.ts | 2 +- packages/webamp/demo/js/index.js | 119 +-------------------- packages/webamp/demo/js/webampConfig.ts | 134 ++++++++++++++++++++++++ packages/webamp/js/types.ts | 2 +- packages/webamp/js/webampLazy.tsx | 31 +++--- 6 files changed, 162 insertions(+), 133 deletions(-) create mode 100644 packages/webamp/demo/js/webampConfig.ts diff --git a/packages/webamp/demo/js/Webamp.ts b/packages/webamp/demo/js/Webamp.ts index 9aca6b38..87bfbd5d 100644 --- a/packages/webamp/demo/js/Webamp.ts +++ b/packages/webamp/demo/js/Webamp.ts @@ -4,7 +4,12 @@ // away once we've figured out how to expose all the things that the demo site // needs, or reduce the things that the demo site needs access to. -export { default as WebampLazy } from "../../js/webampLazy"; +export { + default as WebampLazy, + Options, + PrivateOptions, + WindowLayout, +} from "../../js/webampLazy"; export { ButterchurnOptions, Track, diff --git a/packages/webamp/demo/js/config.ts b/packages/webamp/demo/js/config.ts index b6b3deee..fb260444 100644 --- a/packages/webamp/demo/js/config.ts +++ b/packages/webamp/demo/js/config.ts @@ -33,7 +33,7 @@ if ("URLSearchParams" in window) { // SHOW_DESKTOP_ICONS = Boolean(params.get("icons")); } -export const skinUrl = config.skinUrl === undefined ? null : config.skinUrl; +export const skinUrl = config.skinUrl ?? null; // https://freemusicarchive.org/music/netBloc_Artists/netBloc_Vol_24_tiuqottigeloot/ const album = "netBloc Vol. 24: tiuqottigeloot"; diff --git a/packages/webamp/demo/js/index.js b/packages/webamp/demo/js/index.js index 9c020a7a..cd0b19a0 100644 --- a/packages/webamp/demo/js/index.js +++ b/packages/webamp/demo/js/index.js @@ -2,19 +2,11 @@ import * as Sentry from "@sentry/browser"; import ReactDOM from "react-dom"; -import createMiddleware from "redux-sentry-middleware"; import isButterchurnSupported from "butterchurn/lib/isSupported.min"; -import { loggerMiddleware } from "./eventLogger"; +import { getWebampConfig } from "./webampConfig"; import { WebampLazy, - WINDOWS, - STEP_MARQUEE, - UPDATE_TIME_ELAPSED, - UPDATE_WINDOW_POSITIONS, - SET_VOLUME, - SET_BALANCE, - SET_BAND_VALUE, DISABLE_MARQUEE, TOGGLE_REPEAT, TOGGLE_SHUFFLE, @@ -22,33 +14,12 @@ import { SET_DUMMY_VIZ_DATA, } from "./Webamp"; -import { getButterchurnOptions } from "./butterchurnOptions"; -import dropboxFilePicker from "./dropboxFilePicker"; -import availableSkins from "./avaliableSkins"; - -import { - skinUrl as configSkinUrl, - initialTracks, - initialState, - disableMarquee, -} from "./config"; +import { disableMarquee, skinUrl as configSkinUrl } from "./config"; import DemoDesktop from "./DemoDesktop"; import enableMediaSession from "./mediaSession"; -import screenshotInitialState from "./screenshotInitialState"; const DEFAULT_DOCUMENT_TITLE = document.title; -const NOISY_ACTION_TYPES = new Set([ - STEP_MARQUEE, - UPDATE_TIME_ELAPSED, - UPDATE_WINDOW_POSITIONS, - SET_VOLUME, - SET_BALANCE, - SET_BAND_VALUE, -]); - -const MIN_MILKDROP_WIDTH = 725; - let screenshot = false; let skinUrl = configSkinUrl; if ("URLSearchParams" in window) { @@ -67,17 +38,6 @@ window.addEventListener("dragenter", supressDragAndDrop); window.addEventListener("dragover", supressDragAndDrop); window.addEventListener("drop", supressDragAndDrop); -let lastActionType = null; - -// Filter out consecutive common actions -function filterBreadcrumbActions(action) { - const noisy = - NOISY_ACTION_TYPES.has(action.type) && - NOISY_ACTION_TYPES.has(lastActionType); - lastActionType = action.type; - return !noisy; -} - try { Sentry.init({ dsn: SENTRY_DSN, @@ -90,11 +50,6 @@ try { console.error(e); } -const sentryMiddleware = createMiddleware(Sentry, { - filterBreadcrumbActions, - stateTransformer: getDebugData, -}); - async function main() { const about = document.getElementsByClassName("about")[0]; if (screenshot) { @@ -107,66 +62,11 @@ async function main() { } about.classList.add("loaded"); - let __butterchurnOptions = null; - let __initialWindowLayout = null; if (isButterchurnSupported()) { - const startWithMilkdropHidden = - document.body.clientWidth < MIN_MILKDROP_WIDTH || - skinUrl != null || - screenshot; - - __butterchurnOptions = getButterchurnOptions(startWithMilkdropHidden); - - if (startWithMilkdropHidden) { - __initialWindowLayout = { - [WINDOWS.MAIN]: { position: { x: 0, y: 0 } }, - [WINDOWS.EQUALIZER]: { position: { x: 0, y: 116 } }, - [WINDOWS.PLAYLIST]: { position: { x: 0, y: 232 }, size: [0, 0] }, - [WINDOWS.MILKDROP]: { position: { x: 0, y: 348 }, size: [0, 0] }, - }; - } else { - __initialWindowLayout = { - [WINDOWS.MAIN]: { position: { x: 0, y: 0 } }, - [WINDOWS.EQUALIZER]: { position: { x: 0, y: 116 } }, - [WINDOWS.PLAYLIST]: { position: { x: 0, y: 232 }, size: [0, 4] }, - [WINDOWS.MILKDROP]: { position: { x: 275, y: 0 }, size: [7, 12] }, - }; - } - document.getElementById("butterchurn-share").style.display = "flex"; } - const initialSkin = !skinUrl ? null : { url: skinUrl }; - - const webamp = new WebampLazy({ - initialSkin, - initialTracks: screenshot ? null : initialTracks, - availableSkins, - filePickers: [dropboxFilePicker], - enableHotkeys: true, - handleTrackDropEvent: (e) => { - const trackJson = e.dataTransfer.getData("text/json"); - if (trackJson == null) { - return null; - } - try { - const track = JSON.parse(trackJson); - return [track]; - } catch (err) { - return null; - } - }, - requireJSZip: () => - import(/* webpackChunkName: "jszip" */ "jszip/dist/jszip"), - requireMusicMetadata: () => - import( - /* webpackChunkName: "music-metadata-browser" */ "music-metadata-browser/dist/index" - ), - __initialWindowLayout, - __initialState: screenshot ? screenshotInitialState : initialState, - __butterchurnOptions, - __customMiddlewares: [sentryMiddleware, loggerMiddleware], - }); + const webamp = new WebampLazy(getWebampConfig(screenshot, skinUrl)); if (disableMarquee || screenshot) { webamp.store.dispatch({ type: DISABLE_MARQUEE }); @@ -237,17 +137,4 @@ async function main() { } } -function getDebugData(state) { - return { - ...state, - display: { - ...state.display, - skinGenLetterWidths: "[[REDACTED]]", - skinImages: "[[REDACTED]]", - skinCursors: "[[REDACTED]]", - skinRegion: "[[REDACTED]]", - }, - }; -} - main(); diff --git a/packages/webamp/demo/js/webampConfig.ts b/packages/webamp/demo/js/webampConfig.ts new file mode 100644 index 00000000..a83110c2 --- /dev/null +++ b/packages/webamp/demo/js/webampConfig.ts @@ -0,0 +1,134 @@ +import * as Sentry from "@sentry/browser"; +// @ts-ignore +import createMiddleware from "redux-sentry-middleware"; +// @ts-ignore +import isButterchurnSupported from "butterchurn/lib/isSupported.min"; +import { loggerMiddleware } from "./eventLogger"; + +import { + Action, + Options, + PrivateOptions, + WINDOWS, + STEP_MARQUEE, + UPDATE_TIME_ELAPSED, + UPDATE_WINDOW_POSITIONS, + SET_VOLUME, + SET_BALANCE, + SET_BAND_VALUE, + AppState, + WindowLayout, +} from "./Webamp"; + +import { getButterchurnOptions } from "./butterchurnOptions"; +import dropboxFilePicker from "./dropboxFilePicker"; +import availableSkins from "./avaliableSkins"; + +import { initialTracks, initialState } from "./config"; +import screenshotInitialState from "./screenshotInitialState"; + +const NOISY_ACTION_TYPES = new Set([ + STEP_MARQUEE, + UPDATE_TIME_ELAPSED, + UPDATE_WINDOW_POSITIONS, + SET_VOLUME, + SET_BALANCE, + SET_BAND_VALUE, +]); + +const MIN_MILKDROP_WIDTH = 725; + +let lastActionType: string | null = null; + +// Filter out consecutive common actions +function filterBreadcrumbActions(action: Action) { + const noisy = + lastActionType != null && + NOISY_ACTION_TYPES.has(action.type) && + NOISY_ACTION_TYPES.has(lastActionType); + lastActionType = action.type; + return !noisy; +} + +const sentryMiddleware = createMiddleware(Sentry, { + filterBreadcrumbActions, + stateTransformer: getDebugData, +}); + +export function getWebampConfig( + screenshot: boolean, + skinUrl: string | null +): Options & PrivateOptions { + let __butterchurnOptions; + let __initialWindowLayout: WindowLayout | undefined; + if (isButterchurnSupported()) { + const startWithMilkdropHidden = + document.body.clientWidth < MIN_MILKDROP_WIDTH || + skinUrl != null || + screenshot; + + __butterchurnOptions = getButterchurnOptions(startWithMilkdropHidden); + + if (startWithMilkdropHidden) { + __initialWindowLayout = { + [WINDOWS.MAIN]: { position: { x: 0, y: 0 } }, + [WINDOWS.EQUALIZER]: { position: { x: 0, y: 116 } }, + [WINDOWS.PLAYLIST]: { position: { x: 0, y: 232 }, size: [0, 0] }, + [WINDOWS.MILKDROP]: { position: { x: 0, y: 348 }, size: [0, 0] }, + }; + } else { + __initialWindowLayout = { + [WINDOWS.MAIN]: { position: { x: 0, y: 0 } }, + [WINDOWS.EQUALIZER]: { position: { x: 0, y: 116 } }, + [WINDOWS.PLAYLIST]: { position: { x: 0, y: 232 }, size: [0, 4] }, + [WINDOWS.MILKDROP]: { position: { x: 275, y: 0 }, size: [7, 12] }, + }; + } + } + + const initialSkin = !skinUrl ? undefined : { url: skinUrl }; + + return { + initialSkin, + initialTracks: screenshot ? undefined : initialTracks, + availableSkins, + filePickers: [dropboxFilePicker], + enableHotkeys: true, + handleTrackDropEvent: (e) => { + const trackJson = e.dataTransfer.getData("text/json"); + if (trackJson == null) { + return null; + } + try { + const track = JSON.parse(trackJson); + return [track]; + } catch (err) { + return null; + } + }, + requireJSZip: () => + // @ts-ignore + import(/* webpackChunkName: "jszip" */ "jszip/dist/jszip"), + requireMusicMetadata: () => + import( + /* webpackChunkName: "music-metadata-browser" */ "music-metadata-browser/dist/index" + ), + __initialWindowLayout, + __initialState: screenshot ? screenshotInitialState : initialState, + __butterchurnOptions, + __customMiddlewares: [sentryMiddleware, loggerMiddleware], + }; +} + +function getDebugData(state: AppState) { + return { + ...state, + display: { + ...state.display, + skinGenLetterWidths: "[[REDACTED]]", + skinImages: "[[REDACTED]]", + skinCursors: "[[REDACTED]]", + skinRegion: "[[REDACTED]]", + }, + }; +} diff --git a/packages/webamp/js/types.ts b/packages/webamp/js/types.ts index 8a3c4016..dd5b0d60 100644 --- a/packages/webamp/js/types.ts +++ b/packages/webamp/js/types.ts @@ -705,7 +705,7 @@ export interface IMusicMetadataBrowserApi { } export interface Extras { - requireJSZip(): Promise; + requireJSZip(): Promise; requireMusicMetadata(): Promise; convertPreset: ((file: File) => Promise) | null; handleTrackDropEvent?: ( diff --git a/packages/webamp/js/webampLazy.tsx b/packages/webamp/js/webampLazy.tsx index 935cabbd..e2f60307 100644 --- a/packages/webamp/js/webampLazy.tsx +++ b/packages/webamp/js/webampLazy.tsx @@ -39,8 +39,9 @@ import Emitter from "./emitter"; import "../css/base-skin.css"; import { SerializedStateV1 } from "./serializedStates/v1Types"; import Disposable from "./Disposable"; +import { DeepPartial } from "redux"; -interface Options { +export interface Options { /** * An object representing the initial skin to use. * @@ -113,21 +114,23 @@ interface Options { handleSaveListEvent?: (tracks: Track[]) => null | Promise; } -interface PrivateOptions { - avaliableSkins?: { url: string; name: string }[]; // Old misspelled name - requireJSZip(): Promise; // TODO: Type JSZip - requireMusicMetadata(): Promise; // TODO: Type musicmetadata - __initialState?: AppState; - __customMiddlewares?: Middleware[]; - __initialWindowLayout: { - [windowId: string]: { - size: null | [number, number]; - position: WindowPosition; - }; +export type WindowLayout = { + [windowId: string]: { + size?: null | [number, number]; + position: WindowPosition; }; - __butterchurnOptions: ButterchurnOptions; +}; + +export interface PrivateOptions { + avaliableSkins?: { url: string; name: string }[]; // Old misspelled name + requireJSZip(): Promise; // TODO: Type JSZip + requireMusicMetadata(): Promise; // TODO: Type musicmetadata + __initialState?: DeepPartial; + __customMiddlewares?: Middleware[]; + __initialWindowLayout?: WindowLayout; + __butterchurnOptions?: ButterchurnOptions; // This is used by https://winampify.io/ to proxy through to Spotify's API. - __customMediaClass: typeof Media; // This should have the same interface as Media + __customMediaClass?: typeof Media; // This should have the same interface as Media } // Return a promise that resolves when the store matches a predicate.