webamp/packages/webamp-demo/js/webampConfig.ts
Jordan Eldredge c7a282c1fd
Split demo site into its own package (#1351)
* Split demo site into its own package

Move the demo site from packages/webamp/demo/ into packages/webamp-demo/
as a standalone workspace package. This cleanly separates the library
(published to npm) from the demo site (deployed to webamp.org).

Key changes:
- Demo imports webamp source via relative paths (no aliases needed)
- Demo has its own package.json with demo-specific deps
- Simplified vite config (just nodePolyfills plugin)
- Removed vite branching from rollupPlugins.mjs (library-only now)
- Renamed build-library -> build in webamp package
- Updated turbo.json, CI, netlify config, and code-size workflow
- Removed demo-only deps from webamp package (sentry, butterchurn stays
  for the butterchurn bundle)
- Zero bundle size change for the library

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix: add type-check dependency to webamp#build task

The webamp-docs package needs type declarations from webamp to
type-check. These are generated by tsc (type-check), which must run
before the build task.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add updated readme to webamp-demo package

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Document the live reloading dev flow in both readmes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix code-size CI: use deploy script that exists on both branches

The compressed-size-action checks out master and runs the build script.
Master doesn't have a root "build" script, so revert to using "deploy"
which exists on both branches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-07 14:40:07 -07:00

141 lines
4.1 KiB
TypeScript

import * as Sentry from "@sentry/browser";
// @ts-ignore
import createMiddleware from "redux-sentry-middleware";
// @ts-ignore
import isButterchurnSupported from "butterchurn/dist/isSupported.min";
import { loggerMiddleware } from "./eventLogger";
import * as SoundCloud from "./SoundCloud";
import { Action, Options, AppState, WindowLayout } from "../../webamp/js/types";
import { getButterchurnOptions } from "./butterchurnOptions";
import dropboxFilePicker from "./dropboxFilePicker";
import availableSkins from "./availableSkins";
import { initialTracks, initialState } from "./config";
import screenshotInitialState from "./screenshotInitialState";
import { InjectableDependencies, PrivateOptions } from "../../webamp/js/webampLazy";
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 async function getWebampConfig(
screenshot: boolean,
skinUrl: string | null,
soundCloudPlaylist: SoundCloud.SoundCloudPlaylist | null
): Promise<Options & PrivateOptions & InjectableDependencies> {
let __butterchurnOptions;
let windowLayout: WindowLayout | undefined;
if (isButterchurnSupported()) {
const startWithMilkdropHidden = skinUrl != null || screenshot;
__butterchurnOptions = getButterchurnOptions(startWithMilkdropHidden);
if (
startWithMilkdropHidden ||
document.body.clientWidth < MIN_MILKDROP_WIDTH
) {
windowLayout = {
main: { position: { left: 0, top: 0 } },
equalizer: { position: { left: 0, top: 116 } },
playlist: {
position: { left: 0, top: 232 },
size: { extraHeight: 0, extraWidth: 0 },
},
milkdrop: {
position: { left: 0, top: 348 },
size: { extraHeight: 0, extraWidth: 0 },
},
};
} else {
windowLayout = {
main: { position: { left: 0, top: 0 } },
equalizer: { position: { left: 0, top: 116 } },
playlist: {
position: { left: 0, top: 232 },
size: { extraHeight: 4, extraWidth: 0 },
},
milkdrop: {
position: { left: 275, top: 0 },
size: { extraHeight: 12, extraWidth: 7 },
},
};
}
}
const initialSkin = !skinUrl ? undefined : { url: skinUrl };
return {
initialSkin,
// eslint-disable-next-line no-nested-ternary
initialTracks: screenshot
? undefined
: soundCloudPlaylist != null
? SoundCloud.tracksFromPlaylist(soundCloudPlaylist)
: initialTracks,
availableSkins,
windowLayout,
filePickers: [dropboxFilePicker],
enableHotkeys: true,
enableMediaSession: 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: () =>
// @ts-ignore
import(/* webpackChunkName: "music-metadata" */ "music-metadata"),
__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]]",
},
};
}