Skip to content
Snippets Groups Projects
Verified Commit 371dc012 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Merge branch 'master' into develop

parents e24c1f23 d8dd76f1
No related branches found
No related tags found
No related merge requests found
......@@ -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"
Added copy-to-clipboard button with Subsonic password input (#814)
Fixed broken translation on home and track detail page (#833)
Fixed secondary menus truncated on narrow screens (#855)
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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment