Merge upstream master and update web dependencies

This commit is contained in:
Tyler Vigario 2020-06-09 17:16:31 -07:00
commit 66bf1f1510
No known key found for this signature in database
GPG Key ID: 4D670648A0376AA4
13 changed files with 105 additions and 62 deletions

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

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.

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'

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()
# ====================== # ======================

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

97
web/package-lock.json generated
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",

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"

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));
} }

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;
} }

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>