SpotifyControls: fix SeekBar not updating (#3381)

Also slightly reworks LazyComponents for more useful typing
This commit is contained in:
Vending Machine 2025-04-14 15:21:30 +02:00 committed by GitHub
parent a8c01a2a05
commit 0f4d3dfd3a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 57 additions and 27 deletions

View file

@ -142,8 +142,7 @@ export default definePlugin({
// Thus, we sanity check webpack modules
Layer(props: LayerProps) {
try {
// @ts-ignore
[FocusLock.$$vencordInternal(), ComponentDispatch, Classes].forEach(e => e.test);
[FocusLock.$$vencordGetWrappedComponent(), ComponentDispatch, Classes].forEach(e => e.test);
} catch {
new Logger("BetterSettings").error("Failed to find some components");
return props.children;

View file

@ -174,8 +174,8 @@ function loadAndCacheShortcut(key: string, val: any, forceLoad: boolean) {
function unwrapProxy(value: any) {
if (value[SYM_LAZY_GET]) {
forceLoad ? currentVal[SYM_LAZY_GET]() : currentVal[SYM_LAZY_CACHED];
} else if (value.$$vencordInternal) {
return forceLoad ? value.$$vencordInternal() : value;
} else if (value.$$vencordGetWrappedComponent) {
return forceLoad ? value.$$vencordGetWrappedComponent() : value;
}
return value;

View file

@ -28,6 +28,7 @@ import { openImageModal } from "@utils/discord";
import { classes, copyWithToast } from "@utils/misc";
import { ContextMenuApi, FluxDispatcher, Forms, Menu, React, useEffect, useState, useStateFromStores } from "@webpack/common";
import { SeekBar } from "./SeekBar";
import { SpotifyStore, Track } from "./SpotifyStore";
const cl = classNameFactory("vc-spotify-");
@ -160,7 +161,7 @@ const seek = debounce((v: number) => {
SpotifyStore.seek(v);
});
function SeekBar() {
function SpotifySeekBar() {
const { duration } = SpotifyStore.track!;
const [storePosition, isSettingPosition, isPlaying] = useStateFromStores(
@ -181,6 +182,12 @@ function SeekBar() {
}
}, [storePosition, isSettingPosition, isPlaying]);
const onChange = (v: number) => {
if (isSettingPosition) return;
setPosition(v);
seek(v);
};
return (
<div id={cl("progress-bar")}>
<Forms.FormText
@ -190,16 +197,13 @@ function SeekBar() {
>
{msToHuman(position)}
</Forms.FormText>
<Menu.MenuSliderControl
<SeekBar
initialValue={position}
minValue={0}
maxValue={duration}
value={position}
onChange={(v: number) => {
if (isSettingPosition) return;
setPosition(v);
seek(v);
}}
renderValue={msToHuman}
onValueChange={onChange}
asValueChanges={onChange}
onValueRender={msToHuman}
/>
<Forms.FormText
variant="text-xs/medium"
@ -382,7 +386,7 @@ export function Player() {
return (
<div id={cl("player")} style={exportTrackImageStyle}>
<Info track={track} />
<SeekBar />
<SpotifySeekBar />
<Controls />
</div>
);

View file

@ -0,0 +1,25 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { LazyComponent } from "@utils/lazyReact";
import { Slider } from "@webpack/common";
export const SeekBar = LazyComponent(() => {
const SliderClass = Slider.$$vencordGetWrappedComponent();
// Discord's Slider does not update `state.value` when `props.initialValue` changes if state.value is not nullish.
// We extend their class and override their `getDerivedStateFromProps` to update the value
return class SeekBar extends SliderClass {
static getDerivedStateFromProps(props: any, state: any) {
const newState = super.getDerivedStateFromProps!(props, state);
if (newState) {
newState.value = props.initialValue;
}
return newState;
}
};
});