Skip to content

Commit

Permalink
fix: fix {{sound-position-slider}} modifier gestures
Browse files Browse the repository at this point in the history
feat: add {{sound-position-progress}} modifier
  • Loading branch information
jkeen committed Nov 8, 2021
1 parent b3b8747 commit 9c48a18
Show file tree
Hide file tree
Showing 12 changed files with 360 additions and 23 deletions.
51 changes: 51 additions & 0 deletions addon/modifiers/sound-position-progress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* This is the modifier used to transform an element into a progress bar, where it will take up the width equivalent to the sound's position
* ```hbs
<div {{sound-position-progress @identifier}}>
</div>
```
*
@class {{sound-position-progress}}
@type Modifier
*/

import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import Modifier from 'ember-modifier';

export default class SoundPositionProgressModifier extends Modifier {
@service stereo;

get url() {
return this.args.positional[0]
}

get loadedSound() {
return this.stereo.findSound(this.url);
}

@action onPositionChange() {
this.element.style.width = `${(this.loadedSound.position / this.loadedSound.duration) * 100}%`;
this.element.style.pointerEvents = 'none';
}

didInstall() {
this.element.setAttribute('data-sound-position-progress', true)
}

didReceiveArguments() {
if (this.url) {
this.stereo.soundProxy(this.url).afterLoad(sound => {
sound.on('audio-position-changed', this.onPositionChange);
})
}
}

willRemove() {
try {
if (this.loadedSound) {
this.loadedSound.off('audio-position-changed', this.onPositionChange);
}
} catch (e) { /* geez, relax */ }
}
}
68 changes: 51 additions & 17 deletions addon/modifiers/sound-position-slider.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
/**
* This is the modifier used to transform an element into a position control, where clicking it will change a sound's position
* ```hbs
<div {{stereo-position-track @identifier}}>
<div {{stereo-position @identifier}}>
</div>
```
*
@class {{stereo-position-track}}
@class {{sound-position-slider}}
@type Modifier
*/

import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import { task, waitForProperty } from 'ember-concurrency';
import { next } from '@ember/runloop';
import Modifier from 'ember-modifier';

export default class SoundPositionSliderModifier extends Modifier {
import DidPanModifier from 'ember-gesture-modifiers/modifiers/did-pan';
export default class SoundPositionSliderModifier extends DidPanModifier {
@service stereo;

get url() {
Expand Down Expand Up @@ -55,7 +54,7 @@ export default class SoundPositionSliderModifier extends Modifier {

@action
handleTap(e) {
var rect = e.target.getBoundingClientRect();
var rect = this.element.getBoundingClientRect();
var x = e.clientX - rect.left; //x position within the element.

if (
Expand All @@ -77,17 +76,42 @@ export default class SoundPositionSliderModifier extends Modifier {
}

didInstall() {
this.element.setAttribute('data-stereo-position-track', true)
if (this.isRangeControl) {
this.element.setAttribute('max', 100);
this.element.setAttribute('min', 0);
this.element.setAttribute('value', 0);
this.element.setAttribute('disabled', 'disabled');
} else {
this.element.addEventListener('click', this.handleTap, true);
this.element.addEventListener('mousedown', this.handleTap, true);
this.element.addEventListener('tap', this.handleTap, true);
super.didInstall(...arguments);
this.element.addEventListener('click', this.handleTap);
this.element.addEventListener('mousedown', this.handleTap);
this.element.addEventListener('tap', this.handleTap);
}
this.element.setAttribute('data-sound-position-slider', true)
}


@action
onPanStart() {
}

@action
onPan(e) {
if (
this.loadedSound &&
this.loadedSound.isFastForwardable &&
this.loadedSound.isRewindable &&
this.element
) {
var rect = this.element.getBoundingClientRect();
let percentPosition = ((e.current.x - rect.x) / rect.width)
let actualPosition = percentPosition * this.loadedSound.duration;
this.loadedSound.position = actualPosition;
}
}

@action
onPanEnd() {
}

didReceiveArguments() {
Expand All @@ -101,10 +125,19 @@ export default class SoundPositionSliderModifier extends Modifier {
}
}).catch(() => { })
} else {
this.afterLoad.perform(sound => {
sound.on('audio-position-changed', this.onPositionChange.bind(this));
super.removeEventListeners();

super.threshold = 10;
super.axis = 'horizontal';
super.capture = false;
super.preventScroll = false;
super.pointerTypes = ['touch', 'mouse'];

}).catch(() => { });
super.didPanStart = this.onPanStart.bind(this)
super.didPan = this.onPan.bind(this)
super.didPanEnd = this.onPanEnd.bind(this)

super.addEventListeners();
}
}

Expand All @@ -117,13 +150,14 @@ export default class SoundPositionSliderModifier extends Modifier {
this.element.removeEventListener('change', this.onChange, true);
}
else {
super.willRemove(...arguments);
if (this.loadedSound) {
this.loadedSound.off('audio-position-changed', this.onPositionChange.bind(this));
}
this.element.removeEventListener('change', this.onChange, true);
this.element.removeEventListener('click', this.handleTap, true);
this.element.removeEventListener('tap', this.handleTap, true);
this.element.removeEventListener('mousedown', this.handleTap, true);
this.element.removeEventListener('change', this.onChange);
this.element.removeEventListener('click', this.handleTap);
this.element.removeEventListener('tap', this.handleTap);
this.element.removeEventListener('mousedown', this.handleTap);
}
} catch (e) { /* geez, relax */ }
}
Expand Down
1 change: 1 addition & 0 deletions app/modifiers/sound-position-progress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ember-stereo/modifiers/sound-position-progress';
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"debug": "4.3.2",
"ember-auto-import": "^1.11.3",
"ember-cli-babel": "^7.26.6",
"ember-gesture-modifiers": "^2.0.0",
"ember-cli-htmlbars": "^5.7.1",
"ember-concurrency": "^2.1.2",
"ember-get-config": "^0.3.0",
Expand Down
107 changes: 107 additions & 0 deletions tests/dummy/app/components/docs/custom-position-control.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<div class='stereo-player'>
<div class='stereo-player-main'>
<div class='stereo-player-controls'>
<button
{{on 'click' (rewind-sound @identifier increment=5000)}}
disabled={{not (sound-is-rewindable @identifier)}}
type='button'
class='stereo-button'
>
{{svg-jar
'skip-backward-outline'
height=20
width=30
title='Skip Backward'
}}
</button>

<button
{{on 'click' (toggle-play-sound @identifier)}}
type='button'
class='stereo-button'
>
{{#if (sound-is-playing @identifier)}}
{{svg-jar 'pause-outline' height=20 width=30 title='Pause'}}
{{else if (sound-is-loading @identifier)}}
{{svg-jar
'loading-outline'
height=20
width=30
title='Loading'
class='animate-spin'
}}
{{else if (sound-is-loaded @identifier)}}
{{svg-jar 'resume-outline' height=20 width=30 title='Pause'}}
{{else}}
{{svg-jar 'play-outline' height=20 width=30 title='Play'}}
{{/if}}
</button>

<button
{{on 'click' (fastforward-sound @identifier increment=5000)}}
disabled={{not (sound-is-fastforwardable @identifier)}}
type='button'
class='stereo-button'
>
{{svg-jar
'skip-forward-outline'
height=20
width=30
title='Skip Forward'
}}
</button>
</div>

<div class='stereo-player-position'>
{{sound-position @identifier format='time'}}
{{#if (sound-is-seekable @identifier)}}
{{! template-lint-disable require-input-label }}
{{! BEGIN-SNIPPET position-modifiers.hbs }}
<div {{sound-position-slider @identifier}} class="stereo-player-position-slider" >
<div {{sound-position-progress @identifier}} class="stereo-player-position-progress" ></div>
</div>
{{! END-SNIPPET }}
{{else}}
<div
class='{{if
(sound-is-playing @identifier)
'from-accent-0 to-accent-2 bg-gradient-to-r animate-gradient-x animated'
'bg-on-surface-3'
}}
w-full h-2 rounded-md inset-1 shadow-inset'
>
</div>
{{/if}}
{{sound-duration @identifier format='time'}}
</div>

<div class='stereo-player-volume'>
<Input
{{stereo-volume}}
id='stereo-volume'
@type='range'
class='flex-auto flex-shrink w-16 lg:w-1/6'
/>
<label for='stereo-volume' class='stereo-volume'>
<button type='button' {{on 'click' (toggle-stereo-mute)}}>
{{#if (gt (stereo-volume) 0)}}
{{svg-jar 'volume-low-outline' height=20 width=30}}
{{else}}
{{svg-jar 'volume-mute-outline' height=20 width=30}}
{{/if}}
</button>
</label>
</div>
</div>

{{#if (sound-is-errored @identifier)}}
<div class='stereo-player-errors'>
{{sound-error-details @identifier}}
</div>
{{/if}}
</div>


<DocsDemo as |demo|>
{{demo.snippet 'position-modifiers.hbs'}}
</DocsDemo>
1 change: 0 additions & 1 deletion tests/dummy/app/components/sound-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export default class SoundDisplay extends Component {
this.soundProxy = this.stereo.soundProxy(this.args.url)
}


get loadedSound() {
return this.stereo.findSound(this.args.url);
}
Expand Down
1 change: 1 addition & 0 deletions tests/dummy/app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Router.map(function () {
this.route('event-monitoring');
this.route('waiting-for-sounds');
this.route('volume');
this.route('custom-position-controls');
this.route('testing');
});

Expand Down
11 changes: 11 additions & 0 deletions tests/dummy/app/styles/components/_stereo-player.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@
@apply flex items-center flex-grow w-full gap-2 whitespace-nowrap;
}

.stereo-player-position-slider {
@apply relative w-full flex items-center justify-start bg-on-surface-3 rounded h-2;
}
.stereo-player-position-thumb {
@apply bg-on-surface-3 absolute h-4 w-4 flex rounded-lg shadow-sm;
top: 15px;
}
.stereo-player-position-progress {
@apply bg-accent-0 h-2 flex rounded;
}

.stereo-player input[type='range'] {
@apply bg-on-surface-2;
}
Expand Down
2 changes: 2 additions & 0 deletions tests/dummy/app/templates/docs/custom-position-controls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

{{docs/custom-position-control identifier="/sounds/works-just-like-a-vcr.mp3"}}
2 changes: 1 addition & 1 deletion tests/dummy/config/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module.exports = function (environment) {
EXTEND_PROTOTYPES: {
// Prevent Ember Data from overriding Date.parse.
Date: false,
},
}
},

APP: {
Expand Down
14 changes: 14 additions & 0 deletions tests/integration/modifiers/sound-position-progress-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';

module('Integration | Modifier | sound-position-progress', function (hooks) {
setupRenderingTest(hooks);

test('it renders', async function (assert) {
await render(hbs`<div {{sound-position-progress}}></div>`);

assert.ok(true);
});
});
Loading

0 comments on commit 9c48a18

Please sign in to comment.