Merge upstream master and update web dependencies
This commit is contained in:
commit
66bf1f1510
@ -31,6 +31,7 @@ username = botamusique
|
||||
comment = Hi, I'm here to play radio, local music or youtube/soundcloud music. Have fun!
|
||||
# default volume from 0 to 1.
|
||||
volume = 0.1
|
||||
stereo = True
|
||||
# playback mode should be one of "one-shot", "repeat", "random", "autoplay"
|
||||
playback_mode = one-shot
|
||||
autoplay_length = 5
|
||||
|
@ -39,6 +39,9 @@ port = 64738
|
||||
# 'admin': Users allowed to kill the bot, or ban URLs. Separated by ';'
|
||||
#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.
|
||||
# This option will be overridden by value in the database.
|
||||
|
@ -64,7 +64,7 @@ class ReverseProxied(object):
|
||||
|
||||
|
||||
web = Flask(__name__)
|
||||
web.config['TEMPLATES_AUTO_RELOAD'] = True
|
||||
#web.config['TEMPLATES_AUTO_RELOAD'] = True
|
||||
log = logging.getLogger("bot")
|
||||
user = 'Remote Control'
|
||||
|
||||
|
26
mumbleBot.py
26
mumbleBot.py
@ -38,12 +38,13 @@ class MumbleBot:
|
||||
self.log.info(f"bot: botamusique version {self.version}, starting...")
|
||||
signal.signal(signal.SIGINT, self.ctrl_caught)
|
||||
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'):
|
||||
self.volume_set = var.db.getfloat('bot', 'volume')
|
||||
|
||||
self.volume = self.volume_set
|
||||
|
||||
self.stereo = var.config.getboolean('bot', 'stereo', fallback=True)
|
||||
|
||||
if args.channel:
|
||||
self.channel = args.channel
|
||||
else:
|
||||
@ -62,6 +63,7 @@ class MumbleBot:
|
||||
self.song_start_at = -1
|
||||
self.last_ffmpeg_err = ""
|
||||
self.read_pcm_size = 0
|
||||
self.pcm_buffer_size = 0
|
||||
# self.download_threads = []
|
||||
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
|
||||
@ -104,7 +106,9 @@ class MumbleBot:
|
||||
self.username = var.config.get("bot", "username")
|
||||
|
||||
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.set_codec_profile("audio")
|
||||
@ -369,8 +373,11 @@ class MumbleBot:
|
||||
else:
|
||||
ffmpeg_debug = "warning"
|
||||
|
||||
channels = 2 if self.stereo else 1
|
||||
self.pcm_buffer_size = 960*channels
|
||||
|
||||
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))
|
||||
|
||||
# The ffmpeg process is a thread
|
||||
@ -381,7 +388,7 @@ class MumbleBot:
|
||||
else:
|
||||
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):
|
||||
# Function start if the next music isn't ready
|
||||
@ -452,8 +459,8 @@ class MumbleBot:
|
||||
self.song_start_at = time.time() - self.playhead
|
||||
self.playhead = time.time() - self.song_start_at
|
||||
|
||||
raw_music = self.thread.stdout.read(480)
|
||||
self.read_pcm_size += 480
|
||||
raw_music = self.thread.stdout.read(self.pcm_buffer_size)
|
||||
self.read_pcm_size += self.pcm_buffer_size
|
||||
|
||||
if self.redirect_ffmpeg_log:
|
||||
try:
|
||||
@ -476,7 +483,8 @@ class MumbleBot:
|
||||
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.
|
||||
# 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:
|
||||
current = var.playlist.current_item()
|
||||
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.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()
|
||||
|
||||
# ======================
|
||||
|
@ -1,5 +1,3 @@
|
||||
opuslib==2.0.0
|
||||
protobuf==3.4.0
|
||||
flask
|
||||
youtube-dl
|
||||
python-magic
|
||||
@ -7,5 +5,5 @@ Pillow
|
||||
mutagen
|
||||
requests
|
||||
packaging
|
||||
pymumble
|
||||
pymumble>=1.2
|
||||
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
97
web/package-lock.json
generated
@ -1117,6 +1117,12 @@
|
||||
"integrity": "sha512-iYCgjm1dGPRuo12+BStjd1HiVQqhlRhWDOQigNxn023HcjnhsiFz9pc6CzJj4HwDCSQca9bxTL4PxJDbkdm3PA==",
|
||||
"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": {
|
||||
"version": "14.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.4.tgz",
|
||||
@ -2877,9 +2883,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"eslint": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.1.0.tgz",
|
||||
"integrity": "sha512-DfS3b8iHMK5z/YLSme8K5cge168I8j8o1uiVmFCgnnjxZQbCGyraF8bMl7Ju4yfBmCuxD7shOF7eqGkcuIHfsA==",
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.2.0.tgz",
|
||||
"integrity": "sha512-B3BtEyaDKC5MlfDa2Ha8/D6DsS4fju95zs0hjS3HdGazw+LNayai38A25qMppK37wWGWNYSPOR6oYzlz5MHsRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
@ -2888,10 +2894,10 @@
|
||||
"cross-spawn": "^7.0.2",
|
||||
"debug": "^4.0.1",
|
||||
"doctrine": "^3.0.0",
|
||||
"eslint-scope": "^5.0.0",
|
||||
"eslint-scope": "^5.1.0",
|
||||
"eslint-utils": "^2.0.0",
|
||||
"eslint-visitor-keys": "^1.1.0",
|
||||
"espree": "^7.0.0",
|
||||
"eslint-visitor-keys": "^1.2.0",
|
||||
"espree": "^7.1.0",
|
||||
"esquery": "^1.2.0",
|
||||
"esutils": "^2.0.2",
|
||||
"file-entry-cache": "^5.0.1",
|
||||
@ -2937,9 +2943,9 @@
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
|
||||
"integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
@ -2971,15 +2977,21 @@
|
||||
}
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
|
||||
"integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz",
|
||||
"integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esrecurse": "^4.1.0",
|
||||
"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": {
|
||||
"version": "12.4.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
|
||||
@ -3091,23 +3103,24 @@
|
||||
}
|
||||
},
|
||||
"eslint-plugin-import": {
|
||||
"version": "2.20.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz",
|
||||
"integrity": "sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg==",
|
||||
"version": "2.21.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.21.1.tgz",
|
||||
"integrity": "sha512-qYOOsgUv63vHof7BqbzuD+Ud34bXHxFJxntuAC1ZappFZXYbRIek3aJ7jc9i2dHDGDyZ/0zlO0cpioES265Lsw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"array-includes": "^3.0.3",
|
||||
"array.prototype.flat": "^1.2.1",
|
||||
"array-includes": "^3.1.1",
|
||||
"array.prototype.flat": "^1.2.3",
|
||||
"contains-path": "^0.1.0",
|
||||
"debug": "^2.6.9",
|
||||
"doctrine": "1.5.0",
|
||||
"eslint-import-resolver-node": "^0.3.2",
|
||||
"eslint-module-utils": "^2.4.1",
|
||||
"eslint-import-resolver-node": "^0.3.3",
|
||||
"eslint-module-utils": "^2.6.0",
|
||||
"has": "^1.0.3",
|
||||
"minimatch": "^3.0.4",
|
||||
"object.values": "^1.1.0",
|
||||
"object.values": "^1.1.1",
|
||||
"read-pkg-up": "^2.0.0",
|
||||
"resolve": "^1.12.0"
|
||||
"resolve": "^1.17.0",
|
||||
"tsconfig-paths": "^3.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"doctrine": {
|
||||
@ -3123,12 +3136,12 @@
|
||||
}
|
||||
},
|
||||
"eslint-plugin-jsdoc": {
|
||||
"version": "26.0.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-26.0.2.tgz",
|
||||
"integrity": "sha512-KtZjqtM3Z8x84vQBFKGUyBbZRGXYHVWSJ2XyYSUTc8KhfFrvzQ/GXPp6f1M1/YCNzP3ImD5RuDNcr+OVvIZcBA==",
|
||||
"version": "27.0.5",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-27.0.5.tgz",
|
||||
"integrity": "sha512-LU2sclCdHe4ykYlb2Jb7Nk7L6xd8PfwANV1KRgwHV78kCo/D8aeTdinNZb8BpZQEmu4HbrY82SPZIvyYumHVTQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"comment-parser": "^0.7.4",
|
||||
"comment-parser": "^0.7.5",
|
||||
"debug": "^4.1.1",
|
||||
"jsdoctypeparser": "^6.1.0",
|
||||
"lodash": "^4.17.15",
|
||||
@ -3214,14 +3227,14 @@
|
||||
"dev": true
|
||||
},
|
||||
"espree": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-7.0.0.tgz",
|
||||
"integrity": "sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz",
|
||||
"integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^7.1.1",
|
||||
"acorn": "^7.2.0",
|
||||
"acorn-jsx": "^5.2.0",
|
||||
"eslint-visitor-keys": "^1.1.0"
|
||||
"eslint-visitor-keys": "^1.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
@ -3229,6 +3242,12 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz",
|
||||
"integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==",
|
||||
"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
|
||||
},
|
||||
"sass": {
|
||||
"version": "1.26.7",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.26.7.tgz",
|
||||
"integrity": "sha512-xgNazdkr6yvgHEfNaOjKtZzhDZmKYMCmoRKMPrTDo7YvjaITIzU2DDYsIUuN/atAg7/JOxPeCQHH7TtCo5Tq2g==",
|
||||
"version": "1.26.8",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.26.8.tgz",
|
||||
"integrity": "sha512-yvtzyrKLGiXQu7H12ekXqsfoGT/aTKeMDyVzCB675k1HYuaj0py63i8Uf4SI9CHXj6apDhpfwbUr3gGOjdpu2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chokidar": ">=2.0.0 <4.0.0"
|
||||
@ -6839,6 +6858,18 @@
|
||||
"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": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
||||
|
@ -30,16 +30,16 @@
|
||||
"babel-loader": "^8.1.0",
|
||||
"core-js": "^3.6.5",
|
||||
"css-loader": "^3.5.3",
|
||||
"eslint": "^7.1.0",
|
||||
"eslint": "^7.2.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-plugin-jsdoc": "^26.0.2",
|
||||
"eslint-plugin-import": "^2.21.1",
|
||||
"eslint-plugin-jsdoc": "^27.0.5",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"html-webpack-plugin": "^4.3.0",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"regenerator-runtime": "^0.13.5",
|
||||
"sass": "^1.26.7",
|
||||
"sass": "^1.26.8",
|
||||
"sass-loader": "^8.0.2",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.11"
|
||||
|
@ -1057,6 +1057,7 @@ function playerSetIdle() {
|
||||
playerTitle.textContent = '-- IDLE --';
|
||||
playerArtist.textContent = '';
|
||||
setProgressBar(playerBar, 0);
|
||||
clearInterval(playhead_timer);
|
||||
}
|
||||
|
||||
function updatePlayerInfo(item) {
|
||||
@ -1118,9 +1119,9 @@ function updatePlayerPlayhead(playhead) {
|
||||
setProgressBar(playerBar, player_playhead_position / currentPlayingItem.duration, secondsToStr(player_playhead_position));
|
||||
if (playing) {
|
||||
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));
|
||||
}, 100); // delay in milliseconds
|
||||
}, 300); // delay in milliseconds
|
||||
}
|
||||
} else {
|
||||
if (playing) {
|
||||
@ -1142,7 +1143,7 @@ playerBarBox.addEventListener('mousedown', function() {
|
||||
|
||||
playerBarBox.addEventListener('mouseup', function(event) {
|
||||
playerBarBox.removeEventListener('mousemove', playheadDragged);
|
||||
const percent = event.offsetX / playerBarBox.clientWidth;
|
||||
const percent = (event.clientX - playerBarBox.getBoundingClientRect().x) / playerBarBox.clientWidth;
|
||||
request('post', {
|
||||
move_playhead: percent * currentPlayingItem.duration,
|
||||
});
|
||||
@ -1150,7 +1151,7 @@ playerBarBox.addEventListener('mouseup', function(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));
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,11 @@ export function isOverflown(element) {
|
||||
return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
|
||||
}
|
||||
|
||||
export function setProgressBar(bar, progress, text='') {
|
||||
const progStr = (progress*100).toString();
|
||||
export function setProgressBar(bar, progress, text = '') {
|
||||
const progPos = (-1 * (1 - progress) * bar.scrollWidth).toString();
|
||||
const progStr = (progress * 100).toString();
|
||||
bar.setAttribute('aria-valuenow', progStr);
|
||||
bar.style.width = progStr + '%';
|
||||
bar.style.transform = "translateX(" + progPos + "px)";
|
||||
bar.textContent = text;
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@
|
||||
</div>
|
||||
<span id="playerArtist">Artist</span>
|
||||
<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>
|
||||
@ -493,7 +493,7 @@
|
||||
<span class="uploadItemTitle mr-3"></span>
|
||||
<span class="uploadItemError text-danger"></span>
|
||||
<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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user