Commit 7a38a209 authored by Agate's avatar Agate 💬
Browse files

Merge branch 'develop' of dev.funkwhale.audio:funkwhale/funkwhale into develop

parents dcd8e941 e5212792
......@@ -1223,6 +1223,7 @@ VERSATILEIMAGEFIELD_RENDITION_KEY_SETS = {
"attachment_square": [
("original", "url"),
("medium_square_crop", "crop__200x200"),
("large_square_crop", "crop__600x600"),
],
}
VERSATILEIMAGEFIELD_SETTINGS = {
......
......@@ -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):
"""
......
......@@ -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):
......
......@@ -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:
......
......@@ -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"):
......
......@@ -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"
),
},
}
......
Added a new, large thumbnail size for cover images (#1205
\ No newline at end of file
Enforce authentication when viewing remote channels, profiles and libraries (#1210)
\ No newline at end of file
......@@ -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">
......
......@@ -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…"),
......
......@@ -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 => {
......
......@@ -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'
......
......@@ -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
......@@ -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
......
......@@ -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() {
......
......@@ -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() {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment