Fix early resolution of renderWhenReady

This commit is contained in:
Jordan Eldredge 2025-06-29 15:19:52 -07:00
parent 4c07731d76
commit a618b049eb
3 changed files with 34 additions and 9 deletions

View file

@ -10,6 +10,7 @@
- `webamp.toggleShuffle`
- `webamp.toggleRepeat`
- Add new config option `enableMediaSession` to allow Webamp to connect to the browser's Media Session API. This enables OS/hardware level media controls like play/pause/next/previous.
- Ensure the promise returned from `renderWhenReady` only resolves after the Webamp instance has been fully mounted and inserted into the DOM. Previously it resolved after the DOM node was created but before it was inserted into the DOM.
## 2.1.2 [CURRENT]

View file

@ -30,12 +30,19 @@ import cssText from "../../css/webamp.css?inline";
interface Props {
filePickers: FilePicker[];
media: IMedia;
parentDomNode: HTMLElement;
onMount?: () => void;
}
/**
* Constructs the windows to render
*/
export default function App({ media, filePickers }: Props) {
export default function App({
media,
filePickers,
onMount,
parentDomNode,
}: Props) {
const closed = useTypedSelector(Selectors.getClosed);
const genWindowsInfo = useTypedSelector(Selectors.getGenWindows);
const zIndex = useTypedSelector(Selectors.getZIndex);
@ -58,11 +65,11 @@ export default function App({ media, filePickers }: Props) {
}, [webampNode, zIndex]);
useLayoutEffect(() => {
document.body.appendChild(webampNode);
parentDomNode.appendChild(webampNode);
return () => {
document.body.removeChild(webampNode);
parentDomNode.removeChild(webampNode);
};
}, [webampNode]);
}, [webampNode, parentDomNode]);
useEffect(() => {
const handleWindowResize = () => {
@ -95,6 +102,12 @@ export default function App({ media, filePickers }: Props) {
};
}, [browserWindowSizeChanged, webampNode]);
useEffect(() => {
if (onMount != null) {
onMount();
}
}, [onMount]);
const renderWindows = useCallback(() => {
return Utils.objectMap(genWindowsInfo, (w, id) => {
if (!w.open) {

View file

@ -101,10 +101,6 @@ class Webamp {
__customMediaClass,
} = this.options;
if (options.enableMediaSession) {
enableMediaSession(this);
}
// TODO: Make this much cleaner.
let convertPreset = null;
if (__butterchurnOptions != null) {
@ -142,6 +138,10 @@ class Webamp {
}
) as Store;
if (options.enableMediaSession) {
enableMediaSession(this);
}
if (enableDoubleSizeMode) {
this.store.dispatch(Actions.toggleDoubleSizeMode());
}
@ -473,11 +473,22 @@ class Webamp {
}
});
let onMount: (() => void) | undefined;
const mountPromise = new Promise<void>((resolve) => {
onMount = resolve;
});
this._root.render(
<Provider store={this.store}>
<App media={this.media} filePickers={this.options.filePickers || []} />
<App
media={this.media}
filePickers={this.options.filePickers || []}
onMount={onMount}
parentDomNode={document.body}
/>
</Provider>
);
await mountPromise;
}
/**