-
Notifications
You must be signed in to change notification settings - Fork 3
Composite Refactoring with Strategies #157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
2f5e57e
2b122fa
ec75544
2fee76c
ce0275a
43f6148
02deb6e
c5f6f1c
038603e
f596794
711208b
dc56eb5
a79bc7b
ea490d0
212fe23
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
|
|
||
| import { Status } from './Status.Types.js'; | ||
|
|
||
| export class BaseControlStrategy { | ||
| static play() {} | ||
| static pause() {} | ||
| } | ||
|
|
||
|
|
||
| export class clickSelector extends BaseControlStrategy { | ||
| static play(className) { | ||
| let element = document.querySelector(className); | ||
| if (!element) { | ||
| return; | ||
| } | ||
|
|
||
| element.click(); | ||
| } | ||
|
|
||
| static pause(className) { | ||
| clickSelector.play(className); | ||
| } | ||
| } | ||
|
|
||
| /* class for standard audio/video media elements */ | ||
| export class mediaToggle extends BaseControlStrategy { | ||
| static play(className) { | ||
| let element = document.querySelector(className); | ||
| element && element.paused && element.play(); | ||
| } | ||
|
|
||
| static pause(className) { | ||
| let element = document.querySelector(className); | ||
| element && !element.paused && element.pause(); | ||
| } | ||
| } | ||
|
|
||
| /* clicking the storedSelector, injected by the Service */ | ||
| export class clickStoredSelector extends BaseControlStrategy { | ||
| static play() { | ||
| if (this.selector) { | ||
| this.selector.click(); | ||
| } | ||
| } | ||
|
|
||
| static pause() { | ||
| clickStoredSelector.play.call(this); | ||
| } | ||
| } | ||
|
|
||
| /* custom for jouele, based on its buttons position */ | ||
| export class joueleStoredSelector extends BaseControlStrategy { | ||
| static pause() { | ||
| clickStoredSelector.pause.call(this); | ||
| } | ||
|
|
||
| static play() { | ||
| if (this.selector) { | ||
| this.selector.previousSibling.click(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
| export class oneOfTheVideos extends BaseControlStrategy { | ||
| static getVideosArray() { | ||
| return Array.from(document.getElementsByTagName('video')); | ||
| } | ||
|
|
||
| static pause() { | ||
| oneOfTheVideos.getVideosArray() | ||
| .filter((player) => !player.paused) | ||
| .forEach((player) => { | ||
| player.pause(); | ||
| }); | ||
| } | ||
|
|
||
| static play() { | ||
| oneOfTheVideos.getVideosArray() | ||
| .filter((player) => player.paused && player.played.length > 0) | ||
| .forEach((player) => { | ||
| player.play(); | ||
| }); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| /* Base Service class */ | ||
| export class Service { | ||
| /** | ||
| @param options {Object} | ||
| @param options.statusStrategy {Class} | ||
| @param options.statusArgs {Array} (optional) | ||
| @param options.controlStrategy {Class} | ||
| @param options.playArgs {Array} (optional) | ||
| @param options.pauseArgs {Array} (optional) | ||
| */ | ||
| constructor(options) { | ||
| this.options = options; | ||
| } | ||
|
|
||
| getStatus() { | ||
| return this.options.statusStrategy.getStatus.apply(this, this.options.statusArgs); | ||
| } | ||
|
|
||
| play() { | ||
| this.options.controlStrategy.play.apply(this, this.options.playArgs); | ||
| } | ||
|
|
||
| pause() { | ||
| this.options.controlStrategy.pause.apply(this, this.options.pauseArgs); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,219 @@ | ||
| import { Service } from './Service.js'; | ||
| import * as StatusStrategies from './Status.Strategies.js'; | ||
| import * as ControlStrategies from './Control.Strategies.js'; | ||
|
|
||
| // #TODO: move it to build-time | ||
| function oneSelectorHelper(hosts, statusArgs, playArgs, pauseArgs) { | ||
| return { | ||
| hosts, | ||
| options: { | ||
| statusStrategy: StatusStrategies.checkSelector, | ||
| statusArgs: [ statusArgs ], | ||
| controlStrategy: ControlStrategies.clickSelector, | ||
| playArgs: [ playArgs ], | ||
| pauseArgs: [ pauseArgs ] | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| function getOneSelector() { | ||
| return [ | ||
| [ | ||
| [ 'vimeo.com', 'player.vimeo.com' ], | ||
| '.play.state-playing', | ||
| '.play.state-paused', | ||
| '.play.state-playing' | ||
| ], [ | ||
| [ 'vk.com' ], | ||
| '.top_audio_player.top_audio_player_playing', | ||
| '.top_audio_player_play', | ||
| '.top_audio_player_play' | ||
| ], [ | ||
| [ 'muzebra.com' ], | ||
| '.player.jp-state-playing', | ||
| '.player.jp-play', | ||
| '.player.jp-pause' | ||
| ], [ | ||
| [ 'music.yandex.ru', 'music.yandex.ua' ], | ||
| '.player-controls__btn_play.player-controls__btn_pause', | ||
| '.player-controls__btn_play', | ||
| '.player-controls__btn_pause' | ||
| ], [ | ||
| [ 'mixcloud.com' ], | ||
| '.player-control.pause-state', | ||
| '.player-control', | ||
| '.player-control' | ||
| ], [ | ||
| [ 'soundcloud.com' ], | ||
| '.playControl.playing', | ||
| '.playControl', | ||
| '.playControl.playing' | ||
| ], [ | ||
| [ 'jazzradio.com', 'rockradio.com', 'radiotunes.com', 'classicalradio.com', 'zenradio.com' ], | ||
| '#play-button .icon-pause', | ||
| '#play-button .ctl', | ||
| '#play-button .ctl' | ||
| ], [ | ||
| [ 'v5player.slipstreamradio.com', 'accuradio.com' ], | ||
| '#playerPauseButton', | ||
| '#playerPlayButton', | ||
| '#playerPauseButton' | ||
| ], [ | ||
| [ 'open.spotify.com' ], | ||
| ".control-button[class*='pause']", | ||
| ".control-button[class*='play']", | ||
| ".control-button[class*='pause']" | ||
| ], [ | ||
| [ 'bandcamp.com' ], | ||
| '.inline_player .playbutton.playing', | ||
| '.inline_player .playbutton', | ||
| '.inline_player .playbutton.playing' | ||
| ], [ | ||
| [ 'promodj.com' ], | ||
| '.playerr_bigplaybutton .playerr_bigpausebutton', | ||
| '.playerr_bigplaybutton .playerr_bigplaybutton', | ||
| '.playerr_bigplaybutton .playerr_bigpausebutton' | ||
| ], [ | ||
| [ 'courses.prometheus.org.ua' ], | ||
| '.video-controls .video_control.pause', | ||
| '.video-controls .video_control.play', | ||
| '.video-controls .video_control.pause' | ||
| ], [ | ||
| [ 'coursera.org' ], | ||
| '.c-video-control.vjs-control.vjs-playing', | ||
| '.c-video-control.vjs-control.vjs-paused', | ||
| '.c-video-control.vjs-control.vjs-playing' | ||
| ], [ | ||
| [ 'di.fm' ], | ||
| '#webplayer-region .controls .icon-pause', | ||
| '#webplayer-region .controls .icon-play', | ||
| '#webplayer-region .controls .icon-pause' | ||
| ], [ | ||
| [ 'audible.ca', 'audible.com', 'audible.com.au' ], | ||
| '#adbl-cloud-player-controls .adblPauseButton:not(.bc-hidden)', | ||
| '#adbl-cloud-player-controls .adblPauseButton:not(.bc-hidden)', | ||
| '#adbl-cloud-player-controls .adblPauseButton:not(.bc-hidden)' | ||
| ], [ | ||
| [ 'coub.com' ], | ||
| '.coub.active[play-state="playing"]', | ||
| '.coub.active .viewer__replay', | ||
| '.coub.active .viewer__click', | ||
| ], [ | ||
| [ 'livestream.com' ], | ||
| '.playback-control .play-holder.lsp-hidden', | ||
| '.playback-control .play-holder', | ||
| '.playback-control .pause-holder' | ||
| ], [ | ||
| [ 'beatport.com' ], | ||
| '#Player__pause-button', | ||
| '#Player__play-button', | ||
| '#Player__pause-button' | ||
| ], [ | ||
| [ 'radio.garden' ], | ||
| '.icon-toggle.mod-mute .icon-button.mod-sound', | ||
| '.icon-toggle.mod-mute .icon-button.mod-muted', | ||
| '.icon-toggle.mod-mute .icon-button.mod-sound' | ||
| ] | ||
| ].map(item => oneSelectorHelper.apply(null, item)); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wow, looks like a magic :)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean, in this case you should always remember what's 2, 3, 4 arguments for.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's true, but it will be very redundant with the amount of services that we have |
||
|
|
||
| } | ||
|
|
||
| export const servicesRegistry = () => { | ||
|
|
||
| return getOneSelector().concat([ | ||
| { | ||
| hosts: [ 'radiolist.com.ua' ], | ||
| options: { | ||
| statusStrategy: StatusStrategies.checkSelectorAndStore, | ||
| statusArgs: [ '.jouele-status-playing .jouele-info-control-button-icon_pause' ], | ||
| controlStrategy: ControlStrategies.joueleStoredSelector | ||
| } | ||
| }, { | ||
| hosts: [ 'megogo.net' ], | ||
| options: { | ||
| statusStrategy: StatusStrategies.mediaSelector, | ||
| statusArgs: [ 'video[class*="player:video"]' ], | ||
| controlStrategy: ControlStrategies.mediaToggle, | ||
| playArgs: [ 'video[class*="player:video"]' ], | ||
| pauseArgs: [ 'video[class*="player:video"]' ] | ||
| } | ||
| }, { | ||
| hosts: [ 'dailymotion.com' ], | ||
| options: { | ||
| statusStrategy: StatusStrategies.mediaSelector, | ||
| statusArgs: [ '#dmp_Video' ], | ||
| controlStrategy: ControlStrategies.mediaToggle, | ||
| playArgs: [ '#dmp_Video' ], | ||
| pauseArgs: [ '#dmp_Video' ] | ||
| } | ||
| }, { | ||
| hosts: [ 'netflix.com' ], | ||
| options: { | ||
| statusStrategy: StatusStrategies.mediaSelector, | ||
| statusArgs: [ '.VideoContainer video' ], | ||
| controlStrategy: ControlStrategies.mediaToggle, | ||
| playArgs: [ '.VideoContainer video' ], | ||
| pauseArgs: [ '.VideoContainer video' ] | ||
| } | ||
| }, { | ||
| hosts: [ 'egghead.io' ], | ||
| options: { | ||
| statusStrategy: StatusStrategies.mediaSelector, | ||
| statusArgs: [ '.bitmovinplayer-container video' ], | ||
| controlStrategy: ControlStrategies.mediaToggle, | ||
| playArgs: [ '.bitmovinplayer-container video' ], | ||
| pauseArgs: [ '.bitmovinplayer-container video' ] | ||
| } | ||
| }, { | ||
| hosts: [ 'udemy.com' ], | ||
| options: { | ||
| statusStrategy: StatusStrategies.mediaSelector, | ||
| statusArgs: [ 'video' ], | ||
| controlStrategy: ControlStrategies.mediaToggle, | ||
| playArgs: [ 'video' ], | ||
| pauseArgs: [ 'video' ] | ||
| } | ||
| }, { | ||
| hosts: [ 'musicforprogramming.net' ], | ||
| options: { | ||
| statusStrategy: StatusStrategies.mediaSelector, | ||
| statusArgs: [ '#player' ], | ||
| controlStrategy: ControlStrategies.mediaToggle, | ||
| playArgs: [ '#player' ], | ||
| pauseArgs: [ '#player' ] | ||
| } | ||
| }, { | ||
| hosts: [ 'netflix.com' ], | ||
| options: { | ||
| statusStrategy: StatusStrategies.mediaSelector, | ||
| statusArgs: [ '.VideoContainer video' ], | ||
| controlStrategy: ControlStrategies.mediaToggle, | ||
| playArgs: [ '.VideoContainer video' ], | ||
| pauseArgs: [ '.VideoContainer video' ] | ||
| } | ||
| }, { | ||
| hosts: [ 'hearthis.at' ], | ||
| options: { | ||
| statusStrategy: StatusStrategies.checkSelector, | ||
| statusArgs: [ 'body.play' ], | ||
| controlStrategy: { /* custom */}, | ||
| } | ||
| }, { | ||
| hosts: ['ted.com', 'facebook.com', 'kickstarter.com', 'music.youtube.com' ], | ||
| options: { | ||
| statusStrategy: StatusStrategies.oneOfTheVideosPlaying, | ||
| controlStrategy: ControlStrategies.oneOfTheVideos, | ||
| } | ||
| }, | ||
| ]) | ||
| }; | ||
|
|
||
| export function getService(domain) { | ||
| const matchedService = servicesRegistry().find(serviceConfig => serviceConfig.hosts.includes(domain)); | ||
|
|
||
| if (!matchedService) { | ||
| return; | ||
| } | ||
|
|
||
| return new Service(matchedService.options); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.