mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
refactor(SpeedMenu): use option list instead of multiselect
This commit is contained in:
parent
328ad68824
commit
d601608735
5 changed files with 101 additions and 21 deletions
33
src/routes/Player/SpeedMenu/Option/Option.js
Normal file
33
src/routes/Player/SpeedMenu/Option/Option.js
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (C) 2017-2022 Smart code 203358507
|
||||
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const classnames = require('classnames');
|
||||
const { Button } = require('stremio/common');
|
||||
const styles = require('./styles');
|
||||
|
||||
const OptionButton = ({ className, value, selected, onSelect }) => {
|
||||
const onClick = React.useCallback(() => {
|
||||
if (typeof onSelect === 'function') {
|
||||
onSelect(value);
|
||||
}
|
||||
}, [onSelect, value]);
|
||||
return (
|
||||
<Button
|
||||
className={classnames(className, styles['option'], { 'selected': selected })}
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className={styles['label']}>{ value }x</div>
|
||||
<div className={styles['icon']} />
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
OptionButton.propTypes = {
|
||||
className: PropTypes.string,
|
||||
value: PropTypes.number,
|
||||
selected: PropTypes.bool,
|
||||
onSelect: PropTypes.func,
|
||||
};
|
||||
|
||||
module.exports = OptionButton;
|
||||
5
src/routes/Player/SpeedMenu/Option/index.js
Normal file
5
src/routes/Player/SpeedMenu/Option/index.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// Copyright (C) 2017-2022 Smart code 203358507
|
||||
|
||||
const Option = require('./Option');
|
||||
|
||||
module.exports = Option;
|
||||
38
src/routes/Player/SpeedMenu/Option/styles.less
Normal file
38
src/routes/Player/SpeedMenu/Option/styles.less
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (C) 2017-2022 Smart code 203358507
|
||||
|
||||
@import (reference) '~@stremio/stremio-colors/less/stremio-colors.less';
|
||||
|
||||
.option {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 1.5em;
|
||||
|
||||
&:global(.selected) {
|
||||
background-color: @color-background;
|
||||
|
||||
.icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: @color-background-light2;
|
||||
}
|
||||
|
||||
.label {
|
||||
flex: 1;
|
||||
font-weight: 400;
|
||||
color: @color-surface-light5-90;
|
||||
}
|
||||
|
||||
.icon {
|
||||
flex: none;
|
||||
display: none;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border-radius: 100%;
|
||||
margin-left: 1rem;
|
||||
background-color: @color-accent3-90;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const classnames = require('classnames');
|
||||
const { Multiselect } = require('stremio/common');
|
||||
const Option = require('./Option');
|
||||
const styles = require('./styles');
|
||||
|
||||
const RATES = Array.from(Array(8).keys(), (n) => n * 0.25 + 0.25).reverse();
|
||||
|
|
@ -12,31 +12,29 @@ const SpeedMenu = ({ className, playbackSpeed, onPlaybackSpeedChanged }) => {
|
|||
const onMouseDown = React.useCallback((event) => {
|
||||
event.nativeEvent.speedMenuClosePrevented = true;
|
||||
}, []);
|
||||
const onOptionSelect = React.useCallback((event) => {
|
||||
if (typeof onPlaybackSpeedChanged === 'function' && event.value) {
|
||||
onPlaybackSpeedChanged(parseFloat(event.value));
|
||||
const onOptionSelect = React.useCallback((value) => {
|
||||
if (typeof onPlaybackSpeedChanged === 'function') {
|
||||
onPlaybackSpeedChanged(value);
|
||||
}
|
||||
}, [onPlaybackSpeedChanged]);
|
||||
const selectableOptions = React.useMemo(() => ({
|
||||
title: 'Playback Speed',
|
||||
options: RATES.map((rate) => ({
|
||||
value: `${rate}`,
|
||||
label: `${rate}x`,
|
||||
title: `${rate}x`
|
||||
})),
|
||||
selected: [`${playbackSpeed}`],
|
||||
renderLabelText: () => `${playbackSpeed}x`,
|
||||
onSelect: onOptionSelect
|
||||
}), [playbackSpeed, onOptionSelect]);
|
||||
return (
|
||||
<div className={classnames(className, styles['speed-menu-container'])} onMouseDown={onMouseDown}>
|
||||
<div className={styles['title']}>
|
||||
Playback Speed
|
||||
</div>
|
||||
<Multiselect
|
||||
{...selectableOptions}
|
||||
className={styles['select-input-container']}
|
||||
/>
|
||||
<div className={styles['options-container']}>
|
||||
{
|
||||
RATES.map((rate) => (
|
||||
<Option
|
||||
className={styles['option']}
|
||||
key={rate}
|
||||
value={rate}
|
||||
selected={rate === playbackSpeed}
|
||||
onSelect={onOptionSelect}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,7 +15,13 @@
|
|||
margin: 1rem;
|
||||
}
|
||||
|
||||
.select-input-container {
|
||||
padding: 1rem 1.5rem;
|
||||
.options-container {
|
||||
flex: 0 1 auto;
|
||||
max-height: calc(3.2rem * 8);
|
||||
overflow-y: auto;
|
||||
|
||||
.option {
|
||||
height: 3.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue