mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
refactor(react,html): implement hook-style component architecture for MuteButton
React changes: - Add muteButtonStateDef with keys, stateTransform, and requestMethods - Refactor useMuteButtonState to use shallowEqual optimization - Migrate from useMediaDispatch to useMediaStore pattern - Create request methods factory for consistent state management - Improve type safety and performance with optimized state selection HTML changes: - Rename MediaMuteButton class to MuteButtonBase for consistency - Restructure event handling logic to match PlayButton pattern - Add TODO comment for React vs. W.C. data-* attribute discrepancies - Update component factory usage to use renamed base class This completes the migration to hook-style architecture that can be shared between HTML and React implementations, matching the PlayButton pattern. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
committed by
Christian Pillsbury
co-authored by
Claude
parent
115f181548
commit
882019f458
@@ -5,21 +5,21 @@ import {
|
||||
} from '../utils/component-factory';
|
||||
import { MediaChromeButton } from './media-chrome-button';
|
||||
|
||||
export class MediaMuteButton extends MediaChromeButton {
|
||||
export class MuteButtonBase extends MediaChromeButton {
|
||||
_state:
|
||||
| {
|
||||
muted: boolean;
|
||||
volumeLevel: string;
|
||||
requestUnmute: () => void;
|
||||
requestMute: () => void;
|
||||
requestUnmute: () => void;
|
||||
}
|
||||
| undefined;
|
||||
|
||||
handleEvent(event: Event) {
|
||||
const { type } = event;
|
||||
if (type === 'click') {
|
||||
const state = this._state;
|
||||
if (state) {
|
||||
const state = this._state;
|
||||
if (state) {
|
||||
if (type === 'click') {
|
||||
if (state.muted) {
|
||||
state.requestUnmute();
|
||||
} else {
|
||||
@@ -39,6 +39,7 @@ export class MediaMuteButton extends MediaChromeButton {
|
||||
|
||||
_update(props: any, state: any) {
|
||||
this._state = state;
|
||||
/** @TODO Follow up with React vs. W.C. data-* attributes discrepancies (CJP) */
|
||||
// Make generic
|
||||
this.toggleAttribute('data-muted', props['data-muted']);
|
||||
this.setAttribute('data-volume-level', props['data-volume-level']);
|
||||
@@ -102,7 +103,7 @@ export const useMuteButtonProps: PropsHook<{
|
||||
* Equivalent to React's MuteButton = toConnectedComponent(...)
|
||||
*/
|
||||
export const MuteButton = toConnectedHTMLComponent(
|
||||
MediaMuteButton,
|
||||
MuteButtonBase,
|
||||
useMuteButtonState,
|
||||
useMuteButtonProps,
|
||||
'MuteButton',
|
||||
|
||||
@@ -1,27 +1,58 @@
|
||||
import { useMediaDispatch, useMediaSelector } from '@vjs-10/react-media-store';
|
||||
import {
|
||||
shallowEqual,
|
||||
// useMediaDispatch,
|
||||
useMediaSelector,
|
||||
useMediaStore,
|
||||
} from '@vjs-10/react-media-store';
|
||||
import * as React from 'react';
|
||||
import { toConnectedComponent } from '../utils/component-factory';
|
||||
|
||||
export const useMuteButtonState = (_props: any) => {
|
||||
/** @TODO Fix type issues with hooks (CJP) */
|
||||
const volumeLevel = useMediaSelector(
|
||||
(state: any) => state.volumeLevel,
|
||||
) as string;
|
||||
const muted = useMediaSelector((state: any) => state.muted) as boolean;
|
||||
/**
|
||||
* MuteButton state hook - equivalent to React's useMuteButtonState
|
||||
* Handles media store state subscription and transformation
|
||||
*/
|
||||
export const muteButtonStateDef = {
|
||||
keys: ['muted', 'volumeLevel'],
|
||||
stateTransform: (rawState: any) => ({
|
||||
muted: rawState.muted ?? false,
|
||||
volumeLevel: rawState.volumeLevel ?? 'off',
|
||||
}),
|
||||
/** @TODO Consider "promoting" this up to state-mediator defs + media store (CJP) */
|
||||
requestMethods: (mediaStore: ReturnType<typeof useMediaStore>) => {
|
||||
return {
|
||||
requestMute() {
|
||||
const type = 'muterequest';
|
||||
mediaStore.dispatch({ type });
|
||||
},
|
||||
requestUnmute() {
|
||||
const type = 'unmuterequest';
|
||||
mediaStore.dispatch({ type });
|
||||
},
|
||||
};
|
||||
},
|
||||
} as const;
|
||||
|
||||
const dispatch = useMediaDispatch();
|
||||
const requestMute = React.useCallback(() => {
|
||||
dispatch({ type: 'muterequest' });
|
||||
}, [dispatch]);
|
||||
const requestUnmute = React.useCallback(() => {
|
||||
dispatch({ type: 'unmuterequest' });
|
||||
}, [dispatch]);
|
||||
export const useMuteButtonState = (_props: any) => {
|
||||
const mediaStore = useMediaStore();
|
||||
/** @TODO Fix type issues with hooks (CJP) */
|
||||
const mediaState = useMediaSelector(
|
||||
muteButtonStateDef.stateTransform,
|
||||
shallowEqual,
|
||||
);
|
||||
|
||||
const [methods, setMethods] = React.useState(
|
||||
muteButtonStateDef.requestMethods(mediaStore),
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
setMethods(muteButtonStateDef.requestMethods(mediaStore));
|
||||
}, [mediaStore]);
|
||||
|
||||
return {
|
||||
volumeLevel,
|
||||
muted,
|
||||
requestMute,
|
||||
requestUnmute,
|
||||
volumeLevel: mediaState.volumeLevel,
|
||||
muted: mediaState.muted,
|
||||
requestMute: methods.requestMute,
|
||||
requestUnmute: methods.requestUnmute,
|
||||
} as const;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user