Merge branch 'master' into develop
This commit is contained in:
commit
371dc01205
|
@ -12,7 +12,7 @@ def guess_mimetype(f):
|
|||
t = magic.from_buffer(f.read(b), mime=True)
|
||||
if not t.startswith("audio/"):
|
||||
# failure, we try guessing by extension
|
||||
mt, _ = mimetypes.guess_type(f.path)
|
||||
mt, _ = mimetypes.guess_type(f.name)
|
||||
if mt:
|
||||
t = mt
|
||||
return t
|
||||
|
|
|
@ -36,3 +36,12 @@ def test_get_audio_file_data(name, expected):
|
|||
result = utils.get_audio_file_data(f)
|
||||
|
||||
assert result == expected
|
||||
|
||||
|
||||
def test_guess_mimetype_dont_crash_with_s3(factories, mocker, settings):
|
||||
"""See #857"""
|
||||
settings.DEFAULT_FILE_STORAGE = "funkwhale_api.common.storage.ASCIIS3Boto3Storage"
|
||||
mocker.patch("magic.from_buffer", return_value="none")
|
||||
f = factories["music.Upload"].build(audio_file__filename="test.mp3")
|
||||
|
||||
assert utils.guess_mimetype(f.audio_file) == "audio/mpeg"
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Added copy-to-clipboard button with Subsonic password input (#814)
|
|
@ -0,0 +1 @@
|
|||
Fixed broken translation on home and track detail page (#833)
|
|
@ -0,0 +1 @@
|
|||
Fixed secondary menus truncated on narrow screens (#855)
|
|
@ -0,0 +1 @@
|
|||
Fix broken upload for specific files when using S3 storage (#857)
|
|
@ -68,12 +68,7 @@
|
|||
<div class="ui list">
|
||||
<div class="item">
|
||||
<i class="tag icon"></i>
|
||||
<div
|
||||
class="content"
|
||||
v-translate="{url: musicbrainzUrl}"
|
||||
translate-context="Content/Home/List item/Verb">
|
||||
Get quality metadata about your music thanks to <a href="%{ url }" target="_blank">MusicBrainz</a>
|
||||
</div>
|
||||
<div class="content" v-html="musicbrainzItem"></div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<i class="plus icon"></i>
|
||||
|
@ -147,6 +142,10 @@ export default {
|
|||
return {
|
||||
title: this.$pgettext('Head/Home/Title', "Welcome")
|
||||
}
|
||||
},
|
||||
musicbrainzItem () {
|
||||
let msg = this.$pgettext('Content/Home/List item/Verb', 'Get quality metadata about your music thanks to <a href="%{ url }" target="_blank">MusicBrainz</a>')
|
||||
return this.$gettextInterpolate(msg, {url: this.musicbrainzUrl})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,12 @@
|
|||
</div>
|
||||
<template v-if="subsonicEnabled">
|
||||
<div v-if="token" class="field">
|
||||
<password-input v-model="token" />
|
||||
<password-input
|
||||
ref="passwordInput"
|
||||
v-model="token"
|
||||
:key="token"
|
||||
:copy-button="true"
|
||||
:default-show="showToken"/>
|
||||
</div>
|
||||
<dangerous-button
|
||||
v-if="token"
|
||||
|
@ -69,7 +74,8 @@ export default {
|
|||
errors: [],
|
||||
success: false,
|
||||
isLoading: false,
|
||||
successMessage: ''
|
||||
successMessage: '',
|
||||
showToken: false
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
@ -98,6 +104,7 @@ export default {
|
|||
let self = this
|
||||
let url = `users/users/${this.$store.state.auth.username}/subsonic-token/`
|
||||
return axios.post(url, {}).then(response => {
|
||||
self.showToken = true
|
||||
self.token = response.data['subsonic_api_token']
|
||||
self.isLoading = false
|
||||
self.success = true
|
||||
|
|
|
@ -10,20 +10,37 @@
|
|||
<span @click="showPassword = !showPassword" :title="labels.title" class="ui icon button">
|
||||
<i class="eye icon"></i>
|
||||
</span>
|
||||
<button v-if="copyButton" @click.prevent="copy" class="ui icon button" :title="labels.copy">
|
||||
<i class="copy icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
function copyStringToClipboard (str) {
|
||||
// cf https://techoverflow.net/2018/03/30/copying-strings-to-the-clipboard-using-pure-javascript/
|
||||
let el = document.createElement('textarea');
|
||||
el.value = str;
|
||||
el.setAttribute('readonly', '');
|
||||
el.style = {position: 'absolute', left: '-9999px'};
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(el);
|
||||
}
|
||||
|
||||
export default {
|
||||
props: ['value', 'index'],
|
||||
props: ['value', 'index', 'defaultShow', 'copyButton'],
|
||||
data () {
|
||||
return {
|
||||
showPassword: false
|
||||
showPassword: this.defaultShow || false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
labels () {
|
||||
return {
|
||||
title: this.$pgettext('Content/Settings/Button.Tooltip/Verb', 'Show/hide password')
|
||||
title: this.$pgettext('Content/Settings/Button.Tooltip/Verb', 'Show/hide password'),
|
||||
copy: this.$pgettext('*/*/Button.Label/Short, Verb', 'Copy')
|
||||
}
|
||||
},
|
||||
passwordInputType () {
|
||||
|
@ -32,6 +49,11 @@ export default {
|
|||
}
|
||||
return 'password'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
copy () {
|
||||
copyStringToClipboard(this.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -14,11 +14,7 @@
|
|||
<i class="circular inverted music orange icon"></i>
|
||||
<div class="content">
|
||||
{{ track.title }}
|
||||
<div class="sub header">
|
||||
<div translate-context="Content/Track/Paragraph"
|
||||
v-translate="{album: track.album.title, artist: track.artist.name, albumUrl: albumUrl, artistUrl: artistUrl}"
|
||||
>From album <a class="internal" href="%{ albumUrl }">%{ album }</a> by <a class="internal" href="%{ artistUrl }">%{ artist }</a></div>
|
||||
</div>
|
||||
<div class="sub header" v-html="subtitle"></div>
|
||||
</div>
|
||||
</h2>
|
||||
<div class="header-buttons">
|
||||
|
@ -230,6 +226,10 @@ export default {
|
|||
")"
|
||||
)
|
||||
},
|
||||
subtitle () {
|
||||
let msg = this.$pgettext('Content/Track/Paragraph', 'From album <a class="internal" href="%{ albumUrl }">%{ album }</a> by <a class="internal" href="%{ artistUrl }">%{ artist }</a>')
|
||||
return this.$gettextInterpolate(msg, {album: this.track.album.title, artist: this.track.artist.name, albumUrl: this.albumUrl, artistUrl: this.artistUrl})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
id() {
|
||||
|
|
|
@ -131,6 +131,7 @@ body {
|
|||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
border: none;
|
||||
overflow-y: auto;
|
||||
.ui.item {
|
||||
border: none;
|
||||
border-bottom-style: none;
|
||||
|
|
Loading…
Reference in New Issue