Merge upstream master and update web dependencies

This commit is contained in:
Tyler Vigario
2020-06-09 17:16:31 -07:00
13 changed files with 105 additions and 62 deletions
+1
View File
@@ -31,6 +31,7 @@ username = botamusique
comment = Hi, I'm here to play radio, local music or youtube/soundcloud music. Have fun! comment = Hi, I'm here to play radio, local music or youtube/soundcloud music. Have fun!
# default volume from 0 to 1. # default volume from 0 to 1.
volume = 0.1 volume = 0.1
stereo = True
# playback mode should be one of "one-shot", "repeat", "random", "autoplay" # playback mode should be one of "one-shot", "repeat", "random", "autoplay"
playback_mode = one-shot playback_mode = one-shot
autoplay_length = 5 autoplay_length = 5
+3
View File
@@ -39,6 +39,9 @@ port = 64738
# 'admin': Users allowed to kill the bot, or ban URLs. Separated by ';' # 'admin': Users allowed to kill the bot, or ban URLs. Separated by ';'
#admin = User1;User2; #admin = User1;User2;
# 'stereo': After 1.4.0, mumble starts to support stereo stream. Enable this option for stereo
# stream transmission. Otherwise the bot will down mix stereo sound into mono.
#stereo = True
# 'volume' is default volume from 0 to 1. # 'volume' is default volume from 0 to 1.
# This option will be overridden by value in the database. # This option will be overridden by value in the database.
+1 -1
View File
@@ -64,7 +64,7 @@ class ReverseProxied(object):
web = Flask(__name__) web = Flask(__name__)
web.config['TEMPLATES_AUTO_RELOAD'] = True #web.config['TEMPLATES_AUTO_RELOAD'] = True
log = logging.getLogger("bot") log = logging.getLogger("bot")
user = 'Remote Control' user = 'Remote Control'
+17 -9
View File
@@ -38,12 +38,13 @@ class MumbleBot:
self.log.info(f"bot: botamusique version {self.version}, starting...") self.log.info(f"bot: botamusique version {self.version}, starting...")
signal.signal(signal.SIGINT, self.ctrl_caught) signal.signal(signal.SIGINT, self.ctrl_caught)
self.cmd_handle = {} self.cmd_handle = {}
self.volume_set = var.config.getfloat('bot', 'volume') self.volume_set = var.config.getfloat('bot', 'volume', fallback=0.1)
if var.db.has_option('bot', 'volume'): if var.db.has_option('bot', 'volume'):
self.volume_set = var.db.getfloat('bot', 'volume') self.volume_set = var.db.getfloat('bot', 'volume')
self.volume = self.volume_set self.volume = self.volume_set
self.stereo = var.config.getboolean('bot', 'stereo', fallback=True)
if args.channel: if args.channel:
self.channel = args.channel self.channel = args.channel
else: else:
@@ -62,6 +63,7 @@ class MumbleBot:
self.song_start_at = -1 self.song_start_at = -1
self.last_ffmpeg_err = "" self.last_ffmpeg_err = ""
self.read_pcm_size = 0 self.read_pcm_size = 0
self.pcm_buffer_size = 0
# self.download_threads = [] # self.download_threads = []
self.wait_for_ready = False # flag for the loop are waiting for download to complete in the other thread self.wait_for_ready = False # flag for the loop are waiting for download to complete in the other thread
self.on_killing = threading.Lock() # lock to acquire when killing ffmpeg thread is asked but ffmpeg is not self.on_killing = threading.Lock() # lock to acquire when killing ffmpeg thread is asked but ffmpeg is not
@@ -104,7 +106,9 @@ class MumbleBot:
self.username = var.config.get("bot", "username") self.username = var.config.get("bot", "username")
self.mumble = pymumble.Mumble(host, user=self.username, port=port, password=password, tokens=tokens, self.mumble = pymumble.Mumble(host, user=self.username, port=port, password=password, tokens=tokens,
debug=var.config.getboolean('debug', 'mumbleConnection'), certfile=certificate) stereo=self.stereo,
debug=var.config.getboolean('debug', 'mumbleConnection'),
certfile=certificate)
self.mumble.callbacks.set_callback(pymumble.constants.PYMUMBLE_CLBK_TEXTMESSAGERECEIVED, self.message_received) self.mumble.callbacks.set_callback(pymumble.constants.PYMUMBLE_CLBK_TEXTMESSAGERECEIVED, self.message_received)
self.mumble.set_codec_profile("audio") self.mumble.set_codec_profile("audio")
@@ -369,8 +373,11 @@ class MumbleBot:
else: else:
ffmpeg_debug = "warning" ffmpeg_debug = "warning"
channels = 2 if self.stereo else 1
self.pcm_buffer_size = 960*channels
command = ("ffmpeg", '-v', ffmpeg_debug, '-nostdin', '-i', command = ("ffmpeg", '-v', ffmpeg_debug, '-nostdin', '-i',
uri, '-ss', f"{start_from:f}", '-ac', '1', '-f', 's16le', '-ar', '48000', '-') uri, '-ss', f"{start_from:f}", '-ac', str(channels), '-f', 's16le', '-ar', '48000', '-')
self.log.debug("bot: execute ffmpeg command: " + " ".join(command)) self.log.debug("bot: execute ffmpeg command: " + " ".join(command))
# The ffmpeg process is a thread # The ffmpeg process is a thread
@@ -381,7 +388,7 @@ class MumbleBot:
else: else:
pipe_rd, pipe_wd = None, None pipe_rd, pipe_wd = None, None
self.thread = sp.Popen(command, stdout=sp.PIPE, stderr=pipe_wd, bufsize=480) self.thread = sp.Popen(command, stdout=sp.PIPE, stderr=pipe_wd, bufsize=self.pcm_buffer_size)
def async_download_next(self): def async_download_next(self):
# Function start if the next music isn't ready # Function start if the next music isn't ready
@@ -452,8 +459,8 @@ class MumbleBot:
self.song_start_at = time.time() - self.playhead self.song_start_at = time.time() - self.playhead
self.playhead = time.time() - self.song_start_at self.playhead = time.time() - self.song_start_at
raw_music = self.thread.stdout.read(480) raw_music = self.thread.stdout.read(self.pcm_buffer_size)
self.read_pcm_size += 480 self.read_pcm_size += self.pcm_buffer_size
if self.redirect_ffmpeg_log: if self.redirect_ffmpeg_log:
try: try:
@@ -476,7 +483,8 @@ class MumbleBot:
if not self.is_pause and (self.thread is None or self.thread.poll() is not None): if not self.is_pause and (self.thread is None or self.thread.poll() is not None):
# bot is not paused, but ffmpeg thread has gone. # bot is not paused, but ffmpeg thread has gone.
# indicate that last song has finished, or the bot just resumed from pause, or something is wrong. # indicate that last song has finished, or the bot just resumed from pause, or something is wrong.
if self.read_pcm_size < 481 and len(var.playlist) > 0 and var.playlist.current_index != -1 \ if self.read_pcm_size < self.pcm_buffer_size and len(var.playlist) > 0 \
and var.playlist.current_index != -1 \
and self.last_ffmpeg_err: and self.last_ffmpeg_err:
current = var.playlist.current_item() current = var.playlist.current_item()
self.log.error("bot: cannot play music %s", current.format_debug_string()) self.log.error("bot: cannot play music %s", current.format_debug_string())
@@ -770,7 +778,7 @@ if __name__ == '__main__':
var.tmp_folder = util.solve_filepath(var.config.get('bot', 'tmp_folder')) var.tmp_folder = util.solve_filepath(var.config.get('bot', 'tmp_folder'))
var.cache = MusicCache(var.music_db) var.cache = MusicCache(var.music_db)
if var.config.get("bot", "refresh_cache_on_startup", fallback=True): if var.config.getboolean("bot", "refresh_cache_on_startup", fallback=True):
var.cache.build_dir_cache() var.cache.build_dir_cache()
# ====================== # ======================
+1 -3
View File
@@ -1,5 +1,3 @@
opuslib==2.0.0
protobuf==3.4.0
flask flask
youtube-dl youtube-dl
python-magic python-magic
@@ -7,5 +5,5 @@ Pillow
mutagen mutagen
requests requests
packaging packaging
pymumble pymumble>=1.2
pyradios pyradios
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+64 -33
View File
@@ -1117,6 +1117,12 @@
"integrity": "sha512-iYCgjm1dGPRuo12+BStjd1HiVQqhlRhWDOQigNxn023HcjnhsiFz9pc6CzJj4HwDCSQca9bxTL4PxJDbkdm3PA==", "integrity": "sha512-iYCgjm1dGPRuo12+BStjd1HiVQqhlRhWDOQigNxn023HcjnhsiFz9pc6CzJj4HwDCSQca9bxTL4PxJDbkdm3PA==",
"dev": true "dev": true
}, },
"@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
"@types/node": { "@types/node": {
"version": "14.0.4", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.4.tgz",
@@ -2877,9 +2883,9 @@
"dev": true "dev": true
}, },
"eslint": { "eslint": {
"version": "7.1.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.1.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.2.0.tgz",
"integrity": "sha512-DfS3b8iHMK5z/YLSme8K5cge168I8j8o1uiVmFCgnnjxZQbCGyraF8bMl7Ju4yfBmCuxD7shOF7eqGkcuIHfsA==", "integrity": "sha512-B3BtEyaDKC5MlfDa2Ha8/D6DsS4fju95zs0hjS3HdGazw+LNayai38A25qMppK37wWGWNYSPOR6oYzlz5MHsRQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/code-frame": "^7.0.0", "@babel/code-frame": "^7.0.0",
@@ -2888,10 +2894,10 @@
"cross-spawn": "^7.0.2", "cross-spawn": "^7.0.2",
"debug": "^4.0.1", "debug": "^4.0.1",
"doctrine": "^3.0.0", "doctrine": "^3.0.0",
"eslint-scope": "^5.0.0", "eslint-scope": "^5.1.0",
"eslint-utils": "^2.0.0", "eslint-utils": "^2.0.0",
"eslint-visitor-keys": "^1.1.0", "eslint-visitor-keys": "^1.2.0",
"espree": "^7.0.0", "espree": "^7.1.0",
"esquery": "^1.2.0", "esquery": "^1.2.0",
"esutils": "^2.0.2", "esutils": "^2.0.2",
"file-entry-cache": "^5.0.1", "file-entry-cache": "^5.0.1",
@@ -2937,9 +2943,9 @@
} }
}, },
"chalk": { "chalk": {
"version": "4.0.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"dev": true, "dev": true,
"requires": { "requires": {
"ansi-styles": "^4.1.0", "ansi-styles": "^4.1.0",
@@ -2971,15 +2977,21 @@
} }
}, },
"eslint-scope": { "eslint-scope": {
"version": "5.0.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz",
"integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==",
"dev": true, "dev": true,
"requires": { "requires": {
"esrecurse": "^4.1.0", "esrecurse": "^4.1.0",
"estraverse": "^4.1.1" "estraverse": "^4.1.1"
} }
}, },
"eslint-visitor-keys": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz",
"integrity": "sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ==",
"dev": true
},
"globals": { "globals": {
"version": "12.4.0", "version": "12.4.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
@@ -3091,23 +3103,24 @@
} }
}, },
"eslint-plugin-import": { "eslint-plugin-import": {
"version": "2.20.2", "version": "2.21.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.21.1.tgz",
"integrity": "sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg==", "integrity": "sha512-qYOOsgUv63vHof7BqbzuD+Ud34bXHxFJxntuAC1ZappFZXYbRIek3aJ7jc9i2dHDGDyZ/0zlO0cpioES265Lsw==",
"dev": true, "dev": true,
"requires": { "requires": {
"array-includes": "^3.0.3", "array-includes": "^3.1.1",
"array.prototype.flat": "^1.2.1", "array.prototype.flat": "^1.2.3",
"contains-path": "^0.1.0", "contains-path": "^0.1.0",
"debug": "^2.6.9", "debug": "^2.6.9",
"doctrine": "1.5.0", "doctrine": "1.5.0",
"eslint-import-resolver-node": "^0.3.2", "eslint-import-resolver-node": "^0.3.3",
"eslint-module-utils": "^2.4.1", "eslint-module-utils": "^2.6.0",
"has": "^1.0.3", "has": "^1.0.3",
"minimatch": "^3.0.4", "minimatch": "^3.0.4",
"object.values": "^1.1.0", "object.values": "^1.1.1",
"read-pkg-up": "^2.0.0", "read-pkg-up": "^2.0.0",
"resolve": "^1.12.0" "resolve": "^1.17.0",
"tsconfig-paths": "^3.9.0"
}, },
"dependencies": { "dependencies": {
"doctrine": { "doctrine": {
@@ -3123,12 +3136,12 @@
} }
}, },
"eslint-plugin-jsdoc": { "eslint-plugin-jsdoc": {
"version": "26.0.2", "version": "27.0.5",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-26.0.2.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-27.0.5.tgz",
"integrity": "sha512-KtZjqtM3Z8x84vQBFKGUyBbZRGXYHVWSJ2XyYSUTc8KhfFrvzQ/GXPp6f1M1/YCNzP3ImD5RuDNcr+OVvIZcBA==", "integrity": "sha512-LU2sclCdHe4ykYlb2Jb7Nk7L6xd8PfwANV1KRgwHV78kCo/D8aeTdinNZb8BpZQEmu4HbrY82SPZIvyYumHVTQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"comment-parser": "^0.7.4", "comment-parser": "^0.7.5",
"debug": "^4.1.1", "debug": "^4.1.1",
"jsdoctypeparser": "^6.1.0", "jsdoctypeparser": "^6.1.0",
"lodash": "^4.17.15", "lodash": "^4.17.15",
@@ -3214,14 +3227,14 @@
"dev": true "dev": true
}, },
"espree": { "espree": {
"version": "7.0.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-7.0.0.tgz", "resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz",
"integrity": "sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw==", "integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==",
"dev": true, "dev": true,
"requires": { "requires": {
"acorn": "^7.1.1", "acorn": "^7.2.0",
"acorn-jsx": "^5.2.0", "acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.1.0" "eslint-visitor-keys": "^1.2.0"
}, },
"dependencies": { "dependencies": {
"acorn": { "acorn": {
@@ -3229,6 +3242,12 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz",
"integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==", "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==",
"dev": true "dev": true
},
"eslint-visitor-keys": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz",
"integrity": "sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ==",
"dev": true
} }
} }
}, },
@@ -6085,9 +6104,9 @@
"dev": true "dev": true
}, },
"sass": { "sass": {
"version": "1.26.7", "version": "1.26.8",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.26.7.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.8.tgz",
"integrity": "sha512-xgNazdkr6yvgHEfNaOjKtZzhDZmKYMCmoRKMPrTDo7YvjaITIzU2DDYsIUuN/atAg7/JOxPeCQHH7TtCo5Tq2g==", "integrity": "sha512-yvtzyrKLGiXQu7H12ekXqsfoGT/aTKeMDyVzCB675k1HYuaj0py63i8Uf4SI9CHXj6apDhpfwbUr3gGOjdpu2Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"chokidar": ">=2.0.0 <4.0.0" "chokidar": ">=2.0.0 <4.0.0"
@@ -6839,6 +6858,18 @@
"repeat-string": "^1.6.1" "repeat-string": "^1.6.1"
} }
}, },
"tsconfig-paths": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz",
"integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==",
"dev": true,
"requires": {
"@types/json5": "^0.0.29",
"json5": "^1.0.1",
"minimist": "^1.2.0",
"strip-bom": "^3.0.0"
}
},
"tslib": { "tslib": {
"version": "1.13.0", "version": "1.13.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
+4 -4
View File
@@ -30,16 +30,16 @@
"babel-loader": "^8.1.0", "babel-loader": "^8.1.0",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"css-loader": "^3.5.3", "css-loader": "^3.5.3",
"eslint": "^7.1.0", "eslint": "^7.2.0",
"eslint-config-google": "^0.14.0", "eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.20.2", "eslint-plugin-import": "^2.21.1",
"eslint-plugin-jsdoc": "^26.0.2", "eslint-plugin-jsdoc": "^27.0.5",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"html-webpack-plugin": "^4.3.0", "html-webpack-plugin": "^4.3.0",
"mini-css-extract-plugin": "^0.9.0", "mini-css-extract-plugin": "^0.9.0",
"postcss-loader": "^3.0.0", "postcss-loader": "^3.0.0",
"regenerator-runtime": "^0.13.5", "regenerator-runtime": "^0.13.5",
"sass": "^1.26.7", "sass": "^1.26.8",
"sass-loader": "^8.0.2", "sass-loader": "^8.0.2",
"webpack": "^4.43.0", "webpack": "^4.43.0",
"webpack-cli": "^3.3.11" "webpack-cli": "^3.3.11"
+5 -4
View File
@@ -1057,6 +1057,7 @@ function playerSetIdle() {
playerTitle.textContent = '-- IDLE --'; playerTitle.textContent = '-- IDLE --';
playerArtist.textContent = ''; playerArtist.textContent = '';
setProgressBar(playerBar, 0); setProgressBar(playerBar, 0);
clearInterval(playhead_timer);
} }
function updatePlayerInfo(item) { function updatePlayerInfo(item) {
@@ -1118,9 +1119,9 @@ function updatePlayerPlayhead(playhead) {
setProgressBar(playerBar, player_playhead_position / currentPlayingItem.duration, secondsToStr(player_playhead_position)); setProgressBar(playerBar, player_playhead_position / currentPlayingItem.duration, secondsToStr(player_playhead_position));
if (playing) { if (playing) {
playhead_timer = setInterval(function() { playhead_timer = setInterval(function() {
player_playhead_position += 0.1; player_playhead_position += 0.3;
setProgressBar(playerBar, player_playhead_position / currentPlayingItem.duration, secondsToStr(player_playhead_position)); setProgressBar(playerBar, player_playhead_position / currentPlayingItem.duration, secondsToStr(player_playhead_position));
}, 100); // delay in milliseconds }, 300); // delay in milliseconds
} }
} else { } else {
if (playing) { if (playing) {
@@ -1142,7 +1143,7 @@ playerBarBox.addEventListener('mousedown', function() {
playerBarBox.addEventListener('mouseup', function(event) { playerBarBox.addEventListener('mouseup', function(event) {
playerBarBox.removeEventListener('mousemove', playheadDragged); playerBarBox.removeEventListener('mousemove', playheadDragged);
const percent = event.offsetX / playerBarBox.clientWidth; const percent = (event.clientX - playerBarBox.getBoundingClientRect().x) / playerBarBox.clientWidth;
request('post', { request('post', {
move_playhead: percent * currentPlayingItem.duration, move_playhead: percent * currentPlayingItem.duration,
}); });
@@ -1150,7 +1151,7 @@ playerBarBox.addEventListener('mouseup', function(event) {
}); });
function playheadDragged(event) { function playheadDragged(event) {
const percent = event.offsetX / playerBarBox.clientWidth; const percent = (event.clientX - playerBarBox.getBoundingClientRect().x) / playerBarBox.clientWidth;
setProgressBar(playerBar, percent, secondsToStr(percent * currentPlayingItem.duration)); setProgressBar(playerBar, percent, secondsToStr(percent * currentPlayingItem.duration));
} }
+4 -3
View File
@@ -2,10 +2,11 @@ export function isOverflown(element) {
return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth; return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
} }
export function setProgressBar(bar, progress, text='') { export function setProgressBar(bar, progress, text = '') {
const progStr = (progress*100).toString(); const progPos = (-1 * (1 - progress) * bar.scrollWidth).toString();
const progStr = (progress * 100).toString();
bar.setAttribute('aria-valuenow', progStr); bar.setAttribute('aria-valuenow', progStr);
bar.style.width = progStr + '%'; bar.style.transform = "translateX(" + progPos + "px)";
bar.textContent = text; bar.textContent = text;
} }
+2 -2
View File
@@ -425,7 +425,7 @@
</div> </div>
<span id="playerArtist">Artist</span> <span id="playerArtist">Artist</span>
<div id="playerBarBox" class="progress"> <div id="playerBarBox" class="progress">
<div id="playerBar" class="progress-bar" role="progressbar" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div> <div id="playerBar" class="progress-bar pr-2" role="progressbar" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" style="width: 100%; text-align: right; transform: translateX(-100%);"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -493,7 +493,7 @@
<span class="uploadItemTitle mr-3"></span> <span class="uploadItemTitle mr-3"></span>
<span class="uploadItemError text-danger"></span> <span class="uploadItemError text-danger"></span>
<div class="progress" style="margin-top: 5px; height: 10px;"> <div class="progress" style="margin-top: 5px; height: 10px;">
<div class="uploadProgress progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div> <div class="uploadProgress progress-bar pr-2" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 100%; text-align: right; transform: translateX(-100%);"></div>
</div> </div>
</div> </div>
</div> </div>