Skip to content

Commit

Permalink
feat(controls): Add react version of mp3 controls behind option (#1302)
Browse files Browse the repository at this point in the history
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
jstoffan and mergify[bot] authored Feb 4, 2021
1 parent 9f26b06 commit e437b13
Show file tree
Hide file tree
Showing 13 changed files with 631 additions and 67 deletions.
2 changes: 1 addition & 1 deletion src/lib/Preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -1872,7 +1872,7 @@ class Preview extends EventEmitter {
// Ignore key events when we are inside certain fields
if (
!target ||
KEYDOWN_EXCEPTIONS.indexOf(target.nodeName) > -1 ||
(KEYDOWN_EXCEPTIONS.indexOf(target.nodeName) > -1 && !target.getAttribute('data-allow-keydown')) ||
(target.nodeName === 'DIV' && !!target.getAttribute('contenteditable'))
) {
return;
Expand Down
12 changes: 11 additions & 1 deletion src/lib/__tests__/Preview-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2748,6 +2748,7 @@ describe('lib/Preview', () => {
preventDefault: jest.fn(),
stopPropagation: jest.fn(),
target: {
getAttribute: jest.fn(),
nodeName: KEYDOWN_EXCEPTIONS[0],
},
};
Expand All @@ -2768,7 +2769,7 @@ describe('lib/Preview', () => {
expect(stubs.decodeKeydown).not.toBeCalled();
});

test('should do nothing if there is no target the target is a keydown exception', () => {
test('should do nothing if there is no target or the target is a keydown exception', () => {
preview.keydownHandler(stubs.event);
expect(stubs.decodeKeydown).not.toBeCalled();
});
Expand All @@ -2790,6 +2791,15 @@ describe('lib/Preview', () => {
expect(stubs.event.preventDefault).not.toBeCalled();
});

test('should pass the event to the viewer if the target is an input but allows keydown handling', () => {
stubs.decodeKeydown.mockReturnValue('M');
stubs.event.target.getAttribute = jest.fn(() => true); // data-allow-keydown=true
preview.viewer.onKeydown = jest.fn(() => true);
preview.keydownHandler(stubs.event);

expect(preview.viewer.onKeydown).toBeCalledWith('M', stubs.event);
});

test('should navigate left is key is ArrowLeft and the event has not been consumed', () => {
preview.viewer.onKeydown = jest.fn(() => false);
stubs.event.target.nodeName = 'ArrowLeft';
Expand Down
6 changes: 4 additions & 2 deletions src/lib/viewers/controls/media/DurationLabels.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
.bp-DurationLabels {
display: flex;
align-items: center;
margin-right: 10px;
margin-left: 10px;
margin-right: 5px;
margin-left: 5px;
}

.bp-DurationLabels-label {
Expand All @@ -13,5 +13,7 @@
padding-right: 4px;
padding-left: 4px;
color: $white;
font-size: 12px;
line-height: 12px;
cursor: default;
}
19 changes: 19 additions & 0 deletions src/lib/viewers/media/MP3Controls.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@import '~box-ui-elements/es/styles/variables';

.bp-MP3Controls {
display: flex;
flex-direction: column;
width: 360px; // Required because the controls are the only visible elements within the viewer
background-color: $black;
}

.bp-MP3Controls-bar {
display: flex;
justify-content: space-between;
padding: 0 10px 5px;
}

.bp-MP3Controls-group {
display: flex;
align-items: center;
}
44 changes: 44 additions & 0 deletions src/lib/viewers/media/MP3Controls.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import DurationLabels, { Props as DurationLabelsProps } from '../controls/media/DurationLabels';
import PlayPauseToggle, { Props as PlayControlsProps } from '../controls/media/PlayPauseToggle';
import SettingsControls from '../controls/media/SettingsControls';
import TimeControls, { Props as TimeControlsProps } from '../controls/media/TimeControls';
import VolumeControls, { Props as VolumeControlsProps } from '../controls/media/VolumeControls';
import './MP3Controls.scss';

export type Props = DurationLabelsProps & PlayControlsProps & TimeControlsProps & VolumeControlsProps;

export default function MP3Controls({
bufferedRange,
currentTime,
durationTime,
isPlaying,
onMuteChange,
onPlayPause,
onTimeChange,
onVolumeChange,
volume,
}: Props): JSX.Element {
return (
<div className="bp-MP3Controls">
<TimeControls
bufferedRange={bufferedRange}
currentTime={currentTime}
durationTime={durationTime}
onTimeChange={onTimeChange}
/>

<div className="bp-MP3Controls-bar">
<div className="bp-MP3Controls-group">
<PlayPauseToggle isPlaying={isPlaying} onPlayPause={onPlayPause} />
<VolumeControls onMuteChange={onMuteChange} onVolumeChange={onVolumeChange} volume={volume} />
<DurationLabels currentTime={currentTime} durationTime={durationTime} />
</div>

<div className="bp-MP3Controls-group">
<SettingsControls />
</div>
</div>
</div>
);
}
38 changes: 34 additions & 4 deletions src/lib/viewers/media/MP3Viewer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React from 'react';
import MediaBaseViewer from './MediaBaseViewer';
import MP3Controls from './MP3Controls';
import './MP3.scss';

const CSS_CLASS_MP3 = 'bp-media-mp3';
Expand All @@ -23,18 +25,46 @@ class MP3Viewer extends MediaBaseViewer {
this.mediaEl.setAttribute('preload', 'auto');
}

destroy() {
if (this.controls) {
this.controls.destroy();
}

super.destroy();
}

/**
* Loads the controls
*
* @private
* @return {void}
* @inheritdoc
*/
loadUI() {
super.loadUI();
this.mediaControls.show();
this.mediaControls.resizeTimeScrubber();
}

/**
* @inheritdoc
*/
renderUI() {
if (!this.controls) {
return;
}

this.controls.render(
<MP3Controls
bufferedRange={this.mediaEl.buffered}
currentTime={this.mediaEl.currentTime}
durationTime={this.mediaEl.duration}
isPlaying={!this.mediaEl.paused}
onMuteChange={this.toggleMute}
onPlayPause={this.togglePlay}
onTimeChange={this.handleTimeupdateFromMediaControls}
onVolumeChange={this.setVolume}
volume={this.mediaEl.volume}
/>,
);
}

/**
* Auto-play was prevented, pause the audio
*
Expand Down
Loading

0 comments on commit e437b13

Please sign in to comment.