Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Philipp Wolfer
funkwhale
Commits
7a38a209
Commit
7a38a209
authored
Aug 31, 2020
by
Agate
💬
Browse files
Merge branch 'develop' of dev.funkwhale.audio:funkwhale/funkwhale into develop
parents
dcd8e941
e5212792
Changes
16
Hide whitespace changes
Inline
Side-by-side
api/config/settings/common.py
View file @
7a38a209
...
...
@@ -1223,6 +1223,7 @@ VERSATILEIMAGEFIELD_RENDITION_KEY_SETS = {
"attachment_square"
:
[
(
"original"
,
"url"
),
(
"medium_square_crop"
,
"crop__200x200"
),
(
"large_square_crop"
,
"crop__600x600"
),
],
}
VERSATILEIMAGEFIELD_SETTINGS
=
{
...
...
api/funkwhale_api/common/models.py
View file @
7a38a209
...
...
@@ -267,6 +267,13 @@ class Attachment(models.Model):
proxy_url
=
reverse
(
"api:v1:attachments-proxy"
,
kwargs
=
{
"uuid"
:
self
.
uuid
})
return
federation_utils
.
full_url
(
proxy_url
+
"?next=medium_square_crop"
)
@
property
def
download_url_large_square_crop
(
self
):
if
self
.
file
:
return
utils
.
media_url
(
self
.
file
.
crop
[
"600x600"
].
url
)
proxy_url
=
reverse
(
"api:v1:attachments-proxy"
,
kwargs
=
{
"uuid"
:
self
.
uuid
})
return
federation_utils
.
full_url
(
proxy_url
+
"?next=large_square_crop"
)
class
MutationAttachment
(
models
.
Model
):
"""
...
...
api/funkwhale_api/common/serializers.py
View file @
7a38a209
...
...
@@ -297,6 +297,7 @@ class AttachmentSerializer(serializers.Serializer):
urls
[
"source"
]
=
o
.
url
urls
[
"original"
]
=
o
.
download_url_original
urls
[
"medium_square_crop"
]
=
o
.
download_url_medium_square_crop
urls
[
"large_square_crop"
]
=
o
.
download_url_large_square_crop
return
urls
def
create
(
self
,
validated_data
):
...
...
api/funkwhale_api/common/views.py
View file @
7a38a209
...
...
@@ -175,7 +175,7 @@ class AttachmentViewSet(
return
r
size
=
request
.
GET
.
get
(
"next"
,
"original"
).
lower
()
if
size
not
in
[
"original"
,
"medium_square_crop"
]:
if
size
not
in
[
"original"
,
"medium_square_crop"
,
"large_square_crop"
]:
size
=
"original"
try
:
...
...
api/funkwhale_api/federation/tasks.py
View file @
7a38a209
...
...
@@ -429,7 +429,7 @@ def fetch(fetch_obj):
)
except
Exception
:
logger
.
exception
(
"Error while fetching actor outbox: %s"
,
obj
.
actor
.
outbox
.
url
"Error while fetching actor outbox: %s"
,
obj
.
actor
.
outbox
_
url
)
else
:
if
result
.
get
(
"next_page"
):
...
...
api/tests/common/test_serializers.py
View file @
7a38a209
...
...
@@ -200,6 +200,9 @@ def test_attachment_serializer_existing_file(factories, to_api_date):
"medium_square_crop"
:
federation_utils
.
full_url
(
attachment
.
file
.
crop
[
"200x200"
].
url
),
"large_square_crop"
:
federation_utils
.
full_url
(
attachment
.
file
.
crop
[
"600x600"
].
url
),
},
}
...
...
@@ -227,6 +230,9 @@ def test_attachment_serializer_remote_file(factories, to_api_date):
"medium_square_crop"
:
federation_utils
.
full_url
(
proxy_url
+
"?next=medium_square_crop"
),
"large_square_crop"
:
federation_utils
.
full_url
(
proxy_url
+
"?next=large_square_crop"
),
},
}
...
...
changes/changelog.d/1205.enhancement
0 → 100644
View file @
7a38a209
Added a new, large thumbnail size for cover images (#1205
\ No newline at end of file
changes/changelog.d/1210.enhancement
0 → 100644
View file @
7a38a209
Enforce authentication when viewing remote channels, profiles and libraries (#1210)
\ No newline at end of file
front/src/components/Queue.vue
View file @
7a38a209
...
...
@@ -6,8 +6,8 @@
<div
class=
"ui six wide column current-track"
>
<div
class=
"ui basic segment"
id=
"player"
>
<template
v-if=
"currentTrack"
>
<img
ref=
"cover"
alt=
""
v-if=
"currentTrack.cover && currentTrack.cover.urls.
original
"
:src=
"$store.getters['instance/absoluteUrl'](currentTrack.cover.urls.
original
)"
>
<img
ref=
"cover"
alt=
""
v-else-if=
"currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.urls.
original
"
:src=
"$store.getters['instance/absoluteUrl'](currentTrack.album.cover.urls.
original
)"
>
<img
ref=
"cover"
alt=
""
v-if=
"currentTrack.cover && currentTrack.cover.urls.
large_square_crop
"
:src=
"$store.getters['instance/absoluteUrl'](currentTrack.cover.urls.
large_square_crop
)"
>
<img
ref=
"cover"
alt=
""
v-else-if=
"currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.urls.
large_square_crop
"
:src=
"$store.getters['instance/absoluteUrl'](currentTrack.album.cover.urls.
large_square_crop
)"
>
<img
class=
"ui image"
alt=
""
v-else
src=
"../assets/audio/default-cover.png"
>
<h1
class=
"ui header"
>
<div
class=
"content ellipsis"
>
...
...
front/src/components/library/AlbumDropdown.vue
View file @
7a38a209
...
...
@@ -20,6 +20,15 @@
<button
class=
"ui floating dropdown circular icon basic button"
:title=
"labels.more"
v-dropdown=
"
{direction: 'downward'}">
<i
class=
"ellipsis vertical icon"
></i>
<div
class=
"menu"
>
<a
:href=
"object.fid"
v-if=
"domain != $store.getters['instance/domain']"
target=
"_blank"
class=
"basic item"
>
<i
class=
"external icon"
></i>
<translate
:translate-params=
"
{domain: domain}" translate-context="Content/*/Button.Label/Verb">View on %{ domain }
</translate>
</a>
<div
role=
"button"
v-if=
"isEmbedable"
...
...
@@ -86,6 +95,7 @@ import EmbedWizard from "@/components/audio/EmbedWizard"
import
Modal
from
'
@/components/semantic/Modal
'
import
ReportMixin
from
'
@/components/mixins/Report
'
import
{
getDomain
}
from
'
@/utils
'
export
default
{
mixins
:
[
ReportMixin
],
...
...
@@ -108,6 +118,11 @@ export default {
}
},
computed
:
{
domain
()
{
if
(
this
.
object
)
{
return
getDomain
(
this
.
object
.
fid
)
}
},
labels
()
{
return
{
more
:
this
.
$pgettext
(
'
*/*/Button.Label/Noun
'
,
"
More…
"
),
...
...
front/src/components/library/ArtistBase.vue
View file @
7a38a209
...
...
@@ -57,6 +57,15 @@
<button
class=
"ui floating dropdown icon button"
ref=
"dropdown"
v-dropdown
>
<i
class=
"dropdown icon"
></i>
<div
class=
"menu"
>
<a
:href=
"object.fid"
v-if=
"domain != $store.getters['instance/domain']"
target=
"_blank"
class=
"basic item"
>
<i
class=
"external icon"
></i>
<translate
:translate-params=
"
{domain: domain}" translate-context="Content/*/Button.Label/Verb">View on %{ domain }
</translate>
</a>
<button
role=
"button"
v-if=
"publicLibraries.length > 0"
...
...
@@ -137,6 +146,8 @@ import RadioButton from "@/components/radios/Button"
import
TagsList
from
"
@/components/tags/List
"
import
ReportMixin
from
'
@/components/mixins/Report
'
import
{
getDomain
}
from
'
@/utils
'
const
FETCH_URL
=
"
albums/
"
export
default
{
...
...
@@ -205,6 +216,11 @@ export default {
}
},
computed
:
{
domain
()
{
if
(
this
.
object
)
{
return
getDomain
(
this
.
object
.
fid
)
}
},
isPlayable
()
{
return
(
this
.
object
.
albums
.
filter
(
a
=>
{
...
...
front/src/components/library/TrackBase.vue
View file @
7a38a209
...
...
@@ -44,6 +44,14 @@
<button
class=
"ui floating dropdown circular icon basic button"
:title=
"labels.more"
v-dropdown=
"
{direction: 'downward'}">
<i
class=
"ellipsis vertical icon"
></i>
<div
class=
"menu"
style=
"right: 0; left: auto"
>
<a
:href=
"track.fid"
v-if=
"domain != $store.getters['instance/domain']"
target=
"_blank"
class=
"basic item"
>
<i
class=
"external icon"
></i>
<translate
:translate-params=
"
{domain: domain}" translate-context="Content/*/Button.Label/Verb">View on %{ domain }
</translate>
</a>
<div
role=
"button"
v-if=
"publicLibraries.length > 0"
...
...
@@ -116,6 +124,7 @@
import
time
from
"
@/utils/time
"
import
axios
from
"
axios
"
import
url
from
"
@/utils/url
"
import
{
getDomain
}
from
'
@/utils
'
import
logger
from
"
@/logging
"
import
PlayButton
from
"
@/components/audio/PlayButton
"
import
TrackFavoriteIcon
from
"
@/components/favorites/TrackFavoriteIcon
"
...
...
@@ -190,6 +199,11 @@ export default {
}
},
computed
:
{
domain
()
{
if
(
this
.
track
)
{
return
getDomain
(
this
.
track
.
fid
)
}
},
publicLibraries
()
{
return
this
.
libraries
.
filter
(
l
=>
{
return
l
.
privacy_level
===
'
everyone
'
...
...
front/src/utils.js
View file @
7a38a209
...
...
@@ -51,3 +51,9 @@ export function checkRedirectToLogin (store, router) {
router
.
push
({
name
:
'
login
'
,
query
:
{
next
:
router
.
currentRoute
.
fullPath
}})
}
}
export
function
getDomain
(
url
)
{
let
parser
=
document
.
createElement
(
"
a
"
)
parser
.
href
=
url
return
parser
.
hostname
}
\ No newline at end of file
front/src/views/auth/ProfileBase.vue
View file @
7a38a209
...
...
@@ -9,6 +9,14 @@
<button
class=
"ui pointing dropdown icon small basic right floated button"
ref=
"dropdown"
v-dropdown=
"
{direction: 'downward'}" style="position: absolute; right: 1em; top: 1em;">
<i
class=
"ellipsis vertical icon"
></i>
<div
class=
"menu"
>
<a
:href=
"object.fid"
v-if=
"object.domain != $store.getters['instance/domain']"
target=
"_blank"
class=
"basic item"
>
<i
class=
"external icon"
></i>
<translate
:translate-params=
"
{domain: object.domain}" translate-context="Content/*/Button.Label/Verb">View on %{ domain }
</translate>
</a>
<div
role=
"button"
class=
"basic item"
...
...
@@ -93,7 +101,12 @@ export default {
}
},
created
()
{
this
.
fetch
()
let
authenticated
=
this
.
$store
.
state
.
auth
.
authenticated
if
(
!
authenticated
&&
this
.
domain
&&
this
.
$store
.
getters
[
'
instance/domain
'
]
!=
this
.
domain
)
{
this
.
$router
.
push
({
name
:
'
login
'
,
query
:
{
next
:
this
.
$route
.
fullPath
}})
}
else
{
this
.
fetch
()
}
},
beforeRouteUpdate
(
to
,
from
,
next
)
{
to
.
meta
.
preserveScrollPosition
=
true
...
...
front/src/views/channels/DetailBase.vue
View file @
7a38a209
...
...
@@ -84,6 +84,14 @@
<i
class=
"code icon"
></i>
<translate
translate-context=
"Content/*/Button.Label/Verb"
>
Embed
</translate>
</a>
<a
:href=
"object.url"
v-if=
"object.actor.domain != $store.getters['instance/domain']"
target=
"_blank"
class=
"basic item"
>
<i
class=
"external icon"
></i>
<translate
:translate-params=
"{domain: object.actor.domain}"
translate-context=
"Content/*/Button.Label/Verb"
>
View on %{ domain }
</translate>
</a>
<div
class=
"divider"
></div>
<a
href=
""
...
...
@@ -270,6 +278,10 @@ export default {
},
async
created
()
{
await
this
.
fetchData
()
let
authenticated
=
this
.
$store
.
state
.
auth
.
authenticated
if
(
!
authenticated
&&
this
.
$store
.
getters
[
'
instance/domain
'
]
!=
this
.
object
.
actor
.
domain
)
{
this
.
$router
.
push
({
name
:
'
login
'
,
query
:
{
next
:
this
.
$route
.
fullPath
}})
}
},
methods
:
{
async
fetchData
()
{
...
...
front/src/views/library/DetailBase.vue
View file @
7a38a209
...
...
@@ -7,6 +7,14 @@
<button
class=
"ui pointing dropdown icon small basic right floated button"
ref=
"dropdown"
v-dropdown=
"
{direction: 'downward'}" style="position: absolute; right: 1em; top: 1em;">
<i
class=
"ellipsis vertical icon"
></i>
<div
class=
"menu"
>
<a
:href=
"object.fid"
v-if=
"object.actor.domain != $store.getters['instance/domain']"
target=
"_blank"
class=
"basic item"
>
<i
class=
"external icon"
></i>
<translate
:translate-params=
"
{domain: object.actor.domain}" translate-context="Content/*/Button.Label/Verb">View on %{ domain }
</translate>
</a>
<div
role=
"button"
class=
"basic item"
...
...
@@ -148,6 +156,10 @@ export default {
},
async
created
()
{
await
this
.
fetchData
()
let
authenticated
=
this
.
$store
.
state
.
auth
.
authenticated
if
(
!
authenticated
&&
this
.
$store
.
getters
[
'
instance/domain
'
]
!=
this
.
object
.
actor
.
domain
)
{
this
.
$router
.
push
({
name
:
'
login
'
,
query
:
{
next
:
this
.
$route
.
fullPath
}})
}
},
methods
:
{
async
fetchData
()
{
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment