@@ -12,11 +12,14 @@ import { Core } from '../services/core';
1212import { ListItem , MenuOption , View } from '../ui-components' ;
1313import { ifClass , joinClasses } from '../utils/classes' ;
1414import styles from './Player.module.css' ;
15+ import { useSettings } from '../contexts/SettingsProvider' ;
16+ import { clamp } from '../utils/clamp' ;
1517
1618export default function Player ( ) : VNode {
1719 const [ chapters , setChapters ] = useState < Chapter [ ] | null > ( null ) ;
1820 const [ podcast , setPodcast ] = useState < Podcast | null > ( null ) ;
1921 const [ browsingChapters , setBrowsingChapters ] = useState ( false ) ;
22+ const [ changingSpeed , setChangingSpeed ] = useState ( false ) ;
2023 const [ status , setStatus ] = useState < PlaybackStatus > ( {
2124 playing : false ,
2225 currentTime : 0 ,
@@ -25,6 +28,7 @@ export default function Player(): VNode {
2528 const [ accentColor , setAccentColor ] = useState < string > ( ) ;
2629
2730 const player = usePlayer ( ) ;
31+ const { settings, setSetting } = useSettings ( ) ;
2832
2933 useEffect ( ( ) => {
3034 const episode = player . episode ;
@@ -98,6 +102,18 @@ export default function Player(): VNode {
98102 case 'minus30' :
99103 newStatus = player . jump ( - 30 ) ;
100104 break ;
105+ case 'speedDown' :
106+ setSetting (
107+ 'playbackSpeed' ,
108+ clamp ( Math . round ( ( settings . playbackSpeed - 0.2 ) * 100 ) / 100 , 0.6 , 4 )
109+ ) ;
110+ break ;
111+ case 'speedUp' :
112+ setSetting (
113+ 'playbackSpeed' ,
114+ clamp ( Math . round ( ( settings . playbackSpeed + 0.2 ) * 100 ) / 100 , 0.6 , 4 )
115+ ) ;
116+ break ;
101117 case 'detail' :
102118 route ( `/episode/${ player . episode . id } ` ) ;
103119 break ;
@@ -115,8 +131,6 @@ export default function Player(): VNode {
115131 ? { id : 'pause' , label : 'Pause' }
116132 : { id : 'play' , label : 'Play' } ,
117133 { id : 'stop' , label : 'Stop' } ,
118- { id : 'plus30' , label : '+30 seconds' } ,
119- { id : 'minus30' , label : '-30 seconds' } ,
120134 { id : 'detail' , label : 'View episode detail' } ,
121135 ]
122136 : [ ] ;
@@ -132,14 +146,19 @@ export default function Player(): VNode {
132146 useDpad ( {
133147 priority : SelectablePriority . Low ,
134148 onEnter : handleClick ,
135- onChange : ( itemId ) => setBrowsingChapters ( ! ! itemId ?. startsWith ( 'chapter' ) ) ,
136- options : { mode : 'updown' } ,
149+ onChange : ( itemId ) => {
150+ setChangingSpeed ( itemId === 'speed' ) ;
151+ setBrowsingChapters ( ! ! itemId ?. startsWith ( 'chapter' ) ) ;
152+ } ,
153+ options : { stopPropagation : false } ,
137154 } ) ;
138155
139156 useNavKeys (
140157 {
141- ArrowLeft : ( ) => handleAction ( 'minus30' ) ,
142- ArrowRight : ( ) => handleAction ( 'plus30' ) ,
158+ ArrowLeft : ( ) =>
159+ changingSpeed ? handleAction ( 'speedDown' ) : handleAction ( 'minus30' ) ,
160+ ArrowRight : ( ) =>
161+ changingSpeed ? handleAction ( 'speedUp' ) : handleAction ( 'plus30' ) ,
143162 Enter : ( ) => {
144163 if ( ! player . episode ) {
145164 return ;
@@ -195,6 +214,11 @@ export default function Player(): VNode {
195214 { `${ formatTime ( status . duration ) } ` }
196215 </ span >
197216 < div className = { styles . spacer } />
217+ < span
218+ className = { styles . speed }
219+ data-selectable-priority = { SelectablePriority . Low }
220+ data-selectable-id = "speed"
221+ > { `${ settings . playbackSpeed } x` } </ span >
198222 { chapters && chapters . length > 0 ? (
199223 < div className = { styles . chevronDown } />
200224 ) : null }
0 commit comments