Skip to content

Commit

Permalink
DE-7720: Fix touch interaction (#45)
Browse files Browse the repository at this point in the history
Some components react only to mouse
and not to touch events. This makes
the UI hard to use touch-based platforms
(e.g. Android phone).

Add support for touch interaction
by listening to touch events.
  • Loading branch information
fingerartur authored Sep 9, 2024
1 parent bd771e8 commit c3c354d
Show file tree
Hide file tree
Showing 17 changed files with 73 additions and 48 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
## Fixes

* Fix rounding of duration.
* Fix UI interaction on mobile platforms.

# 0.7.3 (Beta)

Expand Down
22 changes: 11 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@babel/preset-env": "^7.22.4",
"@babel/preset-react": "^7.22.3",
"@babel/preset-typescript": "^7.21.5",
"@castlabs/prestoplay": "^6.11.1-beta.2",
"@castlabs/prestoplay": "^6.16.1-beta.4",
"@finga/eslint-config": "^1.2.1",
"@rollup/plugin-commonjs": "^23.0.2",
"@rollup/plugin-image": "^3.0.2",
Expand Down Expand Up @@ -88,7 +88,7 @@
"typescript": "^4.8.4"
},
"peerDependencies": {
"@castlabs/prestoplay": "^6.11.1-beta.1",
"@castlabs/prestoplay": "^6.11.1-beta.4",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
Expand Down
13 changes: 8 additions & 5 deletions src/components/BaseButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface BaseButtonProps extends BaseComponentProps {
/**
* The click callback
*/
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => unknown
onClick?: (e: React.UIEvent) => unknown
/**
* By default, the base button has an icon. If no icon is set, for instance
* through the css style, use this property to disable icon rendering and
Expand All @@ -35,7 +35,7 @@ export const BaseButton = forwardRef((props: BaseButtonProps, ref: ForwardedRef<
const generateIcon = () => props.disableIcon ? undefined :
<i className={'pp-ui pp-ui-icon'}/>

const onClick = (e: React.MouseEvent<HTMLButtonElement>) => {
const onClick = (e: React.UIEvent) => {
if (props.disabled) {
return
}
Expand All @@ -46,15 +46,18 @@ export const BaseButton = forwardRef((props: BaseButtonProps, ref: ForwardedRef<
}
}

const className = `pp-ui pp-ui-button ${props.disableIcon ? 'pp-ui-button-no-icon': ''} `
+`${props.disabled ? 'pp-ui-disabled' : 'pp-ui-enabled'} ${props.className ?? ''}`

return (
<button
type="button" ref={ref}
data-testid={props.testId}
tabIndex={props.disabled ? -1 : 0}
style={props.style}
className={`pp-ui pp-ui-button ${props.disableIcon ? 'pp-ui-button-no-icon': ''} `
+`${props.disabled ? 'pp-ui-disabled' : 'pp-ui-enabled'} ${props.className ?? ''}`}
onClick={onClick}>
className={className}
onClick={onClick}
onTouchEnd={onClick}>
{generateIcon()}
{props.children}
</button>
Expand Down
2 changes: 1 addition & 1 deletion src/components/FullscreenButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export const FullscreenButton = (props: FullscreenButtonProps) => {
disableIcon={props.disableIcon}
disabled={!enabled}
className={`pp-ui-fullscreen pp-ui-fullscreen-${isFullscreen ? 'enabled' : 'disabled'} ${props.className || ''}`}
style={props.style}
style={props.style}
>
{props.children}
</BaseButton>
Expand Down
2 changes: 1 addition & 1 deletion src/components/MenuSlidein.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const MenuSlidein = (props: MenuSlideinProps) => {
}

ref.current?.addEventListener('transitionend', handleTransitionEnd)

return () => {
ref.current?.removeEventListener('transitionend', handleTransitionEnd)
}
Expand Down
7 changes: 5 additions & 2 deletions src/components/MenuSlideinToggleButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const MenuSlideinToggleButton = (props: MenuSlideinToggleProps) => {
const enabled = usePrestoEnabledState()
const ref = useRef<HTMLButtonElement>(null)

function toggle(event: React.MouseEvent) {
function toggle(event: React.UIEvent) {
setVisible(!isVisible)
player.slideInMenuVisible = !isVisible
event.stopPropagation()
Expand All @@ -39,8 +39,11 @@ export const MenuSlideinToggleButton = (props: MenuSlideinToggleProps) => {

return (
<BaseButton
ref={ref}
testId="pp-ui-slideinmenu-toggle"
onClick={toggle} disableIcon={false} disabled={!enabled} ref={ref}
onClick={toggle}
disableIcon={false}
disabled={!enabled}
className={`pp-ui-slideinmenu-toggle ${props.className || ''}`}
style={props.style}
>
Expand Down
4 changes: 2 additions & 2 deletions src/components/MuteButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface MuteButtonProps extends BasePlayerComponentButtonProps {
children?: React.ReactNode
/**
* Whether audio is muted or not.
*
*
* By default you should leave this `undefined` and let the component
* display the real mute state of the player.
*/
Expand All @@ -35,7 +35,7 @@ export const MuteButton = (props: MuteButtonProps) => {
setMuted(presto.isMuted() ?? false)
})

function toggle(e: React.MouseEvent) {
function toggle(e: React.UIEvent) {
if (e.defaultPrevented || !presto) {return}
presto.setMuted(!presto.isMuted())
}
Expand Down
4 changes: 3 additions & 1 deletion src/components/PlayerSurface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export const PlayerSurface = (props: PlayerProps) => {
}
}

const mouseClick = (e: React.MouseEvent) => {
const mouseClick = (e: React.UIEvent) => {
if (!e.defaultPrevented) {
if (props.player.slideInMenuVisible) {
props.player.slideInMenuVisible = false
Expand Down Expand Up @@ -255,7 +255,9 @@ export const PlayerSurface = (props: PlayerProps) => {
className={`pp-ui pp-ui-surface ${isIpadOS() ? 'pp-ui-ipad' : ''} ${props.className || ''}`}
style={props.style}
onClick={mouseClick}
onTouchEnd={mouseClick}
onMouseMove={mouseMove}
onTouchMove={mouseMove}
onKeyDown={onKeyDown}
tabIndex={0}
>
Expand Down
12 changes: 7 additions & 5 deletions src/components/RateButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ import type { BasePlayerComponentButtonProps } from './types'
export interface RateButtonProps extends BasePlayerComponentButtonProps {
/**
* Playback rate/speed factor.
*
*
* e.g. 2 to play twice as fast, or 0.5 to play half as fast.
*
*
* Defaults to 2.
*/
factor?: number
/**
* Maximum allowed playback rate.
*
*
* Defaults to 64.
*/
max?: number
/**
* Minimum allowed playback rate.
*
*
* Defaults to 0.5.
*/
min?: number
Expand All @@ -52,7 +52,9 @@ export const RateButton = (props: RateButtonProps) => {
return (
<BaseButton
testId="pp-ui-rate-button"
onClick={adjustRate} disableIcon={props.disableIcon} disabled={!enabled}
onClick={adjustRate}
disableIcon={props.disableIcon}
disabled={!enabled}
className={`pp-ui-rate pp-ui-rate-${factor < 1 ? 'fr' : 'ff'} ${props.className || ''}`}
style={props.style}
>
Expand Down
4 changes: 3 additions & 1 deletion src/components/SeekButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ export const SeekButton = (props: SeekButtonProps) => {
return (
<BaseButton
testId="pp-ui-seek-button"
onClick={seek} disableIcon={props.disableIcon} disabled={!enabled}
onClick={seek}
disableIcon={props.disableIcon}
disabled={!enabled}
className={`pp-ui-seek pp-ui-seek-${props.seconds < 0 ? 'back' : 'forward'} ${props.className || ''}`}
style={props.style}
>
Expand Down
9 changes: 6 additions & 3 deletions src/components/SettingsButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const SettingsButton = forwardRef((props: SettingsButtonProps) => {
const enabled = usePrestoEnabledState()
const ref = useRef<HTMLButtonElement>(null)

function toggle(event: React.MouseEvent) {
function toggle(event: React.UIEvent) {
setVisible(!isVisible)
player.slideInMenuVisible = !isVisible

Expand All @@ -46,9 +46,12 @@ export const SettingsButton = forwardRef((props: SettingsButtonProps) => {
})

return (
<BaseButton ref={ref}
<BaseButton
ref={ref}
testId="pp-ui-settings-button"
onClick={toggle} disableIcon={false} disabled={!enabled}
onClick={toggle}
disableIcon={false}
disabled={!enabled}
className={`pp-ui-settings-button ${props.className || ''}`}
style={props.style}
>
Expand Down
4 changes: 3 additions & 1 deletion src/components/StartButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ export const StartButton = (props: StartButtonProps) => {
<div
data-testid="pp-ui-start-button"
className={`pp-ui-start-button-container ${props.className ?? ''}`} style={props.style}>
<BaseButton onClick={start} ref={ref}
<BaseButton
onClick={start}
ref={ref}
disableIcon={false}
style={props.style}
className="pp-ui pp-ui-start-button" />
Expand Down
16 changes: 9 additions & 7 deletions src/components/TrackGroupButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { MouseEventHandler, useContext, useState } from 'react'
import React, { UIEventHandler, useContext, useState } from 'react'

import { PrestoContext } from '../context/PrestoContext'
import { usePrestoEnabledState, usePrestoUiEvent } from '../react'
Expand All @@ -22,7 +22,7 @@ export interface TrackGroupButtonProps extends BaseComponentProps {
hideCurrentlyActive?: boolean
hideWhenUnavailable?: boolean
trackLabel?: TrackLabeler
onClick?: MouseEventHandler | undefined
onClick?: UIEventHandler | undefined
usePlayingRenditionInAbrLabel?: boolean
}

Expand Down Expand Up @@ -64,18 +64,20 @@ export const TrackGroupButton = (props: TrackGroupButtonProps) => {
} as DefaultTrackLabelerOptions)}/>
}

const className = classNames({
'pp-ui': true,
'pp-ui-track-group-button': true,
'pp-ui-hide': !!props.hideWhenUnavailable && !hasTracks(),
}, props.className)

return (
<BaseButton
testId="pp-ui-track-group-button"
disableIcon={true}
style={props.style}
onClick={props.onClick}
disabled={!enabled}
className={classNames({
'pp-ui': true,
'pp-ui-track-group-button': true,
'pp-ui-hide': !!props.hideWhenUnavailable && !hasTracks(),
}, props.className)}>
className={className}>
<Label label={props.label} className={'pp-ui-label-title'}/>
{renderActiveTrackLabel()}
</BaseButton>
Expand Down
12 changes: 7 additions & 5 deletions src/components/TrackSelectionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface TrackSelectionButtonProps extends BaseComponentProps {
*/
export const TrackSelectionButton = memo((props: TrackSelectionButtonProps) => {
const { player } = useContext(PrestoContext)

const selectTrack = () => {
player.selectTrack(props.track)
}
Expand All @@ -29,14 +29,16 @@ export const TrackSelectionButton = memo((props: TrackSelectionButtonProps) => {
return player.getTrackLabel(props.track, props.trackLabel)
}

const className = classNames({
'pp-ui': true,
'pp-ui-track-selection-button': true,
}, props.className)

return (
<BaseButton
testId="pp-ui-track-selection-button"
style={props.style}
className={classNames({
'pp-ui': true,
'pp-ui-track-selection-button': true,
}, props.className)}
className={className}
onClick={selectTrack}
disableIcon={true}>
<TrackLabel label={label()} selected={props.track.selected}/>
Expand Down
4 changes: 3 additions & 1 deletion src/interstitial/components/PlayerSurfaceHlsi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ export const PlayerSurfaceHlsi = (props: PlayerProps) => {

const onAnchorRef = useCallback((anchor: HTMLDivElement) => {
if (!anchor) {return}
props.player.initHlsi({ ...(props.interstitialOptions ?? {}), anchorEl: anchor })
const options = (props.interstitialOptions ?? { config: {} })
const config = options.config ?? {}
props.player.initHlsi({ ...options, config, anchorEl: anchor })
}, [])

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ exports[`<PlayPauseButton /> should match snapshot 1`] = `
className="pp-ui pp-ui-button pp-ui-enabled pp-ui-playpause-toggle pp-ui-playpause-toggle-play "
data-testid="pp-ui-playpause-toggle"
onClick={[Function]}
onTouchEnd={[Function]}
tabIndex={0}
type="button"
>
Expand Down

0 comments on commit c3c354d

Please sign in to comment.